wxListBox input handling works for single and multi selection ones (not
extended yet) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8242 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "wx/univ/renderer.h" // for wxHitTest
|
#include "wx/univ/renderer.h" // for wxHitTest
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxListBox;
|
||||||
class WXDLLEXPORT wxRenderer;
|
class WXDLLEXPORT wxRenderer;
|
||||||
class WXDLLEXPORT wxScrollBar;
|
class WXDLLEXPORT wxScrollBar;
|
||||||
|
|
||||||
@@ -214,6 +215,14 @@ public:
|
|||||||
const wxMouseEvent& event);
|
const wxMouseEvent& event);
|
||||||
virtual bool HandleMouseMove(wxControl *control,
|
virtual bool HandleMouseMove(wxControl *control,
|
||||||
const wxMouseEvent& event);
|
const wxMouseEvent& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// get the listbox item under mouse and return -1 if there is none
|
||||||
|
int HitTest(const wxListBox *listbox, const wxMouseEvent& event);
|
||||||
|
|
||||||
|
wxRenderer *m_renderer;
|
||||||
|
|
||||||
|
wxWindow *m_winCapture;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WX_UNIV_INPHAND_H_
|
#endif // _WX_UNIV_INPHAND_H_
|
||||||
|
@@ -123,6 +123,7 @@ public:
|
|||||||
// actions
|
// actions
|
||||||
void Activate();
|
void Activate();
|
||||||
void Select(bool sel = TRUE);
|
void Select(bool sel = TRUE);
|
||||||
|
void EnsureVisible();
|
||||||
|
|
||||||
// get, calculating it if necessary, the number of items per page and the
|
// get, calculating it if necessary, the number of items per page and the
|
||||||
// height of each line
|
// height of each line
|
||||||
@@ -187,6 +188,15 @@ private:
|
|||||||
// the number of items per page
|
// the number of items per page
|
||||||
size_t m_itemsPerPage;
|
size_t m_itemsPerPage;
|
||||||
|
|
||||||
|
// if the number of items has changed we may need to show/hide the
|
||||||
|
// scrollbar
|
||||||
|
bool m_updateScrollbar,
|
||||||
|
m_showScrollbar;
|
||||||
|
|
||||||
|
// if the current item has changed, we might need to scroll if it went out
|
||||||
|
// of the window
|
||||||
|
bool m_currentChanged;
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
DECLARE_DYNAMIC_CLASS(wxListBox)
|
DECLARE_DYNAMIC_CLASS(wxListBox)
|
||||||
};
|
};
|
||||||
|
@@ -150,9 +150,6 @@ public:
|
|||||||
// the control looks "nice" if it uses the adjusted rectangle
|
// the control looks "nice" if it uses the adjusted rectangle
|
||||||
virtual void AdjustSize(wxSize *size, const wxWindow *window) = 0;
|
virtual void AdjustSize(wxSize *size, const wxWindow *window) = 0;
|
||||||
|
|
||||||
// hit testing functions
|
|
||||||
// ---------------------
|
|
||||||
|
|
||||||
// gets the bounding box for a scrollbar element for the given (by default
|
// gets the bounding box for a scrollbar element for the given (by default
|
||||||
// - current) thumb position
|
// - current) thumb position
|
||||||
virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
|
virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
|
||||||
@@ -170,6 +167,9 @@ public:
|
|||||||
virtual int PixelToScrollbar(const wxScrollBar *scrollbar,
|
virtual int PixelToScrollbar(const wxScrollBar *scrollbar,
|
||||||
wxCoord coord) = 0;
|
wxCoord coord) = 0;
|
||||||
|
|
||||||
|
// get the height of a listbox item from the base font height
|
||||||
|
virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) = 0;
|
||||||
|
|
||||||
// virtual dtor for any base class
|
// virtual dtor for any base class
|
||||||
virtual ~wxRenderer();
|
virtual ~wxRenderer();
|
||||||
|
|
||||||
@@ -288,6 +288,8 @@ public:
|
|||||||
virtual int PixelToScrollbar(const wxScrollBar *scrollbar,
|
virtual int PixelToScrollbar(const wxScrollBar *scrollbar,
|
||||||
wxCoord coord)
|
wxCoord coord)
|
||||||
{ return m_renderer->PixelToScrollbar(scrollbar, coord); }
|
{ return m_renderer->PixelToScrollbar(scrollbar, coord); }
|
||||||
|
virtual wxCoord GetListboxItemHeight(wxCoord fontHeight)
|
||||||
|
{ return m_renderer->GetListboxItemHeight(fontHeight); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxRenderer *m_renderer;
|
wxRenderer *m_renderer;
|
||||||
|
@@ -107,6 +107,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// event handlers
|
// event handlers
|
||||||
void OnButton(wxCommandEvent& event);
|
void OnButton(wxCommandEvent& event);
|
||||||
|
void OnListBox(wxCommandEvent& event);
|
||||||
void OnLeftUp(wxMouseEvent& event);
|
void OnLeftUp(wxMouseEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -139,6 +140,7 @@ IMPLEMENT_APP(MyUnivApp)
|
|||||||
|
|
||||||
BEGIN_EVENT_TABLE(MyUnivFrame, wxFrame)
|
BEGIN_EVENT_TABLE(MyUnivFrame, wxFrame)
|
||||||
EVT_BUTTON(-1, MyUnivFrame::OnButton)
|
EVT_BUTTON(-1, MyUnivFrame::OnButton)
|
||||||
|
EVT_LISTBOX(-1, MyUnivFrame::OnListBox)
|
||||||
|
|
||||||
EVT_LEFT_UP(MyUnivFrame::OnLeftUp)
|
EVT_LEFT_UP(MyUnivFrame::OnLeftUp)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
@@ -311,10 +313,15 @@ MyUnivFrame::MyUnivFrame(const wxString& title)
|
|||||||
_T("is one of my"),
|
_T("is one of my"),
|
||||||
_T("really"),
|
_T("really"),
|
||||||
_T("wonderful"),
|
_T("wonderful"),
|
||||||
_T("examples."),
|
_T("examples"),
|
||||||
};
|
};
|
||||||
new wxListBox(this, -1, wxPoint(550, 10), wxDefaultSize,
|
wxListBox *lbox = new wxListBox(this, -1, wxPoint(550, 10), wxDefaultSize,
|
||||||
WXSIZEOF(choices), choices);
|
WXSIZEOF(choices), choices,
|
||||||
|
wxLB_MULTIPLE);
|
||||||
|
for ( int i = 0; i < 20; i++ )
|
||||||
|
{
|
||||||
|
lbox->Append(wxString::Format(_T("entry %d"), i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyUnivFrame::OnButton(wxCommandEvent& event)
|
void MyUnivFrame::OnButton(wxCommandEvent& event)
|
||||||
@@ -330,6 +337,11 @@ void MyUnivFrame::OnButton(wxCommandEvent& event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyUnivFrame::OnListBox(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
wxLogDebug(_T("Listbox item %d selected."), event.GetInt());
|
||||||
|
}
|
||||||
|
|
||||||
void MyUnivFrame::OnLeftUp(wxMouseEvent& event)
|
void MyUnivFrame::OnLeftUp(wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
if ( event.ControlDown() )
|
if ( event.ControlDown() )
|
||||||
|
@@ -65,9 +65,12 @@ void wxListBox::Init()
|
|||||||
|
|
||||||
// no items hence no current item
|
// no items hence no current item
|
||||||
m_current = -1;
|
m_current = -1;
|
||||||
|
m_currentChanged = FALSE;
|
||||||
|
|
||||||
// no need to update anything initially
|
// no need to update anything initially
|
||||||
m_updateCount = 0;
|
m_updateCount = 0;
|
||||||
|
m_updateScrollbar =
|
||||||
|
m_showScrollbar = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxListBox::Create(wxWindow *parent,
|
bool wxListBox::Create(wxWindow *parent,
|
||||||
@@ -83,6 +86,8 @@ bool wxListBox::Create(wxWindow *parent,
|
|||||||
if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) )
|
if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
SetWindow(this);
|
||||||
|
|
||||||
SetBackgroundColour(*wxWHITE);
|
SetBackgroundColour(*wxWHITE);
|
||||||
|
|
||||||
if ( style & wxLB_SORT )
|
if ( style & wxLB_SORT )
|
||||||
@@ -108,6 +113,8 @@ int wxListBox::DoAppend(const wxString& item)
|
|||||||
size_t index = m_strings.Add(item);
|
size_t index = m_strings.Add(item);
|
||||||
m_clientData.Insert(NULL, index);
|
m_clientData.Insert(NULL, index);
|
||||||
|
|
||||||
|
m_updateScrollbar = TRUE;
|
||||||
|
|
||||||
RefreshItem(m_strings.GetCount() - 1);
|
RefreshItem(m_strings.GetCount() - 1);
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
@@ -126,6 +133,8 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
|
|||||||
m_clientData.Insert(NULL, pos + n);
|
m_clientData.Insert(NULL, pos + n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_updateScrollbar = TRUE;
|
||||||
|
|
||||||
RefreshItems(pos, count);
|
RefreshItems(pos, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,11 +148,11 @@ void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
|
|||||||
for ( size_t n = 0; n < count; n++ )
|
for ( size_t n = 0; n < count; n++ )
|
||||||
{
|
{
|
||||||
size_t index = m_strings.Add(items[n]);
|
size_t index = m_strings.Add(items[n]);
|
||||||
|
m_clientData.Insert(clientData ? clientData[n] : NULL, index);
|
||||||
if ( clientData )
|
|
||||||
m_clientData.Insert(clientData[n], index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_updateScrollbar = TRUE;
|
||||||
|
|
||||||
RefreshAll();
|
RefreshAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,6 +180,8 @@ void wxListBox::Clear()
|
|||||||
{
|
{
|
||||||
DoClear();
|
DoClear();
|
||||||
|
|
||||||
|
m_updateScrollbar = TRUE;
|
||||||
|
|
||||||
RefreshAll();
|
RefreshAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +198,8 @@ void wxListBox::Delete(int n)
|
|||||||
|
|
||||||
m_clientData.RemoveAt(n);
|
m_clientData.RemoveAt(n);
|
||||||
|
|
||||||
|
m_updateScrollbar = TRUE;
|
||||||
|
|
||||||
RefreshItems(n, GetCount() - n);
|
RefreshItems(n, GetCount() - n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,12 +279,15 @@ int wxListBox::GetSelections(wxArrayInt& selections) const
|
|||||||
|
|
||||||
void wxListBox::Refresh(bool eraseBackground, const wxRect *rect)
|
void wxListBox::Refresh(bool eraseBackground, const wxRect *rect)
|
||||||
{
|
{
|
||||||
// do nothing here if we didn't call it ourselves
|
if ( rect )
|
||||||
if ( m_updateCount )
|
wxLogTrace(_T("listbox"), _T("Refreshing (%d, %d)-(%d, %d)"),
|
||||||
{
|
rect->x, rect->y,
|
||||||
|
rect->x + rect->width, rect->y + rect->height);
|
||||||
|
else
|
||||||
|
wxLogTrace(_T("listbox"), _T("Refreshing all"));
|
||||||
|
|
||||||
wxControl::Refresh(eraseBackground, rect);
|
wxControl::Refresh(eraseBackground, rect);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void wxListBox::RefreshItems(int from, int count)
|
void wxListBox::RefreshItems(int from, int count)
|
||||||
{
|
{
|
||||||
@@ -339,6 +355,29 @@ void wxListBox::RefreshAll()
|
|||||||
|
|
||||||
void wxListBox::OnIdle(wxIdleEvent& event)
|
void wxListBox::OnIdle(wxIdleEvent& event)
|
||||||
{
|
{
|
||||||
|
if ( m_updateScrollbar )
|
||||||
|
{
|
||||||
|
// is our height enough to show all items?
|
||||||
|
wxCoord lineHeight = GetLineHeight();
|
||||||
|
bool showScrollbar = GetCount()*lineHeight > GetClientSize().y;
|
||||||
|
if ( showScrollbar != m_showScrollbar )
|
||||||
|
{
|
||||||
|
// TODO: support for horz scrollbar
|
||||||
|
SetScrollbars(0, lineHeight, 0, GetCount());
|
||||||
|
|
||||||
|
m_showScrollbar = showScrollbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_updateScrollbar = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_currentChanged )
|
||||||
|
{
|
||||||
|
EnsureVisible();
|
||||||
|
|
||||||
|
m_currentChanged = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if ( m_updateCount )
|
if ( m_updateCount )
|
||||||
{
|
{
|
||||||
// only refresh the items which must be refreshed
|
// only refresh the items which must be refreshed
|
||||||
@@ -375,6 +414,13 @@ void wxListBox::OnIdle(wxIdleEvent& event)
|
|||||||
void wxListBox::DoDraw(wxControlRenderer *renderer)
|
void wxListBox::DoDraw(wxControlRenderer *renderer)
|
||||||
{
|
{
|
||||||
// draw the border first
|
// draw the border first
|
||||||
|
if ( m_showScrollbar )
|
||||||
|
{
|
||||||
|
// we need to draw a border around the client area
|
||||||
|
renderer->GetRect().width -= GetScrollbar(wxVERTICAL)->GetSize().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the base class version does it for us
|
||||||
wxControl::DoDraw(renderer);
|
wxControl::DoDraw(renderer);
|
||||||
|
|
||||||
// adjust the DC to account for scrolling
|
// adjust the DC to account for scrolling
|
||||||
@@ -385,9 +431,9 @@ void wxListBox::DoDraw(wxControlRenderer *renderer)
|
|||||||
#if 0
|
#if 0
|
||||||
int y;
|
int y;
|
||||||
GetViewStart(NULL, &y);
|
GetViewStart(NULL, &y);
|
||||||
#endif
|
|
||||||
wxCoord lineHeight = GetLineHeight();
|
wxCoord lineHeight = GetLineHeight();
|
||||||
wxRegion rgnUpdate = GetUpdateRegion();
|
wxRegion rgnUpdate = GetUpdateRegion();
|
||||||
|
//dc.SetClippingRegion(rgnUpdate);
|
||||||
wxRect rectUpdate = rgnUpdate.GetBox();
|
wxRect rectUpdate = rgnUpdate.GetBox();
|
||||||
size_t itemFirst = rectUpdate.GetTop() / lineHeight,
|
size_t itemFirst = rectUpdate.GetTop() / lineHeight,
|
||||||
itemLast = (rectUpdate.GetBottom() + lineHeight - 1) / lineHeight,
|
itemLast = (rectUpdate.GetBottom() + lineHeight - 1) / lineHeight,
|
||||||
@@ -398,11 +444,15 @@ void wxListBox::DoDraw(wxControlRenderer *renderer)
|
|||||||
|
|
||||||
if ( itemLast > itemMax )
|
if ( itemLast > itemMax )
|
||||||
itemLast = itemMax;
|
itemLast = itemMax;
|
||||||
|
#else
|
||||||
|
size_t itemFirst = 0,
|
||||||
|
itemLast = m_strings.GetCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
// do draw them
|
// do draw them
|
||||||
wxLogTrace(_T("listbox"), _T("Repainting items %d..%d"),
|
wxLogTrace(_T("listbox"), _T("Repainting items %d..%d"),
|
||||||
itemFirst, itemLast);
|
itemFirst, itemLast);
|
||||||
dc.SetClippingRegion(rgnUpdate);
|
|
||||||
renderer->DrawItems(this, itemFirst, itemLast);
|
renderer->DrawItems(this, itemFirst, itemLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +474,8 @@ bool wxListBox::SetFont(const wxFont& font)
|
|||||||
|
|
||||||
void wxListBox::CalcItemsPerPage()
|
void wxListBox::CalcItemsPerPage()
|
||||||
{
|
{
|
||||||
m_lineHeight = wxClientDC(this).GetCharHeight() + 2;
|
m_lineHeight = GetRenderer()->
|
||||||
|
GetListboxItemHeight(wxClientDC(this).GetCharHeight());
|
||||||
m_itemsPerPage = GetClientSize().y / m_lineHeight;
|
m_itemsPerPage = GetClientSize().y / m_lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,6 +578,8 @@ bool wxListBox::SendEvent(int item, wxEventType type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void wxListBox::SetCurrentItem(int n)
|
void wxListBox::SetCurrentItem(int n)
|
||||||
|
{
|
||||||
|
if ( n != m_current )
|
||||||
{
|
{
|
||||||
if ( m_current != -1 )
|
if ( m_current != -1 )
|
||||||
RefreshItem(n);
|
RefreshItem(n);
|
||||||
@@ -534,8 +587,49 @@ void wxListBox::SetCurrentItem(int n)
|
|||||||
m_current = n;
|
m_current = n;
|
||||||
|
|
||||||
if ( m_current != -1 )
|
if ( m_current != -1 )
|
||||||
|
{
|
||||||
|
if ( !HasMultipleSelection() )
|
||||||
|
{
|
||||||
|
// for a single selection listbox, the current item is always
|
||||||
|
// the one selected
|
||||||
|
Select(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentChanged = TRUE;
|
||||||
|
|
||||||
RefreshItem(n);
|
RefreshItem(n);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//else: nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxListBox::EnsureVisible()
|
||||||
|
{
|
||||||
|
if ( !m_showScrollbar )
|
||||||
|
{
|
||||||
|
// nothing to do - everything is shown anyhow
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int first;
|
||||||
|
GetViewStart(0, &first);
|
||||||
|
if ( first > m_current )
|
||||||
|
{
|
||||||
|
// we need to scroll upwards, so make the current item appear on top
|
||||||
|
// of the shown range
|
||||||
|
Scroll(0, m_current);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int last = first + GetClientSize().y / GetLineHeight() - 1;
|
||||||
|
if ( last < m_current )
|
||||||
|
{
|
||||||
|
// scroll down: the current item appears at the bottom of the
|
||||||
|
// range
|
||||||
|
Scroll(0, m_current - (last - first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wxListBox::ChangeCurrent(int diff)
|
void wxListBox::ChangeCurrent(int diff)
|
||||||
{
|
{
|
||||||
@@ -625,6 +719,17 @@ bool wxListBox::PerformAction(const wxControlAction& action,
|
|||||||
wxStdListboxInputHandler::wxStdListboxInputHandler(wxInputHandler *handler)
|
wxStdListboxInputHandler::wxStdListboxInputHandler(wxInputHandler *handler)
|
||||||
: wxStdInputHandler(handler)
|
: wxStdInputHandler(handler)
|
||||||
{
|
{
|
||||||
|
m_winCapture = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxStdListboxInputHandler::HitTest(const wxListBox *lbox,
|
||||||
|
const wxMouseEvent& event)
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
lbox->CalcUnscrolledPosition(0, event.GetPosition().y, NULL, &y);
|
||||||
|
int item = y / lbox->GetLineHeight();
|
||||||
|
|
||||||
|
return item < lbox->GetCount() ? item : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxStdListboxInputHandler::HandleKey(wxControl *control,
|
bool wxStdListboxInputHandler::HandleKey(wxControl *control,
|
||||||
@@ -664,14 +769,53 @@ bool wxStdListboxInputHandler::HandleKey(wxControl *control,
|
|||||||
bool wxStdListboxInputHandler::HandleMouse(wxControl *control,
|
bool wxStdListboxInputHandler::HandleMouse(wxControl *control,
|
||||||
const wxMouseEvent& event)
|
const wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
if ( event.LeftDown() )
|
// single and extended listboxes behave similarly with respect to the
|
||||||
|
// mouse events: for both of them clicking the item selects or toggles it,
|
||||||
|
// but multiple selection listboxes are different: the item is focused
|
||||||
|
// when clicked and only toggled when the button is released
|
||||||
|
if ( ((control->GetWindowStyle() & wxLB_MULTIPLE) && event.ButtonUp())
|
||||||
|
|| event.ButtonDown() || event.LeftDClick() )
|
||||||
{
|
{
|
||||||
wxListBox *lbox = wxStaticCast(control, wxListBox);
|
wxListBox *lbox = wxStaticCast(control, wxListBox);
|
||||||
int item = event.GetPosition().y / lbox->GetLineHeight();
|
int item = HitTest(lbox, event);
|
||||||
if ( item < lbox->GetCount() )
|
if ( item != -1 )
|
||||||
{
|
{
|
||||||
lbox->PerformAction(wxACTION_LISTBOX_SETFOCUS, item);
|
wxControlAction action;
|
||||||
lbox->PerformAction(wxACTION_LISTBOX_TOGGLE);
|
if ( event.ButtonUp() )
|
||||||
|
{
|
||||||
|
m_winCapture->ReleaseMouse();
|
||||||
|
m_winCapture = NULL;
|
||||||
|
|
||||||
|
action = wxACTION_LISTBOX_TOGGLE;
|
||||||
|
}
|
||||||
|
else if ( event.ButtonDown() )
|
||||||
|
{
|
||||||
|
if ( lbox->HasMultipleSelection() )
|
||||||
|
{
|
||||||
|
if ( lbox->GetWindowStyle() & wxLB_MULTIPLE )
|
||||||
|
{
|
||||||
|
// capture the mouse to track the selected item
|
||||||
|
m_winCapture = lbox;
|
||||||
|
m_winCapture->CaptureMouse();
|
||||||
|
|
||||||
|
action = wxACTION_LISTBOX_SETFOCUS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
action = wxACTION_LISTBOX_TOGGLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // single selection
|
||||||
|
{
|
||||||
|
action = wxACTION_LISTBOX_SELECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // event.LeftDClick()
|
||||||
|
{
|
||||||
|
action = wxACTION_LISTBOX_ACTIVATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbox->PerformAction(action, item);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -684,8 +828,29 @@ bool wxStdListboxInputHandler::HandleMouse(wxControl *control,
|
|||||||
bool wxStdListboxInputHandler::HandleMouseMove(wxControl *control,
|
bool wxStdListboxInputHandler::HandleMouseMove(wxControl *control,
|
||||||
const wxMouseEvent& event)
|
const wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
// we don't react to this at all
|
if ( !m_winCapture || (event.GetEventObject() != m_winCapture) )
|
||||||
|
{
|
||||||
|
// we don't react to this
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: not yet... should track the mouse outside and start an auto
|
||||||
|
// scroll timer - but this should be probably done in
|
||||||
|
// wxScrolledWindow itself (?)
|
||||||
|
if ( !event.Moving() )
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
wxListBox *lbox = wxStaticCast(control, wxListBox);
|
||||||
|
int item = HitTest(lbox, event);
|
||||||
|
if ( item == -1 )
|
||||||
|
{
|
||||||
|
// mouse is below the last item
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbox->PerformAction(wxACTION_LISTBOX_SETFOCUS, item);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_LISTBOX
|
#endif // wxUSE_LISTBOX
|
||||||
|
@@ -578,14 +578,22 @@ void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
|
|||||||
void wxControlRenderer::DrawItems(const wxListBox *lbox,
|
void wxControlRenderer::DrawItems(const wxListBox *lbox,
|
||||||
size_t itemFirst, size_t itemLast)
|
size_t itemFirst, size_t itemLast)
|
||||||
{
|
{
|
||||||
|
// prepare for the drawing: calc the initial position
|
||||||
wxCoord lineHeight = lbox->GetLineHeight();
|
wxCoord lineHeight = lbox->GetLineHeight();
|
||||||
|
int lines, pixelsPerLine;
|
||||||
|
lbox->GetViewStart(NULL, &lines);
|
||||||
|
lbox->GetScrollPixelsPerUnit(NULL, &pixelsPerLine);
|
||||||
wxRect rect = m_rect;
|
wxRect rect = m_rect;
|
||||||
rect.y += itemFirst*lineHeight;
|
rect.y += itemFirst*lineHeight - lines*pixelsPerLine;
|
||||||
rect.height = lineHeight;
|
rect.height = lineHeight;
|
||||||
|
|
||||||
|
// an item should have the focused rect only when the app has focus, so
|
||||||
|
// make sure that we never set wxCONTROL_FOCUSED flag if it doesn't
|
||||||
|
int itemCurrent = wxTheApp->IsActive() ? lbox->GetCurrentItem() : -1;
|
||||||
for ( size_t n = itemFirst; n < itemLast; n++ )
|
for ( size_t n = itemFirst; n < itemLast; n++ )
|
||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if ( (int)n == lbox->GetCurrentItem() )
|
if ( (int)n == itemCurrent )
|
||||||
flags |= wxCONTROL_FOCUSED;
|
flags |= wxCONTROL_FOCUSED;
|
||||||
if ( lbox->IsSelected(n) )
|
if ( lbox->IsSelected(n) )
|
||||||
flags |= wxCONTROL_SELECTED;
|
flags |= wxCONTROL_SELECTED;
|
||||||
|
@@ -111,6 +111,8 @@ public:
|
|||||||
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
|
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
|
||||||
int thumbPos = -1);
|
int thumbPos = -1);
|
||||||
virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
|
virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
|
||||||
|
virtual wxCoord GetListboxItemHeight(wxCoord fontHeight)
|
||||||
|
{ return fontHeight + 2; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// DrawBackground() helpers
|
// DrawBackground() helpers
|
||||||
@@ -393,7 +395,7 @@ wxGTKRenderer::wxGTKRenderer(const wxColourScheme *scheme)
|
|||||||
{
|
{
|
||||||
// init data
|
// init data
|
||||||
m_scheme = scheme;
|
m_scheme = scheme;
|
||||||
m_sizeScrollbarArrow = wxSize(16, 14);
|
m_sizeScrollbarArrow = wxSize(15, 14);
|
||||||
|
|
||||||
// init pens
|
// init pens
|
||||||
m_penBlack = wxPen(scheme->Get(wxColourScheme::SHADOW_DARK), 0, wxSOLID);
|
m_penBlack = wxPen(scheme->Get(wxColourScheme::SHADOW_DARK), 0, wxSOLID);
|
||||||
@@ -522,8 +524,8 @@ void wxGTKRenderer::DrawBorder(wxDC& dc,
|
|||||||
switch ( border )
|
switch ( border )
|
||||||
{
|
{
|
||||||
case wxBORDER_SUNKEN:
|
case wxBORDER_SUNKEN:
|
||||||
DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
|
DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
|
||||||
DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
|
DrawAntiShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxBORDER_STATIC:
|
case wxBORDER_STATIC:
|
||||||
@@ -721,6 +723,13 @@ void wxGTKRenderer::DrawItem(wxDC& dc,
|
|||||||
dc.SetTextForeground(m_scheme->Get(wxColourScheme::HIGHLIGHT_TEXT));
|
dc.SetTextForeground(m_scheme->Get(wxColourScheme::HIGHLIGHT_TEXT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( flags & wxCONTROL_FOCUSED )
|
||||||
|
{
|
||||||
|
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||||
|
wxRect rectFocus = rect;
|
||||||
|
DrawRect(dc, &rectFocus, m_penBlack);
|
||||||
|
}
|
||||||
|
|
||||||
wxRect rectText = rect;
|
wxRect rectText = rect;
|
||||||
rectText.x += 2;
|
rectText.x += 2;
|
||||||
rectText.y++;
|
rectText.y++;
|
||||||
@@ -784,6 +793,8 @@ void wxGTKRenderer::DrawArrowBorder(wxDC& dc,
|
|||||||
rect2.Inflate(-1);
|
rect2.Inflate(-1);
|
||||||
rectInner.Inflate(-2);
|
rectInner.Inflate(-2);
|
||||||
|
|
||||||
|
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR), *rect);
|
||||||
|
|
||||||
// find the side not to draw and also adjust the rectangles to compensate
|
// find the side not to draw and also adjust the rectangles to compensate
|
||||||
// for it
|
// for it
|
||||||
wxDirection sideToOmit;
|
wxDirection sideToOmit;
|
||||||
@@ -792,7 +803,7 @@ void wxGTKRenderer::DrawArrowBorder(wxDC& dc,
|
|||||||
case wxUP:
|
case wxUP:
|
||||||
sideToOmit = wxDOWN;
|
sideToOmit = wxDOWN;
|
||||||
rect2.height += 1;
|
rect2.height += 1;
|
||||||
rectInner.height += 2;
|
rectInner.height += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxDOWN:
|
case wxDOWN:
|
||||||
@@ -800,13 +811,13 @@ void wxGTKRenderer::DrawArrowBorder(wxDC& dc,
|
|||||||
rect2.y -= 1;
|
rect2.y -= 1;
|
||||||
rect2.height += 1;
|
rect2.height += 1;
|
||||||
rectInner.y -= 2;
|
rectInner.y -= 2;
|
||||||
rectInner.height += 2;
|
rectInner.height += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxLEFT:
|
case wxLEFT:
|
||||||
sideToOmit = wxRIGHT;
|
sideToOmit = wxRIGHT;
|
||||||
rect2.width += 1;
|
rect2.width += 1;
|
||||||
rectInner.width += 2;
|
rectInner.width += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxRIGHT:
|
case wxRIGHT:
|
||||||
@@ -814,7 +825,7 @@ void wxGTKRenderer::DrawArrowBorder(wxDC& dc,
|
|||||||
rect2.x -= 1;
|
rect2.x -= 1;
|
||||||
rect2.width += 1;
|
rect2.width += 1;
|
||||||
rectInner.x -= 2;
|
rectInner.x -= 2;
|
||||||
rectInner.width += 2;
|
rectInner.width += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -844,7 +855,6 @@ void wxGTKRenderer::DrawArrowBorder(wxDC& dc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*rect = rectInner;
|
*rect = rectInner;
|
||||||
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR), rectInner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// gtk_default_draw_arrow() takes ~350 lines and we can't do much better here
|
// gtk_default_draw_arrow() takes ~350 lines and we can't do much better here
|
||||||
|
@@ -128,6 +128,8 @@ public:
|
|||||||
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
|
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
|
||||||
int thumbPos = -1);
|
int thumbPos = -1);
|
||||||
virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
|
virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
|
||||||
|
virtual wxCoord GetListboxItemHeight(wxCoord fontHeight)
|
||||||
|
{ return fontHeight + 2; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// common part of DrawLabel() and DrawItem()
|
// common part of DrawLabel() and DrawItem()
|
||||||
|
@@ -289,6 +289,8 @@ void wxWindow::SetScrollbar(int orient,
|
|||||||
bool refresh)
|
bool refresh)
|
||||||
{
|
{
|
||||||
wxScrollBar *scrollbar = GetScrollbar(orient);
|
wxScrollBar *scrollbar = GetScrollbar(orient);
|
||||||
|
if ( range )
|
||||||
|
{
|
||||||
if ( !scrollbar )
|
if ( !scrollbar )
|
||||||
{
|
{
|
||||||
// create it
|
// create it
|
||||||
@@ -306,6 +308,19 @@ void wxWindow::SetScrollbar(int orient,
|
|||||||
|
|
||||||
scrollbar->SetScrollbar(pos, thumb, range, thumb, refresh);
|
scrollbar->SetScrollbar(pos, thumb, range, thumb, refresh);
|
||||||
}
|
}
|
||||||
|
else // no range means no scrollbar
|
||||||
|
{
|
||||||
|
if ( scrollbar )
|
||||||
|
{
|
||||||
|
delete scrollbar;
|
||||||
|
|
||||||
|
if ( orient & wxVERTICAL )
|
||||||
|
m_scrollbarVert = NULL;
|
||||||
|
else
|
||||||
|
m_scrollbarHorz = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
|
void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user