From d0a84b63384ca1c1d8d20581fb56abbd1d826617 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Wed, 14 Jun 2006 15:54:24 +0000
Subject: [PATCH] fill in flags parameter of HitTest() for all book controls;
 added new wxNB_HITTEST_ONPAGE bit

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39719 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/notebook.tex    |  1 +
 include/wx/notebook.h         |  3 +-
 include/wx/toolbook.h         | 12 +++++--
 samples/notebook/notebook.cpp | 61 +++++++++++++++++++++++++++++------
 samples/notebook/notebook.h   |  7 +++-
 src/common/bookctrl.cpp       |  4 +--
 src/generic/listbkg.cpp       | 31 ++++++++++++++----
 src/generic/toolbkg.cpp       | 33 +++++++++++++++++++
 src/generic/treebkg.cpp       | 30 +++++++++++++++--
 src/gtk/notebook.cpp          | 15 +++++++++
 src/msw/notebook.cpp          |  2 ++
 11 files changed, 173 insertions(+), 26 deletions(-)

diff --git a/docs/latex/wx/notebook.tex b/docs/latex/wx/notebook.tex
index 82e7e3f24e..b7ca119732 100644
--- a/docs/latex/wx/notebook.tex
+++ b/docs/latex/wx/notebook.tex
@@ -287,6 +287,7 @@ inside the tab is returned as well.
 \twocolitem{{\bf wxNB\_HITTEST\_ONICON}}{The point was over an icon (currently wxMSW only).}
 \twocolitem{{\bf wxNB\_HITTEST\_ONLABEL}}{The point was over a label (currently wxMSW only).}
 \twocolitem{{\bf wxNB\_HITTEST\_ONITEM}}{The point was over an item, but not on the label or icon.}
+\twocolitem{{\bf wxNB\_HITTEST\_ONPAGE}}{The point was over a currently selected page, not over any tab. Note that this flag is present only if {\tt wxNOT\_FOUND} is returned.}
 \end{twocollist}
 }
 
diff --git a/include/wx/notebook.h b/include/wx/notebook.h
index ec2065c5e3..bb36c49302 100644
--- a/include/wx/notebook.h
+++ b/include/wx/notebook.h
@@ -32,7 +32,8 @@ enum
     wxNB_HITTEST_NOWHERE = 1,   // not on tab
     wxNB_HITTEST_ONICON  = 2,   // on icon
     wxNB_HITTEST_ONLABEL = 4,   // on label
-    wxNB_HITTEST_ONITEM  = wxNB_HITTEST_ONICON | wxNB_HITTEST_ONLABEL
+    wxNB_HITTEST_ONITEM  = wxNB_HITTEST_ONICON | wxNB_HITTEST_ONLABEL,
+    wxNB_HITTEST_ONPAGE  = 8    // not on tab control, but over the selected page
 };
 
 typedef wxWindow wxNotebookPage;  // so far, any window can be a page
diff --git a/include/wx/toolbook.h b/include/wx/toolbook.h
index 472054e467..1227d82483 100644
--- a/include/wx/toolbook.h
+++ b/include/wx/toolbook.h
@@ -57,6 +57,7 @@ public:
                 const wxString& name = wxEmptyString);
 
 
+    // implement base class virtuals
     virtual int GetSelection() const;
     virtual bool SetPageText(size_t n, const wxString& strText);
     virtual wxString GetPageText(size_t n) const;
@@ -72,11 +73,16 @@ public:
     virtual void SetImageList(wxImageList *imageList);
 
     virtual bool DeleteAllPages();
+    virtual int HitTest(const wxPoint& pt, long *flags = NULL) const;
 
+
+    // methods which are not part of base wxBookctrl API
+
+    // get the underlying toolbar
     wxToolBarBase* GetToolBar() const { return (wxToolBarBase*)m_bookctrl; }
 
-    // Not part of the wxBookctrl API, but must be called in OnIdle or
-    // by application to realize the toolbar and select the initial page.
+    // must be called in OnIdle or by application to realize the toolbar and
+    // select the initial page.
     void Realize();
 
 protected:
@@ -97,7 +103,7 @@ protected:
     bool m_needsRealizing;
 
     // maximum bitmap size
-    wxSize  m_maxBitmapSize;
+    wxSize m_maxBitmapSize;
 
 private:
     // common part of all constructors
diff --git a/samples/notebook/notebook.cpp b/samples/notebook/notebook.cpp
index b0eb08c72f..a3d0d45d72 100644
--- a/samples/notebook/notebook.cpp
+++ b/samples/notebook/notebook.cpp
@@ -22,6 +22,8 @@
 
 #include "wx/imaglist.h"
 #include "wx/artprov.h"
+#include "wx/cshelp.h"
+#include "wx/utils.h"
 #include "notebook.h"
 
 #if !defined(__WXMSW__) && !defined(__WXPM__)
@@ -177,7 +179,7 @@ wxPanel *CreatePage(wxBookCtrlBase *parent, const wxString&pageName)
 }
 
 MyFrame::MyFrame()
-       : wxFrame(NULL, wxID_ANY,  wxString(wxT("wxWidgets book controls sample")))
+    : wxFrame(NULL, wxID_ANY,  wxString(wxT("wxWidgets book controls sample")))
 {
 #if wxUSE_NOTEBOOK
     m_type = Type_Notebook;
@@ -224,18 +226,21 @@ MyFrame::MyFrame()
     menuOrient->AppendRadioItem(ID_ORIENT_LEFT,    wxT("&Left\tCtrl-8"));
     menuOrient->AppendRadioItem(ID_ORIENT_RIGHT,   wxT("&Right\tCtrl-9"));
 
-    wxMenu *menuOperations = new wxMenu;
-    menuOperations->Append(ID_ADD_PAGE, wxT("&Add page\tAlt-A"));
-    menuOperations->Append(ID_INSERT_PAGE, wxT("&Insert page\tAlt-I"));
-    menuOperations->Append(ID_DELETE_CUR_PAGE, wxT("&Delete current page\tAlt-D"));
-    menuOperations->Append(ID_DELETE_LAST_PAGE, wxT("D&elete last page\tAlt-L"));
-    menuOperations->Append(ID_NEXT_PAGE, wxT("&Next page\tAlt-N"));
+    wxMenu *menuPageOperations = new wxMenu;
+    menuPageOperations->Append(ID_ADD_PAGE, wxT("&Add page\tAlt-A"));
+    menuPageOperations->Append(ID_INSERT_PAGE, wxT("&Insert page\tAlt-I"));
+    menuPageOperations->Append(ID_DELETE_CUR_PAGE, wxT("&Delete current page\tAlt-D"));
+    menuPageOperations->Append(ID_DELETE_LAST_PAGE, wxT("D&elete last page\tAlt-L"));
+    menuPageOperations->Append(ID_NEXT_PAGE, wxT("&Next page\tAlt-N"));
 #if wxUSE_TREEBOOK
-    menuOperations->AppendSeparator();
-    menuOperations->Append(ID_ADD_PAGE_BEFORE, wxT("Insert page &before\tAlt-B"));
-    menuOperations->Append(ID_ADD_SUB_PAGE, wxT("Add s&ub page\tAlt-U"));
+    menuPageOperations->AppendSeparator();
+    menuPageOperations->Append(ID_ADD_PAGE_BEFORE, wxT("Insert page &before\tAlt-B"));
+    menuPageOperations->Append(ID_ADD_SUB_PAGE, wxT("Add s&ub page\tAlt-U"));
 #endif
 
+    wxMenu *menuOperations = new wxMenu;
+    menuOperations->Append(ID_HITTEST, wxT("&Hit test\tCtrl-H"));
+
     wxMenu *menuFile = new wxMenu;
     menuFile->Append(wxID_ANY, wxT("&Type"), menuType, wxT("Type of control"));
     menuFile->Append(wxID_ANY, wxT("&Orientation"), menuOrient, wxT("Orientation of control"));
@@ -248,6 +253,7 @@ MyFrame::MyFrame()
 
     wxMenuBar *menuBar = new wxMenuBar;
     menuBar->Append(menuFile, wxT("&File"));
+    menuBar->Append(menuPageOperations, wxT("&Pages"));
     menuBar->Append(menuOperations, wxT("&Operations"));
     SetMenuBar(menuBar);
 
@@ -481,6 +487,8 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(ID_DELETE_LAST_PAGE, MyFrame::OnDeleteLastPage)
     EVT_MENU(ID_NEXT_PAGE, MyFrame::OnNextPage)
 
+    EVT_MENU(ID_HITTEST, MyFrame::OnHitTest)
+
     // Book controls
 #if wxUSE_NOTEBOOK
     EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, MyFrame::OnNotebook)
@@ -512,6 +520,38 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_IDLE(MyFrame::OnIdle)
 END_EVENT_TABLE()
 
+void MyFrame::AddFlagStrIfFlagPresent(wxString & flagStr, long flags, long flag, const wxChar * flagName) const
+{
+    if( (flags & flag) == flag )
+    {
+        if( !flagStr.empty() )
+            flagStr += _T(" | ");
+        flagStr += flagName;
+    }
+}
+
+void MyFrame::OnHitTest(wxCommandEvent& WXUNUSED(event))
+{
+    wxBookCtrlBase * book = GetCurrentBook();
+    const wxPoint pt = ::wxGetMousePosition();
+
+    long flags;
+    int pagePos = book->HitTest( book->ScreenToClient(pt), &flags );
+
+    wxString flagsStr;
+
+    AddFlagStrIfFlagPresent( flagsStr, flags, wxNB_HITTEST_NOWHERE, _T("wxNB_HITTEST_NOWHERE") );
+    AddFlagStrIfFlagPresent( flagsStr, flags, wxNB_HITTEST_ONICON,  _T("wxNB_HITTEST_ONICON") );
+    AddFlagStrIfFlagPresent( flagsStr, flags, wxNB_HITTEST_ONLABEL, _T("wxNB_HITTEST_ONLABEL") );
+    AddFlagStrIfFlagPresent( flagsStr, flags, wxNB_HITTEST_ONPAGE,  _T("wxNB_HITTEST_ONPAGE") );
+
+    wxLogMessage(wxT("HitTest at (%d,%d): %d: %s"),
+                 pt.x,
+                 pt.y,
+                 pagePos,
+                 flagsStr.c_str());
+}
+
 void MyFrame::OnType(wxCommandEvent& event)
 {
     m_type = wx_static_cast(BookType, event.GetId() - ID_BOOK_NOTEBOOK);
@@ -562,6 +602,7 @@ void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
 wxPanel *MyFrame::CreateNewPage() const
 {
     wxPanel *panel = new wxPanel(m_bookCtrl, wxID_ANY );
+
     (void) new wxButton(panel, wxID_ANY, wxT("First button"), wxPoint(10, 10));
     (void) new wxButton(panel, wxID_ANY, wxT("Second button"), wxPoint(50, 100));
 
diff --git a/samples/notebook/notebook.h b/samples/notebook/notebook.h
index e194dbf5db..776edf7d14 100644
--- a/samples/notebook/notebook.h
+++ b/samples/notebook/notebook.h
@@ -52,6 +52,8 @@ public:
     void OnAddSubPage(wxCommandEvent& event);
     void OnAddPageBefore(wxCommandEvent& event);
 
+    void OnHitTest(wxCommandEvent& event);
+
     void OnBookCtrl(wxBookCtrlBaseEvent& event);
 #if wxUSE_NOTEBOOK
     void OnNotebook(wxNotebookEvent& event) { OnBookCtrl(event); }
@@ -83,6 +85,7 @@ private:
     void RecreateBook();
     wxPanel *CreateNewPage() const;
     int TranslateBookFlag(int nb, int lb, int chb, int tbk, int toolbk) const;
+    void AddFlagStrIfFlagPresent(wxString & flagStr, long flags, long flag, const wxChar * flagName) const;
 
     // Sample setup
     enum BookType
@@ -139,7 +142,9 @@ enum ID_COMMANDS
     ID_DELETE_LAST_PAGE,
     ID_NEXT_PAGE,
     ID_ADD_PAGE_BEFORE,
-    ID_ADD_SUB_PAGE
+    ID_ADD_SUB_PAGE,
+
+    ID_HITTEST
 };
 
 /*
diff --git a/src/common/bookctrl.cpp b/src/common/bookctrl.cpp
index 16e4cf3e9a..a0c4781508 100644
--- a/src/common/bookctrl.cpp
+++ b/src/common/bookctrl.cpp
@@ -186,9 +186,9 @@ void wxBookCtrlBase::OnHelp(wxHelpEvent& event)
             page = GetPage((size_t)pagePos);
         }
     }
-
-    if ( !page )
+    else // event.GetOrigin() != wxHelpEvent::Origin_HelpButton
     {
+        // if event came from keyboard then show the current page help
         page = GetCurrentPage();
     }
 
diff --git a/src/generic/listbkg.cpp b/src/generic/listbkg.cpp
index f096095e55..c29bf85131 100644
--- a/src/generic/listbkg.cpp
+++ b/src/generic/listbkg.cpp
@@ -161,22 +161,41 @@ void wxListbook::OnSize(wxSizeEvent& event)
     wxBookCtrlBase::OnSize(event);
 }
 
-int wxListbook::HitTest(const wxPoint& pt, long * WXUNUSED(flags)) const
+int wxListbook::HitTest(const wxPoint& pt, long *flags) const
 {
     int pagePos = wxNOT_FOUND;
 
-    const wxPoint clientPt = ClientToScreen(GetListView()->ScreenToClient(pt));
+    if ( flags )
+        *flags = wxNB_HITTEST_NOWHERE;
 
-    if ( wxRect(GetListView()->GetSize()).Inside(clientPt) )
+    // convert from listbook control coordinates to list control coordinates
+    const wxListView * const list = GetListView();
+    const wxPoint listPt = list->ScreenToClient(ClientToScreen(pt));
+
+    // is the point inside list control?
+    if ( wxRect(list->GetSize()).Inside(listPt) )
     {
         int flagsList;
-        pagePos = GetListView()->HitTest(clientPt, flagsList);
+        pagePos = list->HitTest(listPt, flagsList);
 
-        if ( !(flagsList & wxLIST_HITTEST_ONITEM) )
+        if ( flags )
         {
-            pagePos = wxNOT_FOUND;
+            if ( pagePos != wxNOT_FOUND )
+                *flags = 0;
+
+            if ( flagsList & (wxLIST_HITTEST_ONITEMICON |
+                              wxLIST_HITTEST_ONITEMSTATEICON ) )
+                *flags |= wxNB_HITTEST_ONICON;
+
+            if ( flagsList & wxLIST_HITTEST_ONITEMLABEL )
+                *flags |= wxNB_HITTEST_ONLABEL;
         }
     }
+    else // not over list control at all
+    {
+        if ( flags && GetPageRect().Inside(pt) )
+            *flags |= wxNB_HITTEST_ONPAGE;
+    }
 
     return pagePos;
 }
diff --git a/src/generic/toolbkg.cpp b/src/generic/toolbkg.cpp
index e0cbd98b81..0822ab0ae8 100644
--- a/src/generic/toolbkg.cpp
+++ b/src/generic/toolbkg.cpp
@@ -309,6 +309,39 @@ void wxToolbook::Realize()
     DoSize();
 }
 
+int wxToolbook::HitTest(const wxPoint& pt, long *flags) const
+{
+    int pagePos = wxNOT_FOUND;
+
+    if ( flags )
+        *flags = wxNB_HITTEST_NOWHERE;
+
+    // convert from wxToolbook coordinates to wxToolBar ones
+    const wxToolBarBase * const tbar = GetToolBar();
+    const wxPoint tbarPt = tbar->ScreenToClient(ClientToScreen(pt));
+
+    // is the point over the toolbar?
+    if ( wxRect(tbar->GetSize()).Inside(tbarPt) )
+    {
+        const wxToolBarToolBase * const
+            tool = tbar->FindToolForPosition(tbarPt.x, tbarPt.y);
+
+        if ( tool )
+        {
+            pagePos = tbar->GetToolPos(tool->GetId());
+            if ( flags )
+                *flags = wxNB_HITTEST_ONICON | wxNB_HITTEST_ONLABEL;
+        }
+    }
+    else // not over the toolbar
+    {
+        if ( flags && GetPageRect().Inside(pt) )
+            *flags |= wxNB_HITTEST_ONPAGE;
+    }
+
+    return pagePos;
+}
+
 void wxToolbook::OnIdle(wxIdleEvent& event)
 {
     if (m_needsRealizing)
diff --git a/src/generic/treebkg.cpp b/src/generic/treebkg.cpp
index 57593a5bb1..fcf10b9d35 100644
--- a/src/generic/treebkg.cpp
+++ b/src/generic/treebkg.cpp
@@ -723,13 +723,18 @@ void wxTreebook::OnTreeNodeExpandedCollapsed(wxTreeEvent & event)
 // wxTreebook geometry management
 // ----------------------------------------------------------------------------
 
-int wxTreebook::HitTest(wxPoint const & pt, long * WXUNUSED(flags)) const
+int wxTreebook::HitTest(wxPoint const & pt, long * flags) const
 {
     int pagePos = wxNOT_FOUND;
 
-    wxTreeCtrl * const tree = GetTreeCtrl();
-    const wxPoint treePt = ClientToScreen(tree->ScreenToClient(pt));
+    if ( flags )
+        *flags = wxNB_HITTEST_NOWHERE;
 
+    // convert from wxTreebook coorindates to wxTreeCtrl ones
+    const wxTreeCtrl * const tree = GetTreeCtrl();
+    const wxPoint treePt = tree->ScreenToClient(ClientToScreen(pt));
+
+    // is it over the tree?
     if ( wxRect(tree->GetSize()).Inside(treePt) )
     {
         int flagsTree;
@@ -739,6 +744,25 @@ int wxTreebook::HitTest(wxPoint const & pt, long * WXUNUSED(flags)) const
         {
             pagePos = DoInternalFindPageById(id);
         }
+
+        if ( flags )
+        {
+            if ( pagePos != wxNOT_FOUND )
+                *flags = 0;
+
+            if ( flagsTree & (wxTREE_HITTEST_ONITEMBUTTON |
+                              wxTREE_HITTEST_ONITEMICON |
+                              wxTREE_HITTEST_ONITEMSTATEICON) )
+                *flags |= wxNB_HITTEST_ONICON;
+
+            if ( flagsTree & wxTREE_HITTEST_ONITEMLABEL )
+                *flags |= wxNB_HITTEST_ONLABEL;
+        }
+    }
+    else // not over the tree
+    {
+        if ( flags && GetPageRect().Inside( pt ) )
+            *flags |= wxNB_HITTEST_ONPAGE;
     }
 
     return pagePos;
diff --git a/src/gtk/notebook.cpp b/src/gtk/notebook.cpp
index 2e144a6a0b..25efc437f8 100644
--- a/src/gtk/notebook.cpp
+++ b/src/gtk/notebook.cpp
@@ -795,7 +795,22 @@ int wxNotebook::HitTest(const wxPoint& pt, long *flags) const
     }
 
     if ( flags )
+    {
         *flags = wxNB_HITTEST_NOWHERE;
+        wxWindowBase * page = GetCurrentPage();
+        if ( page )
+        {
+            // rect origin is in notebook's parent coordinates
+            wxRect rect = page->GetRect();
+
+            // adjust it to the notebook's coordinates
+            wxPoint pos = GetPosition();
+            rect.x -= pos.x;
+            rect.y -= pos.y;
+            if ( rect.Inside( pt ) )
+                *flags |= wxNB_HITTEST_ONPAGE;
+        }
+    }
 
     return wxNOT_FOUND;
 }
diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp
index 0d8d2bb56d..f34fcbc97b 100644
--- a/src/msw/notebook.cpp
+++ b/src/msw/notebook.cpp
@@ -818,6 +818,8 @@ int wxNotebook::HitTest(const wxPoint& pt, long *flags) const
             *flags |= wxNB_HITTEST_ONICON;
         if ((hitTestInfo.flags & TCHT_ONITEMLABEL) == TCHT_ONITEMLABEL)
             *flags |= wxNB_HITTEST_ONLABEL;
+        if ( item == wxNOT_FOUND && GetPageSize().Inside(pt) )
+            *flags |= wxNB_HITTEST_ONPAGE;
     }
 
     return item;
-- 
2.50.0

