wxTreeFindTimer( wxGenericTreeCtrl *owner ) { m_owner = owner; }
- virtual void Notify() { m_owner->m_findPrefix.clear(); }
+ virtual void Notify() { m_owner->ResetFindState(); }
private:
wxGenericTreeCtrl *m_owner;
END_EVENT_TABLE()
wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner,
- wxGenericTreeItem *item)
- : m_itemEdited(item), m_startValue(item->GetText())
+ wxGenericTreeItem *itm)
+ : m_itemEdited(itm), m_startValue(itm->GetText())
{
m_owner = owner;
m_aboutToFinish = false;
(void)Create(m_owner, wxID_ANY, m_startValue,
rect.GetPosition(), rect.GetSize());
- SetSelection(-1, -1);
+ SelectAll();
}
void wxTreeTextCtrl::EndEdit(bool discardChanges)
m_renameTimer = NULL;
m_findTimer = NULL;
+ m_findBell = 0; // default is to not ring bell at all
m_dropEffectAboveItem = false;
#endif
if ( !wxControl::Create( parent, id, pos, size,
- style|wxHSCROLL|wxVSCROLL,
+ style|wxHSCROLL|wxVSCROLL|wxWANTS_CHARS,
validator,
name ) )
return false;
delete m_imageListButtons;
}
+void wxGenericTreeCtrl::EnableBellOnNoMatch( bool on )
+{
+ m_findBell = on;
+}
+
// -----------------------------------------------------------------------------
// accessors
// -----------------------------------------------------------------------------
m_textCtrl = NULL;
}
+void wxGenericTreeCtrl::ResetFindState()
+{
+ m_findPrefix.clear();
+ if ( m_findBell )
+ m_findBell = 1;
+}
+
// find the first item starting with the given prefix after the given item
wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent,
const wxString& prefixOrig) const
{
itemid = GetNext(itemid);
}
- // If we haven't found the item, id.IsOk() will be false, as per
- // documentation
+ // If we haven't found the item but wrapped back to the one we started
+ // from, id.IsOk() must be false
+ if ( itemid == idParent )
+ {
+ itemid = wxTreeItemId();
+ }
}
return itemid;
// update the control before scrolling it
if (m_dirty)
-#if defined( __WXMSW__ ) || defined(__WXMAC__)
+ {
+#if defined( __WXMSW__ )
Update();
+#elif defined(__WXMAC__)
+ Update();
+ DoDirtyProcessing();
#else
DoDirtyProcessing();
#endif
-
+ }
+
wxGenericTreeItem *gitem = (wxGenericTreeItem*) item.m_pItem;
int itemY = gitem->GetY();
{
// need to scroll up by enough to show this item fully
itemY += itemHeight - clientHeight;
+#ifdef __WXOSX__
+ // because itemY below will be divided by PIXELS_PER_UNIT it may
+ // be rounded down, with the result of the item still only being
+ // partially visible, so make sure we are rounding up
+ itemY += PIXELS_PER_UNIT-1;
+#endif
}
else if ( itemY > start_y*PIXELS_PER_UNIT )
{
yOrigin = abs(yOrigin);
GetClientSize(&width, &height);
- // Move end points to the begining/end of the view?
+ // Move end points to the beginning/end of the view?
if (y_mid < yOrigin)
y_mid = yOrigin;
if (oldY > yOrigin + height)
if ( !event.HasModifiers() &&
((keyCode >= '0' && keyCode <= '9') ||
(keyCode >= 'a' && keyCode <= 'z') ||
- (keyCode >= 'A' && keyCode <= 'Z' )))
+ (keyCode >= 'A' && keyCode <= 'Z') ||
+ (keyCode == '_')))
{
// find the next item starting with the given prefix
wxChar ch = (wxChar)keyCode;
+ wxTreeItemId id;
- wxTreeItemId id = FindItem(m_current, m_findPrefix + ch);
- if ( !id.IsOk() )
+ // if the same character is typed multiple times then go to the
+ // next entry starting with that character instead of searching
+ // for an item starting with multiple copies of this character,
+ // this is more useful and is how it works under Windows.
+ if ( m_findPrefix.length() == 1 && m_findPrefix[0] == ch )
{
- // no such item
- break;
+ id = FindItem(m_current, ch);
+ }
+ else
+ {
+ const wxString newPrefix(m_findPrefix + ch);
+ id = FindItem(m_current, newPrefix);
+ if ( id.IsOk() )
+ m_findPrefix = newPrefix;
}
-
- SelectItem(id);
-
- m_findPrefix += ch;
// also start the timer to reset the current prefix if the user
// doesn't press any more alnum keys soon -- we wouldn't want
m_findTimer = new wxTreeFindTimer(this);
}
+ // Notice that we should start the timer even if we didn't find
+ // anything to make sure we reset the search state later.
m_findTimer->Start(wxTreeFindTimer::DELAY, wxTIMER_ONE_SHOT);
+
+ if ( id.IsOk() )
+ {
+ SelectItem(id);
+
+ // Reset the bell flag if it had been temporarily disabled
+ // before.
+ if ( m_findBell )
+ m_findBell = 1;
+ }
+ else // No such item
+ {
+ // Signal it with a bell if enabled.
+ if ( m_findBell == 1 )
+ {
+ ::wxBell();
+
+ // Disable it for the next unsuccessful match, we only
+ // beep once, this is usually enough and continuing to
+ // do it would be annoying.
+ m_findBell = -1;
+ }
+ }
}
else
{
// question might just have been added and no screen
// update taken place.
if ( m_dirty )
-#if defined( __WXMSW__ ) || defined(__WXMAC__)
- Update();
-#else
DoDirtyProcessing();
-#endif
// TODO: use textCtrlClass here to create the control of correct class
m_textCtrl = new wxTreeTextCtrl(this, itemEdit);
wxTreeEvent
hevent(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, this, hoverItem);
- if ( GetEventHandler()->ProcessEvent(hevent) && hevent.IsAllowed() )
+ if ( GetEventHandler()->ProcessEvent(hevent) )
{
- SetToolTip(hevent.m_label);
+ // If the user permitted the tooltip change, update it, otherwise
+ // remove any old tooltip we might have.
+ if ( hevent.IsAllowed() )
+ SetToolTip(hevent.m_label);
+ else
+ SetToolTip(NULL);
}
}
#endif
// ==> LeftDown() || LeftDClick()
if ( event.LeftDown() )
{
- m_lastOnSame = item == m_current;
+ // If we click on an already selected item but do it to return
+ // the focus to the control, it shouldn't start editing the
+ // item label because it's too easy to start editing
+ // accidentally (and also because nobody else does it like
+ // this). So only set this flag, used to decide whether we
+ // should start editing the label later, if we already have
+ // focus.
+ m_lastOnSame = item == m_current && HasFocus();
}
if ( flags & wxTREE_HITTEST_ONITEMBUTTON )
return true;
}
-// Process the tooltip event, to speed up event processing.
-// Doesn't actually get a tooltip.
void wxGenericTreeCtrl::OnGetToolTip( wxTreeEvent &event )
{
- event.Veto();
+#if wxUSE_TOOLTIPS
+ wxTreeItemId itemId = event.GetItem();
+ const wxGenericTreeItem* const pItem = (wxGenericTreeItem*)itemId.m_pItem;
+
+ // Check if the item fits into the client area:
+ if ( pItem->GetX() + pItem->GetWidth() > GetClientSize().x )
+ {
+ // If it doesn't, show its full text in the tooltip.
+ event.SetLabel(pItem->GetText());
+ }
+ else
+#endif // wxUSE_TOOLTIPS
+ {
+ // veto processing the event, nixing any tooltip
+ event.Veto();
+ }
}