From c00fed0ef4d70c9b45d9b8405f636d30eadb7ea6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 9 Mar 2006 12:48:52 +0000 Subject: [PATCH] added wxListBox::HitTest() from Ryan (patch 1446207) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37923 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + docs/latex/wx/listbox.tex | 19 +++++++++ include/wx/gtk/listbox.h | 2 + include/wx/listbox.h | 7 +++ include/wx/mac/carbon/listbox.h | 1 + include/wx/msw/listbox.h | 1 + samples/listbox/lboxtest.cpp | 16 +++++++ src/gtk/listbox.cpp | 24 +++++++++++ src/mac/carbon/listbox.cpp | 76 +++++++++++++++++++++++++++++++++ src/msw/listbox.cpp | 10 +++++ 10 files changed, 157 insertions(+) diff --git a/docs/changes.txt b/docs/changes.txt index d8f127eca3..053ee2f8b1 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -91,6 +91,7 @@ All (GUI): - Implemented wxDisplay::GetFromWindow() for platforms other than MSW. - UpdateUI handler can now show/hide the window too (Ronald Weiss) - More than one filter allowed in in wxDocTemplate filter. +- Added wxListBox::HitTest() wxMSW: diff --git a/docs/latex/wx/listbox.tex b/docs/latex/wx/listbox.tex index 649ba91e59..75e7b48b5b 100644 --- a/docs/latex/wx/listbox.tex +++ b/docs/latex/wx/listbox.tex @@ -201,6 +201,25 @@ parameter for wxPython, which is a list of strings.} \perlnote{In wxPerl there is just an array reference in place of {\tt nItems} and {\tt items}.} +\membersection{wxListBox::HitTest}\label{wxlistboxhittest} + +\constfunc{int}{HitTest}{\param{const wxPoint&}{ point}} + +Returns the item located at \arg{point}, or \texttt{wxNOT\_FOUND} if there +is no item located at \arg{point}. + +\newsince{2.7.0}. It is currently implemented for wxMSW, wxMac and wxGTK2 +ports. + +\wxheading{Parameters} + +\docparam{point}{Point of item (in client coordinates) to obtain} + +\wxheading{Return value} + +Item located at \arg{point}, or \texttt{wxNOT\_FOUND} if unimplemented +or the item does not exist. + \membersection{wxListBox::IsSelected}\label{wxlistboxisselected} \constfunc{bool}{IsSelected}{\param{int}{ n}} diff --git a/include/wx/gtk/listbox.h b/include/wx/gtk/listbox.h index 0acc30272e..7804a96625 100644 --- a/include/wx/gtk/listbox.h +++ b/include/wx/gtk/listbox.h @@ -114,6 +114,8 @@ protected: virtual void* DoGetItemClientData(int n) const; virtual void DoSetItemClientObject(int n, wxClientData* clientData); virtual wxClientData* DoGetItemClientObject(int n) const; + virtual int DoListHitTest(const wxPoint& point) const; + void DoApplyWidgetStyle(GtkRcStyle *style); private: diff --git a/include/wx/listbox.h b/include/wx/listbox.h index 0556f805cf..d22b0f47d3 100644 --- a/include/wx/listbox.h +++ b/include/wx/listbox.h @@ -107,6 +107,9 @@ public: // instead bool Selected(int n) const { return IsSelected(n); } + // returns the item number at a point or wxNOT_FOUND + int HitTest(const wxPoint& point) const { return DoListHitTest(point); } + protected: // NB: due to wxGTK implementation details, DoInsert() is implemented // using DoInsertItems() and not the other way round @@ -121,6 +124,10 @@ protected: virtual void DoSetSelection(int n, bool select) = 0; + // there is already wxWindow::DoHitTest() so call this one differently + virtual int DoListHitTest(const wxPoint& WXUNUSED(point)) const + { return wxNOT_FOUND; } + DECLARE_NO_COPY_CLASS(wxListBoxBase) }; diff --git a/include/wx/mac/carbon/listbox.h b/include/wx/mac/carbon/listbox.h index 0d55320f54..7aa58cc559 100644 --- a/include/wx/mac/carbon/listbox.h +++ b/include/wx/mac/carbon/listbox.h @@ -113,6 +113,7 @@ protected: virtual void DoSetItemClientObject(int n, wxClientData* clientData); virtual wxClientData* DoGetItemClientObject(int n) const; virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); + virtual int DoListHitTest(const wxPoint& point) const; void MacDelete( int n ) ; void MacInsert( int n , const wxString& item) ; diff --git a/include/wx/msw/listbox.h b/include/wx/msw/listbox.h index 46acf9a572..1ed147948b 100644 --- a/include/wx/msw/listbox.h +++ b/include/wx/msw/listbox.h @@ -142,6 +142,7 @@ protected: virtual void* DoGetItemClientData(int n) const; virtual void DoSetItemClientObject(int n, wxClientData* clientData); virtual wxClientData* DoGetItemClientObject(int n) const; + virtual int DoListHitTest(const wxPoint& point) const; // free memory (common part of Clear() and dtor) void Free(); diff --git a/samples/listbox/lboxtest.cpp b/samples/listbox/lboxtest.cpp index 8f92c1920a..d2bbec8e79 100644 --- a/samples/listbox/lboxtest.cpp +++ b/samples/listbox/lboxtest.cpp @@ -124,6 +124,7 @@ protected: void OnListbox(wxCommandEvent& event); void OnListboxDClick(wxCommandEvent& event); + void OnListboxRDown(wxMouseEvent& event); void OnCheckOrRadioBox(wxCommandEvent& event); @@ -487,6 +488,9 @@ LboxTestFrame::LboxTestFrame(const wxString& title) m_logTarget = new LboxLogger(m_lboxLog, wxLog::GetActiveTarget()); wxLog::SetActiveTarget(m_logTarget); #endif // wxUSE_LOG + + m_lbox->Connect(wxEVT_RIGHT_DOWN, + wxMouseEventHandler(LboxTestFrame::OnListboxRDown), NULL, this); } LboxTestFrame::~LboxTestFrame() @@ -699,6 +703,18 @@ void LboxTestFrame::OnListboxDClick(wxCommandEvent& event) wxLogMessage(_T("Listbox item %d double clicked"), sel); } +void LboxTestFrame::OnListboxRDown(wxMouseEvent& event) +{ + int item = m_lbox->HitTest(event.GetPosition()); + + if ( item != wxNOT_FOUND ) + wxLogMessage(_T("Listbox item %d right clicked"), item); + else + wxLogMessage(_T("Listbox right clicked but no item clicked upon")); + + event.Skip(); +} + void LboxTestFrame::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event)) { m_dirty = true; diff --git a/src/gtk/listbox.cpp b/src/gtk/listbox.cpp index f6dd76bf7d..42a5fe109a 100644 --- a/src/gtk/listbox.cpp +++ b/src/gtk/listbox.cpp @@ -1015,6 +1015,30 @@ void wxListBox::DoSetFirstItem( int n ) gtk_adjustment_set_value( adjustment, y ); } +// ---------------------------------------------------------------------------- +// hittest +// ---------------------------------------------------------------------------- + +int wxListBox::DoListHitTest(const wxPoint& point) +{ + //Need to translate from master window since it is in client coords + gint binx, biny; + gdk_window_get_geometry(gtk_tree_view_get_bin_window(m_treeview), + &binx, &biny, NULL, NULL, NULL); + + GtkTreePath* path; + if(!gtk_tree_view_get_path_at_pos(m_treeview, + point.x - binx, point.y - biny, + &path, NULL, NULL, NULL)) //last two == x,y rel to cell + { + return wxNOT_FOUND; + } + + int index = gtk_tree_path_get_indices(path)[0]; + gtk_tree_path_free(path); + + return index; +} // ---------------------------------------------------------------------------- // helpers diff --git a/src/mac/carbon/listbox.cpp b/src/mac/carbon/listbox.cpp index 8d55c0f0ba..1dc7a3c2e4 100644 --- a/src/mac/carbon/listbox.cpp +++ b/src/mac/carbon/listbox.cpp @@ -782,6 +782,82 @@ void wxListBox::MacScrollTo( int n ) verify_noerr( m_peer->RevealItem( id , kTextColumnId , kDataBrowserRevealWithoutSelecting ) ) ; } +int wxListBox::DoListHitTest(const wxPoint& point) const +{ + //Yuck - there is no easy way to get a databrowseritem from a point + //so we need to iterate through our items to see which one this falls under + int count = GetCount(); + DataBrowserTableViewColumnID colId = 0; + + //Get column property id (req. for call to itempartbounds) + GetDataBrowserTableViewColumnProperty(m_peer->GetControlRef(), 0, &colId); + + for(int i = 1; i <= count; ++i) + { + Rect bounds; + GetDataBrowserItemPartBounds(m_peer->GetControlRef(), i, colId, + kDataBrowserPropertyEnclosingPart, + &bounds); + + //translate to client coords + MacRootWindowToWindow(&bounds.left, &bounds.top); + MacRootWindowToWindow(&bounds.right, &bounds.bottom); + +#if 0 //debugging :) + wxPrintf(wxT("L:%i R:%i T:%i B:%i HT:%i,%i\n"), + bounds.left, bounds.right, + bounds.top, bounds.bottom, + point.x, point.y); + fflush(stdout); +#endif + //if point is within the bounds, return this item + if( (point.x >= bounds.left && point.x <= bounds.right) && + (point.y >= bounds.top && point.y <= bounds.bottom) ) + { + return i - 1; //found + } + } + + return wxNOT_FOUND; +} + +int wxListBox::MacHitTest(const wxPoint& point) +{ + //Yuck - there is no easy way to get a databrowseritem from a point + //so we need to iterate through our items to see which one this falls under + + // TODO: binary search would be faster + int count = GetCount(); + DataBrowserTableViewColumnID colId = 0; + + //Get column property id (req. for call to itempartbounds) + GetDataBrowserTableViewColumnProperty(m_peer->GetControlRef(), 0, &colId); + + for(int i = 1; i <= count; ++i) + { + Rect bounds; + GetDataBrowserItemPartBounds(m_peer->GetControlRef(), i, colId, + kDataBrowserPropertyEnclosingPart, + &bounds); + + //translate to client coords + // + // TODO: it would probably be more efficient to translate point to + // screen coordinates once outside of the loop + MacRootWindowToWindow(&bounds.left, &bounds.top); + MacRootWindowToWindow(&bounds.right, &bounds.bottom); + + //if point is within the bounds, return this item + if( (point.x >= bounds.left && point.x <= bounds.right) && + (point.y >= bounds.top && point.y <= bounds.bottom) ) + { + return i - 1; //found + } + } + + return wxNOT_FOUND; +} + #if !TARGET_API_MAC_OSX void wxListBox::OnChar(wxKeyEvent& event) diff --git a/src/msw/listbox.cpp b/src/msw/listbox.cpp index 1f8a77955d..7abbf18e2b 100644 --- a/src/msw/listbox.cpp +++ b/src/msw/listbox.cpp @@ -552,6 +552,16 @@ wxListBox::DoInsertItems(const wxArrayString& items, int pos) InvalidateBestSize(); } +int wxListBox::DoListHitTest(const wxPoint& point) const +{ + LRESULT lRes = ::SendMessage(GetHwnd(), LB_ITEMFROMPOINT, + 0L, MAKELONG(point.x, point.y)); + + // non zero high-order word means that this item is outside of the client + // area, IOW the point is outside of the listbox + return HIWORD(lRes) ? wxNOT_FOUND : lRes; +} + void wxListBox::SetString(int N, const wxString& s) { wxCHECK_RET( N >= 0 && N < m_noItems, -- 2.47.2