X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b771aa29dd34686cc92ef4675978b1fdc1a47a29..45e0dc94770d598a1cc84d83730d470dd1cfbcca:/src/generic/treectlg.cpp diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index f2b3ca9dde..d16901dee4 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -55,6 +55,54 @@ static const int NO_IMAGE = -1; #define 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 // ----------------------------------------------------------------------------- @@ -96,6 +144,7 @@ private: wxString *m_res; wxGenericTreeCtrl *m_owner; wxString m_startValue; + bool m_finished; DECLARE_EVENT_TABLE() }; @@ -108,7 +157,6 @@ public: wxGenericTreeItem() { m_data = NULL; } wxGenericTreeItem( wxGenericTreeItem *parent, const wxString& text, - wxDC& dc, int image, int selImage, wxTreeItemData *data ); @@ -305,21 +353,24 @@ wxTreeTextCtrl::wxTreeTextCtrl( wxWindow *parent, (*m_accept) = FALSE; (*m_res) = wxEmptyString; m_startValue = value; + m_finished = FALSE; } void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) { - // TODO focus doesn't return to the wxTextCtrl when this closes... if (event.m_keyCode == WXK_RETURN) { (*m_accept) = TRUE; (*m_res) = GetValue(); - if ((*m_accept) && ((*m_res) != m_startValue)) + if ((*m_res) != m_startValue) m_owner->OnRenameAccept(); if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this); + + m_finished = TRUE; + m_owner->SetFocus(); // This doesn't work. TODO. return; } @@ -331,6 +382,9 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this); + m_finished = TRUE; + m_owner->SetFocus(); // This doesn't work. TODO. + return; } event.Skip(); @@ -338,12 +392,18 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) { + if (m_finished) + { + event.Skip(); + return; + } + // auto-grow the textctrl: wxSize parentSize = m_owner->GetSize(); wxPoint myPos = GetPosition(); wxSize mySize = GetSize(); int sx, sy; - GetTextExtent(GetValue() + _T("MM"), &sx, &sy); + GetTextExtent(GetValue() + _T("M"), &sx, &sy); if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x; if (mySize.x > sx) sx = mySize.x; SetSize(sx, -1); @@ -351,37 +411,30 @@ void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) event.Skip(); } -void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) ) +void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event ) { + if (m_finished) + { + event.Skip(); + return; + } + if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this); - if ((*m_accept) && ((*m_res) != m_startValue)) + (*m_accept) = TRUE; + (*m_res) = GetValue(); + + if ((*m_res) != m_startValue) m_owner->OnRenameAccept(); } -#if 0 -// ----------------------------------------------------------------------------- -// wxTreeEvent -// ----------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxNotifyEvent) - -wxTreeEvent::wxTreeEvent( wxEventType commandType, int id ) - : wxNotifyEvent( commandType, id ) -{ - m_code = 0; - m_itemOld = (wxGenericTreeItem *)NULL; -} -#endif - // ----------------------------------------------------------------------------- // wxGenericTreeItem // ----------------------------------------------------------------------------- wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent, const wxString& text, - wxDC& WXUNUSED(dc), int image, int selImage, wxTreeItemData *data) : m_text(text) @@ -616,7 +669,7 @@ void wxGenericTreeCtrl::Init() m_hilightBrush = new wxBrush ( - wxSystemSettings::GetSystemColour + wxSystemSettings::GetColour ( wxSYS_COLOUR_HIGHLIGHT ), @@ -625,7 +678,7 @@ void wxGenericTreeCtrl::Init() m_hilightUnfocusedBrush = new wxBrush ( - wxSystemSettings::GetSystemColour + wxSystemSettings::GetColour ( wxSYS_COLOUR_BTNSHADOW ), @@ -644,7 +697,7 @@ void wxGenericTreeCtrl::Init() m_renameTimer = new wxTreeRenameTimer( this ); m_lastOnSame = FALSE; - m_normalFont = wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ); + m_normalFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); m_boldFont = wxFont( m_normalFont.GetPointSize(), m_normalFont.GetFamily(), m_normalFont.GetStyle(), @@ -660,6 +713,31 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, const wxValidator &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; + } + wxScrolledWindow::Create( parent, id, pos, size, style|wxHSCROLL|wxVSCROLL, name ); @@ -676,10 +754,10 @@ bool wxGenericTreeCtrl::Create(wxWindow *parent, SetValidator( validator ); #endif - SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) ); + SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX ) ); // m_dottedPen = wxPen( "grey", 0, wxDOT ); too slow under XFree86 - m_dottedPen = wxPen( "grey", 0, 0 ); + m_dottedPen = wxPen( wxT("grey"), 0, 0 ); return TRUE; } @@ -688,6 +766,9 @@ wxGenericTreeCtrl::~wxGenericTreeCtrl() { delete m_hilightBrush; delete m_hilightUnfocusedBrush; + + if (m_arrowRight) delete m_arrowRight; + if (m_arrowDown) delete m_arrowDown; DeleteAllItems(); @@ -898,7 +979,12 @@ bool wxGenericTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); - return !((wxGenericTreeItem*) item.m_pItem)->GetChildren().IsEmpty(); + // consider that the item does have children if it has the "+" button: it + // might not have them (if it had never been expanded yet) but then it + // could have them as well and it's better to err on this side rather than + // disabling some operations which are restricted to the items with + // children for an item which does have them + return ((wxGenericTreeItem*) item.m_pItem)->HasPlus(); } bool wxGenericTreeCtrl::IsExpanded(const wxTreeItemId& item) const @@ -1032,15 +1118,6 @@ wxTreeItemId wxGenericTreeCtrl::GetNext(const wxTreeItemId& item) const } } -wxTreeItemId wxGenericTreeCtrl::GetPrev(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxFAIL_MSG(wxT("not implemented")); - - return wxTreeItemId(); -} - wxTreeItemId wxGenericTreeCtrl::GetFirstVisibleItem() const { wxTreeItemId id = GetRootItem(); @@ -1101,9 +1178,8 @@ wxTreeItemId wxGenericTreeCtrl::DoInsertItem(const wxTreeItemId& parentId, m_dirty = TRUE; // do this first so stuff below doesn't cause flicker - wxClientDC dc(this); wxGenericTreeItem *item = - new wxGenericTreeItem( parent, text, dc, image, selImage, data ); + new wxGenericTreeItem( parent, text, image, selImage, data ); if ( data != NULL ) { @@ -1123,9 +1199,13 @@ wxTreeItemId wxGenericTreeCtrl::AddRoot(const wxString& text, m_dirty = TRUE; // do this first so stuff below doesn't cause flicker - wxClientDC dc(this); - m_anchor = new wxGenericTreeItem((wxGenericTreeItem *)NULL, text, dc, + m_anchor = new wxGenericTreeItem((wxGenericTreeItem *)NULL, text, image, selImage, data); + if ( data != NULL ) + { + data->m_pItem = (long) m_anchor; + } + if (HasFlag(wxTR_HIDE_ROOT)) { // if root is hidden, make sure we can navigate @@ -1133,10 +1213,6 @@ wxTreeItemId wxGenericTreeCtrl::AddRoot(const wxString& text, m_anchor->SetHasPlus(); Expand(m_anchor); } - if ( data != NULL ) - { - data->m_pItem = (long) m_anchor; - } if (!HasFlag(wxTR_MULTIPLE)) { @@ -1402,7 +1478,13 @@ void wxGenericTreeCtrl::UnselectAllChildren(wxGenericTreeItem *item) void wxGenericTreeCtrl::UnselectAll() { - UnselectAllChildren((wxGenericTreeItem*) GetRootItem().m_pItem); + wxTreeItemId rootItem = GetRootItem(); + + // the tree might not have the root item at all + if ( rootItem ) + { + UnselectAllChildren((wxGenericTreeItem*) rootItem.m_pItem); + } } // Recursive function ! @@ -1869,18 +1951,29 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) int offset = HasFlag(wxTR_ROW_LINES) ? 1 : 0; - if ( item->IsSelected() && image != NO_IMAGE ) + if ( HasFlag(wxTR_FULL_ROW_HIGHLIGHT) ) { - // 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. - dc.DrawRectangle( item->GetX() + image_w - 2, item->GetY()+offset, - item->GetWidth() - image_w + 2, total_h-offset ); + int x, y, w, h; + + DoGetPosition(&x, &y); + DoGetSize(&w, &h); + dc.DrawRectangle(x, item->GetY()+offset, w, total_h-offset); } else { - dc.DrawRectangle( item->GetX()-2, item->GetY()+offset, - item->GetWidth()+2, total_h-offset ); + if ( item->IsSelected() && 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. + dc.DrawRectangle( item->GetX() + image_w - 2, item->GetY()+offset, + item->GetWidth() - image_w + 2, total_h-offset ); + } + else + { + dc.DrawRectangle( item->GetX()-2, item->GetY()+offset, + item->GetWidth()+2, total_h-offset ); + } } if ( image != NO_IMAGE ) @@ -1913,10 +2006,26 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level } else if (level == 0) { + // always expand hidden root + int origY = y; wxArrayGenericTreeItems& children = item->GetChildren(); - size_t n, count = children.Count(); - for (n = 0; n < count; ++n) - PaintLevel(children[n], dc, 1, y); + int count = children.Count(); + if (count > 0) + { + int n = 0, oldY; + do { + oldY = y; + PaintLevel(children[n], dc, 1, y); + } while (++n < count); + + if (!HasFlag(wxTR_NO_LINES) && HasFlag(wxTR_LINES_AT_ROOT) && count > 0) + { + // draw line down to last child + origY += GetLineHeight(children[0])>>1; + oldY += GetLineHeight(children[n-1])>>1; + dc.DrawLine(3, origY, 3, oldY); + } + } return; } @@ -1933,22 +2042,68 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level if (IsExposed(exposed_x, exposed_y, 10000, h)) // 10000 = very much { + wxPen *pen = +#ifndef __WXMAC__ + // don't draw rect outline if we already have the + // background color under Mac + (item->IsSelected() && m_hasFocus) ? wxBLACK_PEN : +#endif // !__WXMAC__ + wxTRANSPARENT_PEN; + + wxColour colText; + if ( item->IsSelected() ) + { + colText = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); + } + else + { + wxTreeItemAttr *attr = item->GetAttributes(); + if (attr && attr->HasTextColour()) + colText = attr->GetTextColour(); + else + colText = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + } + + // prepare to draw + dc.SetTextForeground(colText); + dc.SetPen(*pen); + + // draw + PaintItem(item, dc); + + if (HasFlag(wxTR_ROW_LINES)) + { + // if the background colour is white, choose a + // contrasting color for the lines + dc.SetPen(*((GetBackgroundColour() == *wxWHITE) + ? wxMEDIUM_GREY_PEN : wxWHITE_PEN)); + dc.DrawLine(0, y_top, 10000, y_top); + dc.DrawLine(0, y, 10000, y); + } + + // restore DC objects + dc.SetBrush(*wxWHITE_BRUSH); + dc.SetPen(m_dottedPen); + dc.SetTextForeground(*wxBLACK); + if (item->HasPlus() && HasButtons()) // should the item show a button? { if (!HasFlag(wxTR_NO_LINES)) { - if (x > (signed)m_indent || HasFlag(wxTR_LINES_AT_ROOT)) + 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); } if (m_imageListButtons != NULL) { // draw the image button here - int image_h = 0, image_w = 0, image = wxCLOSED_BUTTON; - if (item->IsExpanded()) image = wxOPEN_BUTTON; + int image_h = 0, image_w = 0, image = wxTreeItemIcon_Normal; + if (item->IsExpanded()) image = wxTreeItemIcon_Expanded; if (item->IsSelected()) - image += wxOPEN_BUTTON_SELECTED - wxOPEN_BUTTON; + 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); @@ -1960,32 +2115,41 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level else if (HasFlag(wxTR_TWIST_BUTTONS)) { // draw the twisty button here - dc.SetPen(*wxBLACK_PEN); - dc.SetBrush(*m_hilightBrush); - - wxPoint button[3]; - - if (item->IsExpanded()) + + if (HasFlag(wxTR_AQUA_BUTTONS)) { - 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; + if (item->IsExpanded()) + dc.DrawBitmap( *m_arrowDown, x-5, y_mid-6, TRUE ); + else + dc.DrawBitmap( *m_arrowRight, x-5, y_mid-6, TRUE ); } 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.SetBrush(*m_hilightBrush); + dc.SetPen(*wxBLACK_PEN); + wxPoint button[3]; - dc.SetPen(m_dottedPen); + 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)) { @@ -2004,51 +2168,12 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level { // draw the horizontal line here int x_start = x; - if (x > (signed)m_indent || HasFlag(wxTR_LINES_AT_ROOT)) + 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); } - - wxPen *pen = -#ifndef __WXMAC__ - // don't draw rect outline if we already have the - // background color under Mac - (item->IsSelected() && m_hasFocus) ? wxBLACK_PEN : -#endif // !__WXMAC__ - wxTRANSPARENT_PEN; - - wxColour colText; - if (item->IsSelected() && m_hasFocus) - { - colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT); - } - else - { - wxTreeItemAttr *attr = item->GetAttributes(); - if (attr && attr->HasTextColour()) - colText = attr->GetTextColour(); - else - colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); - } - - // prepare to draw - dc.SetTextForeground(colText); - dc.SetPen(*pen); - - // draw - PaintItem(item, dc); - - if (HasFlag(wxTR_ROW_LINES)) - { - dc.SetPen(*wxWHITE_PEN); - dc.DrawLine(0, y_top, 10000, y_top); - dc.DrawLine(0, y, 10000, y); - } - - // restore DC objects - dc.SetBrush(*wxWHITE_BRUSH); - dc.SetPen(m_dottedPen); - dc.SetTextForeground(*wxBLACK); } if (item->IsExpanded()) @@ -2064,10 +2189,10 @@ void wxGenericTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level PaintLevel(children[n], dc, level, y); } while (++n < count); - if (!HasFlag(wxTR_NO_LINES)) + if (!HasFlag(wxTR_NO_LINES) && count > 0) { // draw line down to last child - oldY += GetLineHeight(children[n-1])/2; + oldY += GetLineHeight(children[n-1])>>1; if (HasButtons()) y_mid += 5; dc.DrawLine(x, y_mid, x, oldY); } @@ -2181,9 +2306,13 @@ void wxGenericTreeCtrl::OnKillFocus( wxFocusEvent &event ) void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) { wxTreeEvent te( wxEVT_COMMAND_TREE_KEY_DOWN, GetId() ); - te.m_code = (int)event.KeyCode(); + te.m_evtKey = event; te.SetEventObject( this ); - GetEventHandler()->ProcessEvent( te ); + if ( GetEventHandler()->ProcessEvent( te ) ) + { + // intercepted by the user code + return; + } if ( (m_current == 0) || (m_key_current == 0) ) { @@ -2241,7 +2370,6 @@ void wxGenericTreeCtrl::OnChar( wxKeyEvent &event ) { wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() ); event.m_item = (long) m_current; - event.m_code = 0; event.SetEventObject( this ); GetEventHandler()->ProcessEvent( event ); } @@ -2666,7 +2794,6 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) { wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, GetId()); nevent.m_item = (long) item; - nevent.m_code = 0; CalcScrolledPosition(x, y, &nevent.m_pointDrag.x, &nevent.m_pointDrag.y); @@ -2727,23 +2854,22 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event ) m_renameTimer->Stop(); m_lastOnSame = FALSE; - if (item->HasPlus()) - { - // for a "directory" node, toggle expansion - Toggle(item); - } - else + // send activate event first + wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() ); + nevent.m_item = (long) item; + CalcScrolledPosition(x, y, + &nevent.m_pointDrag.x, + &nevent.m_pointDrag.y); + nevent.SetEventObject( this ); + if ( !GetEventHandler()->ProcessEvent( nevent ) ) { - // for a "file" node, activate it - wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, - GetId() ); - nevent.m_item = (long) item; - nevent.m_code = 0; - CalcScrolledPosition(x, y, - &nevent.m_pointDrag.x, - &nevent.m_pointDrag.y); - nevent.SetEventObject( this ); - GetEventHandler()->ProcessEvent( nevent ); + // if the user code didn't process the activate event, + // handle it ourselves by toggling the item when it is + // double clicked + if ( item->HasPlus() ) + { + Toggle(item); + } } } } @@ -2922,4 +3048,28 @@ void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item) } } +// ---------------------------------------------------------------------------- +// changing colours: we need to refresh the tree control +// ---------------------------------------------------------------------------- + +bool wxGenericTreeCtrl::SetBackgroundColour(const wxColour& colour) +{ + if ( !wxWindow::SetBackgroundColour(colour) ) + return FALSE; + + Refresh(); + + return TRUE; +} + +bool wxGenericTreeCtrl::SetForegroundColour(const wxColour& colour) +{ + if ( !wxWindow::SetForegroundColour(colour) ) + return FALSE; + + Refresh(); + + return TRUE; +} + #endif // wxUSE_TREECTRL