NCBI C++ ToolKit
sticky_tooltip_handler.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef GGUI_WIDGETS_WX___STICKY_TOOL_HANDLER__HPP
2 #define GGUI_WIDGETS_WX___STICKY_TOOL_HANDLER__HPP
3  /* ===========================================================================
4  *
5  * PUBLIC DOMAIN NOTICE
6  * National Center for Biotechnology Information
7  *
8  * This software/database is a "United States Government Work" under the
9  * terms of the United States Copyright Act. It was written as part of
10  * the author's official duties as a United States Government employee and
11  * thus cannot be copyrighted. This software/database is freely available
12  * to the public for use. The National Library of Medicine and the U.S.
13  * Government have not placed any restriction on its use or reproduction.
14  *
15  * Although all reasonable efforts have been taken to ensure the accuracy
16  * and reliability of the software and data, the NLM and the U.S.
17  * Government do not and cannot warrant the performance or results that
18  * may be obtained by using this software or data. The NLM and the U.S.
19  * Government disclaim all warranties, express or implied, including
20  * warranties of performance, merchantability or fitness for any particular
21  * purpose.
22  *
23  * Please cite the author in any work or product based on this material.
24  *
25  * ===========================================================================
26  *
27  * Authors: Bob Falk
28  *
29  * File Description:
30  *
31  * For a class to support sticky tool tips, it needs to:
32  *
33  * 1. Be derived from IStickyTooltipHandlerHost. CGlWidgetPane (gl_widget_base.hpp)
34  * already is, so GL windows derived from CGlWidgetPane already have this. This
35  * derived class defines the virtual functions TTHH_GetWindow and
36  * TTHH_TTHH_PopupMenuDisplayed.
37  *
38  * 2. Call the IStickyTooltipHandlerHost TTHH_Init() after construction (to get
39  * a pointer to the underlying window). CGlWidgetPane already does this.
40  *
41  * 3. In the implementation of the class that needs sticky tool tip support,
42  * e.g. CPhyloTreePane (phylo_tree_pane.hpp), implement the virtual functions
43  * that determine if a tool tip is needed: TTHH_NeedTooltip(const wxPoint & pt)
44  * and that returns the contents (string with line breaks) for the tool tip:
45  * TTHH_GetTooltip(const wxRect & rect). Note that the "NeedTooltip" function
46  * must return a string that serves as a unique id within the window that
47  * is implementing tip support.
48  *
49  * TTHH_GetTooltip returns an object of type CTooltipInfo in which both the
50  * tip text and the supported buttons (defaults to all) are saved.
51  * The text, in addition to having line breaks for each new line can have
52  * URLs that, when clicked on, will bring up the user's default browser
53  * with a new page for that link. The urls format is standard html, e.g.:
54  *
55  * "This is text for a tooltip. The next line has a url.
56  * A url: <a href="https://www.ncbi.nlm.nih.gov">Visit NCBI</a> in a tip"
57  *
58  * To implement these two functions, it may be most appropriate to forward
59  * the request to the pane's rendering object, e.g. IPhyloTreeRender, since
60  * that has the information to determine if a location (x,y) on the pane
61  * has a graphics object that requires tip support. The rendering objects
62  * are NOT derived from IStickyTooltipHandlerHost however. This is a change
63  * from the previous tool tip handler, ITooltipHandlerHost.
64  *
65  * 4. In the same class, decare an instance of CStickyTooltipHandler and register
66  * it the same way other mouse/interaction handlers are registered:
67  * m_TooltipManager.SetHost(static_cast<IStickyTooltipHandlerHost*>(this));
68  * x_RegisterHandler(dynamic_cast<IGlEventHandler*>(&m_TooltipManager),
69  * fMatrixArea, &m_MatrixPane);
70  *
71  * 5. Implement support for buttons on the tooltip windows. Note pin/unpin
72  * support is built in, but the commands for search, zoom, and info are
73  * not. To add support for these, add event table macros to the class
74  * derived from CGlWidgetPane (and therefore IStickyTooltipHandlerHost) for
75  * the respective command events, e.g.:
76  * EVT_BUTTON(eCmdSearchTip, CPhyloTreeWidget::OnSearchTip)
77  * EVT_BUTTON(eCmdZoomTip, CPhyloTreeWidget::OnZoomTip)
78  * EVT_BUTTON(eCmdInfoTip, CPhyloTreeWidget::OnInfoTip)
79  *
80  * Also addd support, if desired, for highlighting the screen element to
81  * which the tip is attached via the following two commands:
82  * EVT_BUTTON(eCmdTipActive, CPhyloTreeWidget::OnTipActivated)
83  * EVT_BUTTON(eCmdTipInactive, CPhyloTreeWidget::OnTipDeactivated)
84  *
85  * It is also possible to keep track of tips that are currently attached to
86  * the current view by catching the following events which are fired when
87  * a new tip is added to the view or is removed from the view.
88  * EVT_BUTTON(eCmdTipAdded, CPhyloTreeWidget::OnTipAdded)
89  * EVT_BUTTON(eCmdTipRemoved, CPhyloTreeWidget::OnTipRemoved)
90  *
91  * When implementing these commands, it will be useful to get a pointer to
92  * the tooltip, particularly so you can get its unique ID string. The
93  * pointer to the tip is stored in the command event and you can get it via:
94  *
95  * void CPhyloTreeWidget::OnSearchTip(wxCommandEvent & evt)
96  * {
97  * // Need the tool tip window for the event - we stored its pointer in
98  * // the button's (event objects) client data when the button was created
99  * wxEvtHandler* obj = dynamic_cast<wxEvtHandler*>(evt.GetEventObject());
100  * if (obj != NULL) {
101  * CTooltipFrame* f = static_cast<CTooltipFrame*>(obj->GetClientData());
102  * std::string unique_id = f->GetTipInfo().GetTipID();
103  * }
104  * }
105  *
106  * 6. The sticky tooltips are top-level dialog windows, and may pop-up in front
107  * of other windows based on when each window was created or raise()'d.
108  * Other windows can be forced in front of tips by calling Raise() on them
109  * when needed.
110  *
111  * To keep the normal undocked windows (CFloatingFrame) windows in front of
112  * tooltips on the main window, you have to pass in a pointer to the IServiceLocator
113  * which gives sticky tooltips access to CDockManager which can raise all
114  * the CFloatingFrame objects in correct Z order when needed. For PhyTree
115  * this was added to the view object (CPhyTreeView) in the InitView() function:
116  *
117  * bool CPhyTreeView::InitView(TConstScopedObjects& objects)
118  * {
119  * m_PhyWidget->SetServiceLocator(m_Workbench);
120  * .....
121  *
122  */
123 
124 #include <corelib/ncbistl.hpp>
125 #include <ncbiconf.h>
126 
127 #include <gui/gui_export.h>
130 #include <gui/opengl/glrect.hpp>
131 #include <wx/timer.h>
132 
133 #include <vector>
134 using std::vector;
135 
136 #if defined(__WXOSX_CARBON__) || defined(__WXMAC_CARBON__)
137 #include <Carbon/Carbon.h>
138 #endif
139 
141 
143 class IServiceLocator;
144 
145 ///////////////////////////////////////////////////////////////////////////////
146 /// IStickyTooltipHandlerHost - Class from which windows that want to
147 /// support sticky tooltips ultimately need to be derived. Classes
148 /// then need to add support for the TTHH_* functions to suppport
149 /// tool tips.
151 {
152 public:
153  struct TipLocation {
156  : TipRect(r)
157  , TipID(id) {}
160  };
161 
162 
163 public:
165  virtual ~IStickyTooltipHandlerHost();
166 
167  /// Init calls virtual functions so can't be called from ctor
168  void TTHH_Init();
169 
170  /// Return id of the underlying element to dispaly a tooltip, otherwise ""
171  virtual string TTHH_NeedTooltip(const wxPoint & /*pt*/) { return ""; }
172  /// Return the contents to be displayed in the tool tip
173  virtual CTooltipInfo TTHH_GetTooltip(const wxRect & /*rect*/) { return CTooltipInfo(); }
174  /// Return the pointer to the underlying window
175  virtual wxWindow* TTHH_GetWindow() { return NULL; }
176  /// Return true if underlying window is currently displaying a popup menu
177  virtual bool TTHH_PopupMenuDisplayed() { return false; }
178  /// Return true if the specified URL has been processed. Used for custom commands.
179  virtual bool TTHH_ProcessURL(const wxString & /*href*/) { return false; }
180 
181  /// Return id and position information for currently displayed tips.
182  /// This allows windows showing tips to add visual elements linking the
183  /// tip window on screen to its corresponding graphical element.
184  std::vector<TipLocation> GetDisplayedTips() { return m_CurrentTips; }
185 
186  /// Set service locator so we can find other views and adjust z order
187  void SetServiceLocator(IServiceLocator* s) { m_ServiceLocator = s; }
188 
189 protected:
190  friend class CStickyTooltipHandler;
191 
192  /// Sets information on current tips that can be queried by the user.
193  void x_SetCurrentTips(std::vector<TipLocation>& tips) { m_CurrentTips = tips; }
194 
195  /// Return the undering wxFrame parent for a wxWindow object
196  wxFrame* GetUnderlyingFrame();
197  /// Return true if the hosting window is ultimately enclosed in a
198  /// CFloatingFrame class (meaning its in a floating window)
199  bool IsFloatingWindow();
200  /// If the tip window is docked in the main window (not a CFloatingFrame)
201  /// this raises all the CFloatingFrame windows to make sure none of them
202  /// are overlapped by tooltips
203  void RaiseOverlappingWindows(wxRect r);
204  /// Retruns true if Any window is currently being dragged
205  bool IsDragging();
206  /// Mac only - create or return window group for this window
207  void InitWindowGroup(int dock_count=0);
208 
209  /// Needed to find other views
211 
212  std::vector<TipLocation> m_CurrentTips;
213 
214 #if defined(__WXOSX_CARBON__) || defined(__WXMAC_CARBON__)
215  /// Get window group
216  WindowGroupRef GetWindowGroup() { return m_TipGroupWinRef; }
217  WindowGroupRef m_TipGroupWinRef;
218 
219  struct CWindowRef {
220  CWindowRef() : m_Ref(NULL), m_DockCount(0) {}
221  CWindowRef(WindowGroupRef r, int dc) : m_Ref(r), m_DockCount(dc) {}
222  WindowGroupRef m_Ref;
223  int m_DockCount;
224  };
225 
226  static std::vector<std::pair<wxWindow*,CWindowRef> > sm_Windows;
227 #endif
228 };
229 
230 ///////////////////////////////////////////////////////////////////////////////
231 /// CStickyTooltipHandler : Class that manages all the tooltips
232 /// for a specific window. Primarily it responds to move, size, and
233 /// dock/undock messages of the hosting window in order to make
234 /// the tips look as if they are attached to the window. The tooltip
235 /// windows are toplevel windows just like their hosting windows.
236 /// This means quite a bit is also done to make sure that the tips always
237 /// appear in front of their parent window, and never jump in front
238 /// of another application window that is on top of their parent
239 /// window. The details of managing this feature are in some cases platform
240 /// dependent.
242  : public wxTimer
243  , public IGlEventHandler
244  , public ILinkEventHandler
245 {
246 public:
248  virtual ~CStickyTooltipHandler();
249 
250  // initialize support for menu commands (popup on tip windows)
251  static void RegisterCommands();
252 
253  virtual void SetHost(IStickyTooltipHandlerHost* host) { m_Host = host; }
254 
255  /// @name IGlEventHandler implementaion
256  /// @{
257  virtual void SetPane(CGlPane* pane) { m_Pane = pane; }
258  virtual wxEvtHandler* GetEvtHandler() { return this; }
259  /// @}
260 
261  /// @name ILinkEventHandler implementaion
262  /// @{
263  virtual bool OnLinkClicked(const wxString &href) { _ASSERT(m_Host); return m_Host->TTHH_ProcessURL(href); }
264  /// @}
265 
266  /// Add tool tip to current window
267  virtual void AddTip(CTooltipFrame* tt);
268  /// Add an unpinned tip to the window. Since there can be only one,
269  /// delete the current upinned tip (m_UnpinnedTip) if any.
270  virtual void AddUnpinned(CTooltipFrame* tt);
271  /// Take the current upinned tip and pin it (add it to m_ToolTips)
272  virtual void PinUnpinned(CTooltipFrame* tt);
273  /// Remove a tip from m_ToolTips, and set m_UnpinnedTip to the tip
274  virtual void UnpinPinned(CTooltipFrame* tt);
275  /// Delete the current unpinned tip (if any)
276  virtual void ClearUnpinned();
277 
278  /// Move all the tooltip windows along with the parent
279  virtual void ParentMove(const wxPoint& screen_pos);
280  /// Called when parent is unhidden to show all tips
281  virtual void ParentShow(bool show);
282  /// Clips all tip windows to parent window
283  virtual void Resize();
284  /// Determines which tip mouse is on (if any) and brings it to front
285  virtual void OnTimer(wxTimerEvent& event);
286 
287  /// Hides tips and then copies them from m_ToolTips to m_SuspendedTips -
288  /// called before docking starts.
289  virtual void Suspend();
290  /// Recreates suspended tips (old tips are deleted).
291  virtual void ReCreate(int dock_count = 0);
292  /// Currently does nothing.
293  virtual void OnSetFocus();
294 
295  /// Checks if a new tip should be popped up for the current location
296  void CheckForNewTip(wxPoint pos);
297 
298  /// Commands propogated from parent windows to initiate move, resize,
299  /// docking (suspend/recreate), hide, and show of current tips
300  void OnMotion(wxMouseEvent& event);
301  void OnRightMouseDown(wxMouseEvent& event);
302  void OnMouseWheel(wxMouseEvent& event);
303  void OnLeaveWindow(wxMouseEvent& event);
304  void OnSize(wxSizeEvent& event);
305  void OnWindowMoveCmd(wxCommandEvent& event);
306  void OnSuspendCmd(wxCommandEvent& event);
307  void OnReCreateCmd(wxCommandEvent& event);
308  void OnMainWindowDockCmd(wxCommandEvent& event);
309  void OnActivateCmd(wxCommandEvent& event);
310  void OnWindowShowCmd(wxCommandEvent& event);
311  void OnWindowHideCmd(wxCommandEvent& event);
312  void OnTipRelease(wxCommandEvent& event);
313  void OnTipMove(wxCommandEvent& event);
314 
315  /// Commands from buttons on individual tips
316  void OnCloseTip(wxCommandEvent& event);
317  void OnPinTip(wxCommandEvent& event);
318 
319  /// Any command that updates tip position should use this to keep
320  /// the list of user-accessible tip information up-to-date.
321  void UpdateTips();
322 
323  // wxTimer function
324  void Notify();
325 
326  float& GetMoveThreshold() { return m_MouseMoveThreshold; }
327  float& GetUnpinnedMoveThreshold() { return m_UnpinnedMouseMoveThreshold; }
328  int& GetClearUnpinnedDelay() { return m_ClearUnpinnedDelay; }
329  float& GetPopupDistance() { return m_PopupDistance; }
330  int& GetTipPopupDelay() { return m_TipPopupDelay; }
331 
332 protected:
333  bool checkChildFocus(wxWindow* fwin, wxWindow* checkwin);
334 
335  /// Host window for tips
337 
338  /// At a given time, only 1 tip can be unpinned
340  /// position of mouse when need for new tip indicated
341  wxPoint m_TipInitPos;
342 
343  /// If the mouse pointer is inside the boundries of a tip,that tip
344  /// is m_ActiveTip. Otherwise nULL
346  /// Timer to watch mouse and change active tip as mouse moves
347  wxTimer m_Timer;
348  /// Tracks suspend count for window for debugging
350  /// Timer to clear away unpinned tip if mouse starts moving
352 
353  /// All tooltips for current window (m_Host)
354  std::vector<CTooltipFrame*> m_ToolTips;
355  /// Hidden tooltips (tips are all hidden when window is being (un)docked)
356  std::vector<CTooltipFrame*> m_SuspendedTips;
357 
358  /// Mouse move threshold for disabling tip before it pops up
360  /// Mouse move threshold for disabling tip after it pops up
362  /// When the mouse starts moving after a tip pops up, this is the delay
363  /// until the tip is removed (mouse must get inside tip before this time)
365  /// Distance from tip that the tooltip pops up
367  /// Delay between seeing the need for a tip and displaying it
369 
371 
372  DECLARE_EVENT_TABLE()
373 };
374 
376 
377 #endif // GGUI_WIDGETS_WX___STICKY_TOOL_HANDLER__HPP
class CGlPane
Definition: glpane.hpp:62
CStickyTooltipHandler : Class that manages all the tooltips for a specific window.
IStickyTooltipHandlerHost * m_Host
Host window for tips.
int m_TipPopupDelay
Delay between seeing the need for a tip and displaying it.
int m_SuspendCount
Tracks suspend count for window for debugging.
int m_ClearUnpinnedDelay
When the mouse starts moving after a tip pops up, this is the delay until the tip is removed (mouse m...
float m_UnpinnedMouseMoveThreshold
Mouse move threshold for disabling tip after it pops up.
float m_MouseMoveThreshold
Mouse move threshold for disabling tip before it pops up.
CTooltipFrame * m_ActiveTip
If the mouse pointer is inside the boundries of a tip,that tip is m_ActiveTip.
virtual void SetHost(IStickyTooltipHandlerHost *host)
wxTimer m_TimerClearUnpinned
Timer to clear away unpinned tip if mouse starts moving.
virtual wxEvtHandler * GetEvtHandler()
virtual void SetPane(CGlPane *pane)
void OnCloseTip(wxCommandEvent &event)
Commands from buttons on individual tips.
float m_PopupDistance
Distance from tip that the tooltip pops up.
virtual bool OnLinkClicked(const wxString &href)
Invoked when an URL is clicked.
wxPoint m_TipInitPos
position of mouse when need for new tip indicated
wxTimer m_Timer
Timer to watch mouse and change active tip as mouse moves.
std::vector< CTooltipFrame * > m_ToolTips
All tooltips for current window (m_Host)
std::vector< CTooltipFrame * > m_SuspendedTips
Hidden tooltips (tips are all hidden when window is being (un)docked)
CTooltipFrame * m_UnpinnedTip
At a given time, only 1 tip can be unpinned.
The tooltip window that displays tip information.
Contents of a single tool tip including display text and an ID that will indicate which underlying vi...
IGlEventHandler.
Interface, used to forward handling of URL click events.
IServiceLocator - an abstract mechanism for locating services.
Definition: service.hpp:71
IStickyTooltipHandlerHost - Class from which windows that want to support sticky tooltips ultimately ...
virtual string TTHH_NeedTooltip(const wxPoint &)
Return id of the underlying element to dispaly a tooltip, otherwise "".
virtual CTooltipInfo TTHH_GetTooltip(const wxRect &)
Return the contents to be displayed in the tool tip.
virtual wxWindow * TTHH_GetWindow()
Return the pointer to the underlying window.
std::vector< TipLocation > m_CurrentTips
virtual bool TTHH_PopupMenuDisplayed()
Return true if underlying window is currently displaying a popup menu.
IServiceLocator * m_ServiceLocator
Needed to find other views.
virtual bool TTHH_ProcessURL(const wxString &)
Return true if the specified URL has been processed. Used for custom commands.
std::vector< TipLocation > GetDisplayedTips()
Return id and position information for currently displayed tips.
void SetServiceLocator(IServiceLocator *s)
Set service locator so we can find other views and adjust z order.
void x_SetCurrentTips(std::vector< TipLocation > &tips)
Sets information on current tips that can be queried by the user.
string
Definition: cgiapp.hpp:690
#define NULL
Definition: ncbistd.hpp:225
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define NCBI_GUIWIDGETS_WX_EXPORT
Definition: gui_export.h:543
Defines to provide correct exporting from DLLs in Windows.
Front end for a platform-specific configuration summary.
The NCBI C++/STL use hints.
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
TipLocation(const CGlRect< float > &r, const std::string &id)
#define _ASSERT
Modified on Fri Sep 20 14:57:28 2024 by modify_doxy.py rev. 669887