]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/treectlg.cpp
support for toggle bitmap button
[wxWidgets.git] / src / generic / treectlg.cpp
index 6005ae07d1ced576903c4354c66ede987fb3216e..da93936fdf2a0d7375a423ed23bbe0e4f8f71080 100644 (file)
@@ -86,7 +86,7 @@ public:
 private:
     wxGenericTreeCtrl *m_owner;
 
-    DECLARE_NO_COPY_CLASS(wxTreeRenameTimer)
+    wxDECLARE_NO_COPY_CLASS(wxTreeRenameTimer);
 };
 
 // control used for in-place edit
@@ -114,7 +114,7 @@ private:
     bool                m_aboutToFinish;
 
     DECLARE_EVENT_TABLE()
-    DECLARE_NO_COPY_CLASS(wxTreeTextCtrl)
+    wxDECLARE_NO_COPY_CLASS(wxTreeTextCtrl);
 };
 
 // timer used to clear wxGenericTreeCtrl::m_findPrefix if no key was pressed
@@ -132,7 +132,7 @@ public:
 private:
     wxGenericTreeCtrl *m_owner;
 
-    DECLARE_NO_COPY_CLASS(wxTreeFindTimer)
+    wxDECLARE_NO_COPY_CLASS(wxTreeFindTimer);
 };
 
 // a tree item
@@ -355,7 +355,7 @@ private:
     unsigned int        m_isBold      :1; // render the label in bold font
     unsigned int        m_ownsAttr    :1; // delete attribute when done
 
-    DECLARE_NO_COPY_CLASS(wxGenericTreeItem)
+    wxDECLARE_NO_COPY_CLASS(wxGenericTreeItem);
 };
 
 // =============================================================================
@@ -429,45 +429,32 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner,
     m_owner = owner;
     m_aboutToFinish = false;
 
-    int w = m_itemEdited->GetWidth(),
-        h = m_itemEdited->GetHeight();
-
-    int x, y;
-    m_owner->CalcScrolledPosition(item->GetX(), item->GetY(), &x, &y);
-
-    int image_h = 0,
-        image_w = 0;
-
-    int image = item->GetCurrentImage();
-    if ( image != NO_IMAGE )
-    {
-        if ( m_owner->m_imageListNormal )
-        {
-            m_owner->m_imageListNormal->GetSize( image, image_w, image_h );
-            image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
-        }
-        else
-        {
-            wxFAIL_MSG(_T("you must create an image list to use images!"));
-        }
-    }
+    wxRect rect;
+    m_owner->GetBoundingRect(m_itemEdited, rect, true);
 
-    // FIXME: what are all these hardcoded 4, 8 and 11s really?
-    x += image_w;
-    w -= image_w + 4;
-#ifdef __WXMAC__
-    wxSize bs = DoGetBestSize() ;
-    // edit control height
-    if ( h > bs.y - 8 )
-    {
-        int diff = h - ( bs.y - 8 ) ;
-        h -= diff ;
-        y += diff / 2 ;
-    }
-#endif
+    // corrects position and size for better appearance
+#ifdef __WXMSW__
+    rect.x -= 5;
+    rect.width += 10;
+#elif defined(__WXGTK__)
+    rect.x -= 5;
+    rect.y -= 2;
+    rect.width  += 8;
+    rect.height += 4;
+#elif defined(__WXMAC__)
+    int bestHeight = GetBestSize().y - 8;
+    if ( rect.height > bestHeight )
+    {
+        int diff = rect.height - bestHeight;
+        rect.height -= diff;
+        rect.y += diff / 2;
+    }
+#endif // platforms
 
     (void)Create(m_owner, wxID_ANY, m_startValue,
-                 wxPoint(x - 4, y - 4), wxSize(w + 11, h + 8));
+                 rect.GetPosition(), rect.GetSize());
+
+    SetSelection(-1, -1);
 }
 
 void wxTreeTextCtrl::EndEdit(bool discardChanges)
@@ -554,7 +541,7 @@ void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event )
         wxPoint myPos = GetPosition();
         wxSize mySize = GetSize();
         int sx, sy;
-        GetTextExtent(GetValue() + _T("M"), &sx, &sy);
+        GetTextExtent(GetValue() + wxT("M"), &sx, &sy);
         if (myPos.x + sx > parentSize.x)
             sx = parentSize.x - myPos.x;
         if (mySize.x > sx)
@@ -979,18 +966,14 @@ void wxGenericTreeCtrl::Init()
     m_findTimer = NULL;
 
     m_dropEffectAboveItem = false;
-    
+
     m_dndEffect = NoEffect;
     m_dndEffectItem = NULL;
 
     m_lastOnSame = false;
 
 #if defined( __WXMAC__ )
-#if wxOSX_USE_ATSU_TEXT
-    m_normalFont.MacCreateFromThemeFont( kThemeViewsFont ) ;
-#else
-    m_normalFont.MacCreateFromUIFont( kCTFontViewsFontType ) ;
-#endif
+    m_normalFont.CreateSystemFont(wxOSX_SYSTEM_FONT_VIEWS);
 #else
     m_normalFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
 #endif
@@ -1017,8 +1000,16 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent,
 
     if (major < 10)
         style |= wxTR_ROW_LINES;
+
+    if (style & wxTR_HAS_BUTTONS)
+        style |= wxTR_NO_LINES;
 #endif // __WXMAC__
 
+#ifdef __WXGTK20__
+    if (style & wxTR_HAS_BUTTONS)
+        style |= wxTR_NO_LINES;
+#endif
+
     if ( !wxControl::Create( parent, id, pos, size,
                              style|wxHSCROLL|wxVSCROLL,
                              validator,
@@ -1789,6 +1780,16 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId)
 
     wxGenericTreeItem *parent = item->GetParent();
 
+    // if the selected item will be deleted, select the parent ...
+    wxGenericTreeItem *to_be_selected = parent;
+    if (parent)
+    {
+        // .. unless there is a next sibling like wxMSW does it
+        int pos = parent->GetChildren().Index( item );
+        if ((int)(parent->GetChildren().GetCount()) > pos+1)
+            to_be_selected = parent->GetChildren().Item( pos+1 );
+    }
+
     // don't keep stale pointers around!
     if ( IsDescendantOf(item, m_key_current) )
     {
@@ -1804,7 +1805,7 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId)
     // a different item, in idle time.
     if ( m_select_me && IsDescendantOf(item, m_select_me) )
     {
-        m_select_me = parent;
+        m_select_me = to_be_selected;
     }
 
     if ( IsDescendantOf(item, m_current) )
@@ -1815,7 +1816,7 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId)
 
         // m_current = parent;
         m_current = NULL;
-        m_select_me = parent;
+        m_select_me = to_be_selected;
     }
 
     // remove the item from the tree
@@ -1853,9 +1854,9 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId)
 {
     wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
 
-    wxCHECK_RET( item, _T("invalid item in wxGenericTreeCtrl::Expand") );
+    wxCHECK_RET( item, wxT("invalid item in wxGenericTreeCtrl::Expand") );
     wxCHECK_RET( !HasFlag(wxTR_HIDE_ROOT) || itemId != GetRootItem(),
-                 _T("can't expand hidden root") );
+                 wxT("can't expand hidden root") );
 
     if ( !item->HasPlus() )
         return;
@@ -1890,7 +1891,7 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId)
 void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId)
 {
     wxCHECK_RET( !HasFlag(wxTR_HIDE_ROOT) || itemId != GetRootItem(),
-                 _T("can't collapse hidden root") );
+                 wxT("can't collapse hidden root") );
 
     wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
 
@@ -1982,6 +1983,42 @@ void wxGenericTreeCtrl::UnselectAll()
     }
 }
 
+void wxGenericTreeCtrl::SelectChildren(const wxTreeItemId& parent)
+{
+    wxCHECK_RET( HasFlag(wxTR_MULTIPLE),
+                 "this only works with multiple selection controls" );
+
+    UnselectAll();
+
+    if ( !HasChildren(parent) )
+        return;
+
+
+    wxArrayGenericTreeItems&
+        children = ((wxGenericTreeItem*) parent.m_pItem)->GetChildren();
+    size_t count = children.GetCount();
+
+    wxGenericTreeItem *
+        item = (wxGenericTreeItem*) ((wxTreeItemId)children[0]).m_pItem;
+    wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGING, this, item);
+    event.m_itemOld = m_current;
+
+    if ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() )
+        return;
+
+    for ( size_t n = 0; n < count; ++n )
+    {
+        m_current = m_key_current = children[n];
+        m_current->SetHilight(true);
+        RefreshSelected();
+    }
+
+
+    event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
+    GetEventHandler()->ProcessEvent( event );
+}
+
+
 // Recursive function !
 // To stop we must have crt_item<last_item
 // Algorithm :
@@ -2145,15 +2182,16 @@ void wxGenericTreeCtrl::DoSelectItem(const wxTreeItemId& itemId,
 
 void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, bool select)
 {
+    wxGenericTreeItem * const item = (wxGenericTreeItem*) itemId.m_pItem;
+    wxCHECK_RET( item, wxT("SelectItem(): invalid tree item") );
+
     if ( select )
     {
-        DoSelectItem(itemId, !HasFlag(wxTR_MULTIPLE));
+        if ( !item->IsSelected() )
+            DoSelectItem(itemId, !HasFlag(wxTR_MULTIPLE));
     }
     else // deselect
     {
-        wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
-        wxCHECK_RET( item, wxT("SelectItem(): invalid tree item") );
-
         wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGING, this, item);
         if ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() )
             return;
@@ -2229,61 +2267,42 @@ void wxGenericTreeCtrl::EnsureVisible(const wxTreeItemId& item)
 
 void wxGenericTreeCtrl::ScrollTo(const wxTreeItemId &item)
 {
-    if (!item.IsOk()) return;
+    if (!item.IsOk())
+        return;
 
-    // We have to call this here because the label in
-    // question might just have been added and no screen
-    // update taken place.
+    // update the control before scrolling it
     if (m_dirty)
 #if defined( __WXMSW__ ) || defined(__WXMAC__)
         Update();
 #else
         DoDirtyProcessing();
 #endif
+
     wxGenericTreeItem *gitem = (wxGenericTreeItem*) item.m_pItem;
 
-    // now scroll to the item
-    int item_y = gitem->GetY();
+    int itemY = gitem->GetY();
 
     int start_x = 0;
     int start_y = 0;
     GetViewStart( &start_x, &start_y );
-    start_y *= PIXELS_PER_UNIT;
 
-    int client_h = 0;
-    int client_w = 0;
-    GetClientSize( &client_w, &client_h );
+    const int clientHeight = GetClientSize().y;
+
+    const int itemHeight = GetLineHeight(gitem) + 2;
 
-    if (item_y < start_y+3)
+    if ( itemY + itemHeight > start_y*PIXELS_PER_UNIT + clientHeight )
     {
-        // going down
-        int x = 0;
-        int y = 0;
-        m_anchor->GetSize( x, y, this );
-        y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
-        x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
-        int x_pos = GetScrollPos( wxHORIZONTAL );
-        // Item should appear at top
-        SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT,
-                       x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT,
-                       x_pos, item_y/PIXELS_PER_UNIT );
+        // need to scroll up by enough to show this item fully
+        itemY += itemHeight - clientHeight;
     }
-    else if (item_y+GetLineHeight(gitem) > start_y+client_h)
+    else if ( itemY > start_y*PIXELS_PER_UNIT )
     {
-        // going up
-        int x = 0;
-        int y = 0;
-        m_anchor->GetSize( x, y, this );
-        y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
-        x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
-        item_y += PIXELS_PER_UNIT+2;
-        int x_pos = GetScrollPos( wxHORIZONTAL );
-        // Item should appear at bottom
-        SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT,
-                       x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT,
-                       x_pos,
-                       (item_y+GetLineHeight(gitem)-client_h)/PIXELS_PER_UNIT );
+        // item is already fully visible, don't do anything
+        return;
     }
+    //else: scroll down to make this item the top one displayed
+
+    Scroll(-1, itemY/PIXELS_PER_UNIT);
 }
 
 // FIXME: tree sorting functions are not reentrant and not MT-safe!
@@ -2638,7 +2657,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
 
     // restore normal font
     dc.SetFont( m_normalFont );
-    
+
     if (item == m_dndEffectItem)
     {
         dc.SetPen( *wxBLACK_PEN );
@@ -2918,7 +2937,7 @@ void wxGenericTreeCtrl::DrawBorder(const wxTreeItemId &item)
         m_dndEffect = NoEffect;
         m_dndEffectItem = NULL;
     }
-        
+
     wxRect rect( i->GetX()-1, i->GetY()-1, i->GetWidth()+2, GetLineHeight(i)+2 );
     CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
     RefreshRect( rect );
@@ -2943,7 +2962,7 @@ void wxGenericTreeCtrl::DrawLine(const wxTreeItemId &item, bool below)
         m_dndEffect = NoEffect;
         m_dndEffectItem = NULL;
     }
-        
+
     wxRect rect( i->GetX()-1, i->GetY()-1, i->GetWidth()+2, GetLineHeight(i)+2 );
     CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
     RefreshRect( rect );
@@ -3373,7 +3392,7 @@ bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
 wxTextCtrl *wxGenericTreeCtrl::EditLabel(const wxTreeItemId& item,
                                   wxClassInfo * WXUNUSED(textCtrlClass))
 {
-    wxCHECK_MSG( item.IsOk(), NULL, _T("can't edit an invalid item") );
+    wxCHECK_MSG( item.IsOk(), NULL, wxT("can't edit an invalid item") );
 
     wxGenericTreeItem *itemEdit = (wxGenericTreeItem *)item.m_pItem;
 
@@ -3413,7 +3432,7 @@ wxTextCtrl* wxGenericTreeCtrl::GetEditControl() const
 void wxGenericTreeCtrl::EndEditLabel(const wxTreeItemId& WXUNUSED(item),
                                      bool discardChanges)
 {
-    wxCHECK_RET( m_textCtrl, _T("not editing label") );
+    wxCHECK_RET( m_textCtrl, wxT("not editing label") );
 
     m_textCtrl->EndEdit(discardChanges);
 }
@@ -3589,6 +3608,8 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
 #if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXGTK20__)
             Update();
 #else
+            // TODO: remove this call or use wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI)
+            //       instead (needs to be tested!)
             wxYieldIfNeeded();
 #endif
         }
@@ -3619,9 +3640,11 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
 
         SetCursor(m_oldCursor);
 
-#if defined( __WXMSW__ ) || defined(__WXMAC__)
+#if defined( __WXMSW__ ) || defined(__WXMAC__) || defined(__WXGTK20__)
         Update();
 #else
+        // TODO: remove this call or use wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI)
+        //       instead (needs to be tested!)
         wxYieldIfNeeded();
 #endif
     }