gui/TabControl: Fixed memory leaks
[sdk] / ecere / src / gui / controls / TabControl.ec
index 2761a81..aa5dfa5 100644 (file)
@@ -19,7 +19,7 @@ class TabButton : Button
    {
       return true;
    }
-   
+
    bool OnLeftButtonDown(int x, int y, Modifiers mods)
    {
       Button::OnLeftButtonDown(x, y, mods);
@@ -130,7 +130,7 @@ class TabButton : Button
             surface.DrawLine(x+2,h-1, w-4, h-1);
             surface.PutPixel(x,h-3);
             surface.PutPixel(x+1,h-2);
-            
+
             surface.PutPixel(w-2, h - 3);
             surface.PutPixel(w-3, h - 2);
             break;
@@ -138,7 +138,7 @@ class TabButton : Button
             surface.DrawLine(x+2,0, w-4,0);
             surface.PutPixel(x, 2);
             surface.PutPixel(x+1, 1);
-            
+
             surface.PutPixel(w-2, 2);
             surface.PutPixel(w-3, 1);
             break;
@@ -146,7 +146,7 @@ class TabButton : Button
             surface.DrawLine(w-1,y+2, w-1, h-4);
             surface.PutPixel(w-3, y);
             surface.PutPixel(w-2, y+1);
-            
+
             surface.PutPixel(w - 3, h-2);
             surface.PutPixel(w - 2, h-3);
             break;
@@ -154,7 +154,7 @@ class TabButton : Button
             surface.DrawLine(0,y+2, 0, h-4);
             surface.PutPixel(2, y);
             surface.PutPixel(1, y+1);
-            
+
             surface.PutPixel(2, h-2);
             surface.PutPixel(1, h-3);
             break;
@@ -164,7 +164,7 @@ class TabButton : Button
       if(text)
          surface.TextExtent(text, strlen(text),&tw, &th);
       y = (clientSize.h - th - 1)/2 + (checked ? 0 : -2);
-      
+
       if(ellipsis)
       {
          int width = clientSize.w - 2*6;
@@ -199,7 +199,7 @@ class TabButton : Button
 
          surface.LineStipple(0x5555);
          surface.Rectangle(x1, y1, x2, y2);
-         surface.LineStipple(0);            
+         surface.LineStipple(0);
       }
    }
 }
@@ -211,19 +211,19 @@ static void PlaceButton(TabButton button, TabsPlacement placement, bool selected
    {
       case top:
          button.size = selected ? { 74, 25 } : { 70, 22 };
-         button.anchor = Anchor { left = buttonsOffset + button.tab.id * 70 + 2*of, bottom = 0 };
+         button.anchor = Anchor { left = buttonsOffset + (int)button.tab.id * 70 + 2*of, bottom = 0 };
          break;
       case bottom:
          button.size = selected ? { 74, 25 } : { 70, 22 };
-         button.anchor = Anchor { left = buttonsOffset + button.tab.id * 70 + 2*of, top = 0 };
+         button.anchor = Anchor { left = buttonsOffset + (int)button.tab.id * 70 + 2*of, top = 0 };
          break;
       case left:
          button.size = selected ? { 73, 26 } : { 70, 22 };
-         button.anchor = Anchor { top = buttonsOffset + button.tab.id * 22 + 2*of, right = 0 };
+         button.anchor = Anchor { top = buttonsOffset + (int)button.tab.id * 22 + 2*of, right = 0 };
          break;
       case right:
          button.size = selected ? { 73, 26 } : { 70, 22 };
-         button.anchor = Anchor { top = buttonsOffset + button.tab.id * 22 + 2*of, left = 0 };
+         button.anchor = Anchor { top = buttonsOffset + (int)button.tab.id * 22 + 2*of, left = 0 };
          break;
    }
 }
@@ -231,7 +231,7 @@ static void PlaceButton(TabButton button, TabsPlacement placement, bool selected
 static define skinMainColor = Color { 0, 71, 128 };
 static define skinBackground = Color { 255, 255, 255 };
 static define skinTextColor = skinMainColor;
-static define skinInactiveTextColor = Color { skinMainColor.r - 20, skinMainColor.g - 20, skinMainColor.b - 20 };
+static define skinInactiveTextColor = Color { 0, 51, 108 };
 
 #define CAPTION      14
 #define NAME_OFFSET   2
@@ -296,16 +296,15 @@ public class TabControl : Window
             }
          }
          else
-            return true; 
+            return true;
       }
       return false;
    }
 
-   void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving)
+   void ShowDecorations(Font captionFont, Surface surface, const char * name, bool active, bool moving)
    {
       if(placement == bottom && ((BorderBits)borderStyle).fixed)
       {
-         bool isNormal = (state == normal || state == maximized);
          int top = 0, border = 0, bottom = 0;
          if(state == minimized)
             top = border = bottom = 0;
@@ -326,13 +325,13 @@ public class TabControl : Window
          {
             surface.SetForeground(gray);
             surface.Rectangle(0,1, size.w-1, CAPTION+1);
-            
+
             surface.SetForeground(white);
             surface.Rectangle(1, 1, clientSize.w-2, CAPTION-1);
 
-            surface.SetBackground(skinBackground);         
+            surface.SetBackground(skinBackground);
             surface.Area(2, 2, size.w-3, CAPTION+1);
-            
+
             surface.SetForeground((active ? skinTextColor : skinInactiveTextColor));
             surface.TextOpacity(false);
             surface.TextFont(captionFont);
@@ -340,7 +339,7 @@ public class TabControl : Window
             {
                int buttonsSize = border +
                   ((hasMaximize || hasMinimize) ? 52 : 18);
-               surface.WriteTextDots(left, border + NAME_OFFSETX, top + NAME_OFFSET, 
+               surface.WriteTextDots(left, border + NAME_OFFSETX, top + NAME_OFFSET,
                   size.w - (buttonsSize + border + 4), name, strlen(name));
             }
          }
@@ -366,26 +365,26 @@ public class TabControl : Window
       {
          surface.SetForeground(white);
          surface.Rectangle(
-            clientStart.x + 1 + (placement == left) * 80, 
-            clientStart.y + 1 + (placement == top) * 30, 
-            clientStart.x + clientSize.w - (placement == right) * 80 - 2, 
+            clientStart.x + 1 + (placement == left) * 80,
+            clientStart.y + 1 + (placement == top) * 30,
+            clientStart.x + clientSize.w - (placement == right) * 80 - 2,
             clientStart.y + clientSize.h - (placement == bottom) * 30 - 2);
          surface.SetForeground(gray);
          surface.Rectangle(
-            clientStart.x + (placement == left) * 80, 
-            clientStart.y + (placement == top) * 30, 
-            clientStart.x + clientSize.w - (placement == right) * 80 - 1, 
+            clientStart.x + (placement == left) * 80,
+            clientStart.y + (placement == top) * 30,
+            clientStart.x + clientSize.w - (placement == right) * 80 - 1,
             clientStart.y + clientSize.h - (placement == bottom) * 30 - 1);
       }
 
       if(curButton)
       {
          Box box;
-         int id = curTab ? curTab.id : 0;
+         //int id = curTab ? (int)curTab.id : 0;
          Button button = curButton;
          int x = button.position.x;
          int y = button.position.y;
-         
+
          switch(placement)
          {
             case TabsPlacement::bottom:
@@ -409,7 +408,7 @@ public class TabControl : Window
          surface.SetForeground(white);
          switch(placement)
          {
-            case TabsPlacement::bottom:   surface.VLine(clientSize.h-32 + clientStart.y + 1, clientSize.h-28 + clientStart.y + 1, x + 1 + clientStart.x); break; 
+            case TabsPlacement::bottom:   surface.VLine(clientSize.h-32 + clientStart.y + 1, clientSize.h-28 + clientStart.y + 1, x + 1 + clientStart.x); break;
             case TabsPlacement::top:      surface.VLine(clientStart.y + 30, clientStart.y + 31, x + 1 + clientStart.x); break;
             case TabsPlacement::left:     surface.HLine(78 + clientStart.x, 81 + clientStart.x, y + 1 + clientStart.y); break;
             case TabsPlacement::right:    surface.HLine(clientStart.y + 30, clientStart.y + 31, y + 1 + clientStart.y); break;
@@ -479,7 +478,6 @@ public class TabControl : Window
    {
       if(placement == bottom && ((BorderBits)borderStyle).fixed)
       {
-         bool isNormal = (state == normal || state == maximized);
          MinMaxValue aw = 0, ah = 0;
 
          *x = *y = 0;
@@ -542,7 +540,7 @@ public class TabControl : Window
 
    bool NotifyClicked(Button button, int x, int y, Modifiers mods)
    {
-      if(curTab == (Tab)button.id)
+      if(curTab == (Tab)(intptr)button.id)
          return true;
       //curButton.Activate();
       curButton.MakeActive();
@@ -551,7 +549,7 @@ public class TabControl : Window
       {
          curButton.checked = false;
          button.checked = true;
-         curTab = (Tab)button.id;
+         curTab = (Tab)(intptr)button.id;
 
          if(curButton)
             PlaceButton(curButton, placement, false, buttonsOffset);
@@ -574,23 +572,32 @@ public class TabControl : Window
 
    public void AddTab(Tab tab)
    {
-      tab.parent = this;
+      if(tab.parent != this)
+      {
+         tab.parent = this;
+         return;
+      }
       tab.autoCreate = false;
       tab.id = numTabs;
-      tab.button = TabButton
+      if(!tab.button)
       {
-         parent = tabButtons,
-         master = this, stayDown = true,
-         text = tab.text, id = (uint)tab, NotifyClicked = NotifyClicked,
-         tab = tab,
-         background = background;
-      };
-      incref tab.button;
+         tab.button = TabButton
+         {
+            parent = tabButtons,
+            master = this, stayDown = true,
+            text = tab.text, id = (int64)(intptr)tab, NotifyClicked = NotifyClicked,
+            tab = tab,
+            background = background;
+         };
+         incref tab.button;
+      }
 
       if(created)
       {
          tab.button.Create();
-         incref tab;
+         // This was causing leaks with RemoveTab / AddTab usage in Cartographer...
+         // RemoveTab() does not dec'ref...
+         // incref tab;
       }
 
       numTabs++;
@@ -616,16 +623,19 @@ public class TabControl : Window
    {
       Window child;
       Tab fallbackTab = null;
-      tab.parent = null;
+      // tab.parent = null;
       for(child = tabButtons.children.first; child; child = child.next)
       {
          if(child._class == class(TabButton))
          {
             TabButton button = (TabButton)child;
-            if(button.id == (uint)tab)
+            if(button.id == (int64)(intptr)tab)
             {
                if(button.created)
+               {
                   button.Destroy(0);
+                  numTabs--;
+               }
                break;
             }
             else
@@ -638,12 +648,13 @@ public class TabControl : Window
             fallbackTab = tabButtons.children.first ? ((TabButton)tabButtons.children.first).tab : null;
          if(fallbackTab)
             fallbackTab.SelectTab();
+         else
+            curTab = null;
          /*curTab = fallbackTab;
          curButton = curTab.button;
          curButton.checked = true;
          curTab.autoCreate = true;*/
       }
-      numTabs--;
    }
 
    ~TabControl()
@@ -677,7 +688,7 @@ public class TabControl : Window
             int pleft = button.anchor.left.distance, nleft = newButton ? newButton.anchor.left.distance : 0;
             int ptop = button.anchor.top.distance, ntop = newButton ? newButton.anchor.top.distance : 0;
             if(button == curButton) continue;
-            if((smartKey == left && (pleft < cleft || ptop < ctop) && (!newButton || pleft > nleft || ptop > ntop)) || 
+            if((smartKey == left && (pleft < cleft || ptop < ctop) && (!newButton || pleft > nleft || ptop > ntop)) ||
                (smartKey == right && (pleft > cleft || ptop > ctop) && (!newButton || pleft < nleft || pleft < ptop)))
                newButton = button;
          }
@@ -739,7 +750,7 @@ public class Tab : Window
       button.NotifyClicked(button.master, button, 0, 0, 0);
    }
 
-   watch(text)
+   watch(caption)
    {
       if(button)
          button.text = text;