]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/treectrl.cpp
The new wxRect doesn't compile so I #if 0ed it
[wxWidgets.git] / src / generic / treectrl.cpp
index c69ea64098cf5f01e8e7f6542e1ed336c39c47f4..79a7c6e1cc7a7126abcf14ce1d3ec2e644ff2a18 100644 (file)
@@ -83,7 +83,7 @@ public:
   int GetX() const { return m_x; }
   int GetY() const { return m_y; }
 
-  void SetHeight(int h) { m_height = h; }
+  void SetHeight(int h) { m_text_height = h; }
 
   void SetX(int x) { m_x = x; }
   void SetY(int y) { m_y = y; }
@@ -139,7 +139,7 @@ private:
   int                 m_isBold      :1; // render the label in bold font
 
   int                 m_x, m_y;
-  long                m_height, m_width;
+  long                m_text_height, m_text_width;
   int                 m_xCross, m_yCross;
   int                 m_level;
   wxArrayTreeItems    m_children;
@@ -189,7 +189,7 @@ wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent,
 
   m_parent = parent;
 
-  dc.GetTextExtent( m_text, &m_width, &m_height );
+  dc.GetTextExtent( m_text, &m_text_width, &m_text_height );
 }
 
 wxGenericTreeItem::~wxGenericTreeItem()
@@ -222,7 +222,7 @@ void wxGenericTreeItem::SetText( const wxString &text, wxDC& dc )
 {
   m_text = text;
 
-  dc.GetTextExtent( m_text, &m_width, &m_height );
+  dc.GetTextExtent( m_text, &m_text_width, &m_text_height );
 }
 
 void wxGenericTreeItem::Reset()
@@ -232,7 +232,7 @@ void wxGenericTreeItem::Reset()
   m_selImage = -1;
   m_data = NULL;
   m_x = m_y =
-  m_height = m_width = 0;
+  m_text_height = m_text_width = 0;
   m_xCross =
   m_yCross = 0;
 
@@ -268,7 +268,7 @@ void wxGenericTreeItem::SetCross( int x, int y )
 void wxGenericTreeItem::GetSize( int &x, int &y )
 {
   if ( y < m_y ) y = m_y;
-  int width = m_x +  m_width;
+  int width = m_x +  m_text_width;
   if (width > x) x = width;
 
   if (IsExpanded())
@@ -284,7 +284,7 @@ void wxGenericTreeItem::GetSize( int &x, int &y )
 wxGenericTreeItem *wxGenericTreeItem::HitTest( const wxPoint& point,
                                                bool &onButton )
 {
-  if ((point.y > m_y) && (point.y < m_y + m_height))
+  if ((point.y > m_y) && (point.y < m_y + m_text_height))
   {
     // FIXME why +5?
     //  Because that is the size of the plus sign, RR
@@ -298,7 +298,7 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest( const wxPoint& point,
 
     /* TODO: we should do a query here like
          m_imageListNormal->GetSize( item->GetImage(), image_w, image_h );  */
-    int w = m_width;
+    int w = m_text_width;
     if (m_image != -1) w += 24;
 
     if ((point.x > m_x) && (point.x < m_x+w))
@@ -353,6 +353,7 @@ void wxTreeCtrl::Init()
   m_yScroll = 0;
   m_lineHeight = 10;
   m_indent = 15;
+  m_spacing = 18;
 
   m_hilightBrush = new wxBrush
     (
@@ -403,6 +404,14 @@ size_t wxTreeCtrl::GetCount() const
 void wxTreeCtrl::SetIndent(unsigned int indent)
 {
   m_indent = indent;
+  m_dirty = TRUE;
+  Refresh();
+}
+
+void wxTreeCtrl::SetSpacing(unsigned int spacing)
+{
+  m_spacing = spacing;
+  m_dirty = TRUE;
   Refresh();
 }
 
@@ -879,32 +888,154 @@ void wxTreeCtrl::Unselect()
   }
 }
 
-void wxTreeCtrl::SelectItem(const wxTreeItemId& itemId)
+void wxTreeCtrl::UnselectAllChildren(wxGenericTreeItem *item)
 {
-  wxGenericTreeItem *item = itemId.m_pItem;
+  item->SetHilight(FALSE);
+  RefreshLine(item);
+  
+  if (item->HasChildren())
+    {
+      wxArrayTreeItems& children = item->GetChildren();
+      size_t count = children.Count();
+      for ( size_t n = 0; n < count; ++n )
+       UnselectAllChildren(children[n]);
+    }
+}
 
-  if ( m_current != item )
-  {
+void wxTreeCtrl::UnselectAll()
+{
+  UnselectAllChildren(GetRootItem().m_pItem);
+}
+
+// Recursive function !
+// To stop we must have crt_item<last_item
+// Algorithm = 
+// Tag all next children, when no more children,
+// Move to parent (not to tag) 
+// Keep going, if we found last_item, we stop
+bool wxTreeCtrl::TagNextChildren(wxGenericTreeItem *crt_item, wxGenericTreeItem *last_item, bool select)
+{
+    wxGenericTreeItem *parent = crt_item->GetParent();
+
+    if ( parent == NULL ) // This is root item
+      return TagAllChildrenUntilLast(crt_item, last_item, select);
+
+    wxArrayTreeItems& children = parent->GetChildren();
+    int index = children.Index(crt_item);
+    wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent?
+
+    size_t count = children.Count();
+    for (size_t n=(size_t)(index+1); n<count; ++n)
+      if (TagAllChildrenUntilLast(children[n], last_item, select)) return true;
+
+    return TagNextChildren(parent, last_item, select);
+}
+
+bool wxTreeCtrl::TagAllChildrenUntilLast(wxGenericTreeItem *crt_item, wxGenericTreeItem *last_item, bool select)
+{
+  crt_item->SetHilight(select);
+  RefreshLine(crt_item);
+  
+  if (crt_item==last_item) return true;
+
+  if (crt_item->HasChildren())
+    {
+      wxArrayTreeItems& children = crt_item->GetChildren();
+      size_t count = children.Count();
+      for ( size_t n = 0; n < count; ++n )
+       if (TagAllChildrenUntilLast(children[n], last_item, select)) return true;
+    }
+       
+  return false;
+}
+
+void wxTreeCtrl::SelectItemRange(wxGenericTreeItem *item1, wxGenericTreeItem *item2)
+{
+  // item2 is not necessary after item1
+  wxGenericTreeItem *first=NULL, *last=NULL;
+
+  // choice first' and 'last' between item1 and item2
+  if (item1->GetY()<item2->GetY()) 
+    {
+      first=item1;
+      last=item2;
+    }
+  else 
+    {
+      first=item2;
+      last=item1;
+    }
+
+  bool select=m_current->HasHilight();
+  
+  if (TagAllChildrenUntilLast(first,last,select)) return;
+
+  cout << first->GetText() << " " << last->GetText() << " " << (int) select << endl;
+  TagNextChildren(first,last,select);  
+}
+
+void wxTreeCtrl::SelectItem(const wxTreeItemId& itemId, 
+                           bool unselect_others, 
+                           bool extended_select)
+{ 
+    bool is_single=!(GetWindowStyleFlag() & wxTR_MULTIPLE);
+
+    //wxCHECK_RET( ( (!unselect_others) && is_single),
+    //           _T("this is a single selection tree") );
+
+    // to keep going anyhow !!!
+    if (is_single) 
+    {
+        unselect_others=true;
+        extended_select=false;
+    }
+
+    wxGenericTreeItem *item = itemId.m_pItem;
+    
     wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, GetId() );
     event.m_item = item;
     event.m_itemOld = m_current;
     event.SetEventObject( this );
+    // Here we don't send any selection mode yet ! TO SEE 
+    
+    if (m_current)
+      cout << m_current->GetText() << " " << (int)m_current->HasHilight() << endl;
+
     if ( GetEventHandler()->ProcessEvent( event ) && event.WasVetoed() )
       return;
 
-    if ( m_current )
+    if (m_current)
+    cout << m_current->GetText() << " " << (int)m_current->HasHilight() << endl;
+
+    // ctrl press
+    if (unselect_others)
     {
-      m_current->SetHilight( FALSE );
-      RefreshLine( m_current );
+        if (is_single) Unselect(); // to speed up thing
+       else UnselectAll();
     }
 
-    m_current = item;
-    m_current->SetHilight( TRUE );
-    RefreshLine( m_current );
+    // shift press
+    if (extended_select) 
+    {
+        if (m_current == NULL) m_current=GetRootItem().m_pItem;
+        // don't change the mark (m_current)
+        SelectItemRange(m_current, item);
+    }
+    else
+    {
+        bool select=true; // the default
+
+       // Check if we need to toggle hilight (ctrl mode)
+       if (!unselect_others)
+         select=!item->HasHilight();
+
+        m_current = item;
+       m_current->SetHilight(select);
+       RefreshLine( m_current );
+    }
 
     event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
     GetEventHandler()->ProcessEvent( event );
-  }
 }
 
 void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
@@ -1152,11 +1283,11 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &
 {
     int horizX = level*m_indent;
 
-    item->SetX( horizX+33 );
+    item->SetX( horizX+m_indent+m_spacing );
     item->SetY( y-m_lineHeight/2 );
     item->SetHeight( m_lineHeight );
 
-    item->SetCross( horizX+15, y );
+    item->SetCross( horizX+m_indent, y );
 
     int oldY = y;
 
@@ -1166,24 +1297,25 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &
     if (IsExposed( exposed_x, exposed_y, 10000, m_lineHeight+4 ))  // 10000 = very much
     {
         int startX = horizX;
-        int endX = horizX + 10;
+        int endX = horizX + (m_indent-5);
 
+//        if (!item->HasChildren()) endX += (m_indent+5);
         if (!item->HasChildren()) endX += 20;
 
         dc.DrawLine( startX, y, endX, y );
 
         if (item->HasPlus())
         {
-            dc.DrawLine( horizX+20, y, horizX+30, y );
+            dc.DrawLine( horizX+(m_indent+5), y, horizX+(m_indent+15), y );
             dc.SetPen( *wxGREY_PEN );
             dc.SetBrush( *wxWHITE_BRUSH );
-            dc.DrawRectangle( horizX+10, y-4, 11, 9 );
+            dc.DrawRectangle( horizX+(m_indent-5), y-4, 11, 9 );
             dc.SetPen( *wxBLACK_PEN );
-            dc.DrawLine( horizX+13, y, horizX+18, y );
+            dc.DrawLine( horizX+(m_indent-2), y, horizX+(m_indent+3), y );
 
             if (!item->IsExpanded())
             {
-                dc.DrawLine( horizX+15, y-2, horizX+15, y+3 );
+                dc.DrawLine( horizX+m_indent, y-2, horizX+m_indent, y+3 );
             }
         }
 
@@ -1232,7 +1364,7 @@ void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &
         // delete all its children for example) - don't draw the vertical line
         // in this case
         if (count > 0)
-            dc.DrawLine( horizX+15, oldY+5, horizX+15, semiOldY );
+            dc.DrawLine( horizX+m_indent, oldY+5, horizX+m_indent, semiOldY );
     }
 }
 
@@ -1285,6 +1417,10 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
         return;
     }
 
+    bool is_multiple=(GetWindowStyleFlag() & wxTR_MULTIPLE);
+    bool extended_select=(event.ShiftDown() && is_multiple);
+    bool unselect_others=!(extended_select || (event.ControlDown() && is_multiple));
+
     switch (event.KeyCode())
     {
         case '+':
@@ -1327,14 +1463,17 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 if (!prev)
                 {
                     prev = GetParent( m_current );
-                    long cockie = 0;
-                    wxTreeItemId current = m_current;
-                    if (current == GetFirstChild( prev, cockie ))
-                    {
-                        // otherwise we return to where we came from
-                        SelectItem( prev );
-                        EnsureVisible( prev );
-                        break;
+                   if (prev)
+                   {
+                        long cockie = 0;
+                        wxTreeItemId current = m_current;
+                        if (current == GetFirstChild( prev, cockie ))
+                        {
+                            // otherwise we return to where we came from
+                            SelectItem( prev, unselect_others, extended_select );
+                            EnsureVisible( prev );
+                            break;
+                       }
                     }
                 }
                 if (prev)
@@ -1348,7 +1487,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                         }
                     }
 
-                    SelectItem( prev );
+                    SelectItem( prev, unselect_others, extended_select );
                     EnsureVisible( prev );
                 }
             }
@@ -1361,7 +1500,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 if (prev)
                 {
                     EnsureVisible( prev );
-                    SelectItem( prev );
+                    SelectItem( prev, unselect_others, extended_select );
                 }
             }
             break;
@@ -1378,7 +1517,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 {
                     long cookie = 0;
                     wxTreeItemId child = GetFirstChild( m_current, cookie );
-                    SelectItem( child );
+                    SelectItem( child, unselect_others, extended_select );
                     EnsureVisible( child );
                 }
                 else
@@ -1395,7 +1534,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                     }
                     if (next != 0)
                     {
-                        SelectItem( next );
+                        SelectItem( next, unselect_others, extended_select );
                         EnsureVisible( next );
                     }
                 }
@@ -1423,7 +1562,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 if ( last.IsOk() )
                 {
                     EnsureVisible( last );
-                    SelectItem( last );
+                    SelectItem( last, unselect_others, extended_select );
                 }
             }
             break;
@@ -1435,7 +1574,7 @@ void wxTreeCtrl::OnChar( wxKeyEvent &event )
                 if (prev)
                 {
                     EnsureVisible( prev );
-                    SelectItem( prev );
+                    SelectItem( prev, unselect_others, extended_select );
                 }
             }
             break;
@@ -1492,8 +1631,11 @@ void wxTreeCtrl::OnMouse( wxMouseEvent &event )
         return;
     }
 
-    if (!IsSelected(item))
-        SelectItem(item);  /* we dont support multiple selections, BTW */
+    bool is_multiple=(GetWindowStyleFlag() & wxTR_MULTIPLE);
+    bool extended_select=(event.ShiftDown() && is_multiple);
+    bool unselect_others=!(extended_select || (event.ControlDown() && is_multiple));
+
+    SelectItem(item, unselect_others, extended_select);
 
     if (event.LeftDClick())
     {
@@ -1531,7 +1673,7 @@ void wxTreeCtrl::CalculateLevel( wxGenericTreeItem *item, wxDC &dc, int level, i
 {
     int horizX = level*m_indent;
 
-    item->SetX( horizX+33 );
+    item->SetX( horizX+m_indent+m_spacing );
     item->SetY( y-m_lineHeight/2 );
     item->SetHeight( m_lineHeight );