more bug fixes to multiple selection mode (see #626, comment 47)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59600 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
03ae811e42
commit
7dac12efa7
@ -270,6 +270,10 @@ private:
|
||||
|
||||
void DoExpand(const wxTreeItemId& item, int flag);
|
||||
|
||||
void DoSelectItem(const wxTreeItemId& item, bool select = true);
|
||||
void DoUnselectItem(const wxTreeItemId& item);
|
||||
void DoToggleItemSelection(const wxTreeItemId& item);
|
||||
|
||||
void DoUnselectAll();
|
||||
|
||||
void DeleteTextCtrl();
|
||||
@ -278,6 +282,9 @@ private:
|
||||
// and the tree has wxTR_HIDE_ROOT style)
|
||||
bool IsHiddenRoot(const wxTreeItemId& item) const;
|
||||
|
||||
// clears/sets the currently focused item
|
||||
void ClearFocusedItem();
|
||||
void SetFocusedItem(const wxTreeItemId& item);
|
||||
|
||||
// the hash storing the items attributes (indexed by item ids)
|
||||
wxMapTreeAttr m_attrs;
|
||||
@ -303,6 +310,10 @@ private:
|
||||
// whether focus was lost between subsequent clicks of a single item
|
||||
bool m_focusLost;
|
||||
|
||||
// set when we are changing selection ourselves (only used in multi
|
||||
// selection mode)
|
||||
bool m_changingSelection;
|
||||
|
||||
// whether we need to trigger a state image click event
|
||||
bool m_triggerStateImageClick;
|
||||
|
||||
|
@ -106,6 +106,30 @@ private:
|
||||
|
||||
HTREEITEM TreeItemUnlocker::ms_unlockedItem = NULL;
|
||||
|
||||
// another helper class: set the variable to true during its lifetime and reset
|
||||
// it to false when it is destroyed
|
||||
//
|
||||
// it is currently always used with wxTreeCtrl::m_changingSelection
|
||||
class TempSetter
|
||||
{
|
||||
public:
|
||||
TempSetter(bool& var) : m_var(var)
|
||||
{
|
||||
wxASSERT_MSG( !m_var, "variable shouldn't be already set" );
|
||||
m_var = true;
|
||||
}
|
||||
|
||||
~TempSetter()
|
||||
{
|
||||
m_var = false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool& m_var;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TempSetter);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -724,6 +748,7 @@ void wxTreeCtrl::Init()
|
||||
m_pVirtualRoot = NULL;
|
||||
m_dragStarted = false;
|
||||
m_focusLost = true;
|
||||
m_changingSelection = false;
|
||||
m_triggerStateImageClick = false;
|
||||
|
||||
// initialize the global array of events now as it can't be done statically
|
||||
@ -1622,10 +1647,13 @@ void wxTreeCtrl::Delete(const wxTreeItemId& item)
|
||||
}
|
||||
}
|
||||
|
||||
if ( !TreeView_DeleteItem(GetHwnd(), HITEM(item)) )
|
||||
{
|
||||
wxLogLastError(wxT("TreeView_DeleteItem"));
|
||||
return;
|
||||
TempSetter set(m_changingSelection);
|
||||
if ( !TreeView_DeleteItem(GetHwnd(), HITEM(item)) )
|
||||
{
|
||||
wxLogLastError(wxT("TreeView_DeleteItem"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !selected )
|
||||
@ -1644,8 +1672,8 @@ void wxTreeCtrl::Delete(const wxTreeItemId& item)
|
||||
}
|
||||
else
|
||||
{
|
||||
::SelectItem(GetHwnd(), HITEM(next), false);
|
||||
TreeView_SelectItem(GetHwnd(), 0);
|
||||
DoUnselectItem(next);
|
||||
ClearFocusedItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1787,7 +1815,7 @@ void wxTreeCtrl::Unselect()
|
||||
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
TreeView_SelectItem(GetHwnd(), 0);
|
||||
ClearFocusedItem();
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, wxTreeItemId());
|
||||
@ -1797,7 +1825,7 @@ void wxTreeCtrl::Unselect()
|
||||
}
|
||||
else
|
||||
{
|
||||
TreeView_SelectItem(GetHwnd(), 0);
|
||||
ClearFocusedItem();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1808,7 +1836,7 @@ void wxTreeCtrl::DoUnselectAll()
|
||||
|
||||
for ( size_t n = 0; n < count; n++ )
|
||||
{
|
||||
::UnselectItem(GetHwnd(), HITEM(selections[n]));
|
||||
DoUnselectItem(selections[n]);
|
||||
}
|
||||
|
||||
m_htSelStart.Unset();
|
||||
@ -1827,7 +1855,6 @@ void wxTreeCtrl::UnselectAll()
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
TreeView_SelectItem(GetHwnd(), 0);
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this);
|
||||
changedEvent.m_itemOld = htFocus;
|
||||
@ -1840,6 +1867,13 @@ void wxTreeCtrl::UnselectAll()
|
||||
}
|
||||
}
|
||||
|
||||
void wxTreeCtrl::DoSelectItem(const wxTreeItemId& item, bool select)
|
||||
{
|
||||
TempSetter set(m_changingSelection);
|
||||
|
||||
::SelectItem(GetHwnd(), HITEM(item), select);
|
||||
}
|
||||
|
||||
void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select)
|
||||
{
|
||||
wxCHECK_RET( !IsHiddenRoot(item), _T("can't select hidden root item") );
|
||||
@ -1856,11 +1890,11 @@ void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
HTREEITEM htFocus = (HTREEITEM)TreeView_GetSelection(GetHwnd());
|
||||
::SelectItem(GetHwnd(), HITEM(item), select);
|
||||
DoSelectItem(item, select);
|
||||
|
||||
if ( !htFocus )
|
||||
{
|
||||
::SetFocus(GetHwnd(), HITEM(item));
|
||||
SetFocusedItem(item);
|
||||
}
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
@ -1887,7 +1921,7 @@ void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select)
|
||||
}
|
||||
else // ok
|
||||
{
|
||||
::SetFocus(GetHwnd(), HITEM(item));
|
||||
SetFocusedItem(item);
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, item);
|
||||
@ -2029,6 +2063,37 @@ bool wxTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
|
||||
}
|
||||
}
|
||||
|
||||
void wxTreeCtrl::ClearFocusedItem()
|
||||
{
|
||||
TempSetter set(m_changingSelection);
|
||||
|
||||
if ( !TreeView_SelectItem(GetHwnd(), 0) )
|
||||
{
|
||||
wxLogLastError(wxT("TreeView_SelectItem"));
|
||||
}
|
||||
}
|
||||
|
||||
void wxTreeCtrl::SetFocusedItem(const wxTreeItemId& item)
|
||||
{
|
||||
TempSetter set(m_changingSelection);
|
||||
|
||||
::SetFocus(GetHwnd(), HITEM(item));
|
||||
}
|
||||
|
||||
void wxTreeCtrl::DoUnselectItem(const wxTreeItemId& item)
|
||||
{
|
||||
TempSetter set(m_changingSelection);
|
||||
|
||||
::UnselectItem(GetHwnd(), HITEM(item));
|
||||
}
|
||||
|
||||
void wxTreeCtrl::DoToggleItemSelection(const wxTreeItemId& item)
|
||||
{
|
||||
TempSetter set(m_changingSelection);
|
||||
|
||||
::ToggleItemSelection(GetHwnd(), HITEM(item));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// sorting stuff
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -2152,7 +2217,7 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
::ToggleItemSelection(GetHwnd(), htSel);
|
||||
DoToggleItemSelection(wxTreeItemId(htSel));
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, htSel);
|
||||
@ -2174,7 +2239,7 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
::SelectItem(GetHwnd(), htSel);
|
||||
DoSelectItem(wxTreeItemId(htSel));
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, htSel);
|
||||
@ -2190,10 +2255,9 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
if ( !bCtrl && !bShift )
|
||||
{
|
||||
wxArrayTreeItemIds selections;
|
||||
size_t count = GetSelections(selections);
|
||||
wxTreeItemId next;
|
||||
|
||||
if ( htSel && count > 0 )
|
||||
if ( htSel )
|
||||
{
|
||||
next = vkey == VK_UP
|
||||
? TreeView_GetPrevVisible(GetHwnd(), htSel)
|
||||
@ -2205,14 +2269,6 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
|
||||
if ( IsHiddenRoot(next) )
|
||||
next = TreeView_GetChild(GetHwnd(), HITEM(next));
|
||||
|
||||
if ( vkey == VK_DOWN )
|
||||
{
|
||||
wxTreeItemId next2 = TreeView_GetNextVisible(
|
||||
GetHwnd(), HITEM(next));
|
||||
if ( next2 )
|
||||
next = next2;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !next.IsOk() )
|
||||
@ -2227,8 +2283,8 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
::SelectItem(GetHwnd(), HITEM(next));
|
||||
::SetFocus(GetHwnd(), HITEM(next));
|
||||
DoSelectItem(next);
|
||||
SetFocusedItem(next);
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, next);
|
||||
@ -2269,7 +2325,7 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
}
|
||||
}
|
||||
|
||||
::SetFocus(GetHwnd(), HITEM(next));
|
||||
SetFocusedItem(next);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2291,8 +2347,8 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
::SelectItem(GetHwnd(), HITEM(next));
|
||||
::SetFocus(GetHwnd(), HITEM(next));
|
||||
DoSelectItem(next);
|
||||
SetFocusedItem(next);
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, next);
|
||||
@ -2326,8 +2382,8 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
::SelectItem(GetHwnd(), HITEM(next));
|
||||
::SetFocus(GetHwnd(), HITEM(next));
|
||||
DoSelectItem(next);
|
||||
SetFocusedItem(next);
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this, next);
|
||||
changedEvent.m_itemOld = htSel;
|
||||
@ -2386,7 +2442,7 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
SelectRange(GetHwnd(),
|
||||
HITEM(m_htSelStart), HITEM(next),
|
||||
SR_UNSELECT_OTHERS);
|
||||
::SetFocus(GetHwnd(), HITEM(next));
|
||||
SetFocusedItem(next);
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, next);
|
||||
@ -2404,8 +2460,8 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
::SelectItem(GetHwnd(), HITEM(next));
|
||||
::SetFocus(GetHwnd(), HITEM(next));
|
||||
DoSelectItem(next);
|
||||
SetFocusedItem(next);
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, next);
|
||||
@ -2507,8 +2563,8 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
|
||||
{
|
||||
DoUnselectAll();
|
||||
m_htSelStart.Unset();
|
||||
::SelectItem(GetHwnd(), HITEM(next));
|
||||
::SetFocus(GetHwnd(), HITEM(next));
|
||||
DoSelectItem(next);
|
||||
SetFocusedItem(next);
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, next);
|
||||
@ -2639,7 +2695,6 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
if ( !isMultiple )
|
||||
break;
|
||||
|
||||
processed = true;
|
||||
m_htClickedItem.Unset();
|
||||
|
||||
if ( !(tvht.flags & TVHT_ONITEM) )
|
||||
@ -2657,11 +2712,15 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
Collapse(htItem);
|
||||
}
|
||||
}
|
||||
|
||||
processed = true;
|
||||
}
|
||||
|
||||
m_focusLost = false;
|
||||
break;
|
||||
}
|
||||
|
||||
processed = true;
|
||||
SetFocus();
|
||||
m_htClickedItem = (WXHTREEITEM) htItem;
|
||||
m_ptClick = wxPoint(x, y);
|
||||
@ -2681,9 +2740,9 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
// toggle selected state
|
||||
::ToggleItemSelection(GetHwnd(), htItem);
|
||||
DoToggleItemSelection(wxTreeItemId(htItem));
|
||||
|
||||
::SetFocus(GetHwnd(), htItem);
|
||||
SetFocusedItem(wxTreeItemId(htItem));
|
||||
|
||||
// reset on any click without Shift
|
||||
m_htSelStart.Unset();
|
||||
@ -2738,10 +2797,10 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
}
|
||||
else
|
||||
{
|
||||
::SelectItem(GetHwnd(), htItem);
|
||||
DoSelectItem(wxTreeItemId(htItem));
|
||||
}
|
||||
|
||||
::SetFocus(GetHwnd(), htItem);
|
||||
SetFocusedItem(wxTreeItemId(htItem));
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, htItem);
|
||||
@ -2772,7 +2831,6 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
// clicked outside of the present selection, otherwise,
|
||||
// perform the deselection on mouse-up, this allows
|
||||
// multiple drag and drop to work.
|
||||
|
||||
if ( !IsItemSelected(GetHwnd(), htItem))
|
||||
{
|
||||
wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
|
||||
@ -2782,8 +2840,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
::SelectItem(GetHwnd(), htItem);
|
||||
::SetFocus(GetHwnd(), htItem);
|
||||
DoSelectItem(wxTreeItemId(htItem));
|
||||
SetFocusedItem(wxTreeItemId(htItem));
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, htItem);
|
||||
@ -2793,7 +2851,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
}
|
||||
else
|
||||
{
|
||||
::SetFocus(GetHwnd(), htItem);
|
||||
SetFocusedItem(wxTreeItemId(htItem));
|
||||
}
|
||||
}
|
||||
else // click on a single selected item
|
||||
@ -2808,11 +2866,14 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
// since previous click
|
||||
if ( m_focusLost )
|
||||
{
|
||||
TreeView_SelectItem(GetHwnd(), 0);
|
||||
::SelectItem(GetHwnd(), htItem);
|
||||
ClearFocusedItem();
|
||||
DoSelectItem(wxTreeItemId(htItem));
|
||||
SetFocusedItem(wxTreeItemId(htItem));
|
||||
}
|
||||
else
|
||||
{
|
||||
processed = false;
|
||||
}
|
||||
|
||||
processed = false;
|
||||
}
|
||||
|
||||
// reset on any click without Shift
|
||||
@ -2860,8 +2921,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
::SelectItem(GetHwnd(), htItem);
|
||||
::SetFocus(GetHwnd(), htItem);
|
||||
DoSelectItem(wxTreeItemId(htItem));
|
||||
SetFocusedItem(wxTreeItemId(htItem));
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, htItem);
|
||||
@ -2957,8 +3018,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
if ( IsTreeEventAllowed(changingEvent) )
|
||||
{
|
||||
DoUnselectAll();
|
||||
::SelectItem(GetHwnd(), htItem);
|
||||
::SetFocus(GetHwnd(), htItem);
|
||||
DoSelectItem(wxTreeItemId(htItem));
|
||||
SetFocusedItem(wxTreeItemId(htItem));
|
||||
|
||||
wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
this, htItem);
|
||||
@ -3082,12 +3143,12 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
// use the key to update the selection if it was left
|
||||
// unprocessed
|
||||
MSWHandleSelectionKey(wParam);
|
||||
|
||||
// pretend that we did process it in any case as we already
|
||||
// generated an event for it
|
||||
processed = true;
|
||||
}
|
||||
|
||||
// pretend that we did process it in any case as we already
|
||||
// generated an event for it
|
||||
processed = true;
|
||||
|
||||
//default: for all the other keys leave processed as false so that
|
||||
// the tree control generates a TVN_KEYDOWN for us
|
||||
}
|
||||
@ -3349,7 +3410,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
|
||||
// we have to handle both messages:
|
||||
case TVN_SELCHANGEDA:
|
||||
case TVN_SELCHANGEDW:
|
||||
if ( !HasFlag(wxTR_MULTIPLE) )
|
||||
if ( !HasFlag(wxTR_MULTIPLE) || !m_changingSelection )
|
||||
{
|
||||
eventType = wxEVT_COMMAND_TREE_SEL_CHANGED;
|
||||
}
|
||||
@ -3357,7 +3418,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
|
||||
|
||||
case TVN_SELCHANGINGA:
|
||||
case TVN_SELCHANGINGW:
|
||||
if ( !HasFlag(wxTR_MULTIPLE) )
|
||||
if ( !HasFlag(wxTR_MULTIPLE) || !m_changingSelection )
|
||||
{
|
||||
if ( eventType == wxEVT_NULL )
|
||||
eventType = wxEVT_COMMAND_TREE_SEL_CHANGING;
|
||||
|
Loading…
Reference in New Issue
Block a user