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;
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 )
{
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);
// ==> 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 )