X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ff38281aa1a7576df9e67ac756e7e1087681305e..178edd2a3267f1d80b3f1a9f96717d66c12c10be:/src/generic/treectlg.cpp?ds=sidebyside diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index f2134ffc89..3e40803ef1 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -17,7 +17,7 @@ // headers // ----------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "treectlg.h" #endif @@ -38,9 +38,7 @@ #include "wx/settings.h" #include "wx/dcclient.h" -#ifdef __WXMAC__ - #include "wx/mac/private.h" -#endif +#include "wx/renderer.h" // ----------------------------------------------------------------------------- // array types @@ -48,7 +46,7 @@ class WXDLLEXPORT wxGenericTreeItem; -WX_DEFINE_EXPORTED_ARRAY(wxGenericTreeItem *, wxArrayGenericTreeItems); +WX_DEFINE_EXPORTED_ARRAY_PTR(wxGenericTreeItem *, wxArrayGenericTreeItems); // ---------------------------------------------------------------------------- // constants @@ -58,54 +56,6 @@ static const int NO_IMAGE = -1; static const int PIXELS_PER_UNIT = 10; -// ---------------------------------------------------------------------------- -// Aqua arrows -// ---------------------------------------------------------------------------- - -/* XPM */ -static const char *aqua_arrow_right[] = { -/* columns rows colors chars-per-pixel */ -"13 11 4 1", -" c None", -"b c #C0C0C0", -"c c #707070", -"d c #A0A0A0", -/* pixels */ -" b ", -" ddb ", -" cccdb ", -" cccccd ", -" ccccccdb ", -" ccccccccd", -" ccccccdb ", -" cccccb ", -" cccdb ", -" ddb ", -" b " -}; - -/* XPM */ -static const char *aqua_arrow_down[] = { -/* columns rows colors chars-per-pixel */ -"13 11 4 1", -" c None", -"b c #C0C0C0", -"c c #707070", -"d c #A0A0A0", -/* pixels */ -" ", -" ", -" bdcccccccdb ", -" dcccccccd ", -" bcccccccb ", -" dcccccd ", -" bcccccb ", -" bcccd ", -" dcd ", -" bcb ", -" d " -}; - // ----------------------------------------------------------------------------- // private classes // ----------------------------------------------------------------------------- @@ -619,11 +569,19 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point, else flags |= wxTREE_HITTEST_ONITEMLOWERPART; - // 5 is the size of the plus sign int xCross = m_x - theCtrl->GetSpacing(); +#ifdef __WXMAC__ + // according to the drawing code the triangels are drawn + // at -4 , -4 from the position up to +10/+10 max + if ((point.x > xCross-4) && (point.x < xCross+10) && + (point.y > y_mid-4) && (point.y < y_mid+10) && + HasPlus() && theCtrl->HasButtons() ) +#else + // 5 is the size of the plus sign if ((point.x > xCross-5) && (point.x < xCross+5) && (point.y > y_mid-5) && (point.y < y_mid+5) && HasPlus() && theCtrl->HasButtons() ) +#endif { flags |= wxTREE_HITTEST_ONITEMBUTTON; return this; @@ -716,7 +674,6 @@ BEGIN_EVENT_TABLE(wxGenericTreeCtrl,wxScrolledWindow) EVT_CHAR (wxGenericTreeCtrl::OnChar) EVT_SET_FOCUS (wxGenericTreeCtrl::OnSetFocus) EVT_KILL_FOCUS (wxGenericTreeCtrl::OnKillFocus) - EVT_IDLE (wxGenericTreeCtrl::OnIdle) END_EVENT_TABLE() #if !defined(__WXMSW__) || defined(__WIN16__) || defined(__WXUNIVERSAL__) @@ -790,33 +747,18 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, const wxPoint& pos, const wxSize& size, long style, - const wxValidator &validator, + const wxValidator& wxVALIDATOR_PARAM(validator), const wxString& name ) { #ifdef __WXMAC__ int major,minor; wxGetOsVersion( &major, &minor ); - if (style & wxTR_HAS_BUTTONS) style |= wxTR_MAC_BUTTONS; - if (style & wxTR_HAS_BUTTONS) style &= ~wxTR_HAS_BUTTONS; style &= ~wxTR_LINES_AT_ROOT; style |= wxTR_NO_LINES; if (major < 10) style |= wxTR_ROW_LINES; - if (major >= 10) - style |= wxTR_AQUA_BUTTONS; -#endif - - if (style & wxTR_AQUA_BUTTONS) - { - m_arrowRight = new wxBitmap( aqua_arrow_right ); - m_arrowDown = new wxBitmap( aqua_arrow_down ); - } - else - { - m_arrowRight = NULL; - m_arrowDown = NULL; - } +#endif // __WXMAC__ wxScrolledWindow::Create( parent, id, pos, size, style|wxHSCROLL|wxVSCROLL, name ); @@ -848,9 +790,6 @@ wxGenericTreeCtrl::~wxGenericTreeCtrl() delete m_hilightBrush; delete m_hilightUnfocusedBrush; - delete m_arrowRight; - delete m_arrowDown; - DeleteAllItems(); delete m_renameTimer; @@ -1139,7 +1078,8 @@ wxTreeItemId wxGenericTreeCtrl::GetItemParent(const wxTreeItemId& item) const return ((wxGenericTreeItem*) item.m_pItem)->GetParent(); } -wxTreeItemId wxGenericTreeCtrl::GetFirstChild(const wxTreeItemId& item, long& cookie) const +wxTreeItemId wxGenericTreeCtrl::GetFirstChild(const wxTreeItemId& item, + wxTreeItemIdValue& cookie) const { wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); @@ -1147,7 +1087,40 @@ wxTreeItemId wxGenericTreeCtrl::GetFirstChild(const wxTreeItemId& item, long& co return GetNextChild(item, cookie); } -wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item, long& cookie) const +wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item, + wxTreeItemIdValue& cookie) const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxArrayGenericTreeItems& children = ((wxGenericTreeItem*) item.m_pItem)->GetChildren(); + + // it's ok to cast cookie to size_t, we never have indices big enough to + // overflow "void *" + size_t *pIndex = (size_t *)&cookie; + if ( *pIndex < children.Count() ) + { + return children.Item((*pIndex)++); + } + else + { + // there are no more of them + return wxTreeItemId(); + } +} + +#if WXWIN_COMPATIBILITY_2_4 + +wxTreeItemId wxGenericTreeCtrl::GetFirstChild(const wxTreeItemId& item, + long& cookie) const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + cookie = 0; + return GetNextChild(item, cookie); +} + +wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item, + long& cookie) const { wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); @@ -1163,6 +1136,8 @@ wxTreeItemId wxGenericTreeCtrl::GetNextChild(const wxTreeItemId& item, long& coo } } +#endif // WXWIN_COMPATIBILITY_2_4 + wxTreeItemId wxGenericTreeCtrl::GetLastChild(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); @@ -1355,7 +1330,7 @@ wxTreeItemId wxGenericTreeCtrl::DoInsertItem(const wxTreeItemId& parentId, if ( data != NULL ) { - data->m_pItem = (long) item; + data->m_pItem = item; } parent->Insert( item, previous ); @@ -1375,7 +1350,7 @@ wxTreeItemId wxGenericTreeCtrl::AddRoot(const wxString& text, image, selImage, data); if ( data != NULL ) { - data->m_pItem = (long) m_anchor; + data->m_pItem = m_anchor; } if (HasFlag(wxTR_HIDE_ROOT)) @@ -1463,7 +1438,7 @@ wxTreeItemId wxGenericTreeCtrl::AppendItem(const wxTreeItemId& parentId, void wxGenericTreeCtrl::SendDeleteEvent(wxGenericTreeItem *item) { wxTreeEvent event( wxEVT_COMMAND_TREE_DELETE_ITEM, GetId() ); - event.m_item = (long) item; + event.m_item = item; event.SetEventObject( this ); ProcessEvent( event ); } @@ -1553,7 +1528,7 @@ void wxGenericTreeCtrl::Expand(const wxTreeItemId& itemId) return; wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, GetId() ); - event.m_item = (long) item; + event.m_item = item; event.SetEventObject( this ); if ( ProcessEvent( event ) && !event.IsAllowed() ) @@ -1580,7 +1555,7 @@ void wxGenericTreeCtrl::ExpandAll(const wxTreeItemId& item) return; } - long cookie; + wxTreeItemIdValue cookie; wxTreeItemId child = GetFirstChild(item, cookie); while ( child.IsOk() ) { @@ -1601,7 +1576,7 @@ void wxGenericTreeCtrl::Collapse(const wxTreeItemId& itemId) return; wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, GetId() ); - event.m_item = (long) item; + event.m_item = item; event.SetEventObject( this ); if ( ProcessEvent( event ) && !event.IsAllowed() ) { @@ -1736,21 +1711,12 @@ bool wxGenericTreeCtrl::TagAllChildrenUntilLast(wxGenericTreeItem *crt_item, wxG void wxGenericTreeCtrl::SelectItemRange(wxGenericTreeItem *item1, wxGenericTreeItem *item2) { - // item2 is not necessary after item1 - wxGenericTreeItem *first=NULL, *last=NULL; m_select_me = NULL; + // item2 is not necessary after item1 // choice first' and 'last' between item1 and item2 - if (item1->GetY()GetY()) - { - first=item1; - last=item2; - } - else - { - first=item2; - last=item1; - } + wxGenericTreeItem *first= (item1->GetY()GetY()) ? item1 : item2; + wxGenericTreeItem *last = (item1->GetY()GetY()) ? item2 : item1; bool select = m_current->IsSelected(); @@ -1791,8 +1757,8 @@ void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, } wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, GetId() ); - event.m_item = (long) item; - event.m_itemOld = (long) m_current; + event.m_item = item; + event.m_itemOld = m_current; event.SetEventObject( this ); // TODO : Here we don't send any selection mode yet ! @@ -2316,110 +2282,56 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level dc.SetPen(m_dottedPen); dc.SetTextForeground(*wxBLACK); - if (item->HasPlus() && HasButtons()) // should the item show a button? + if ( !HasFlag(wxTR_NO_LINES) ) { - if (!HasFlag(wxTR_NO_LINES)) - { - if (x > (signed)m_indent) - dc.DrawLine(x - m_indent, y_mid, x - 5, y_mid); - else if (HasFlag(wxTR_LINES_AT_ROOT)) - dc.DrawLine(3, y_mid, x - 5, y_mid); - dc.DrawLine(x + 5, y_mid, x + m_spacing, y_mid); - } + // draw the horizontal line here + int x_start = x; + if (x > (signed)m_indent) + x_start -= m_indent; + else if (HasFlag(wxTR_LINES_AT_ROOT)) + x_start = 3; + dc.DrawLine(x_start, y_mid, x + m_spacing, y_mid); + } - if (m_imageListButtons != NULL) + // should the item show a button? + if ( item->HasPlus() && HasButtons() ) + { + if ( m_imageListButtons ) { // draw the image button here - int image_h = 0, image_w = 0, image = wxTreeItemIcon_Normal; - if (item->IsExpanded()) image = wxTreeItemIcon_Expanded; - if (item->IsSelected()) + int image_h = 0, + image_w = 0; + int image = item->IsExpanded() ? wxTreeItemIcon_Expanded + : wxTreeItemIcon_Normal; + if ( item->IsSelected() ) image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal; + m_imageListButtons->GetSize(image, image_w, image_h); - int xx = x - (image_w>>1); - int yy = y_mid - (image_h>>1); - dc.SetClippingRegion(xx, yy, image_w, image_h); + int xx = x - image_w/2; + int yy = y_mid - image_h/2; + + wxDCClipper clip(dc, xx, yy, image_w, image_h); m_imageListButtons->Draw(image, dc, xx, yy, wxIMAGELIST_DRAW_TRANSPARENT); - dc.DestroyClippingRegion(); - } - else if (HasFlag(wxTR_TWIST_BUTTONS)) - { - // draw the twisty button here - - if (HasFlag(wxTR_AQUA_BUTTONS)) - { - // This causes update problems, so disabling for now. -#if 0 // def __WXMAC__ - wxMacPortSetter helper(&dc) ; - wxMacWindowClipper clipper(this) ; - wxDC::MacSetupBackgroundForCurrentPort( MacGetBackgroundBrush() ) ; - - int loc_x = x - 5 ; - int loc_y = y_mid - 6 ; - MacWindowToRootWindow( & loc_x , & loc_y ) ; - Rect bounds = { loc_y , loc_x , loc_y + 18 , loc_x + 12 } ; - ThemeButtonDrawInfo info = { kThemeStateActive , item->IsExpanded() ? kThemeDisclosureDown : kThemeDisclosureRight , - kThemeAdornmentNone }; - DrawThemeButton( &bounds, kThemeDisclosureButton , - &info , NULL , NULL , NULL , NULL ) ; -#else - if (item->IsExpanded()) - dc.DrawBitmap( *m_arrowDown, x-5, y_mid-6, TRUE ); - else - dc.DrawBitmap( *m_arrowRight, x-5, y_mid-6, TRUE ); -#endif - } - else - { - dc.SetBrush(*m_hilightBrush); - dc.SetPen(*wxBLACK_PEN); - wxPoint button[3]; - - if (item->IsExpanded()) - { - button[0].x = x-5; - button[0].y = y_mid-2; - button[1].x = x+5; - button[1].y = y_mid-2; - button[2].x = x; - button[2].y = y_mid+3; - } - else - { - button[0].y = y_mid-5; - button[0].x = x-2; - button[1].y = y_mid+5; - button[1].x = x-2; - button[2].y = y_mid; - button[2].x = x+3; - } - dc.DrawPolygon(3, button); - dc.SetPen(m_dottedPen); - } } - else // if (HasFlag(wxTR_HAS_BUTTONS)) + else // no custom buttons { - // draw the plus sign here - dc.SetPen(*wxGREY_PEN); - dc.SetBrush(*wxWHITE_BRUSH); - dc.DrawRectangle(x-5, y_mid-4, 11, 9); - dc.SetPen(*wxBLACK_PEN); - dc.DrawLine(x-2, y_mid, x+3, y_mid); - if (!item->IsExpanded()) - dc.DrawLine(x, y_mid-2, x, y_mid+3); - dc.SetPen(m_dottedPen); + static const int wImage = 9; + static const int hImage = 9; + + wxRendererNative::Get().DrawTreeItemButton + ( + this, + dc, + wxRect(x - wImage/2, + y_mid - hImage/2, + wImage, hImage), + item->IsExpanded() + ? wxCONTROL_EXPANDED + : 0 + ); } } - else if (!HasFlag(wxTR_NO_LINES)) // no button; maybe a line? - { - // draw the horizontal line here - int x_start = x; - if (x > (signed)m_indent) - x_start -= m_indent; - else if (HasFlag(wxTR_LINES_AT_ROOT)) - x_start = 3; - dc.DrawLine(x_start, y_mid, x + m_spacing, y_mid); - } } if (item->IsExpanded()) @@ -2634,7 +2546,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) if ( !event.HasModifiers() ) { wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() ); - event.m_item = (long) m_current; + event.m_item = m_current; event.SetEventObject( this ); GetEventHandler()->ProcessEvent( event ); } @@ -2661,7 +2573,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) } if (prev) { - long cookie = 0; + wxTreeItemIdValue cookie; wxTreeItemId current = m_key_current; // TODO: Huh? If we get here, we'd better be the first child of our parent. How else could it be? if (current == GetFirstChild( prev, cookie )) @@ -2716,7 +2628,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) { if (IsExpanded(m_key_current) && HasChildren(m_key_current)) { - long cookie = 0; + wxTreeItemIdValue cookie; wxTreeItemId child = GetFirstChild( m_key_current, cookie ); SelectItem( child, unselect_others, extended_select ); m_key_current=(wxGenericTreeItem*) child.m_pItem; @@ -2727,7 +2639,7 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) if (!next) { wxTreeItemId current = m_key_current; - while (current && !next) + while (current.IsOk() && !next) { current = GetItemParent( current ); if (current) next = GetNextSibling( current ); @@ -2776,8 +2688,8 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) if ( HasFlag(wxTR_HIDE_ROOT) ) { - long dummy; - prev = GetFirstChild(prev, dummy); + wxTreeItemIdValue cookie; + prev = GetFirstChild(prev, cookie); if (!prev) break; } @@ -2882,7 +2794,7 @@ void wxGenericTreeCtrl::Edit( const wxTreeItemId& item ) wxGenericTreeItem *itemEdit = (wxGenericTreeItem *)item.m_pItem; wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, GetId() ); - te.m_item = (long) itemEdit; + te.m_item = itemEdit; te.SetEventObject( this ); if ( GetEventHandler()->ProcessEvent( te ) && !te.IsAllowed() ) { @@ -2913,7 +2825,7 @@ bool wxGenericTreeCtrl::OnRenameAccept(wxGenericTreeItem *item, const wxString& value) { wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, GetId() ); - le.m_item = (long) item; + le.m_item = item; le.SetEventObject( this ); le.m_label = value; le.m_editCancelled = FALSE; @@ -2925,10 +2837,10 @@ void wxGenericTreeCtrl::OnRenameCancelled(wxGenericTreeItem *item) { // let owner know that the edit was cancelled wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, GetId() ); - le.m_item = (long) item; + le.m_item = item; le.SetEventObject( this ); le.m_label = wxEmptyString; - le.m_editCancelled = FALSE; + le.m_editCancelled = TRUE; GetEventHandler()->ProcessEvent( le ); } @@ -2983,7 +2895,7 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) : wxEVT_COMMAND_TREE_BEGIN_DRAG; wxTreeEvent nevent( command, GetId() ); - nevent.m_item = (long) m_current; + nevent.m_item = m_current; nevent.SetEventObject(this); // by default the dragging is not supported, the user code must @@ -3044,7 +2956,7 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) // generate the drag end event wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, GetId()); - event.m_item = (long) item; + event.m_item = item; event.m_pointDrag = pt; event.SetEventObject(this); @@ -3070,13 +2982,28 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) if ( event.RightDown() ) { wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, GetId()); - nevent.m_item = (long) item; + nevent.m_item = item; nevent.m_pointDrag = CalcScrolledPosition(pt); nevent.SetEventObject(this); GetEventHandler()->ProcessEvent(nevent); } else if ( event.LeftUp() ) { + // this facilitates multiple-item drag-and-drop + + if (item && HasFlag(wxTR_MULTIPLE)) + { + wxArrayTreeItemIds selections; + size_t count = GetSelections(selections); + + if (count > 1 && + !event.ControlDown() && + !event.ShiftDown()) + { + SelectItem(item, true, false); + } + } + if ( m_lastOnSame ) { if ( (item == m_current) && @@ -3119,14 +3046,24 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) return; } - // how should the selection work for this event? - bool is_multiple, extended_select, unselect_others; - EventFlagsToSelType(GetWindowStyleFlag(), - event.ShiftDown(), - event.ControlDown(), - is_multiple, extended_select, unselect_others); - SelectItem(item, unselect_others, extended_select); + // clear the previously selected items, if the + // user clicked outside of the present selection. + // otherwise, perform the deselection on mouse-up. + // this allows multiple drag and drop to work. + + if (!IsSelected(item)) + { + // how should the selection work for this event? + bool is_multiple, extended_select, unselect_others; + EventFlagsToSelType(GetWindowStyleFlag(), + event.ShiftDown(), + event.ControlDown(), + is_multiple, extended_select, unselect_others); + + SelectItem(item, unselect_others, extended_select); + } + // For some reason, Windows isn't recognizing a left double-click, // so we need to simulate it here. Allow 200 milliseconds for now. @@ -3140,7 +3077,7 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) // send activate event first wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() ); - nevent.m_item = (long) item; + nevent.m_item = item; nevent.m_pointDrag = CalcScrolledPosition(pt); nevent.SetEventObject( this ); if ( !GetEventHandler()->ProcessEvent( nevent ) ) @@ -3158,8 +3095,10 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) } } -void wxGenericTreeCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) ) +void wxGenericTreeCtrl::OnInternalIdle() { + wxWindow::OnInternalIdle(); + // Check if we need to select the root item // because nothing else has been selected. // Delaying it means that we can invoke event handlers