#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
// -----------------------------------------------------------------------------
wxString *m_res;
wxGenericTreeCtrl *m_owner;
wxString m_startValue;
+ bool m_finished;
DECLARE_EVENT_TABLE()
};
wxGenericTreeItem() { m_data = NULL; }
wxGenericTreeItem( wxGenericTreeItem *parent,
const wxString& text,
- wxDC& dc,
int image,
int selImage,
wxTreeItemData *data );
(*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;
}
if (event.m_keyCode == WXK_ESCAPE)
if (!wxPendingDelete.Member(this))
wxPendingDelete.Append(this);
+ m_finished = TRUE;
+ m_owner->SetFocus(); // This doesn't work. TODO.
+
return;
}
event.Skip();
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);
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_owner->OnRenameAccept();
-}
-
-#if 0
-// -----------------------------------------------------------------------------
-// wxTreeEvent
-// -----------------------------------------------------------------------------
-
-IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxNotifyEvent)
+ (*m_accept) = TRUE;
+ (*m_res) = GetValue();
-wxTreeEvent::wxTreeEvent( wxEventType commandType, int id )
- : wxNotifyEvent( commandType, id )
-{
- m_code = 0;
- m_itemOld = (wxGenericTreeItem *)NULL;
+ if ((*m_res) != m_startValue)
+ m_owner->OnRenameAccept();
}
-#endif
// -----------------------------------------------------------------------------
// wxGenericTreeItem
wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent,
const wxString& text,
- wxDC& WXUNUSED(dc),
int image, int selImage,
wxTreeItemData *data)
: m_text(text)
m_hilightBrush = new wxBrush
(
- wxSystemSettings::GetSystemColour
+ wxSystemSettings::GetColour
(
wxSYS_COLOUR_HIGHLIGHT
),
m_hilightUnfocusedBrush = new wxBrush
(
- wxSystemSettings::GetSystemColour
+ wxSystemSettings::GetColour
(
wxSYS_COLOUR_BTNSHADOW
),
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(),
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 );
- // If the tree display has no buttons, but does have
- // connecting lines, we can use a narrower layout.
- // It may not be a good idea to force this...
+ // If the tree display has no buttons, but does have
+ // connecting lines, we can use a narrower layout.
+ // It may not be a good idea to force this...
if (!HasButtons() && !HasFlag(wxTR_NO_LINES))
{
m_indent= 10;
SetValidator( validator );
#endif
- SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) );
+ SetForegroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
+ 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;
}
delete m_hilightBrush;
delete m_hilightUnfocusedBrush;
+ if (m_arrowRight) delete m_arrowRight;
+ if (m_arrowDown) delete m_arrowDown;
+
DeleteAllItems();
delete m_renameTimer;
void wxGenericTreeCtrl::SetIndent(unsigned int indent)
{
- m_indent = indent;
+ m_indent = (unsigned short) indent;
m_dirty = TRUE;
}
void wxGenericTreeCtrl::SetSpacing(unsigned int spacing)
{
- m_spacing = spacing;
+ m_spacing = (unsigned short) spacing;
m_dirty = TRUE;
}
{
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
}
}
-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();
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 )
{
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
m_anchor->SetHasPlus();
Expand(m_anchor);
}
- if ( data != NULL )
- {
- data->m_pItem = (long) m_anchor;
- }
if (!HasFlag(wxTR_MULTIPLE))
{
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 !
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 )
}
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;
}
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 = GetForegroundColour();
+ }
+
+ // 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);
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))
{
{
// 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() )
- {
- 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())
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);
}
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) )
{
{
wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() );
event.m_item = (long) m_current;
- event.m_code = 0;
event.SetEventObject( this );
GetEventHandler()->ProcessEvent( 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);
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);
+ }
}
}
}
wxCoord text_w = 0;
wxCoord text_h = 0;
- if (item->IsBold())
+ wxTreeItemAttr *attr = item->GetAttributes();
+ if ( attr && attr->HasFont() )
+ dc.SetFont(attr->GetFont());
+ else if ( item->IsBold() )
dc.SetFont(m_boldFont);
dc.GetTextExtent( item->GetText(), &text_w, &text_h );
}
}
+// ----------------------------------------------------------------------------
+// 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