X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f73eddd2a5af3c58fff4e2a6154d9a395b7631a5..524c47aa3adf2af11a3069fd5da035a604f08f66:/src/generic/treectlg.cpp?ds=sidebyside diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index 87a01089a1..b9f5f2cf16 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -42,7 +42,7 @@ #include "wx/renderer.h" #ifdef __WXMAC__ - #include "wx/mac/private.h" + #include "wx/osx/private.h" #endif // ----------------------------------------------------------------------------- @@ -51,7 +51,7 @@ class WXDLLIMPEXP_FWD_CORE wxGenericTreeItem; -WX_DEFINE_EXPORTED_ARRAY_PTR(wxGenericTreeItem *, wxArrayGenericTreeItems); +WX_DEFINE_ARRAY_PTR(wxGenericTreeItem *, wxArrayGenericTreeItems); // ---------------------------------------------------------------------------- // constants @@ -61,6 +61,9 @@ static const int NO_IMAGE = -1; static const int PIXELS_PER_UNIT = 10; +// the margin between the item state image and the item normal image +static const int MARGIN_BETWEEN_STATE_AND_IMAGE = 2; + // the margin between the item image and the item text static const int MARGIN_BETWEEN_IMAGE_AND_TEXT = 4; @@ -92,29 +95,8 @@ class WXDLLEXPORT wxTreeTextCtrl: public wxTextCtrl public: wxTreeTextCtrl(wxGenericTreeCtrl *owner, wxGenericTreeItem *item); - void EndEdit(bool discardChanges = false) - { - if ( discardChanges ) - { - StopEditing(); - } - else - { - m_aboutToFinish = true; - - // Notify the owner about the changes - AcceptChanges(); + void EndEdit( bool discardChanges ); - // Even if vetoed, close the control (consistent with MSW) - Finish(); - } - } - - void StopEditing() - { - Finish(); - m_owner->OnRenameCancelled(m_itemEdited); - } const wxGenericTreeItem* item() const { return m_itemEdited; } protected: @@ -123,13 +105,12 @@ protected: void OnKillFocus( wxFocusEvent &event ); bool AcceptChanges(); - void Finish(); + void Finish( bool setfocus ); private: wxGenericTreeCtrl *m_owner; wxGenericTreeItem *m_itemEdited; wxString m_startValue; - bool m_finished; bool m_aboutToFinish; DECLARE_EVENT_TABLE() @@ -175,14 +156,16 @@ public: int GetImage(wxTreeItemIcon which = wxTreeItemIcon_Normal) const { return m_images[which]; } wxTreeItemData *GetData() const { return m_data; } + int GetState() const { return m_state; } // returns the current image for the item (depending on its // selected/expanded/whatever state) int GetCurrentImage() const; - void SetText( const wxString &text ); + void SetText( const wxString &text ) { m_text = text; } void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; } void SetData(wxTreeItemData *data) { m_data = data; } + void SetState(int state) { m_state = state; } void SetHasPlus(bool has = true) { m_hasPlus = has; } @@ -270,6 +253,8 @@ private: wxTreeItemData *m_data; // user-provided data + int m_state; // item state + wxArrayGenericTreeItems m_children; // list of children wxGenericTreeItem *m_parent; // parent of this item @@ -363,7 +348,6 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, : m_itemEdited(item), m_startValue(item->GetText()) { m_owner = owner; - m_finished = false; m_aboutToFinish = false; int w = m_itemEdited->GetWidth(), @@ -407,6 +391,26 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, wxPoint(x - 4, y - 4), wxSize(w + 11, h + 8)); } +void wxTreeTextCtrl::EndEdit(bool discardChanges) +{ + m_aboutToFinish = true; + + if ( discardChanges ) + { + m_owner->OnRenameCancelled(m_itemEdited); + + Finish( true ); + } + else + { + // Notify the owner about the changes + AcceptChanges(); + + // Even if vetoed, close the control (consistent with MSW) + Finish( true ); + } +} + bool wxTreeTextCtrl::AcceptChanges() { const wxString value = GetValue(); @@ -435,18 +439,14 @@ bool wxTreeTextCtrl::AcceptChanges() return true; } -void wxTreeTextCtrl::Finish() +void wxTreeTextCtrl::Finish( bool setfocus ) { - if ( !m_finished ) - { - m_owner->ResetTextControl(); - - wxPendingDelete.Append(this); + m_owner->ResetTextControl(); - m_finished = true; + wxPendingDelete.Append(this); + if (setfocus) m_owner->SetFocus(); - } } void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) @@ -454,11 +454,11 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) switch ( event.m_keyCode ) { case WXK_RETURN: - EndEdit(); + EndEdit( false ); break; case WXK_ESCAPE: - StopEditing(); + EndEdit( true ); break; default: @@ -468,7 +468,7 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) { - if ( !m_finished ) + if ( !m_aboutToFinish ) { // auto-grow the textctrl: wxSize parentSize = m_owner->GetSize(); @@ -488,18 +488,15 @@ void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event ) { - if ( !m_finished && !m_aboutToFinish ) + if ( !m_aboutToFinish ) { - // We must finish regardless of success, otherwise we'll get - // focus problems: - Finish(); - if ( !AcceptChanges() ) m_owner->OnRenameCancelled( m_itemEdited ); + + Finish( false ); } - // We must let the native text control handle focus, too, otherwise - // it could have problems with the cursor (e.g., in wxGTK). + // We should let the native text control handle focus, too. event.Skip(); } @@ -519,6 +516,7 @@ wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent, m_images[wxTreeItemIcon_SelectedExpanded] = NO_IMAGE; m_data = data; + m_state = wxTREE_ITEMSTATE_NONE; m_x = m_y = 0; m_isCollapsed = true; @@ -563,11 +561,6 @@ void wxGenericTreeItem::DeleteChildren(wxGenericTreeCtrl *tree) m_children.Empty(); } -void wxGenericTreeItem::SetText( const wxString &text ) -{ - m_text = text; -} - size_t wxGenericTreeItem::GetChildrenCount(bool recursively) const { size_t count = m_children.GetCount(); @@ -644,10 +637,20 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point, // assuming every image (normal and selected) has the same size! if ( (GetImage() != NO_IMAGE) && theCtrl->m_imageListNormal ) - theCtrl->m_imageListNormal->GetSize(GetImage(), - image_w, image_h); + theCtrl->m_imageListNormal->GetSize(GetImage(), image_w, image_h); + + int state_w = -1; + int state_h; - if ((image_w != -1) && (point.x <= m_x + image_w + 1)) + if ( (GetState() != wxTREE_ITEMSTATE_NONE) && theCtrl->m_imageListState ) + theCtrl->m_imageListState->GetSize(GetState(), state_w, state_h); + + if ((state_w != -1) && (point.x <= m_x + state_w + 1)) + flags |= wxTREE_HITTEST_ONITEMSTATEICON; + else if ((image_w != -1) && + (point.x <= m_x + + (state_w != -1 ? state_w + MARGIN_BETWEEN_STATE_AND_IMAGE : 0) + + image_w + 1)) flags |= wxTREE_HITTEST_ONITEMICON; else flags |= wxTREE_HITTEST_ONITEMLABEL; @@ -760,7 +763,7 @@ void wxGenericTreeCtrl::Init() ( wxSYS_COLOUR_HIGHLIGHT ), - wxSOLID + wxBRUSHSTYLE_SOLID ); m_hilightUnfocusedBrush = new wxBrush @@ -769,7 +772,7 @@ void wxGenericTreeCtrl::Init() ( wxSYS_COLOUR_BTNSHADOW ), - wxSOLID + wxBRUSHSTYLE_SOLID ); m_imageListButtons = NULL; @@ -782,7 +785,6 @@ void wxGenericTreeCtrl::Init() m_textCtrl = NULL; m_renameTimer = NULL; - m_freezeCount = 0; m_findTimer = NULL; @@ -790,8 +792,8 @@ void wxGenericTreeCtrl::Init() m_lastOnSame = false; -#ifdef __WXMAC_CARBON__ - m_normalFont.MacCreateThemeFont( kThemeViewsFont ) ; +#if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON + m_normalFont.MacCreateFromThemeFont( kThemeViewsFont ) ; #else m_normalFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); #endif @@ -813,21 +815,12 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, const wxString& name ) { #ifdef __WXMAC__ - int major,minor; - wxGetOsVersion( &major, &minor ); + int major, minor; + wxGetOsVersion(&major, &minor); - style &= ~wxTR_LINES_AT_ROOT; - style |= wxTR_NO_LINES; if (major < 10) style |= wxTR_ROW_LINES; - - if (style == 0 || style & wxTR_DEFAULT_STYLE) - style |= wxTR_FULL_ROW_HIGHLIGHT; - #endif // __WXMAC__ -#ifdef __WXGTK20__ - style |= wxTR_NO_LINES; -#endif if ( !wxControl::Create( parent, id, pos, size, style|wxHSCROLL|wxVSCROLL, @@ -854,7 +847,7 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, // style because we apparently get performance problems when using dotted // pen for drawing in some ports -- but under MSW it seems to work fine #ifdef __WXMSW__ - m_dottedPen = wxPen(*wxLIGHT_GREY, 0, wxDOT); + m_dottedPen = wxPen(*wxLIGHT_GREY, 0, wxPENSTYLE_DOT); #else m_dottedPen = *wxGREY_PEN; #endif @@ -959,6 +952,14 @@ wxTreeItemData *wxGenericTreeCtrl::GetItemData(const wxTreeItemId& item) const return ((wxGenericTreeItem*) item.m_pItem)->GetData(); } +int wxGenericTreeCtrl::DoGetItemState(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxTREE_ITEMSTATE_NONE, wxT("invalid tree item") ); + + wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem; + return pItem->GetState(); +} + wxColour wxGenericTreeCtrl::GetItemTextColour(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); @@ -1018,6 +1019,15 @@ void wxGenericTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *da ((wxGenericTreeItem*) item.m_pItem)->SetData(data); } +void wxGenericTreeCtrl::DoSetItemState(const wxTreeItemId& item, int state) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem; + pItem->SetState(state); + RefreshLine(pItem); +} + void wxGenericTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) { wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); @@ -1524,7 +1534,7 @@ void wxGenericTreeCtrl::SendDeleteEvent(wxGenericTreeItem *item) void wxGenericTreeCtrl::ChildrenClosing(wxGenericTreeItem* item) { if (m_textCtrl != NULL && item != m_textCtrl->item() && IsDescendantOf(item, m_textCtrl->item())) { - m_textCtrl->StopEditing(); + m_textCtrl->EndEdit( true ); } if (item != m_key_current && IsDescendantOf(item, m_key_current)) { m_key_current = NULL; @@ -1558,7 +1568,7 @@ void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId) if (m_textCtrl != NULL && IsDescendantOf(item, m_textCtrl->item())) { // can't delete the item being edited, cancel editing it first - m_textCtrl->StopEditing(); + m_textCtrl->EndEdit( true ); } wxGenericTreeItem *parent = item->GetParent(); @@ -1646,9 +1656,16 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId) } item->Expand(); - CalculatePositions(); + if ( !IsFrozen() ) + { + CalculatePositions(); - RefreshSubtree(item); + RefreshSubtree(item); + } + else // frozen + { + m_dirty = true; + } event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED); GetEventHandler()->ProcessEvent( event ); @@ -1910,7 +1927,7 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, bool select) { 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; @@ -2089,6 +2106,20 @@ void wxGenericTreeCtrl::CalculateLineHeight() } } + if ( m_imageListState ) + { + // Calculate a m_lineHeight value from the state Image sizes. + // May be toggle off. Then wxGenericTreeCtrl will spread when + // necessary (which might look ugly). + int n = m_imageListState->GetImageCount(); + for (int i = 0; i < n ; i++) + { + int width = 0, height = 0; + m_imageListState->GetSize(i, width, height); + if (height > m_lineHeight) m_lineHeight = height; + } + } + if (m_imageListButtons) { // Calculate a m_lineHeight value from the Button image sizes. @@ -2126,6 +2157,11 @@ void wxGenericTreeCtrl::SetStateImageList(wxImageList *imageList) if (m_ownsImageListState) delete m_imageListState; m_imageListState = imageList; m_ownsImageListState = false; + m_dirty = true; + // Don't do any drawing if we're setting the list to NULL, + // since we may be in the process of deleting the tree control. + if (imageList) + CalculateLineHeight(); } void wxGenericTreeCtrl::SetButtonsImageList(wxImageList *imageList) @@ -2175,8 +2211,6 @@ int wxGenericTreeCtrl::GetLineHeight(wxGenericTreeItem *item) const void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { - // TODO implement "state" icon on items - wxTreeItemAttr *attr = item->GetAttributes(); if ( attr && attr->HasFont() ) dc.SetFont(attr->GetFont()); @@ -2201,6 +2235,24 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) } } + int state_h = 0, state_w = 0; + int state = item->GetState(); + if ( state != wxTREE_ITEMSTATE_NONE ) + { + if ( m_imageListState ) + { + m_imageListState->GetSize( state, state_w, state_h ); + if ( image != NO_IMAGE ) + state_w += MARGIN_BETWEEN_STATE_AND_IMAGE; + else + state_w += MARGIN_BETWEEN_IMAGE_AND_TEXT; + } + else + { + state = wxTREE_ITEMSTATE_NONE; + } + } + int total_h = GetLineHeight(item); bool drawItemBackground = false; @@ -2221,7 +2273,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { colBg = GetBackgroundColour(); } - dc.SetBrush(wxBrush(colBg, wxSOLID)); + dc.SetBrush(wxBrush(colBg, wxBRUSHSTYLE_SOLID)); } int offset = HasFlag(wxTR_ROW_LINES) ? 1 : 0; @@ -2243,7 +2295,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { int flags = wxCONTROL_SELECTED; if (m_hasFocus -#ifdef __WXMAC__ +#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__) && IsControlActive( (ControlRef)GetHandle() ) #endif ) @@ -2256,19 +2308,20 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) } else { - if ( item->IsSelected() && image != NO_IMAGE ) + if ( item->IsSelected() && + (state != wxTREE_ITEMSTATE_NONE || image != NO_IMAGE) ) { - // If it's selected, and there's an image, then we should - // take care to leave the area under the image painted in the - // background colour. - wxRect rect( item->GetX() + image_w - 2, item->GetY()+offset, - item->GetWidth() - image_w + 2, total_h-offset ); + // If it's selected, and there's an state image or normal image, + // then we should take care to leave the area under the image + // painted in the background colour. + wxRect rect( item->GetX() + state_w + image_w - 2, item->GetY() + offset, + item->GetWidth() - state_w - image_w + 2, total_h - offset ); #if !defined(__WXGTK20__) && !defined(__WXMAC__) dc.DrawRectangle( rect ); #else rect.x -= 1; rect.width += 2; - + int flags = wxCONTROL_SELECTED; if (m_hasFocus) flags |= wxCONTROL_FOCUSED; @@ -2295,7 +2348,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { rect.x -= 1; rect.width += 2; - + int flags = wxCONTROL_SELECTED; if (m_hasFocus) flags |= wxCONTROL_FOCUSED; @@ -2307,20 +2360,30 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) } } + if ( state != wxTREE_ITEMSTATE_NONE ) + { + dc.SetClippingRegion( item->GetX(), item->GetY(), state_w, total_h ); + m_imageListState->Draw( state, dc, + item->GetX(), + item->GetY() + ((total_h > state_h)?((total_h-state_h)/2):0), + wxIMAGELIST_DRAW_TRANSPARENT ); + dc.DestroyClippingRegion(); + } + if ( image != NO_IMAGE ) { - dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, total_h ); + dc.SetClippingRegion( item->GetX() + state_w, item->GetY(), image_w, total_h ); m_imageListNormal->Draw( image, dc, - item->GetX(), - item->GetY() +((total_h > image_h)?((total_h-image_h)/2):0), + item->GetX() + state_w, + item->GetY() + ((total_h > image_h)?((total_h-image_h)/2):0), wxIMAGELIST_DRAW_TRANSPARENT ); dc.DestroyClippingRegion(); } - dc.SetBackgroundMode(wxTRANSPARENT); + dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT); int extraH = (total_h > text_h) ? (total_h - text_h)/2 : 0; dc.DrawText( item->GetText(), - (wxCoord)(image_w + item->GetX()), + (wxCoord)(state_w + image_w + item->GetX()), (wxCoord)(item->GetY() + extraH)); // restore normal font @@ -2383,7 +2446,7 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level wxColour colText; if ( item->IsSelected() -#ifdef __WXMAC__ +#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__) // On wxMac, if the tree doesn't have the focus we draw an empty // rectangle, so we want to make sure that the text is visible // against the normal background, not the highlightbackground, so @@ -3282,6 +3345,12 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) } else if ( event.LeftUp() ) { + if (flags & wxTREE_HITTEST_ONITEMSTATEICON) + { + wxTreeEvent nevent(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, this, item); + GetEventHandler()->ProcessEvent(nevent); + } + // this facilitates multiple-item drag-and-drop if ( /* item && */ HasFlag(wxTR_MULTIPLE)) @@ -3439,6 +3508,24 @@ void wxGenericTreeCtrl::CalculateSize( wxGenericTreeItem *item, wxDC &dc ) } } + int state_h = 0, state_w = 0; + int state = item->GetState(); + if ( state != wxTREE_ITEMSTATE_NONE ) + { + if ( m_imageListState ) + { + m_imageListState->GetSize( state, state_w, state_h ); + if ( image != NO_IMAGE ) + state_w += MARGIN_BETWEEN_STATE_AND_IMAGE; + else + state_w += MARGIN_BETWEEN_IMAGE_AND_TEXT; + } + else + { + state = wxTREE_ITEMSTATE_NONE; + } + } + int total_h = (image_h > text_h) ? image_h : text_h; if (total_h < 30) @@ -3450,7 +3537,7 @@ void wxGenericTreeCtrl::CalculateSize( wxGenericTreeItem *item, wxDC &dc ) if (total_h>m_lineHeight) m_lineHeight=total_h; - item->SetWidth(image_w+text_w+2); + item->SetWidth(state_w + image_w + text_w + 2); } // ----------------------------------------------------------------------------- @@ -3510,13 +3597,13 @@ void wxGenericTreeCtrl::CalculatePositions() void wxGenericTreeCtrl::Refresh(bool eraseBackground, const wxRect *rect) { - if ( !m_freezeCount ) + if ( !IsFrozen() ) wxTreeCtrlBase::Refresh(eraseBackground, rect); } void wxGenericTreeCtrl::RefreshSubtree(wxGenericTreeItem *item) { - if (m_dirty || m_freezeCount) + if (m_dirty || IsFrozen() ) return; wxSize client = GetClientSize(); @@ -3533,7 +3620,7 @@ void wxGenericTreeCtrl::RefreshSubtree(wxGenericTreeItem *item) void wxGenericTreeCtrl::RefreshLine( wxGenericTreeItem *item ) { - if (m_dirty || m_freezeCount) + if (m_dirty || IsFrozen() ) return; wxRect rect; @@ -3546,7 +3633,7 @@ void wxGenericTreeCtrl::RefreshLine( wxGenericTreeItem *item ) void wxGenericTreeCtrl::RefreshSelected() { - if (m_freezeCount) + if (IsFrozen()) return; // TODO: this is awfully inefficient, we should keep the list of all @@ -3557,7 +3644,7 @@ void wxGenericTreeCtrl::RefreshSelected() void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item) { - if (m_freezeCount) + if (IsFrozen()) return; if ( item->IsSelected() ) @@ -3571,19 +3658,14 @@ void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item) } } -void wxGenericTreeCtrl::Freeze() +void wxGenericTreeCtrl::DoThaw() { - m_freezeCount++; -} + wxTreeCtrlBase::DoThaw(); -void wxGenericTreeCtrl::Thaw() -{ - wxCHECK_RET( m_freezeCount > 0, _T("thawing unfrozen tree control?") ); - - if ( --m_freezeCount == 0 ) - { + if ( m_dirty ) + DoDirtyProcessing(); + else Refresh(); - } } // ---------------------------------------------------------------------------- @@ -3644,7 +3726,7 @@ wxGenericTreeCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) void wxGenericTreeCtrl::DoDirtyProcessing() { - if (m_freezeCount) + if (IsFrozen()) return; m_dirty = false;