// Created: 01/02/97
// Modified: 22/10/98 - almost total rewrite, simpler interface (VZ)
// Id: $Id$
-// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
+// Copyright: (c) 1998 Robert Roebling and Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/settings.h"
#include "wx/dcclient.h"
+#ifdef __WXMAC__
+ #include "wx/mac/private.h"
+#endif
+
// -----------------------------------------------------------------------------
// array types
// -----------------------------------------------------------------------------
private:
wxGenericTreeCtrl *m_owner;
+
+ DECLARE_NO_COPY_CLASS(wxTreeRenameTimer)
};
// control used for in-place edit
bool m_finished;
DECLARE_EVENT_TABLE()
+ DECLARE_NO_COPY_CLASS(wxTreeTextCtrl)
};
// timer used to clear wxGenericTreeCtrl::m_findPrefix if no key was pressed
private:
wxGenericTreeCtrl *m_owner;
+
+ DECLARE_NO_COPY_CLASS(wxTreeFindTimer)
};
// a tree item
short m_images[wxTreeItemIcon_Max];
wxCoord m_x; // (virtual) offset from top
- short m_y; // (virtual) offset from left
+ wxCoord m_y; // (virtual) offset from left
short m_width; // width of this item
unsigned char m_height; // height of this item
// children but has a [+] button
int m_isBold :1; // render the label in bold font
int m_ownsAttr :1; // delete attribute when done
+
+ DECLARE_NO_COPY_CLASS(wxGenericTreeItem)
};
// =============================================================================
{
if ( !m_finished )
{
+ m_owner->ResetTextControl();
+
wxPendingDelete.Append(this);
m_finished = TRUE;
void wxGenericTreeCtrl::Init()
{
- m_current = m_key_current = m_anchor = (wxGenericTreeItem *) NULL;
+ m_current = m_key_current = m_anchor = m_select_me = (wxGenericTreeItem *) NULL;
m_hasFocus = FALSE;
m_dirty = FALSE;
m_dragCount = 0;
m_isDragging = FALSE;
m_dropTarget = m_oldSelection = (wxGenericTreeItem *)NULL;
+ m_textCtrl = NULL;
m_renameTimer = NULL;
m_findTimer = NULL;
// navigation
// -----------------------------------------------------------------------------
-wxTreeItemId wxGenericTreeCtrl::GetParent(const wxTreeItemId& item) const
+wxTreeItemId wxGenericTreeCtrl::GetItemParent(const wxTreeItemId& item) const
{
wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
do
{
toFind = GetNextSibling(p);
- p = GetParent(p);
+ p = GetItemParent(p);
} while (p.IsOk() && !toFind.IsOk());
return toFind;
}
return wxTreeItemId();
}
+// called by wxTextTreeCtrl when it marks itself for deletion
+void wxGenericTreeCtrl::ResetTextControl()
+{
+ m_textCtrl = NULL;
+}
+
// find the first item starting with the given prefix after the given item
wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent,
const wxString& prefixOrig) const
// don't keep stale pointers around!
if ( IsDescendantOf(item, m_key_current) )
{
- m_key_current = parent;
+ // 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;
+ }
+
+ // m_select_me records whether we need to select
+ // a different item, in idle time.
+ if ( m_select_me && IsDescendantOf(item, m_select_me) )
+ {
+ m_select_me = parent;
}
if ( IsDescendantOf(item, m_current) )
{
- m_current = parent;
+ // 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;
}
// remove the item from the tree
RefreshLine( m_current );
m_current = NULL;
+ m_select_me = NULL;
}
}
{
// item2 is not necessary after item1
wxGenericTreeItem *first=NULL, *last=NULL;
+ m_select_me = NULL;
// choice first' and 'last' between item1 and item2
if (item1->GetY()<item2->GetY())
{
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 ( GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed() )
return;
- wxTreeItemId parent = GetParent( itemId );
+ wxTreeItemId parent = GetItemParent( itemId );
while (parent.IsOk())
{
if (!IsExpanded(parent))
Expand( parent );
- parent = GetParent( parent );
+ parent = GetItemParent( parent );
}
EnsureVisible( itemId );
if ( item->IsSelected() )
{
+// under mac selections are only a rectangle in case they don't have the focus
+#ifdef __WXMAC__
+ if ( !m_hasFocus )
+ {
+ dc.SetBrush( *wxTRANSPARENT_BRUSH ) ;
+ dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) , 1 , wxSOLID ) ) ;
+ }
+ else
+ {
+ dc.SetBrush( *m_hilightBrush ) ;
+ }
+#else
dc.SetBrush(*(m_hasFocus ? m_hilightBrush : m_hilightUnfocusedBrush));
+#endif
}
else
{
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
{
// draw line down to last child
oldY += GetLineHeight(children[n-1])>>1;
if (HasButtons()) y_mid += 5;
- dc.DrawLine(x, y_mid, x, oldY);
+
+ // Only draw the portion of the line that is visible, in case it is huge
+ wxCoord xOrigin=0, yOrigin=0, width, height;
+ dc.GetDeviceOrigin(&xOrigin, &yOrigin);
+ yOrigin = abs(yOrigin);
+ GetClientSize(&width, &height);
+
+ // Move end points to the begining/end of the view?
+ if (y_mid < yOrigin)
+ y_mid = yOrigin;
+ if (oldY > yOrigin + height)
+ oldY = yOrigin + height;
+
+ // after the adjustments if y_mid is larger than oldY then the line
+ // isn't visible at all so don't draw anything
+ if (y_mid < oldY)
+ dc.DrawLine(x, y_mid, x, oldY);
}
}
}
// home : go to root
// end : go to last item without opening parents
// alnum : start or continue searching for the item with this prefix
- int keyCode = event.KeyCode();
+ int keyCode = event.GetKeyCode();
switch ( keyCode )
{
case '+':
wxTreeItemId prev = GetPrevSibling( m_key_current );
if (!prev)
{
- prev = GetParent( m_key_current );
+ prev = GetItemParent( m_key_current );
if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT))
{
break; // don't go to root if it is hidden
// left arrow goes to the parent
case WXK_LEFT:
{
- wxTreeItemId prev = GetParent( m_current );
+ wxTreeItemId prev = GetItemParent( m_current );
if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT))
{
// don't go to root if it is hidden
wxTreeItemId current = m_key_current;
while (current && !next)
{
- current = GetParent( current );
+ current = GetItemParent( current );
if (current) next = GetNextSibling( current );
}
}
if ( m_dirty )
wxYieldIfNeeded();
- wxTreeTextCtrl *text = new wxTreeTextCtrl(this, itemEdit);
+ m_textCtrl = new wxTreeTextCtrl(this, itemEdit);
+
+ m_textCtrl->SetFocus();
+}
- text->SetFocus();
+// returns a pointer to the text edit control if the item is being
+// edited, NULL otherwise (it's assumed that no more than one item may
+// be edited simultaneously)
+wxTextCtrl* wxGenericTreeCtrl::GetEditControl() const
+{
+ return m_textCtrl;
}
bool wxGenericTreeCtrl::OnRenameAccept(wxGenericTreeItem *item,
void wxGenericTreeCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) )
{
+ // Check if we need to select the root item
+ // because nothing else has been selected.
+ // Delaying it means that we can invoke event handlers
+ // as required, when a first item is selected.
+ if (!HasFlag(wxTR_MULTIPLE) && !GetSelection().IsOk())
+ {
+ if (m_select_me)
+ SelectItem(m_select_me);
+ else if (GetRootItem().IsOk())
+ SelectItem(GetRootItem());
+ }
+
/* after all changes have been done to the tree control,
* we actually redraw the tree when everything is over */