ecere/gui/controls/ListBox: Simplified member access
[sdk] / ecere / src / gui / controls / ListBox.ec
index dab9bdd..5d73e7d 100644 (file)
@@ -54,6 +54,7 @@ private:
 
 public class DataField
 {
+   class_no_expansion;
 public:
    property Class dataType
    {
@@ -119,7 +120,7 @@ public:
       }
    };
    property int sortOrder { get { return this ? sortOrder : 0; } };
-   property char * header
+   property const char * header
    {
       set
       {
@@ -150,9 +151,6 @@ public:
    {
       if(prev != after)
       {
-         int position = 0;
-         DataField field;
-
          listBox.fields.Move(this, after);
 
          // Fix up positions
@@ -181,12 +179,12 @@ public:
             if(cell && cell.isSet && dataType)
             {
                static char tempString[4096];
-               String string;
+               const String string;
                int tw = 0;
                if(dataType.type == normalClass || dataType.type == noHeadClass)
-                  string = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, cell.data[0], tempString, userData, null);
+                  string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, cell.data[0], tempString, userData, null);
                else
-                  string = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, cell.data, tempString, userData, null);
+                  string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, cell.data, tempString, userData, null);
                if(string)
                   display.FontExtent(row.header ? boldFont : font, string, strlen(string), &tw, null);
                else
@@ -235,7 +233,7 @@ private:
    }
 
    DataField prev, next;
-   char * header;
+   const char * header;
    Class dataType;
    int width;
    uint index;
@@ -258,28 +256,28 @@ public class DataRow
    bool skipCheck;
 #endif
 public:
-   property int64 tag { set { tag = value; } get { return tag; } };
+   property int64 tag { set { if(this) tag = value; } get { return this ? tag : 0; } };
    property DataRow previous { get { return prev; } };
    property DataRow next { get { return next; } };
    property int index { get { return (this && (!parent || parent.IsExpanded())) ? index : -1; } };
-   property char * string
+   property const char * string
    {
       set { SetData(listBox.fields.first, value); }
       get { return GetData(listBox.fields.first); }
    };
    property bool isHeader { set { header = value; } get { return this ? header : false; } };
-   property BitmapResource icon { set { icon = value; } get { return icon; } };
+   property BitmapResource icon { set { if(this) icon = value; } get { return this ? icon : null; } };
    property bool collapsed
    {
       set
       {
-         if(collapsed != value)
+         if(this && collapsed != value)
          {
             collapsed = value;
             if(parent.IsExpanded())
             {
                DataRow search;
-               int index;
+               int ix;
 
                if(value)
                {
@@ -304,10 +302,10 @@ public:
                   }
                }
 
-               index = this.index+1;
+               ix = index+1;
                for(search = GetNextRow(); search; search = search.GetNextRow())
-                  search.index = index++;
-               listBox.rowCount = index;
+                  search.index = ix++;
+               listBox.rowCount = ix;
 
                listBox.HideEditBox(false, false, true);
 
@@ -321,7 +319,7 @@ public:
             }
          }
 #ifdef _DEBUG
-         if(!skipCheck)
+         if(this && !skipCheck)
             listBox.CheckConsistency();
 #endif
       }
@@ -486,20 +484,19 @@ public:
          if(listBox && prev != after)
          {
             DataRow search;
-            int afterIndex = -1;
             int headerSize = ((listBox.style.header) ? listBox.rowHeight : 0);
             int height = listBox.clientSize.h + 1 - headerSize;
             int ixCount = (!collapsed && subRows.count) ? GetLastRow().index - index + 1 : 1;
 
             if(!after || after.index < index)
             {
-               if(after == listBox.firstRowShown.prev)
+               if((after && after == listBox.firstRowShown.prev) || (!after && !parent /*&& listBox.firstRowShown.prev*/))
                   listBox.firstRowShown = this;
 
                // All rows between AFTER (exclusive) and ROW (exclusive) are incremented by one
                // ROW is equal to AFTER's index + 1
 
-               for(search = after ? after.next : listBox.rows.first; search && search != this; search = search.GetNextRow())
+               for(search = after ? after.next : (parent ? parent.subRows.first : listBox.rows.first); search && search != this; search = search.GetNextRow())
                   search.index += ixCount;
 
                if(after && after.subRows.first && !after.collapsed)
@@ -508,7 +505,7 @@ public:
                   index = search.index + 1;
                }
                else
-                  index = after ? (after.index + 1) : 0;
+                  index = after ? (after.index + 1) : parent ? parent.index + 1 : 0;
 
                // Fix indices of sub rows
                if(!collapsed)
@@ -520,10 +517,12 @@ public:
             }
             else
             {
-               DataRow nextRow = GetNextRow();
+               DataRow nextRow;
+               int afterIXCount = 1;
+
+               nextRow = GetNextRow();
                if(this == listBox.firstRowShown)
                   listBox.firstRowShown = nextRow;
-               index = after.index;
 
                // All rows between ROW (exclusive) and AFTER (inclusive) are decremented by one
                // ROW is equal to AFTER's index
@@ -533,8 +532,33 @@ public:
                   search.index -= ixCount;
                   if(search == after) break;
                }
+
+               // Fix up's after's sub rows
+               if(after && !after.collapsed)
+               {
+                  DataRow last = after.GetLastRow();
+                  if(last != after)
+                  {
+                     int ix = after.index+1;
+                     for(search = after.GetNextRow(); search; search = search.GetNextRow())
+                     {
+                        afterIXCount++;
+                        search.index = ix++;
+                        if(search == last) break;
+                     }
+                  }
+               }
+               index = after.index + afterIXCount;
+
+               // Fix indices of sub rows
+               if(!collapsed)
+               {
+                  int c, ix = index+1;
+                  for(c = 1, search = GetNextRow(); search && c < ixCount; c++, search = search.GetNextRow())
+                     search.index = ix++;
+               }
             }
-            listBox.rows.Move(this, after);
+            (parent ? parent.subRows : listBox.rows).Move(this, after);
 
 #ifdef _DEBUG
             listBox.CheckConsistency();
@@ -573,7 +597,7 @@ public:
             if((field.dataType.type == normalClass || field.dataType.type == noHeadClass))
                return cell.data[0];
             else
-               return (void *)cell.data;   // Cast for MemoryGuard
+               return cell.data;
          }
       }
       return null;
@@ -611,7 +635,7 @@ public:
             listBox.modifiedDocument = true;
             listBox.Update(null);
             if(dataType && (dataType.type == normalClass || dataType.type == noHeadClass))
-               return (void *)cell.data;     // Cast for MemoryGuard
+               return cell.data;
             else
                return &cell.data;
          }
@@ -702,7 +726,7 @@ public:
                      (sizeof(class ListBoxCell) + field.dataType.typeSize - sizeof(void *)) : sizeof(class ListBoxCell);
                   ListBoxCell cell = (ListBoxCell)new0 byte[size];
                   row.cells.Add(cell);
-                  FillBytes(cell.data, 0, size - (uint)&((ListBoxCell)0).data);
+                  FillBytes(cell.data, 0, size - (uint)(uintptr)&((ListBoxCell)0).data);
                   cell.isSet = false;
                }
             }
@@ -751,7 +775,7 @@ public:
       return null;
    }
 
-   DataRow AddStringf(char * format, ...)
+   DataRow AddStringf(const char * format, ...)
    {
       if(this)
       {
@@ -770,7 +794,7 @@ public:
       return null;
    }
 
-   DataRow AddString(char * string)
+   DataRow AddString(const char * string)
    {
       if(this)
       {
@@ -786,7 +810,7 @@ public:
 private:
    DataRow()
    {
-      subRows.offset = (uint)&((DataRow)0).prev;
+      subRows.offset = (uint)(uintptr)&((DataRow)0).prev;
    }
 
    ~DataRow()
@@ -884,9 +908,9 @@ private:
 
          {
             DataRow search;
-            int index = this.index;
+            int ix = index;
             for(search = this; search; search = search.GetNextRow())
-               search.index = index++;
+               search.index = ix++;
          }
          if(scrollToCurrent)
          {
@@ -964,7 +988,7 @@ public class ListBox : CommonControl
 public:
    // Properties
    property bool freeSelect { property_category $"Behavior" set { style.freeSelect = value; } get { return style.freeSelect; } };
-   property DataRow currentRow { property_category $"Private" /*"Behavior"*/ set { SetCurrentRow(value, false); } get { return currentRow; } };
+   property DataRow currentRow { property_category $"Private" /*"Behavior"*/ set { if(this) SetCurrentRow(value, false); } get { return this ? currentRow : null; } };
    property DataField currentField
    {
       get { return currentField; }
@@ -997,7 +1021,7 @@ public:
             OnApplyGraphics();
          }
       }
-      get { return rowHeight; }
+      get { return this ? rowHeight : 0; }
    };
    property Seconds typingTimeout
    {
@@ -1108,6 +1132,7 @@ public:
    virtual bool Window::NotifyKeyHit(ListBox listBox, DataRow row, Key key, unichar ch);
    virtual bool Window::NotifyModified(ListBox listBox, DataRow row);
    virtual bool Window::NotifyEditing(ListBox listBox, DataRow row);
+   virtual void Window::NotifyMoved(ListBox listBox, DataRow row, Modifiers mods);
 
 #ifdef _DEBUG
    private void CheckConsistency()
@@ -1158,7 +1183,7 @@ public:
                stayOnTop = true;
                inactive = true;
                dontScrollVert = true;
-               id = (uint64)addedField;
+               id = (int64)(intptr)addedField;
                text = addedField.header;
                bevel = (!guiApp.textMode && !style.clearHeader);
                ellipsis = true;
@@ -1185,7 +1210,7 @@ public:
                   (sizeof(class ListBoxCell) + field.dataType.typeSize - sizeof(void *)) : sizeof(class ListBoxCell);
                ListBoxCell cell = (ListBoxCell)new0 byte[size];
                row.cells.Add(cell);
-               FillBytes(cell.data, 0, size - (uint)&((ListBoxCell)0).data);
+               FillBytes(cell.data, 0, size - (uint)(uintptr)&((ListBoxCell)0).data);
                cell.isSet = false;
 
                if(row.subRows.first)
@@ -1281,8 +1306,6 @@ public:
       if(row)
       {
          DataRow search;
-         DataField field;
-         int c;
 
          row.index = 0;
          rows.Insert(null, row);
@@ -1291,7 +1314,7 @@ public:
          for(search = row.GetNextRow(); search; search = search.GetNextRow())
             search.index++;
 
-         this.rowCount++;
+         rowCount++;
          row.cells.Clear();
 
          firstRowShown = row;
@@ -1325,8 +1348,7 @@ public:
                // Find very last row
                {
                   DataRow lastRow;
-                  for(lastRow = rows.last; lastRow && !lastRow.collapsed && lastRow.subRows.last; lastRow)
-                     lastRow = lastRow.subRows.last;
+                  for(lastRow = rows.last; lastRow && !lastRow.collapsed && lastRow.subRows.last; lastRow = lastRow.subRows.last);
                   row.index = lastRow ? (lastRow.index + 1) : 0;
                }
 
@@ -1346,7 +1368,7 @@ public:
                         (sizeof(class ListBoxCell) + field.dataType.typeSize - sizeof(void *)) : sizeof(class ListBoxCell);
                      ListBoxCell cell = (ListBoxCell) new0 byte[size];
                      row.cells.Add(cell);
-                     FillBytes(cell.data, 0, size - (uint)&((ListBoxCell)0).data);
+                     FillBytes(cell.data, 0, size - (uint)(uintptr)&((ListBoxCell)0).data);
                      cell.isSet = false;
                   }
                }
@@ -1401,7 +1423,7 @@ public:
             for(search = row.GetNextRow(); search; search = search.GetNextRow())
                search.index++;
 
-            this.rowCount++;
+            rowCount++;
             row.cells.Clear();
             for(c = 0; c<fields.count; c++)
             {
@@ -1414,7 +1436,7 @@ public:
                      (sizeof(class ListBoxCell) + field.dataType.typeSize - sizeof(void *)) : sizeof(class ListBoxCell);
                   ListBoxCell cell = (ListBoxCell) new0 byte[size];
                   row.cells.Add(cell);
-                  FillBytes(cell.data, 0, size - (uint)&((ListBoxCell)0).data);
+                  FillBytes(cell.data, 0, size - (uint)(uintptr)&((ListBoxCell)0).data);
                   cell.isSet = false;
                }
             }
@@ -1440,7 +1462,7 @@ public:
       return null;
    }
 
-   DataRow AddStringf(char * format, ...)
+   DataRow AddStringf(const char * format, ...)
    {
       if(this)
       {
@@ -1461,7 +1483,7 @@ public:
       return null;
    }
 
-   DataRow AddString(char * string)
+   DataRow AddString(const char * string)
    {
       if(this)
       {
@@ -1498,7 +1520,7 @@ public:
          {
             for(search = row.GetNextRow(); search; search = search.GetNextRow())
                search.index--;
-            this.rowCount--;
+            rowCount--;
          }
 
          HideEditBox(false, false, true);
@@ -1531,8 +1553,8 @@ public:
          //HideEditBox(false, false, true);
 
          SetScrollArea(
-            this.width,
-            (this.rowCount * rowHeight) +
+            width,
+            (rowCount * rowHeight) +
             ((style.header) ? rowHeight : 0) -
             ((!((clientSize.h+1) % rowHeight)) ? rowHeight : 0), true);
 
@@ -1560,11 +1582,10 @@ public:
       return null;
    }
 
-   DataRow FindString(char * searchedString)
+   DataRow FindString(const char * searchedString)
    {
       DataField field;
       bool checkNextField = true;
-      int len = searchedString ? strlen(searchedString) : 0;
 
       for(field = fields.first; field; field = field.next)
       {
@@ -1578,7 +1599,7 @@ public:
                   void * data = row.GetData(field);
                   char tempString[1024] = "";
                   bool needClass = false;
-                  char * string = ((char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
+                  const char * string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
 
                   if(string && string[0])
                      checkNextField = false;
@@ -1592,7 +1613,7 @@ public:
       return null;
    }
 
-   DataRow FindSubString(char * subString)
+   DataRow FindSubString(const char * subString)
    {
       DataField field;
       bool checkNextField = true;
@@ -1612,7 +1633,7 @@ public:
                      void * data = row.GetData(field);
                      char tempString[1024] = "";
                      bool needClass = false;
-                     char * string = ((char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
+                     const char * string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
 
                      if(string && string[0])
                         checkNextField = false;
@@ -1627,13 +1648,13 @@ public:
       return null;
    }
 
-   DataRow FindSubStringi(char * subString)
+   DataRow FindSubStringi(const char * subString)
    {
       DataField field;
       bool checkNextField = true;
       int len = subString ? strlen(subString) : 0;
       DataRow result = null;
-      char * bestResult = null;
+      const char * bestResult = null;
       int bestLen = 0;
 
       if(len)
@@ -1650,7 +1671,7 @@ public:
                      void * data = row.GetData(field);
                      char tempString[1024] = "";
                      bool needClass = false;
-                     char * string = ((char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
+                     const char * string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
 
                      if(string && string[0])
                         checkNextField = false;
@@ -1679,7 +1700,7 @@ public:
       return result;
    }
 
-   DataRow FindSubStringAfter(DataRow after, char * subString)
+   DataRow FindSubStringAfter(DataRow after, const char * subString)
    {
       DataField field;
       bool checkNextField = true;
@@ -1699,7 +1720,7 @@ public:
                      void * data = row.GetData(field);
                      char tempString[1024] = "";
                      bool needClass = false;
-                     char * string = ((char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
+                     const char * string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
 
                      if(string && string[0])
                         checkNextField = false;
@@ -1760,11 +1781,11 @@ public:
             currentRow.Edit(currentField);
 
 
-         this.rowCount = 0;
+         rowCount = 0;
 
          SetScrollArea(
-               this.width,
-               (this.rowCount * rowHeight) +
+               width,
+               (rowCount * rowHeight) +
                ((style.header) ? rowHeight : 0) -
                ((rowHeight && !((clientSize.h+1) % rowHeight)) ? rowHeight : 0), true);
          Update(null);
@@ -1847,8 +1868,8 @@ private:
    ListBox()
    {
       DataField defaultField { };
-      rows.offset = (uint)&((DataRow)0).prev;
-      fields.offset = (uint)&((DataField)0).prev;
+      rows.offset = (uint)(uintptr)&((DataRow)0).prev;
+      fields.offset = (uint)(uintptr)&((DataField)0).prev;
       style.fullRowSelect = true;
       style.fillLastField = true;
       style.expandOnAdd = true;
@@ -1922,7 +1943,6 @@ private:
    {
       if(editData && editData.visible)
       {
-         Class dataType = currentField.dataType;
          if(save)
             editData.SaveData();
 
@@ -1957,8 +1977,6 @@ private:
             */
             PopupEditBox(currentField, repositionOnly);
          }
-         else
-            printf("");
 
          /*else
             currentField = null;*/
@@ -1967,7 +1985,7 @@ private:
 
    void SetCurrentRow(DataRow row, bool notify)
    {
-      if(currentRow != row || (currentRow && currentRow.selectedFlag == unselected))
+      if(this && (currentRow != row || (currentRow && currentRow.selectedFlag == unselected)))
       {
          int headerSize = ((style.header) ? rowHeight : 0);
          int height = clientSize.h + 1 - headerSize;
@@ -2029,7 +2047,7 @@ private:
          int height = rowHeight - (style.alwaysEdit ? 1 : 0);
          int x = 0;
          int y = currentRow.index * rowHeight + (style.header ? rowHeight : 0);
-         int width;
+         int width = 0;
          DataField field;
 
          if(style.collapse && !(style.treeBranch))
@@ -2065,7 +2083,7 @@ private:
             int height = rowHeight - (style.alwaysEdit ? 1 : 0);
             int x = 0;
             int y = currentRow.index * rowHeight + (style.header ? rowHeight : 0);
-            int width;
+            int width = 0;
             //void * data = currentRow.GetData(whichField);
             DataField field;
             DataRow row = null;
@@ -2093,7 +2111,7 @@ private:
                   background = dataBoxBackground;
                   foreground = dataBoxForeground;
 
-                  bool NotifyChanged(bool closingDropDown)
+                  bool NotifyChanged(DataBox dataBox, bool closingDropDown)
                   {
                      DataRow row = null;
                      DataField field = null;
@@ -2178,7 +2196,6 @@ private:
       Font font = fontObject;
       Font boldFont = this.boldFont.font;
 
-
       // Draw gray grid
       if(style.alwaysEdit && style.fullRowSelect)
       {
@@ -2323,7 +2340,7 @@ private:
          int indent = 0;
          DataRow parent;
          Bitmap icon = row.icon ? row.icon.bitmap : null;
-         int collapseRowStart;
+         int collapseRowStart = 0;
          bool lastWasHeader = row.header;
 
          for(parent = row.parent; parent; parent = parent.parent)
@@ -2387,8 +2404,8 @@ private:
             Color colors[] = { formColor, azure, mistyRose, linen, floralWhite, lavender, lavenderBlush, lemonChiffon };
             int level = 0;
             DataRow p = row;
-            while(p = p.parent) level++;
-            background = colors[(level % (sizeof(colors)/sizeof(colors[0]))];
+            while((p = p.parent)) level++;
+            background = colors[level % (sizeof(colors)/sizeof(colors[0]))];
             surface.SetBackground(background);
             surface.Area(rowStart, y, clientSize.w, (y + rowHeight) - 1);
             foreground = branchesColor;
@@ -2436,11 +2453,11 @@ private:
             surface.SetForeground(foreground);
             surface.SetBackground(background);
 
-            ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)class(String)._vTbl[__ecereVMethodID_class_OnDisplay])(class(String), "(none)", surface, x, y - 1 + (rowHeight - fontH)/2, width - EXTRA_SPACE/2, null, Alignment::left, dataDisplayFlags);
+            ((void (*)(void *, const void *, void *, int, int, int, void *, uint, uint))(void *)class(String)._vTbl[__ecereVMethodID_class_OnDisplay])(class(String), "(none)", surface, x, y - 1 + (rowHeight - fontH)/2, width - EXTRA_SPACE/2, null, Alignment::left, dataDisplayFlags);
          }
          else
          {
-            if(!opacity) surface.TextOpacity(false);
+            if(opacity < 1) surface.TextOpacity(false);
             // Draw the rows
             for(field = fields.first; field; field = field.next)
             {
@@ -2504,6 +2521,10 @@ private:
                   foreground = this.background;
                }
 
+#ifdef _DEBUG
+               // surface.WriteTextf(x + 100, y,  "ix: %d", row.index);
+#endif
+
                x += width;// + EXTRA_SPACE;
 
                if(row.header) break;
@@ -2552,17 +2573,17 @@ private:
             break;
       }
       if(firstRowShown) surface.Clip(null);
-      if(this.dragRow && this.dropIndex != -1)
+      if(dragRow && dropIndex != -1)
       {
-         int dropIndex = this.dropIndex;
+         int ix = dropIndex;
          int y;
 
-         if(!style.multiSelect && currentRow.index < this.dropIndex)
-            dropIndex++;
+         if(!style.multiSelect && currentRow.index < dropIndex)
+            ix++;
          surface.DrawingChar(223);
 
          y = style.header ? rowHeight : 0;
-         y += dropIndex * rowHeight - scroll.y;
+         y += ix * rowHeight - scroll.y;
 
          surface.SetForeground(Color { 85, 85, 255 });
          surface.HLine(0, clientSize.w-1, y);
@@ -2572,11 +2593,11 @@ private:
 
    void OnDrawOverChildren(Surface surface)
    {
-      if(draggingField && this.dropField)
+      if(draggingField && dropField)
       {
-         int position = this.dropField.x;
+         int position = dropField.x;
          if(draggingField.x < position)
-            position += this.dropField.width + EXTRA_SPACE;
+            position += dropField.width + EXTRA_SPACE;
 
          surface.SetForeground(Color { 85, 85, 255 });
          surface.VLine(0, rowHeight - 1, position - scroll.x - 2);
@@ -2739,7 +2760,7 @@ private:
 
    bool HeaderPushed(Button control, int x, int y, Modifiers mods)
    {
-      DataField field = (DataField)control.id;
+      DataField field = (DataField)(intptr)control.id;
       // false: dont destroy edit box
       HideEditBox(true, false, true);
       if(style.resizable && ((!field && x < RESIZE_BORDER && fields.last) ||
@@ -2753,9 +2774,9 @@ private:
 
          if(field.fixed) return false;
          resizingField = field;
-         this.resizeX = x + control.position.x;
-         this.startWidth = field.width;
-         this.oldX = x - scroll.x;
+         resizeX = x + control.position.x;
+         startWidth = field.width;
+         oldX = x - scroll.x;
          return false;
       }
       else if(field)
@@ -2782,15 +2803,15 @@ private:
          x += control.position.x;
 
          // Tweak to prevent shrinking field if we're actually moving right
-         if(x - scroll.x > this.oldX &&
-            this.startWidth + x - this.resizeX < field.width)
+         if(x - scroll.x > oldX &&
+            startWidth + x - resizeX < field.width)
          {
-            this.oldX = x - scroll.x;
+            oldX = x - scroll.x;
             return true;
          }
-         this.oldX = x - scroll.x;
+         oldX = x - scroll.x;
 
-         field.width = this.startWidth + x - this.resizeX;
+         field.width = startWidth + x - resizeX;
          field.width = Max(field.width, - EXTRA_SPACE);
 
          AdaptToFieldWidth(field, true);
@@ -2824,9 +2845,9 @@ private:
                   SetScrollPosition(field.x, scroll.y);
                field = null;
             }
-            if(this.dropField != field)
+            if(dropField != field)
             {
-               this.dropField = field;
+               dropField = field;
                if(field)
                {
                   int position = field.x;
@@ -2844,7 +2865,7 @@ private:
                         SetScrollPosition(position, scroll.y);
                   }
 
-                  this.movingFields = true;
+                  movingFields = true;
                }
                Update(null);
             }
@@ -2852,7 +2873,7 @@ private:
       }
       else if(style.resizable)
       {
-         DataField field = (DataField)control.id;
+         DataField field = (DataField)(intptr)control.id;
          if(field)
          {
             if(x < RESIZE_BORDER && field.prev)
@@ -2908,7 +2929,7 @@ private:
                      break;
                   }
                }
-               if(switchField && draggingField != switchField && this.dropField)
+               if(switchField && draggingField != switchField && dropField)
                {
                   for(field = fields.first; field; field = field.next)
                   {
@@ -2940,9 +2961,9 @@ private:
 
    bool HeaderClicked(Button control, int x, int y, Modifiers mods)
    {
-      if(style.header && !this.dropField && style.sortable)
+      if(style.header && !dropField && style.sortable)
       {
-         DataField field = (DataField)control.id;
+         DataField field = (DataField)(intptr)control.id;
          if(sortField == field)
             field.sortOrder *= -1;
          else
@@ -2960,7 +2981,7 @@ private:
    {
       if(style.resizable)
       {
-         DataField field = (DataField)control.id;
+         DataField field = (DataField)(intptr)control.id;
          if(field)
          {
             if(x < RESIZE_BORDER && field.prev)
@@ -2989,7 +3010,7 @@ private:
          if(!visible)
          {
             ReleaseCapture();
-            this.rolledOver = this.dragging = false;
+            rolledOver = dragging = false;
          }
          /*else
             Capture();*/
@@ -3077,12 +3098,12 @@ private:
                      if(cell && cell.isSet && field.dataType)
                      {
                         static char tempString[4096];
-                        char * string;
+                        const char * string;
                         int tw, th;
                         if(field.dataType.type == normalClass || field.dataType.type == noHeadClass)
-                           string = ((char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, cell.data[0], tempString, field.userData, null);
+                           string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, cell.data[0], tempString, field.userData, null);
                         else
-                           string = ((char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, cell.data, tempString, field.userData, null);
+                           string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, cell.data, tempString, field.userData, null);
                         /* GCC-4.4 Bug!
                        if(!string) string = "";
                         display.FontExtent(row.header ? boldFont : font, string, strlen(string), &tw, &th);
@@ -3103,7 +3124,7 @@ private:
          }
          if(!*h)
          {
-            *h = Min(this.maxShown, this.rowCount) * rowHeight;
+            *h = Min(maxShown, rowCount) * rowHeight;
          }
       }
       else
@@ -3142,7 +3163,7 @@ private:
       {
         // Resize left
          DataField field = resizingField;
-         field.width = this.startWidth + x - this.resizeX;
+         field.width = startWidth + x - resizeX;
          field.width = Max(field.width, - EXTRA_SPACE);
 
          AdaptToFieldWidth(field, true);
@@ -3179,22 +3200,22 @@ private:
 
       if(x == MAXINT && y == MAXINT)
       {
-         x = this.mouseX;
-         y = this.mouseY;
+         x = mouseX;
+         y = mouseY;
          isTimer = true;
       }
 
       // ADDED THIS CHECK FOR FieldDropBox LEAKS
-      if(/*!mods.isSideEffect && */(this.rolledOver || !this.dragging))
+      if(/*!mods.isSideEffect && */(rolledOver || !dragging))
       {
          int rowY = (style.header) ? rowHeight : 0;
-         DataRow row = null;
+         DataRow row = null, nextRow;
          int rowIndex;
 
          mouseX = x;
          mouseY = y;
 
-         if(this.dragging &&
+         if(dragging &&
             ((vertScroll && vertScroll.visible &&
              (y < 0 || y >= clientSize.h)) ||
              (horzScroll && horzScroll.visible &&
@@ -3217,19 +3238,29 @@ private:
          // This must be done after the scrolling took place
          rowIndex = firstRowShown ? firstRowShown.index : -1;
          y = Max(y, 0);
-         y = Min(y, clientSize.h-1);
-         for(row = firstRowShown; row; row = row.GetNextRow(), rowIndex ++)
+         y = Min(y, clientSize.h-rowHeight-1);
+         for(row = firstRowShown; row; row = nextRow, rowIndex ++)
          {
+            nextRow = row.GetNextRow();
             rowY += rowHeight;
-            if(rowY > y)
+            if(rowY > y || !nextRow)
             {
                break;
             }
          }
 
+         if(dragRow && style.moveRows)
+         {
+            if(row && row == currentRow)
+               row = row.GetNextRow();
+
+            if(row && row.parent == currentRow)
+               row = row.GetNextRow();
+         }
+
          if(row && currentRow != row)
          {
-            if(this.dragRow && style.moveRows)
+            if(dragRow && style.moveRows)
             {
                if(row.selectedFlag == selected || row.selectedFlag == tempSelected)
                   rowIndex = -1;
@@ -3243,15 +3274,15 @@ private:
                   if(thisRow != row)
                      rowIndex++;
                }
-               if(this.dropIndex != rowIndex)
+               if(dropIndex != rowIndex)
                {
-                  this.dropIndex = rowIndex;
-                  this.editRow = null;
+                  dropIndex = rowIndex;
+                  editRow = null;
                   Update(null);
-                  this.movedRow = true;
+                  movedRow = true;
                }
             }
-            else if((style.freeSelect  || this.dragging) && ((realX>= 0 && realY >= 0 && realX< clientSize.w && realY < clientSize.h) || this.rolledOver))
+            else if((style.freeSelect  || dragging) && ((realX>= 0 && realY >= 0 && realX< clientSize.w && realY < clientSize.h) || rolledOver))
             {
                if(!(style.multiSelect))
                {
@@ -3309,8 +3340,8 @@ private:
 
    bool OnMouseOver(int x, int y, Modifiers mods)
    {
-      if(this.dragging)
-         this.rolledOver = true;
+      if(dragging)
+         rolledOver = true;
       return true;
    }
 
@@ -3359,8 +3390,8 @@ private:
                if(Abs(x - vx) < 2)
                {
                   resizingField = field.prev;
-                  this.resizeX = x;
-                  this.startWidth = resizingField.width;
+                  resizeX = x;
+                  startWidth = resizingField.width;
                   Capture();
                   SetMouseRangeToClient();
                   break;
@@ -3377,7 +3408,6 @@ private:
          int rowIndex = firstRowShown ? firstRowShown.index : -1;
          DataRow previousRow = currentRow;
          DataRow newCurrentRow = null;
-         DataField newCurrentField = null;
          bool moveMultiple = false;
          int numSelected = 0;
          int rowStart = -scroll.x;
@@ -3443,7 +3473,7 @@ private:
                         for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
                            selRow.selectedFlag = unselected;
                         clickedRow = row;
-                        //this.clickedRowIndex = rowIndex;
+                        //clickedRowIndex = rowIndex;
                      }
                      else if(style.moveRows && !(mods.shift) &&
                         (row.selectedFlag == selected || row.selectedFlag == tempSelected) &&
@@ -3461,7 +3491,7 @@ private:
                               row.selectedFlag = selected;
                            }
                            clickedRow = row;
-                           //this.clickedRowIndex = rowIndex;
+                           //clickedRowIndex = rowIndex;
                         }
                         else
                         {
@@ -3536,7 +3566,7 @@ private:
                               else
                                  row.selectedFlag = tempSelected;
                               clickedRow = row;
-                              //this.clickedRowIndex = rowIndex;
+                              //clickedRowIndex = rowIndex;
                            }
                         }
                      }
@@ -3626,9 +3656,11 @@ private:
                {
                   if(style.moveRows)
                   {
-                     this.dragRow = currentRow;
-                     this.dropIndex = -1;
-                     this.movedRow = false;
+                     dragRow = currentRow;
+                     dropIndex = -1;
+                     movedRow = false;
+
+                     Capture();
                   }
                   if(editData && editData.visible && style.alwaysEdit)
                   {
@@ -3664,7 +3696,7 @@ private:
                      }
                   }
                   else if(!(mods.ctrl) && numSelected <= 1)
-                     this.editRow = currentRow;
+                     editRow = currentRow;
 
                   if(style.noDragging && newCurrentRow)
                     NotifyReclick(master, this, newCurrentRow, mods);
@@ -3675,15 +3707,13 @@ private:
                   // activate it
                   if(editData && editData.visible && newCurrentRow)
                   {
-                     DataField field, whichField;
+                     DataField field;
                      int sx = -scroll.x;
                      int indent = 0;
 
                      if(style.collapse && !(style.treeBranch))
                         sx += 15;
 
-                     whichField = currentField;
-
                      {
                         DataRow parent;
                         for(parent = newCurrentRow.parent; parent; parent = parent.parent)
@@ -3793,16 +3823,16 @@ private:
       {
          if(!style.noDragging)
          {
-            this.dragging = true;
+            dragging = true;
             Capture();
          }
          if(x >= 0 && y >= 0 && x < clientSize.w && y < clientSize.h)
-            this.rolledOver = true;
+            rolledOver = true;
          Update(null);
       }
       else
       {
-         this.dragging = false;
+         dragging = false;
          OnLeftButtonUp(x, y, mods);
       }
       return result;
@@ -3826,6 +3856,7 @@ private:
       {
          DataRow row, switchRow = rows.last;
          int rowY = (style.header) ? rowHeight : 0;
+         while(switchRow.lastRow) switchRow = switchRow.lastRow;
          for(row = firstRowShown; row; row = row.GetNextRow())
          {
             rowY += rowHeight;
@@ -3835,7 +3866,7 @@ private:
                break;
             }
          }
-         if(this.editRow == switchRow && y >= 0)
+         if(editRow == switchRow && y >= 0)
          {
             // Find which field
             DataField field;
@@ -3861,9 +3892,9 @@ private:
          }
          else if(style.moveRows && switchRow)
          {
-            if(this.dragRow == switchRow && this.movedRow == false)
+            if(dragRow == switchRow && movedRow == false)
             {
-               DataRow row = this.dragRow;
+               DataRow row = dragRow;
                DataRow selRow;
                if(!(mods.ctrl))
                {
@@ -3927,25 +3958,57 @@ private:
                {
                   for(row = rows.first; row; row = row.GetNextRow())
                   {
-                     if(row == switchRow || row == this.dragRow)
+                     if(row == switchRow || row == dragRow)
                         break;
                   }
 
                   // Switch row first: move before
                   if(row == switchRow)
                   {
-                     if(NotifyMove(master, this, switchRow.prev, mods))
-                        dragRow.Move(switchRow.prev);
+                     DataRow actualMoveRow;
+
+                     if(!switchRow.prev && switchRow.parent == dragRow.parent)
+                        actualMoveRow = null;
+                     else
+                     {
+                        actualMoveRow = switchRow.prev ? switchRow.prev : switchRow;
+                        while(actualMoveRow && actualMoveRow.parent != dragRow.parent && actualMoveRow.parent)
+                           actualMoveRow = actualMoveRow.parent;
+                     }
+
+                     if(!actualMoveRow || (actualMoveRow && actualMoveRow.parent == dragRow.parent))
+                        if(NotifyMove(master, this, actualMoveRow, mods))
+                        {
+                           dragRow.Move(actualMoveRow);
+                           NotifyMoved(master, this, actualMoveRow, mods);
+                        }
                   }
                   // Dragged row first: move after
                   else
                   {
-                     if(NotifyMove(master, this, switchRow, mods))
-                        dragRow.Move(switchRow);
+                     DataRow actualMoveRow = switchRow;
+                     DataRow nextRow = switchRow.GetNextRow();
+
+                     while(nextRow && nextRow.parent != dragRow.parent)
+                        nextRow = nextRow.parent ? nextRow.parent.next : null;
+                     if(nextRow)
+                        actualMoveRow = nextRow.prev;
+
+                     if(!nextRow)
+                        actualMoveRow = dragRow.parent ? dragRow.parent.subRows.last : rows.last;
+
+                     if(!actualMoveRow || (actualMoveRow != dragRow && actualMoveRow.parent == dragRow.parent))
+                        if(NotifyMove(master, this, actualMoveRow, mods))
+                        {
+                           dragRow.Move(actualMoveRow);
+                           NotifyMoved(master, this, actualMoveRow, mods);
+                        }
                   }
                }
             }
          }
+         if(dragRow)
+            ReleaseCapture();
          dragRow = null;
          editRow = null;
          movedRow = false;
@@ -3954,11 +4017,11 @@ private:
       }
 
       timer.Stop();
-      if(this.dragging || style.freeSelect)
+      if(dragging || style.freeSelect)
       {
-         if(this.dragging)
+         if(dragging)
          {
-            this.rolledOver = this.dragging = false;
+            rolledOver = dragging = false;
          }
          if(x >= 0 && y >= 0 && x < clientSize.w && y < clientSize.h && currentRow && style.freeSelect)
          {
@@ -4066,7 +4129,7 @@ private:
                void * data = row.GetData(field);
                char tempString[1024] = "";
                bool needClass = false;
-               char * string = data ? ((char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass) : null;
+               const char * string = data ? ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass) : null;
 
                if(string && string[0])
                   checkNextField = false;
@@ -4075,16 +4138,10 @@ private:
                   if(style.multiSelect)
                   {
                      DataRow selRow;
-                     bool foundRow = false;
 
-                     //this.clickedRowIndex = 0;
                      clickedRow = row;
                      for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
-                     {
-                        if(selRow == row) foundRow = true;
                         selRow.selectedFlag = unselected;
-                        //if(!foundRow) this.clickedRowIndex++;
-                     }
                      row.selectedFlag = selected;
                   }
                   SetCurrentRow(row, true);
@@ -4094,9 +4151,9 @@ private:
                looped = true;
             }
             typingTimer.Stop();
-            if(this.typingTimeOut && !keyHit)
+            if(typingTimeOut && !keyHit)
                typingTimer.Start();
-            if(!result || !this.typingTimeOut || keyHit)
+            if(!result || !typingTimeOut || keyHit)
                typedString[len-1] = '\0';
          }
          if(!checkNextField || result) break;
@@ -4118,7 +4175,7 @@ private:
       }
       else if(key == escape)
       {
-         if(resizingField || this.movingFields || (editData && editData.visible) || this.dragRow)
+         if(resizingField || movingFields || (editData && editData.visible) || dragRow)
          {
             if(editData && editData.visible && style.alwaysEdit && !editData.active)
                return true;
@@ -4126,19 +4183,22 @@ private:
             HideEditBox(false, false, false);
             if(resizingField)
             {
-               resizingField.width = this.startWidth;
+               resizingField.width = startWidth;
                AdaptToFieldWidth(resizingField, true);
                resizingField = null;
                ReleaseCapture();
             }
-            this.dragRow = null;
-            if(this.dragging)
+            if(dragRow)
+               ReleaseCapture();
+
+            dragRow = null;
+            if(dragging)
             {
-               this.dragging = false;
+               dragging = false;
                ReleaseCapture();
             }
 
-            this.movingFields = false;
+            movingFields = false;
             draggingField = null;
             Update(null);
             return false;