#include "wx/renderer.h"
+#ifdef __WXMAC__
+ #include "wx/mac/private.h"
+#endif
+
// -----------------------------------------------------------------------------
// array types
// -----------------------------------------------------------------------------
public:
wxTreeTextCtrl(wxGenericTreeCtrl *owner, wxGenericTreeItem *item);
+ void StopEditing()
+ {
+ Finish();
+ m_owner->OnRenameCancelled(m_itemEdited);
+ }
+ const wxGenericTreeItem* item() const { return m_itemEdited; }
+
protected:
void OnChar( wxKeyEvent &event );
void OnKeyUp( wxKeyEvent &event );
wxGenericTreeItem *m_itemEdited;
wxString m_startValue;
bool m_finished;
+ bool m_aboutToFinish;
DECLARE_EVENT_TABLE()
DECLARE_NO_COPY_CLASS(wxTreeTextCtrl)
void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; }
void SetData(wxTreeItemData *data) { m_data = data; }
- void SetHasPlus(bool has = TRUE) { m_hasPlus = has; }
+ void SetHasPlus(bool has = true) { m_hasPlus = has; }
void SetBold(bool bold) { m_isBold = bold; }
void DeleteChildren(wxGenericTreeCtrl *tree = NULL);
// get count of all children (and grand children if 'recursively')
- size_t GetChildrenCount(bool recursively = TRUE) const;
+ size_t GetChildrenCount(bool recursively = true) const;
void Insert(wxGenericTreeItem *child, size_t index)
{ m_children.Insert(child, index); }
void GetSize( int &x, int &y, const wxGenericTreeCtrl* );
// 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
+ // true if the point belongs to the item's button, otherwise it lies
+ // on the item's label
wxGenericTreeItem *HitTest( const wxPoint& point,
const wxGenericTreeCtrl *,
int &flags,
int level );
- void Expand() { m_isCollapsed = FALSE; }
- void Collapse() { m_isCollapsed = TRUE; }
+ void Expand() { m_isCollapsed = false; }
+ void Collapse() { m_isCollapsed = true; }
- void SetHilight( bool set = TRUE ) { m_hasHilight = set; }
+ void SetHilight( bool set = true ) { m_hasHilight = set; }
// status inquiries
bool HasChildren() const { return !m_children.IsEmpty(); }
if ( !m_attr )
{
m_attr = new wxTreeItemAttr;
- m_ownsAttr = TRUE;
+ m_ownsAttr = true;
}
return *m_attr;
}
{
if ( m_ownsAttr ) delete m_attr;
m_attr = attr;
- m_ownsAttr = FALSE;
+ m_ownsAttr = false;
}
// set them and delete when done
void AssignAttributes(wxTreeItemAttr *attr)
{
SetAttributes(attr);
- m_ownsAttr = TRUE;
+ m_ownsAttr = true;
}
private:
// tree ctrl images for the normal, selected, expanded and
// expanded+selected states
- short m_images[wxTreeItemIcon_Max];
+ int m_images[wxTreeItemIcon_Max];
wxCoord m_x; // (virtual) offset from top
wxCoord m_y; // (virtual) offset from left
- short m_width; // width of this item
- unsigned char m_height; // height of this item
+ int m_width; // width of this item
+ int m_height; // height of this item
// use bitfields to save size
int m_isCollapsed :1;
}
// check if the given item is under another one
-static bool IsDescendantOf(wxGenericTreeItem *parent, wxGenericTreeItem *item)
+static bool IsDescendantOf(const wxGenericTreeItem *parent, const wxGenericTreeItem *item)
{
while ( item )
{
if ( item == parent )
{
// item is a descendant of parent
- return TRUE;
+ return true;
}
item = item->GetParent();
}
- return FALSE;
+ return false;
}
// -----------------------------------------------------------------------------
: m_itemEdited(item), m_startValue(item->GetText())
{
m_owner = owner;
- m_finished = FALSE;
+ m_finished = false;
+ m_aboutToFinish = false;
int w = m_itemEdited->GetWidth(),
h = m_itemEdited->GetHeight();
// FIXME: what are all these hardcoded 4, 8 and 11s really?
x += image_w;
w -= image_w + 4;
+#ifdef __WXMAC__
+ wxSize bs = DoGetBestSize() ;
+ // edit control height
+ if ( h > bs.y - 8 )
+ {
+ int diff = h - ( bs.y - 8 ) ;
+ h -= diff ;
+ y += diff / 2 ;
+ }
+#endif
(void)Create(m_owner, wxID_ANY, m_startValue,
wxPoint(x - 4, y - 4), wxSize(w + 11, h + 8));
if ( value == m_startValue )
{
// nothing changed, always accept
- return TRUE;
+ // when an item remains unchanged, the owner
+ // needs to be notified that the user decided
+ // not to change the tree item label, and that
+ // the edit has been cancelled
+
+ m_owner->OnRenameCancelled(m_itemEdited);
+ return true;
}
if ( !m_owner->OnRenameAccept(m_itemEdited, value) )
{
// vetoed by the user
- return FALSE;
+ return false;
}
// accepted, do rename the item
m_owner->SetItemText(m_itemEdited, value);
- return TRUE;
+ return true;
}
void wxTreeTextCtrl::Finish()
{
- if ( !m_finished )
+ if ( !m_finished && !m_aboutToFinish )
{
m_owner->ResetTextControl();
wxPendingDelete.Append(this);
- m_finished = TRUE;
+ m_finished = true;
- m_owner->SetFocus(); // This doesn't work. TODO.
+ m_owner->SetFocusIgnoringChildren();
}
}
switch ( event.m_keyCode )
{
case WXK_RETURN:
- if ( !AcceptChanges() )
- {
- // vetoed by the user, don't disappear
- break;
- }
- //else: fall through
+ m_aboutToFinish = true;
+ // Notify the owner about the changes
+ AcceptChanges();
+ // Even if vetoed, close the control (consistent with MSW)
+ Finish();
+ break;
case WXK_ESCAPE:
- Finish();
- m_owner->OnRenameCancelled(m_itemEdited);
+ StopEditing();
break;
default:
sx = parentSize.x - myPos.x;
if (mySize.x > sx)
sx = mySize.x;
- SetSize(sx, -1);
+ SetSize(sx, wxDefaultCoord);
}
event.Skip();
void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event )
{
- if ( m_finished )
- {
- event.Skip();
- return;
- }
-
- if ( AcceptChanges() )
+ if ( !m_finished )
{
+ // We must finish regardless of success, otherwise we'll get
+ // focus problems:
Finish();
+
+ if ( !AcceptChanges() )
+ m_owner->OnRenameCancelled( m_itemEdited );
}
+
+ // We must let the native text control handle focus, too, otherwise
+ // it could have problems with the cursor (e.g., in wxGTK).
+ event.Skip();
}
// -----------------------------------------------------------------------------
m_data = data;
m_x = m_y = 0;
- m_isCollapsed = TRUE;
- m_hasHilight = FALSE;
- m_hasPlus = FALSE;
- m_isBold = FALSE;
+ m_isCollapsed = true;
+ m_hasHilight = false;
+ m_hasPlus = false;
+ m_isBold = false;
m_parent = parent;
m_attr = (wxTreeItemAttr *)NULL;
- m_ownsAttr = FALSE;
+ m_ownsAttr = false;
// We don't know the height here yet.
m_width = 0;
tree->SendDeleteEvent(child);
child->DeleteChildren(tree);
+ if (child == tree->m_select_me)
+ tree->m_select_me = NULL;
delete child;
}
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) &&
+ if ((point.x > xCross-6) && (point.x < xCross+6) &&
+ (point.y > y_mid-6) && (point.y < y_mid+6) &&
HasPlus() && theCtrl->HasButtons() )
#endif
{
EVT_CHAR (wxGenericTreeCtrl::OnChar)
EVT_SET_FOCUS (wxGenericTreeCtrl::OnSetFocus)
EVT_KILL_FOCUS (wxGenericTreeCtrl::OnKillFocus)
+ EVT_TREE_ITEM_GETTOOLTIP(wxID_ANY, 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.
void wxGenericTreeCtrl::Init()
{
m_current = m_key_current = m_anchor = m_select_me = (wxGenericTreeItem *) NULL;
- m_hasFocus = FALSE;
- m_dirty = FALSE;
+ m_hasFocus = false;
+ m_dirty = false;
m_lineHeight = 10;
m_indent = 15;
m_imageListNormal = m_imageListButtons =
m_imageListState = (wxImageList *) NULL;
m_ownsImageListNormal = m_ownsImageListButtons =
- m_ownsImageListState = FALSE;
+ m_ownsImageListState = false;
m_dragCount = 0;
- m_isDragging = FALSE;
- m_dropTarget = m_oldSelection = (wxGenericTreeItem *)NULL;
+ m_isDragging = false;
+ m_dropTarget = m_oldSelection = NULL;
+ m_underMouse = NULL;
m_textCtrl = NULL;
m_renameTimer = NULL;
+ m_freezeCount = 0;
+
m_findTimer = NULL;
- m_lastOnSame = FALSE;
+ m_dropEffectAboveItem = false;
+
+ m_lastOnSame = false;
+#ifdef __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(),
SetValidator( validator );
#endif
- SetForegroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
- SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX) );
+ wxVisualAttributes attr = GetDefaultAttributes();
+ SetOwnForegroundColour( attr.colFg );
+ SetOwnBackgroundColour( attr.colBg );
+ if (!m_hasFont)
+ SetOwnFont(attr.font);
// m_dottedPen = wxPen( "grey", 0, wxDOT ); too slow under XFree86
m_dottedPen = wxPen( wxT("grey"), 0, 0 );
- return TRUE;
+ SetBestSize(size);
+
+ return true;
}
wxGenericTreeCtrl::~wxGenericTreeCtrl()
size_t wxGenericTreeCtrl::GetCount() const
{
- return m_anchor == NULL ? 0u : m_anchor->GetChildrenCount();
+ if ( !m_anchor )
+ {
+ // the tree is empty
+ return 0;
+ }
+
+ size_t count = m_anchor->GetChildrenCount();
+ if ( !HasFlag(wxTR_HIDE_ROOT) )
+ {
+ // take the root itself into account
+ count++;
+ }
+
+ return count;
}
void wxGenericTreeCtrl::SetIndent(unsigned int indent)
{
m_indent = (unsigned short) indent;
- m_dirty = TRUE;
+ m_dirty = true;
}
void wxGenericTreeCtrl::SetSpacing(unsigned int spacing)
{
m_spacing = (unsigned short) spacing;
- m_dirty = 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") );
// want to update the inherited styles, but right now
// none of the parents has updatable styles
m_windowStyle = styles;
- m_dirty = TRUE;
+ m_dirty = true;
}
// -----------------------------------------------------------------------------
wxString wxGenericTreeCtrl::GetItemText(const wxTreeItemId& item) const
{
- wxCHECK_MSG( item.IsOk(), wxT(""), wxT("invalid tree item") );
+ wxCHECK_MSG( item.IsOk(), wxEmptyString, wxT("invalid tree item") );
return ((wxGenericTreeItem*) item.m_pItem)->GetText();
}
{
wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+ if (data)
+ data->SetId( item );
+
((wxGenericTreeItem*) item.m_pItem)->SetData(data);
}
}
}
+void wxGenericTreeCtrl::SetItemDropHighlight(const wxTreeItemId& item,
+ bool highlight)
+{
+ wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+ wxColour fg, bg;
+
+ if (highlight)
+ {
+ bg = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
+ fg = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
+ }
+
+ wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem;
+ pItem->Attr().SetTextColour(fg);
+ pItem->Attr().SetBackgroundColour(bg);
+ RefreshLine(pItem);
+}
+
void wxGenericTreeCtrl::SetItemTextColour(const wxTreeItemId& item,
const wxColour& col)
{
m_normalFont.GetFaceName(),
m_normalFont.GetEncoding());
- return TRUE;
+ return true;
}
bool wxGenericTreeCtrl::IsVisible(const wxTreeItemId& item) const
{
- wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+ wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
// An item is only visible if it's not a descendant of a collapsed item
wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem;
while (parent)
{
if (!parent->IsExpanded())
- return FALSE;
+ return false;
parent = parent->GetParent();
}
wxRect rect;
if (!GetBoundingRect(item, rect))
- return FALSE;
+ return false;
if (rect.GetWidth() == 0 || rect.GetHeight() == 0)
- return FALSE;
+ return false;
if (rect.GetBottom() < 0 || rect.GetTop() > clientSize.y)
- return FALSE;
+ return false;
if (rect.GetRight() < 0 || rect.GetLeft() > clientSize.x)
- return FALSE;
+ return false;
- return TRUE;
+ return true;
}
bool wxGenericTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const
{
- wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+ wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
// 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
bool wxGenericTreeCtrl::IsExpanded(const wxTreeItemId& item) const
{
- wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+ wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
return ((wxGenericTreeItem*) item.m_pItem)->IsExpanded();
}
bool wxGenericTreeCtrl::IsSelected(const wxTreeItemId& item) const
{
- wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+ wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
return ((wxGenericTreeItem*) item.m_pItem)->IsSelected();
}
bool wxGenericTreeCtrl::IsBold(const wxTreeItemId& item) const
{
- wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+ wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
return ((wxGenericTreeItem*) item.m_pItem)->IsBold();
}
// called by wxTextTreeCtrl when it marks itself for deletion
void wxGenericTreeCtrl::ResetTextControl()
{
- m_textCtrl = NULL;
+ m_textCtrl = NULL;
}
// find the first item starting with the given prefix after the given item
return AddRoot(text, image, selImage, data);
}
- m_dirty = TRUE; // do this first so stuff below doesn't cause flicker
+ m_dirty = true; // do this first so stuff below doesn't cause flicker
wxGenericTreeItem *item =
new wxGenericTreeItem( parent, text, image, selImage, data );
{
wxCHECK_MSG( !m_anchor, wxTreeItemId(), wxT("tree can have only one root") );
- m_dirty = TRUE; // do this first so stuff below doesn't cause flicker
+ m_dirty = true; // do this first so stuff below doesn't cause flicker
m_anchor = new wxGenericTreeItem((wxGenericTreeItem *)NULL, text,
image, selImage, data);
if (!HasFlag(wxTR_MULTIPLE))
{
m_current = m_key_current = m_anchor;
- m_current->SetHilight( TRUE );
+ m_current->SetHilight( true );
}
return m_anchor;
ProcessEvent( event );
}
+// Don't leave edit or selection on a child which is about to disappear
+void wxGenericTreeCtrl::ChildrenClosing(wxGenericTreeItem* item)
+{
+ if (m_textCtrl != NULL && item != m_textCtrl->item() && IsDescendantOf(item, m_textCtrl->item())) {
+ m_textCtrl->StopEditing();
+ }
+ if (item != m_key_current && IsDescendantOf(item, m_key_current)) {
+ m_key_current = NULL;
+ }
+ if (IsDescendantOf(item, m_select_me)) {
+ m_select_me = item;
+ }
+ if (item != m_current && IsDescendantOf(item, m_current)) {
+ m_current->SetHilight( false );
+ m_current = NULL;
+ m_select_me = item;
+ }
+}
+
void wxGenericTreeCtrl::DeleteChildren(const wxTreeItemId& itemId)
{
- m_dirty = TRUE; // do this first so stuff below doesn't cause flicker
+ m_dirty = true; // do this first so stuff below doesn't cause flicker
wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
+ ChildrenClosing(item);
item->DeleteChildren(this);
}
void wxGenericTreeCtrl::Delete(const wxTreeItemId& itemId)
{
- m_dirty = TRUE; // do this first so stuff below doesn't cause flicker
+ m_dirty = true; // do this first so stuff below doesn't cause flicker
wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
+ if (m_textCtrl != NULL && IsDescendantOf(item, m_textCtrl->item()))
+ {
+ // can't delete the item being edited, cancel editing it first
+ m_textCtrl->StopEditing();
+ }
+
wxGenericTreeItem *parent = item->GetParent();
// don't keep stale pointers around!
// Don't silently change the selection:
// do it properly in idle time, so event
// handlers get called.
-
+
// m_key_current = parent;
m_key_current = NULL;
}
// Don't silently change the selection:
// do it properly in idle time, so event
// handlers get called.
-
+
// m_current = parent;
m_current = NULL;
m_select_me = parent;
// and delete all of its children and the item itself now
item->DeleteChildren(this);
SendDeleteEvent(item);
+
+ if (item == m_select_me)
+ m_select_me = NULL;
+
delete item;
}
return;
}
+ ChildrenClosing(item);
item->Collapse();
#if 0 // TODO why should items be collapsed recursively?
{
if (m_current)
{
- m_current->SetHilight( FALSE );
+ m_current->SetHilight( false );
RefreshLine( m_current );
m_current = NULL;
{
if (item->IsSelected())
{
- item->SetHilight(FALSE);
+ item->SetHilight(false);
RefreshLine(item);
}
size_t count = children.Count();
for (size_t n=(size_t)(index+1); n<count; ++n)
{
- if (TagAllChildrenUntilLast(children[n], last_item, select)) return TRUE;
+ if (TagAllChildrenUntilLast(children[n], last_item, select)) return true;
}
return TagNextChildren(parent, last_item, select);
RefreshLine(crt_item);
if (crt_item==last_item)
- return TRUE;
+ return true;
if (crt_item->HasChildren())
{
for ( size_t n = 0; n < count; ++n )
{
if (TagAllChildrenUntilLast(children[n], last_item, select))
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
void wxGenericTreeCtrl::SelectItemRange(wxGenericTreeItem *item1, wxGenericTreeItem *item2)
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") );
m_select_me = NULL;
-
+
bool is_single=!(GetWindowStyleFlag() & wxTR_MULTIPLE);
wxGenericTreeItem *item = (wxGenericTreeItem*) itemId.m_pItem;
{
if (item->IsSelected())
return; // nothing to do
- unselect_others = TRUE;
- extended_select = FALSE;
+ unselect_others = true;
+ extended_select = false;
}
else if ( unselect_others && item->IsSelected() )
{
}
else
{
- bool select=TRUE; // the default
+ bool select = true; // the default
// Check if we need to toggle hilight (ctrl mode)
if (!unselect_others)
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
wxArrayGenericTreeItems& children = item->GetChildren();
if ( children.Count() > 1 )
{
- m_dirty = TRUE;
+ m_dirty = true;
s_treeBeingSorted = this;
children.Sort(tree_ctrl_compare_func);
{
if (m_ownsImageListNormal) delete m_imageListNormal;
m_imageListNormal = imageList;
- m_ownsImageListNormal = FALSE;
- m_dirty = TRUE;
+ m_ownsImageListNormal = 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)
{
if (m_ownsImageListState) delete m_imageListState;
m_imageListState = imageList;
- m_ownsImageListState = FALSE;
+ m_ownsImageListState = false;
}
void wxGenericTreeCtrl::SetButtonsImageList(wxImageList *imageList)
{
if (m_ownsImageListButtons) delete m_imageListButtons;
m_imageListButtons = imageList;
- m_ownsImageListButtons = FALSE;
- m_dirty = TRUE;
+ m_ownsImageListButtons = false;
+ m_dirty = true;
CalculateLineHeight();
}
void wxGenericTreeCtrl::AssignImageList(wxImageList *imageList)
{
SetImageList(imageList);
- m_ownsImageListNormal = TRUE;
+ m_ownsImageListNormal = true;
}
void wxGenericTreeCtrl::AssignStateImageList(wxImageList *imageList)
{
SetStateImageList(imageList);
- m_ownsImageListState = TRUE;
+ m_ownsImageListState = true;
}
void wxGenericTreeCtrl::AssignButtonsImageList(wxImageList *imageList)
{
SetButtonsImageList(imageList);
- m_ownsImageListButtons = TRUE;
+ m_ownsImageListButtons = true;
}
// -----------------------------------------------------------------------------
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
);
}
}
if (HasButtons()) y_mid += 5;
// Only draw the portion of the line that is visible, in case it is huge
- wxCoord xOrigin=0, yOrigin=0, width, height;
+ wxCoord xOrigin=0, yOrigin=0, width, height;
dc.GetDeviceOrigin(&xOrigin, &yOrigin);
yOrigin = abs(yOrigin);
GetClientSize(&width, &height);
{
// draw a line under the drop target because the item will be
// dropped there
- DrawLine(item, TRUE /* below */);
+ DrawLine(item, !m_dropEffectAboveItem );
}
SetCursor(wxCURSOR_BULLSEYE);
}
// -----------------------------------------------------------------------------
-// wxWindows callbacks
+// wxWidgets callbacks
// -----------------------------------------------------------------------------
void wxGenericTreeCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) )
void wxGenericTreeCtrl::OnSetFocus( wxFocusEvent &event )
{
- m_hasFocus = TRUE;
+ m_hasFocus = true;
RefreshSelected();
void wxGenericTreeCtrl::OnKillFocus( wxFocusEvent &event )
{
- m_hasFocus = FALSE;
+ m_hasFocus = false;
RefreshSelected();
bool is_multiple, extended_select, unselect_others;
EventFlagsToSelType(GetWindowStyleFlag(),
event.ShiftDown(),
- event.ControlDown(),
+ event.CmdDown(),
is_multiple, extended_select, unselect_others);
// + : Expand
}
break;
+ case WXK_MENU:
+ {
+ wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_MENU, GetId() );
+ event.m_item = m_current;
+ event.SetEventObject( this );
+ GetEventHandler()->ProcessEvent( event );
+ break;
+ }
case ' ':
case WXK_RETURN:
if ( !event.HasModifiers() )
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;
}
}
// it may happen if the item was expanded but then all of
// its children have been deleted - so IsExpanded() returned
- // TRUE, but GetLastChild() returned invalid item
+ // true, but GetLastChild() returned invalid item
if ( !lastChild )
break;
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;
(keyCode >= 'A' && keyCode <= 'Z' )))
{
// find the next item starting with the given prefix
- char ch = (char)keyCode;
+ wxChar ch = (wxChar)keyCode;
- wxTreeItemId id = FindItem(m_current, m_findPrefix + (wxChar)ch);
+ wxTreeItemId id = FindItem(m_current, m_findPrefix + ch);
if ( !id.IsOk() )
{
// no such item
wxRect& rect,
bool WXUNUSED(textOnly)) const
{
- wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid item in wxGenericTreeCtrl::GetBoundingRect") );
+ wxCHECK_MSG( item.IsOk(), false, _T("invalid item in wxGenericTreeCtrl::GetBoundingRect") );
wxGenericTreeItem *i = (wxGenericTreeItem*) item.m_pItem;
//rect.height = i->GetHeight();
rect.height = GetLineHeight(i);
- return TRUE;
+ return true;
}
void wxGenericTreeCtrl::Edit( const wxTreeItemId& item )
// 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);
le.m_item = item;
le.SetEventObject( this );
le.m_label = value;
- le.m_editCancelled = FALSE;
+ le.m_editCancelled = false;
return !GetEventHandler()->ProcessEvent( le ) || le.IsAllowed();
}
le.m_item = item;
le.SetEventObject( this );
le.m_label = wxEmptyString;
- le.m_editCancelled = TRUE;
+ le.m_editCancelled = true;
GetEventHandler()->ProcessEvent( le );
}
-
-
-
void wxGenericTreeCtrl::OnRenameTimer()
{
Edit( m_current );
{
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 )
wxTreeEvent nevent( command, GetId() );
nevent.m_item = m_current;
nevent.SetEventObject(this);
+ nevent.SetPoint(pt);
// by default the dragging is not supported, the user code must
// explicitly allow the event for it to take place
if ( GetEventHandler()->ProcessEvent(nevent) && nevent.IsAllowed() )
{
// we're going to drag this item
- m_isDragging = TRUE;
+ m_isDragging = true;
// remember the old cursor because we will change it while
// dragging
if ( m_oldSelection )
{
- m_oldSelection->SetHilight(FALSE);
+ m_oldSelection->SetHilight(false);
RefreshLine(m_oldSelection);
}
}
CaptureMouse();
}
}
- else if ( event.Moving() )
+ else if ( event.Dragging() )
{
if ( item != m_dropTarget )
{
// highlight the current drop target if any
DrawDropEffect(m_dropTarget);
+#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXGTK20__)
+ Update();
+#else
wxYieldIfNeeded();
+#endif
}
}
else if ( (event.LeftUp() || event.RightUp()) && m_isDragging )
if ( m_oldSelection )
{
- m_oldSelection->SetHilight(TRUE);
+ m_oldSelection->SetHilight(true);
RefreshLine(m_oldSelection);
m_oldSelection = (wxGenericTreeItem *)NULL;
}
(void)GetEventHandler()->ProcessEvent(event);
- m_isDragging = FALSE;
+ m_isDragging = false;
m_dropTarget = (wxGenericTreeItem *)NULL;
ReleaseMouse();
SetCursor(m_oldCursor);
+#if defined( __WXMSW__ ) || defined(__WXMAC__)
+ Update();
+#else
wxYieldIfNeeded();
+#endif
}
else
{
+ // If we got to this point, we are not dragging or moving the mouse.
+ // Because the code in carbon/toplevel.cpp will only set focus to the tree
+ // if we skip for EVT_LEFT_DOWN, we MUST skip this event here for focus to work.
+ // We skip even if we didn't hit an item because we still should
+ // restore focus to the tree control even if we didn't exactly hit an item.
+ if ( event.LeftDown() )
+ {
+ event.Skip();
+ }
+
// here we process only the messages which happen on tree items
m_dragCount = 0;
if ( event.RightDown() )
{
+ // If the item is already selected, do not update the selection.
+ // Multi-selections should not be cleared if a selected item is clicked.
+ if (!IsSelected(item))
+ {
+ DoSelectItem(item, true, false);
+ }
+
wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, GetId());
nevent.m_item = item;
nevent.m_pointDrag = CalcScrolledPosition(pt);
nevent.SetEventObject(this);
- GetEventHandler()->ProcessEvent(nevent);
+ event.Skip(!GetEventHandler()->ProcessEvent(nevent));
}
else if ( event.LeftUp() )
{
size_t count = GetSelections(selections);
if (count > 1 &&
- !event.ControlDown() &&
+ !event.CmdDown() &&
!event.ShiftDown())
{
- SelectItem(item, true, false);
+ DoSelectItem(item, true, false);
}
}
m_renameTimer = new wxTreeRenameTimer( this );
}
- m_renameTimer->Start( wxTreeRenameTimer::DELAY, TRUE );
+ m_renameTimer->Start( wxTreeRenameTimer::DELAY, true );
}
- m_lastOnSame = FALSE;
+ m_lastOnSame = false;
}
}
else // !RightDown() && !LeftUp() ==> LeftDown() || LeftDClick()
// 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))
+ // but if Cmd is down, toggle selection of the clicked item
+ if (!IsSelected(item) || event.CmdDown())
{
// how should the selection work for this event?
bool is_multiple, extended_select, unselect_others;
EventFlagsToSelType(GetWindowStyleFlag(),
event.ShiftDown(),
- event.ControlDown(),
+ event.CmdDown(),
is_multiple, extended_select, unselect_others);
- SelectItem(item, unselect_others, extended_select);
+ DoSelectItem(item, unselect_others, extended_select);
}
if ( m_renameTimer )
m_renameTimer->Stop();
- m_lastOnSame = FALSE;
+ m_lastOnSame = false;
// send activate event first
wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, GetId() );
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
* we actually redraw the tree when everything is over */
if (!m_dirty) return;
+ if (m_freezeCount) return;
- m_dirty = FALSE;
+ m_dirty = false;
CalculatePositions();
Refresh();
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();
rect.width = client.x;
rect.height = client.y;
- Refresh(TRUE, &rect);
+ Refresh(true, &rect);
AdjustMyScrollbars();
}
void wxGenericTreeCtrl::RefreshLine( wxGenericTreeItem *item )
{
if (m_dirty) return;
+ if (m_freezeCount) return;
wxRect rect;
CalcScrolledPosition(0, item->GetY(), NULL, &rect.y);
rect.width = GetClientSize().x;
rect.height = GetLineHeight(item); //dc.GetCharHeight() + 6;
- Refresh(TRUE, &rect);
+ Refresh(true, &rect);
}
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
// ----------------------------------------------------------------------------
bool wxGenericTreeCtrl::SetBackgroundColour(const wxColour& colour)
{
if ( !wxWindow::SetBackgroundColour(colour) )
- return FALSE;
+ return false;
+
+ if (m_freezeCount) return true;
Refresh();
- return TRUE;
+ return true;
}
bool wxGenericTreeCtrl::SetForegroundColour(const wxColour& colour)
{
if ( !wxWindow::SetForegroundColour(colour) )
- return FALSE;
+ return false;
+
+ if (m_freezeCount) return true;
Refresh();
- return TRUE;
+ return true;
+}
+
+// Process the tooltip event, to speed up event processing.
+// Doesn't actually get a tooltip.
+void wxGenericTreeCtrl::OnGetToolTip( wxTreeEvent &event )
+{
+ event.Veto();
+}
+
+
+wxSize wxGenericTreeCtrl::DoGetBestSize() const
+{
+ // something is better than nothing...
+ // 100x80 is what the MSW version will get from the default
+ // wxControl::DoGetBestSize
+ return wxSize(100,80);
+}
+
+
+// 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
}
+#if WXWIN_COMPATIBILITY_2_4
+
+int wxGenericTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const
+{
+ return GetItemImage(item, wxTreeItemIcon_Selected);
+}
+
+void wxGenericTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image)
+{
+ SetItemImage(item, image, wxTreeItemIcon_Selected);
+}
+
+#endif // WXWIN_COMPATIBILITY_2_4
+
+#if WXWIN_COMPATIBILITY_2_2
+
+wxTreeItemId wxGenericTreeCtrl::GetParent(const wxTreeItemId& item) const
+{
+ return GetItemParent( item );
+}
+
+#endif // WXWIN_COMPATIBILITY_2_2
+
#endif // wxUSE_TREECTRL