#include "wx/renderer.h"
+#ifdef __WXMAC__
+ #include "wx/mac/private.h"
+#endif
+
// -----------------------------------------------------------------------------
// array types
// -----------------------------------------------------------------------------
class WXDLLEXPORT wxGenericTreeItem;
-WX_DEFINE_EXPORTED_ARRAY_NO_PTR(wxGenericTreeItem *, wxArrayGenericTreeItems);
+WX_DEFINE_EXPORTED_ARRAY_PTR(wxGenericTreeItem *, wxArrayGenericTreeItems);
// ----------------------------------------------------------------------------
// constants
// return the item at given position (or NULL if no item), onButton is
// TRUE if the point belongs to the item's button, otherwise it lies
- // on the button's label
+ // on the item's label
wxGenericTreeItem *HitTest( const wxPoint& point,
const wxGenericTreeCtrl *,
int &flags,
else
flags |= wxTREE_HITTEST_ONITEMLOWERPART;
- // 5 is the size of the plus sign
int xCross = m_x - theCtrl->GetSpacing();
- if ((point.x > xCross-5) && (point.x < xCross+5) &&
- (point.y > y_mid-5) && (point.y < y_mid+5) &&
+#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-6) && (point.x < xCross+6) &&
+ (point.y > y_mid-6) && (point.y < y_mid+6) &&
HasPlus() && theCtrl->HasButtons() )
+#endif
{
flags |= wxTREE_HITTEST_ONITEMBUTTON;
return this;
EVT_CHAR (wxGenericTreeCtrl::OnChar)
EVT_SET_FOCUS (wxGenericTreeCtrl::OnSetFocus)
EVT_KILL_FOCUS (wxGenericTreeCtrl::OnKillFocus)
+ EVT_TREE_ITEM_GETTOOLTIP(-1, wxGenericTreeCtrl::OnGetToolTip)
END_EVENT_TABLE()
-#if !defined(__WXMSW__) || defined(__WIN16__) || defined(__WXUNIVERSAL__)
+#if !defined(__WXMSW__) || defined(__WXUNIVERSAL__)
/*
* wxTreeCtrl has to be a real class or we have problems with
* the run-time information.
m_dragCount = 0;
m_isDragging = FALSE;
- m_dropTarget = m_oldSelection = (wxGenericTreeItem *)NULL;
+ m_dropTarget = m_oldSelection = NULL;
+ m_underMouse = NULL;
m_textCtrl = NULL;
m_renameTimer = NULL;
+ m_freezeCount = 0;
+
m_findTimer = NULL;
m_lastOnSame = FALSE;
+#if defined( __WXMAC__ ) && __WXMAC_CARBON__
+ m_normalFont.MacCreateThemeFont( kThemeViewsFont ) ;
+#else
m_normalFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
+#endif
m_boldFont = wxFont(m_normalFont.GetPointSize(),
m_normalFont.GetFamily(),
m_normalFont.GetStyle(),
const wxPoint& pos,
const wxSize& size,
long style,
- const wxValidator &validator,
+ const wxValidator& wxVALIDATOR_PARAM(validator),
const wxString& name )
{
#ifdef __WXMAC__
SetValidator( validator );
#endif
- SetForegroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
- SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX) );
+ wxVisualAttributes attr = GetDefaultAttributes();
+ SetDefaultForegroundColour( attr.colFg );
+ SetDefaultBackgroundColour( attr.colBg );
+ SetDefaultFont(attr.font);
// m_dottedPen = wxPen( "grey", 0, wxDOT ); too slow under XFree86
m_dottedPen = wxPen( wxT("grey"), 0, 0 );
+ SetBestSize(size);
+
return TRUE;
}
m_dirty = TRUE;
}
-size_t wxGenericTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively)
+size_t
+wxGenericTreeCtrl::GetChildrenCount(const wxTreeItemId& item,
+ bool recursively) const
{
wxCHECK_MSG( item.IsOk(), 0u, wxT("invalid tree item") );
{
wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+ if (data)
+ data->SetId( item );
+
((wxGenericTreeItem*) item.m_pItem)->SetData(data);
}
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()<item2->GetY())
- {
- first=item1;
- last=item2;
- }
- else
- {
- first=item2;
- last=item1;
- }
+ wxGenericTreeItem *first= (item1->GetY()<item2->GetY()) ? item1 : item2;
+ wxGenericTreeItem *last = (item1->GetY()<item2->GetY()) ? item2 : item1;
bool select = m_current->IsSelected();
TagNextChildren(first,last,select);
}
-void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId,
- bool unselect_others,
- bool extended_select)
+void wxGenericTreeCtrl::DoSelectItem(const wxTreeItemId& itemId,
+ bool unselect_others,
+ bool extended_select)
{
wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") );
GetEventHandler()->ProcessEvent( event );
}
+void wxGenericTreeCtrl::SelectItem(const wxTreeItemId& itemId, bool select)
+{
+ if ( select )
+ {
+ DoSelectItem(itemId);
+ }
+ else // deselect
+ {
+ wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
+ wxCHECK_RET( item, wxT("SelectItem(): invalid tree item") );
+
+ item->SetHilight(FALSE);
+ RefreshLine(item);
+ }
+}
+
void wxGenericTreeCtrl::FillArray(wxGenericTreeItem *item,
wxArrayTreeItemIds &array) const
{
void wxGenericTreeCtrl::EnsureVisible(const wxTreeItemId& item)
{
+ wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
if (!item.IsOk()) return;
wxGenericTreeItem *gitem = (wxGenericTreeItem*) item.m_pItem;
// We have to call this here because the label in
// question might just have been added and no screen
// update taken place.
- if (m_dirty) wxYieldIfNeeded();
-
+ if (m_dirty)
+#if defined( __WXMSW__ ) || defined(__WXMAC__)
+ Update();
+#else
+ wxYieldIfNeeded();
+#endif
wxGenericTreeItem *gitem = (wxGenericTreeItem*) item.m_pItem;
// now scroll to the item
}
else // no custom buttons
{
- static const int wImage = 10;
- static const int hImage = 12;
-
+ static const int wImage = 9;
+ static const int hImage = 9;
+
+ int flag = 0;
+ if (item->IsExpanded())
+ flag |= wxCONTROL_EXPANDED;
+ if (item == m_underMouse)
+ flag |= wxCONTROL_CURRENT;
+
wxRendererNative::Get().DrawTreeItemButton
(
this,
wxRect(x - wImage/2,
y_mid - hImage/2,
wImage, hImage),
- item->IsExpanded()
- ? wxCONTROL_EXPANDED
- : 0
+ flag
);
}
}
}
// -----------------------------------------------------------------------------
-// wxWindows callbacks
+// wxWidgets callbacks
// -----------------------------------------------------------------------------
void wxGenericTreeCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) )
if (current == GetFirstChild( prev, cookie ))
{
// otherwise we return to where we came from
- SelectItem( prev, unselect_others, extended_select );
+ DoSelectItem( prev, unselect_others, extended_select );
m_key_current= (wxGenericTreeItem*) prev.m_pItem;
break;
}
}
}
- SelectItem( prev, unselect_others, extended_select );
+ DoSelectItem( prev, unselect_others, extended_select );
m_key_current=(wxGenericTreeItem*) prev.m_pItem;
}
}
}
if (prev)
{
- SelectItem( prev, unselect_others, extended_select );
+ DoSelectItem( prev, unselect_others, extended_select );
}
}
break;
{
wxTreeItemIdValue cookie;
wxTreeItemId child = GetFirstChild( m_key_current, cookie );
- SelectItem( child, unselect_others, extended_select );
+ DoSelectItem( child, unselect_others, extended_select );
m_key_current=(wxGenericTreeItem*) child.m_pItem;
}
else
}
if (next)
{
- SelectItem( next, unselect_others, extended_select );
+ DoSelectItem( next, unselect_others, extended_select );
m_key_current=(wxGenericTreeItem*) next.m_pItem;
}
}
if ( last.IsOk() )
{
- SelectItem( last, unselect_others, extended_select );
+ DoSelectItem( last, unselect_others, extended_select );
}
}
break;
break;
}
- SelectItem( prev, unselect_others, extended_select );
+ DoSelectItem( prev, unselect_others, extended_select );
}
break;
// question might just have been added and no screen
// update taken place.
if ( m_dirty )
+#if defined( __WXMSW__ ) || defined(__WXMAC__)
+ Update();
+#else
wxYieldIfNeeded();
+#endif
m_textCtrl = new wxTreeTextCtrl(this, itemEdit);
{
if ( !m_anchor ) return;
+ wxPoint pt = CalcUnscrolledPosition(event.GetPosition());
+
+ // Is the mouse over a tree item button?
+ int flags = 0;
+ wxGenericTreeItem *thisItem = m_anchor->HitTest(pt, this, flags, 0);
+ wxGenericTreeItem *underMouse = thisItem;
+#if wxUSE_TOOLTIPS
+ bool underMouseChanged = (underMouse != m_underMouse) ;
+#endif // wxUSE_TOOLTIPS
+
+ if ((underMouse) &&
+ (flags & wxTREE_HITTEST_ONITEMBUTTON) &&
+ (!event.LeftIsDown()) &&
+ (!m_isDragging) &&
+ (!m_renameTimer || !m_renameTimer->IsRunning()))
+ {
+ }
+ else
+ {
+ underMouse = NULL;
+ }
+
+ if (underMouse != m_underMouse)
+ {
+ if (m_underMouse)
+ {
+ // unhighlight old item
+ wxGenericTreeItem *tmp = m_underMouse;
+ m_underMouse = NULL;
+ RefreshLine( tmp );
+ }
+
+ m_underMouse = underMouse;
+ if (m_underMouse)
+ RefreshLine( m_underMouse );
+ }
+
+#if wxUSE_TOOLTIPS
+ // Determines what item we are hovering over and need a tooltip for
+ wxTreeItemId hoverItem = thisItem;
+
+ // We do not want a tooltip if we are dragging, or if the rename timer is running
+ if (underMouseChanged && hoverItem.IsOk() && !m_isDragging && (!m_renameTimer || !m_renameTimer->IsRunning()))
+ {
+ // Ask the tree control what tooltip (if any) should be shown
+ wxTreeEvent hevent(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, GetId());
+ hevent.m_item = hoverItem;
+ hevent.SetEventObject(this);
+
+ if ( GetEventHandler()->ProcessEvent(hevent) && hevent.IsAllowed() )
+ {
+ SetToolTip(hevent.m_label);
+ }
+ }
+#endif
+
// we process left mouse up event (enables in-place edit), right down
// (pass to the user code), left dbl click (activate item) and
// dragging/moving events for items drag-and-drop
return;
}
- wxPoint pt = CalcUnscrolledPosition(event.GetPosition());
- int flags = 0;
+ flags = 0;
wxGenericTreeItem *item = m_anchor->HitTest(pt, this, flags, 0);
if ( event.Dragging() && !m_isDragging )
// highlight the current drop target if any
DrawDropEffect(m_dropTarget);
+#if defined( __WXMSW__ ) || defined(__WXMAC__)
+ Update();
+#else
wxYieldIfNeeded();
+#endif
}
}
else if ( (event.LeftUp() || event.RightUp()) && m_isDragging )
SetCursor(m_oldCursor);
+#if defined( __WXMSW__ ) || defined(__WXMAC__)
+ Update();
+#else
wxYieldIfNeeded();
+#endif
}
else
{
!event.ControlDown() &&
!event.ShiftDown())
{
- SelectItem(item, true, false);
+ DoSelectItem(item, true, false);
}
}
event.ControlDown(),
is_multiple, extended_select, unselect_others);
- SelectItem(item, unselect_others, extended_select);
+ DoSelectItem(item, unselect_others, extended_select);
}
* we actually redraw the tree when everything is over */
if (!m_dirty) return;
-
+ if (m_freezeCount) return;
+
m_dirty = FALSE;
CalculatePositions();
dc.SetFont(attr->GetFont());
else if ( item->IsBold() )
dc.SetFont(m_boldFont);
+ else
+ dc.SetFont(m_normalFont);
dc.GetTextExtent( item->GetText(), &text_w, &text_h );
text_h+=2;
void wxGenericTreeCtrl::RefreshSubtree(wxGenericTreeItem *item)
{
if (m_dirty) return;
+ if (m_freezeCount) return;
wxSize client = GetClientSize();
void wxGenericTreeCtrl::RefreshLine( wxGenericTreeItem *item )
{
if (m_dirty) return;
+ if (m_freezeCount) return;
wxRect rect;
CalcScrolledPosition(0, item->GetY(), NULL, &rect.y);
void wxGenericTreeCtrl::RefreshSelected()
{
+ if (m_freezeCount) return;
+
// TODO: this is awfully inefficient, we should keep the list of all
// selected items internally, should be much faster
if ( m_anchor )
void wxGenericTreeCtrl::RefreshSelectedUnder(wxGenericTreeItem *item)
{
+ if (m_freezeCount) return;
+
if ( item->IsSelected() )
RefreshLine(item);
}
}
+void wxGenericTreeCtrl::Freeze()
+{
+ m_freezeCount++;
+}
+
+void wxGenericTreeCtrl::Thaw()
+{
+ wxCHECK_RET( m_freezeCount > 0, _T("thawing unfrozen tree control?") );
+
+ if ( !--m_freezeCount )
+ {
+ Refresh();
+ }
+}
+
// ----------------------------------------------------------------------------
// changing colours: we need to refresh the tree control
// ----------------------------------------------------------------------------
if ( !wxWindow::SetBackgroundColour(colour) )
return FALSE;
+ if (m_freezeCount) return TRUE;
+
Refresh();
return TRUE;
if ( !wxWindow::SetForegroundColour(colour) )
return FALSE;
+ if (m_freezeCount) return TRUE;
+
Refresh();
return TRUE;
}
+// Process the tooltip event, to speed up event processing.
+// Doesn't actually get a tooltip.
+void wxGenericTreeCtrl::OnGetToolTip( wxTreeEvent &event )
+{
+ event.Veto();
+}
+
+
+// NOTE: If using the wxListBox visual attributes works everywhere then this can
+// be removed, as well as the #else case below.
+#define _USE_VISATTR 0
+
+#if _USE_VISATTR
+#include "wx/listbox.h"
+#endif
+
+//static
+wxVisualAttributes
+#if _USE_VISATTR
+wxGenericTreeCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
+#else
+wxGenericTreeCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
+#endif
+{
+#if _USE_VISATTR
+ // Use the same color scheme as wxListBox
+ return wxListBox::GetClassDefaultAttributes(variant);
+#else
+ wxVisualAttributes attr;
+ attr.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+ attr.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
+ attr.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
+ return attr;
+#endif
+}
+
#endif // wxUSE_TREECTRL