implemented multiple selection
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@21040 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "wx/vscroll.h" // base class
|
#include "wx/vscroll.h" // base class
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxSelectionStore;
|
||||||
|
|
||||||
#define wxVListBoxNameStr _T("wxVListBox")
|
#define wxVListBoxNameStr _T("wxVListBox")
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -43,52 +45,29 @@ public:
|
|||||||
wxWindowID id = wxID_ANY,
|
wxWindowID id = wxID_ANY,
|
||||||
const wxPoint& pos = wxDefaultPosition,
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
const wxSize& size = wxDefaultSize,
|
const wxSize& size = wxDefaultSize,
|
||||||
size_t countItems = 0,
|
|
||||||
long style = 0,
|
long style = 0,
|
||||||
const wxString& name = wxVListBoxNameStr)
|
const wxString& name = wxVListBoxNameStr)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
|
|
||||||
(void)Create(parent, id, pos, size, countItems, style, name);
|
(void)Create(parent, id, pos, size, style, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// really creates the control and sets the initial number of items in it
|
// really creates the control and sets the initial number of items in it
|
||||||
// (which may be changed later with SetItemCount())
|
// (which may be changed later with SetItemCount())
|
||||||
//
|
//
|
||||||
// there are no special styles defined for wxVListBox
|
// the only special style which may be specified here is wxLB_MULTIPLE
|
||||||
//
|
//
|
||||||
// returns true on success or false if the control couldn't be created
|
// returns true on success or false if the control couldn't be created
|
||||||
bool Create(wxWindow *parent,
|
bool Create(wxWindow *parent,
|
||||||
wxWindowID id = wxID_ANY,
|
wxWindowID id = wxID_ANY,
|
||||||
const wxPoint& pos = wxDefaultPosition,
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
const wxSize& size = wxDefaultSize,
|
const wxSize& size = wxDefaultSize,
|
||||||
size_t countItems = 0,
|
|
||||||
long style = 0,
|
long style = 0,
|
||||||
const wxString& name = wxVListBoxNameStr);
|
const wxString& name = wxVListBoxNameStr);
|
||||||
|
|
||||||
|
// dtor does some internal cleanup (deletes m_selStore if any)
|
||||||
// operations
|
virtual ~wxVListBox();
|
||||||
// ----------
|
|
||||||
|
|
||||||
// set the number of items to be shown in the control
|
|
||||||
//
|
|
||||||
// this is just a synonym for wxVScrolledWindow::SetLineCount()
|
|
||||||
void SetItemCount(size_t count) { SetLineCount(count); }
|
|
||||||
|
|
||||||
// delete all items from the control
|
|
||||||
void Clear() { SetItemCount(0); }
|
|
||||||
|
|
||||||
// set the selection to the specified item, if it is -1 the selection is
|
|
||||||
// unset
|
|
||||||
void SetSelection(int selection) { DoSetSelection(selection, false); }
|
|
||||||
|
|
||||||
// set the margins: horizontal margin is the distance between the window
|
|
||||||
// border and the item contents while vertical margin is half of the
|
|
||||||
// distance between items
|
|
||||||
//
|
|
||||||
// by default both margins are 0
|
|
||||||
void SetMargins(const wxPoint& pt);
|
|
||||||
void SetMargins(wxCoord x, wxCoord y) { SetMargins(wxPoint(x, y)); }
|
|
||||||
|
|
||||||
|
|
||||||
// accessors
|
// accessors
|
||||||
@@ -97,16 +76,110 @@ public:
|
|||||||
// get the number of items in the control
|
// get the number of items in the control
|
||||||
size_t GetItemCount() const { return GetLineCount(); }
|
size_t GetItemCount() const { return GetLineCount(); }
|
||||||
|
|
||||||
// get the currently selected item or -1 if there is no selection
|
// does this control use multiple selection?
|
||||||
int GetSelection() const { return m_selection; }
|
bool HasMultipleSelection() const { return m_selStore != NULL; }
|
||||||
|
|
||||||
|
// get the currently selected item or wxNOT_FOUND if there is no selection
|
||||||
|
//
|
||||||
|
// this method is only valid for the single selection listboxes
|
||||||
|
int GetSelection() const
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( !HasMultipleSelection(),
|
||||||
|
_T("GetSelection() can't be used with wxLB_MULTIPLE") );
|
||||||
|
|
||||||
|
return m_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is this item the current one?
|
||||||
|
bool IsCurrent(size_t item) const { return item == (size_t)m_current; }
|
||||||
|
|
||||||
// is this item selected?
|
// is this item selected?
|
||||||
bool IsSelected(size_t line) const { return (int)line == m_selection; }
|
bool IsSelected(size_t item) const;
|
||||||
|
|
||||||
|
// get the number of the selected items (maybe 0)
|
||||||
|
//
|
||||||
|
// this method is valid for both single and multi selection listboxes
|
||||||
|
size_t GetSelectedCount() const;
|
||||||
|
|
||||||
|
// get the first selected item, returns wxNOT_FOUND if none
|
||||||
|
//
|
||||||
|
// cookie is an opaque parameter which should be passed to
|
||||||
|
// GetNextSelected() later
|
||||||
|
//
|
||||||
|
// this method is only valid for the multi selection listboxes
|
||||||
|
int GetFirstSelected(unsigned long& cookie) const;
|
||||||
|
|
||||||
|
// get next selection item, return wxNOT_FOUND if no more
|
||||||
|
//
|
||||||
|
// cookie must be the same parameter that was passed to GetFirstSelected()
|
||||||
|
// before
|
||||||
|
//
|
||||||
|
// this method is only valid for the multi selection listboxes
|
||||||
|
int GetNextSelected(unsigned long& cookie) const;
|
||||||
|
|
||||||
// get the margins around each item
|
// get the margins around each item
|
||||||
wxPoint GetMargins() const { return m_ptMargins; }
|
wxPoint GetMargins() const { return m_ptMargins; }
|
||||||
|
|
||||||
|
|
||||||
|
// operations
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
// set the number of items to be shown in the control
|
||||||
|
//
|
||||||
|
// this is just a synonym for wxVScrolledWindow::SetLineCount()
|
||||||
|
void SetItemCount(size_t count);
|
||||||
|
|
||||||
|
// delete all items from the control
|
||||||
|
void Clear() { SetItemCount(0); }
|
||||||
|
|
||||||
|
// set the selection to the specified item, if it is -1 the selection is
|
||||||
|
// unset
|
||||||
|
//
|
||||||
|
// this function is only valid for the single selection listboxes
|
||||||
|
void SetSelection(int selection);
|
||||||
|
|
||||||
|
// selects or deselects the specified item which must be valid (i.e. not
|
||||||
|
// equal to -1)
|
||||||
|
//
|
||||||
|
// return true if the items selection status has changed or false
|
||||||
|
// otherwise
|
||||||
|
//
|
||||||
|
// this function is only valid for the multiple selection listboxes
|
||||||
|
bool Select(size_t item, bool select = true);
|
||||||
|
|
||||||
|
// selects the items in the specified range whose end points may be given
|
||||||
|
// in any order
|
||||||
|
//
|
||||||
|
// return true if any items selection status has changed, false otherwise
|
||||||
|
//
|
||||||
|
// this function is only valid for the single selection listboxes
|
||||||
|
bool SelectRange(size_t from, size_t to);
|
||||||
|
|
||||||
|
// toggle the selection of the specified item (must be valid)
|
||||||
|
//
|
||||||
|
// this function is only valid for the multiple selection listboxes
|
||||||
|
void Toggle(size_t item) { Select(item, !IsSelected(item)); }
|
||||||
|
|
||||||
|
// select all items in the listbox
|
||||||
|
//
|
||||||
|
// the return code indicates if any items were affected by this operation
|
||||||
|
// (true) or if nothing has changed (false)
|
||||||
|
bool SelectAll() { return DoSelectAll(true); }
|
||||||
|
|
||||||
|
// unselect all items in the listbox
|
||||||
|
//
|
||||||
|
// the return code has the same meaning as for SelectAll()
|
||||||
|
bool DeselectAll() { return DoSelectAll(false); }
|
||||||
|
|
||||||
|
// set the margins: horizontal margin is the distance between the window
|
||||||
|
// border and the item contents while vertical margin is half of the
|
||||||
|
// distance between items
|
||||||
|
//
|
||||||
|
// by default both margins are 0
|
||||||
|
void SetMargins(const wxPoint& pt);
|
||||||
|
void SetMargins(wxCoord x, wxCoord y) { SetMargins(wxPoint(x, y)); }
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// the derived class must implement this function to actually draw the item
|
// the derived class must implement this function to actually draw the item
|
||||||
// with the given index on the provided DC
|
// with the given index on the provided DC
|
||||||
@@ -141,18 +214,35 @@ protected:
|
|||||||
// common part of all ctors
|
// common part of all ctors
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
// SetSelection() with additional parameter telling it whether to send a
|
// send the wxEVT_COMMAND_LISTBOX_SELECTED event
|
||||||
// notification event or not
|
void SendSelectedEvent();
|
||||||
void DoSetSelection(int selection, bool sendEvent = true);
|
|
||||||
|
// common implementation of SelectAll() and DeselectAll()
|
||||||
|
bool DoSelectAll(bool select);
|
||||||
|
|
||||||
|
// change the current item (in single selection listbox it also implicitly
|
||||||
|
// changes the selection); current may be -1 in which case there will be
|
||||||
|
// no current item any more
|
||||||
|
//
|
||||||
|
// return true if the current item changed, false otherwise
|
||||||
|
bool DoSetCurrent(int current);
|
||||||
|
|
||||||
|
// common part of keyboard and mouse handling processing code
|
||||||
|
void DoHandleItemClick(int item, bool shiftDown, bool ctrlDown);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// the current selection or -1
|
// the current item or -1
|
||||||
int m_selection;
|
//
|
||||||
|
// if m_selStore == NULL this is also the selected item, otherwise the
|
||||||
|
// selections are managed by m_selStore
|
||||||
|
int m_current;
|
||||||
|
|
||||||
|
// the object managing our selected items if not NULL
|
||||||
|
wxSelectionStore *m_selStore;
|
||||||
|
|
||||||
// margins
|
// margins
|
||||||
wxPoint m_ptMargins;
|
wxPoint m_ptMargins;
|
||||||
|
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#endif //WX_PRECOMP
|
#endif //WX_PRECOMP
|
||||||
|
|
||||||
#include "wx/vlbox.h"
|
#include "wx/vlbox.h"
|
||||||
|
#include "wx/selstore.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// event tables
|
// event tables
|
||||||
@@ -53,14 +54,14 @@ END_EVENT_TABLE()
|
|||||||
|
|
||||||
void wxVListBox::Init()
|
void wxVListBox::Init()
|
||||||
{
|
{
|
||||||
m_selection = -1;
|
m_current = wxNOT_FOUND;
|
||||||
|
m_selStore = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxVListBox::Create(wxWindow *parent,
|
bool wxVListBox::Create(wxWindow *parent,
|
||||||
wxWindowID id,
|
wxWindowID id,
|
||||||
const wxPoint& pos,
|
const wxPoint& pos,
|
||||||
const wxSize& size,
|
const wxSize& size,
|
||||||
size_t countItems,
|
|
||||||
long style,
|
long style,
|
||||||
const wxString& name)
|
const wxString& name)
|
||||||
{
|
{
|
||||||
@@ -69,60 +70,206 @@ bool wxVListBox::Create(wxWindow *parent,
|
|||||||
|
|
||||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX));
|
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX));
|
||||||
|
|
||||||
SetItemCount(countItems);
|
if ( style & wxLB_MULTIPLE )
|
||||||
|
m_selStore = new wxSelectionStore;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxVListBox::~wxVListBox()
|
||||||
|
{
|
||||||
|
delete m_selStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxVListBox::SetItemCount(size_t count)
|
||||||
|
{
|
||||||
|
if ( m_selStore )
|
||||||
|
{
|
||||||
|
// tell the selection store that our number of items has changed
|
||||||
|
m_selStore->SetItemCount(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLineCount(count);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// selection handling
|
// selection handling
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void wxVListBox::DoSetSelection(int selection, bool sendEvent)
|
bool wxVListBox::IsSelected(size_t line) const
|
||||||
{
|
{
|
||||||
if ( selection == m_selection )
|
return m_selStore ? m_selStore->IsSelected(line) : (int)line == m_current;
|
||||||
{
|
|
||||||
// nothing to do
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( m_selection != -1 )
|
bool wxVListBox::Select(size_t item, bool select)
|
||||||
RefreshLine(m_selection);
|
{
|
||||||
|
wxCHECK_MSG( m_selStore, false,
|
||||||
|
_T("Select() may only be used with multiselection listbox") );
|
||||||
|
|
||||||
m_selection = selection;
|
wxCHECK_MSG( item < GetItemCount(), false,
|
||||||
|
_T("Select(): invalid item index") );
|
||||||
|
|
||||||
if ( m_selection != -1 )
|
bool changed = m_selStore->SelectItem(item, select);
|
||||||
|
if ( changed )
|
||||||
|
{
|
||||||
|
// selection really changed
|
||||||
|
RefreshLine(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
DoSetCurrent(item);
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxVListBox::SelectRange(size_t from, size_t to)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( m_selStore, false,
|
||||||
|
_T("SelectRange() may only be used with multiselection listbox") );
|
||||||
|
|
||||||
|
// make sure items are in correct order
|
||||||
|
if ( from > to )
|
||||||
|
{
|
||||||
|
size_t tmp = from;
|
||||||
|
from = to;
|
||||||
|
to = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCHECK_MSG( to < GetItemCount(), false,
|
||||||
|
_T("SelectRange(): invalid item index") );
|
||||||
|
|
||||||
|
wxArrayInt changed;
|
||||||
|
if ( !m_selStore->SelectRange(from, to, true, &changed) )
|
||||||
|
{
|
||||||
|
// too many items have changed, we didn't record them in changed array
|
||||||
|
// so we have no choice but to refresh everything between from and to
|
||||||
|
RefreshLines(from, to);
|
||||||
|
}
|
||||||
|
else // we've got the indices of the changed items
|
||||||
|
{
|
||||||
|
const size_t count = changed.GetCount();
|
||||||
|
if ( !count )
|
||||||
|
{
|
||||||
|
// nothing changed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// refresh just the lines which have really changed
|
||||||
|
for ( size_t n = 0; n < count; n++ )
|
||||||
|
{
|
||||||
|
RefreshLine(changed[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// something changed
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxVListBox::DoSelectAll(bool select)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( m_selStore, false,
|
||||||
|
_T("SelectAll may only be used with multiselection listbox") );
|
||||||
|
|
||||||
|
size_t count = GetItemCount();
|
||||||
|
if ( count )
|
||||||
|
{
|
||||||
|
wxArrayInt changed;
|
||||||
|
if ( !m_selStore->SelectRange(0, count - 1, select) ||
|
||||||
|
!changed.IsEmpty() )
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
|
||||||
|
// something changed
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxVListBox::DoSetCurrent(int current)
|
||||||
|
{
|
||||||
|
if ( current == m_current )
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_current != wxNOT_FOUND )
|
||||||
|
RefreshLine(m_current);
|
||||||
|
|
||||||
|
m_current = current;
|
||||||
|
|
||||||
|
if ( m_current != wxNOT_FOUND )
|
||||||
{
|
{
|
||||||
// if the line is not visible at all, we scroll it into view but we
|
// if the line is not visible at all, we scroll it into view but we
|
||||||
// don't need to refresh it -- it will be redrawn anyhow
|
// don't need to refresh it -- it will be redrawn anyhow
|
||||||
if ( !IsVisible(m_selection) )
|
if ( !IsVisible(m_current) )
|
||||||
{
|
{
|
||||||
ScrollToLine(m_selection);
|
ScrollToLine(m_current);
|
||||||
}
|
}
|
||||||
else // line is at least partly visible
|
else // line is at least partly visible
|
||||||
{
|
{
|
||||||
// it is, indeed, only partly visible, so scroll it into view to
|
// it is, indeed, only partly visible, so scroll it into view to
|
||||||
// make it entirely visible
|
// make it entirely visible
|
||||||
if ( (size_t)m_selection == GetLastVisibleLine() )
|
if ( (size_t)m_current == GetLastVisibleLine() )
|
||||||
{
|
{
|
||||||
ScrollToLine(m_selection);
|
ScrollToLine(m_current);
|
||||||
}
|
}
|
||||||
|
|
||||||
// but in any case refresh it as even if it was only partly visible
|
// but in any case refresh it as even if it was only partly visible
|
||||||
// before we need to redraw it entirely as its background changed
|
// before we need to redraw it entirely as its background changed
|
||||||
RefreshLine(m_selection);
|
RefreshLine(m_current);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send a notification event if we were not called directly by user
|
return true;
|
||||||
if ( sendEvent )
|
}
|
||||||
|
|
||||||
|
void wxVListBox::SendSelectedEvent()
|
||||||
{
|
{
|
||||||
|
wxASSERT_MSG( m_current != wxNOT_FOUND,
|
||||||
|
_T("SendSelectedEvent() shouldn't be called") );
|
||||||
|
|
||||||
wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, GetId());
|
wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, GetId());
|
||||||
event.SetEventObject(this);
|
event.SetEventObject(this);
|
||||||
event.m_commandInt = selection;
|
event.m_commandInt = m_current;
|
||||||
|
|
||||||
(void)GetEventHandler()->ProcessEvent(event);
|
(void)GetEventHandler()->ProcessEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxVListBox::SetSelection(int selection)
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( !HasMultipleSelection(),
|
||||||
|
_T("SetSelection() is invalid with multiselection listbox") );
|
||||||
|
|
||||||
|
DoSetCurrent(selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t wxVListBox::GetSelectedCount() const
|
||||||
|
{
|
||||||
|
return m_selStore ? m_selStore->GetSelectedCount()
|
||||||
|
: m_current == wxNOT_FOUND ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxVListBox::GetFirstSelected(unsigned long& cookie) const
|
||||||
|
{
|
||||||
|
cookie = 0;
|
||||||
|
|
||||||
|
return GetNextSelected(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxVListBox::GetNextSelected(unsigned long& cookie) const
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( m_selStore, wxNOT_FOUND,
|
||||||
|
_T("GetFirst/NextSelected() may only be used with multiselection listboxes") );
|
||||||
|
|
||||||
|
while ( cookie < GetItemCount() )
|
||||||
|
{
|
||||||
|
if ( IsSelected(cookie++) )
|
||||||
|
return cookie - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxNOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -175,13 +322,24 @@ void wxVListBox::OnPaint(wxPaintEvent& event)
|
|||||||
// don't allow drawing outside of the lines rectangle
|
// don't allow drawing outside of the lines rectangle
|
||||||
wxDCClipper clip(dc, rectLine);
|
wxDCClipper clip(dc, rectLine);
|
||||||
|
|
||||||
if ( IsSelected(line) )
|
// we need to render selected and current items differently
|
||||||
|
const bool isSelected = IsSelected(line);
|
||||||
|
if ( isSelected || IsCurrent(line) )
|
||||||
|
{
|
||||||
|
if ( isSelected )
|
||||||
{
|
{
|
||||||
wxBrush brush(wxSystemSettings::
|
wxBrush brush(wxSystemSettings::
|
||||||
GetColour(wxSYS_COLOUR_HIGHLIGHT),
|
GetColour(wxSYS_COLOUR_HIGHLIGHT),
|
||||||
wxSOLID);
|
wxSOLID);
|
||||||
dc.SetBrush(brush);
|
dc.SetBrush(brush);
|
||||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
}
|
||||||
|
else // !selected
|
||||||
|
{
|
||||||
|
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.SetPen(*(IsCurrent(line) ? wxBLACK_PEN : wxTRANSPARENT_PEN));
|
||||||
|
|
||||||
dc.DrawRectangle(rectLine);
|
dc.DrawRectangle(rectLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,53 +364,126 @@ void wxVListBox::OnPaint(wxPaintEvent& event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// wxVListBox keyboard/mouse handling
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
void wxVListBox::DoHandleItemClick(int item, bool shiftDown, bool ctrlDown)
|
||||||
|
{
|
||||||
|
// has anything worth telling the client code about happened?
|
||||||
|
bool notify = false;
|
||||||
|
|
||||||
|
if ( HasMultipleSelection() )
|
||||||
|
{
|
||||||
|
// select the iteem clicked?
|
||||||
|
bool select = true;
|
||||||
|
|
||||||
|
// NB: the keyboard interface we implement here corresponds to
|
||||||
|
// wxLB_EXTENDED rather than wxLB_MULTIPLE but this one makes more
|
||||||
|
// sense IMHO
|
||||||
|
if ( shiftDown )
|
||||||
|
{
|
||||||
|
if ( m_current != wxNOT_FOUND )
|
||||||
|
{
|
||||||
|
select = false;
|
||||||
|
|
||||||
|
// only the range from old m_current to new m_current must be
|
||||||
|
// selected
|
||||||
|
if ( DeselectAll() )
|
||||||
|
notify = true;
|
||||||
|
|
||||||
|
if ( SelectRange(m_current, item) )
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
//else: treat it as ordinary click/keypress
|
||||||
|
}
|
||||||
|
else if ( ctrlDown )
|
||||||
|
{
|
||||||
|
select = false;
|
||||||
|
|
||||||
|
Toggle(item);
|
||||||
|
|
||||||
|
// the status of the item has definitely changed
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
//else: behave as in single selection case
|
||||||
|
|
||||||
|
if ( select )
|
||||||
|
{
|
||||||
|
// make the clicked item the only selection
|
||||||
|
if ( DeselectAll() )
|
||||||
|
notify = true;
|
||||||
|
|
||||||
|
if ( Select(item) )
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// in any case the item should become the current one
|
||||||
|
if ( DoSetCurrent(item) )
|
||||||
|
{
|
||||||
|
if ( !HasMultipleSelection() )
|
||||||
|
{
|
||||||
|
// this has also changed the selection for single selection case
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( notify )
|
||||||
|
{
|
||||||
|
// notify the user about the selection change
|
||||||
|
SendSelectedEvent();
|
||||||
|
}
|
||||||
|
//else: nothing changed at all
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxVListBox keyboard handling
|
// keyboard handling
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void wxVListBox::OnKeyDown(wxKeyEvent& event)
|
void wxVListBox::OnKeyDown(wxKeyEvent& event)
|
||||||
{
|
{
|
||||||
int selection = 0; // just to silent the stupid compiler warnings
|
int current = 0; // just to silent the stupid compiler warnings
|
||||||
switch ( event.GetKeyCode() )
|
switch ( event.GetKeyCode() )
|
||||||
{
|
{
|
||||||
case WXK_HOME:
|
case WXK_HOME:
|
||||||
selection = 0;
|
current = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WXK_END:
|
case WXK_END:
|
||||||
selection = GetLineCount() - 1;
|
current = GetLineCount() - 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WXK_DOWN:
|
case WXK_DOWN:
|
||||||
if ( m_selection == (int)GetLineCount() - 1 )
|
if ( m_current == (int)GetLineCount() - 1 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
selection = m_selection + 1;
|
current = m_current + 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WXK_UP:
|
case WXK_UP:
|
||||||
if ( m_selection == -1 )
|
if ( m_current == wxNOT_FOUND )
|
||||||
selection = GetLineCount() - 1;
|
current = GetLineCount() - 1;
|
||||||
else if ( m_selection != 0 )
|
else if ( m_current != 0 )
|
||||||
selection = m_selection - 1;
|
current = m_current - 1;
|
||||||
else // m_selection == 0
|
else // m_current == 0
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WXK_PAGEDOWN:
|
case WXK_PAGEDOWN:
|
||||||
case WXK_NEXT:
|
case WXK_NEXT:
|
||||||
PageDown();
|
PageDown();
|
||||||
selection = GetFirstVisibleLine();
|
current = GetFirstVisibleLine();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WXK_PAGEUP:
|
case WXK_PAGEUP:
|
||||||
case WXK_PRIOR:
|
case WXK_PRIOR:
|
||||||
if ( m_selection == (int)GetFirstVisibleLine() )
|
if ( m_current == (int)GetFirstVisibleLine() )
|
||||||
{
|
{
|
||||||
PageUp();
|
PageUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
selection = GetFirstVisibleLine();
|
current = GetFirstVisibleLine();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -260,7 +491,7 @@ void wxVListBox::OnKeyDown(wxKeyEvent& event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DoSetSelection(selection);
|
DoHandleItemClick(current, event.ShiftDown(), event.ControlDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -271,13 +502,19 @@ void wxVListBox::OnLeftDown(wxMouseEvent& event)
|
|||||||
{
|
{
|
||||||
int item = HitTest(event.GetPosition());
|
int item = HitTest(event.GetPosition());
|
||||||
|
|
||||||
DoSetSelection(item);
|
DoHandleItemClick(item, event.ShiftDown(),
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
event.MetaDown()
|
||||||
|
#else
|
||||||
|
event.ControlDown()
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxVListBox::OnLeftDClick(wxMouseEvent& event)
|
void wxVListBox::OnLeftDClick(wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
int item = HitTest(event.GetPosition());
|
int item = HitTest(event.GetPosition());
|
||||||
if ( item != -1 )
|
if ( item != wxNOT_FOUND )
|
||||||
{
|
{
|
||||||
wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, GetId());
|
wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, GetId());
|
||||||
event.SetEventObject(this);
|
event.SetEventObject(this);
|
||||||
|
Reference in New Issue
Block a user