Made wxContextHelp implementation generic and added wxFindWindowAtPointer,
[wxWidgets.git] / src / common / helpbase.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: helpbase.cpp
3 // Purpose: Help system base classes
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "helpbase.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/defs.h"
25 #endif
26
27 #include "wx/helpbase.h"
28 #include "wx/app.h"
29
30 #if wxUSE_HELP
31
32 IMPLEMENT_CLASS(wxHelpControllerBase, wxObject)
33
34 /*
35 * Invokes context-sensitive help
36 */
37
38 // This class exists in order to eat events until the left mouse
39 // button is pressed
40 class wxContextHelpEvtHandler: public wxEvtHandler
41 {
42 public:
43 wxContextHelpEvtHandler(wxContextHelp* contextHelp)
44 {
45 m_contextHelp = contextHelp;
46 }
47
48 virtual bool ProcessEvent(wxEvent& event);
49
50 //// Data
51 wxContextHelp* m_contextHelp;
52 };
53
54 IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject)
55
56 wxContextHelp::wxContextHelp(wxWindow* win, bool beginHelp)
57 {
58 m_inHelp = FALSE;
59
60 if (beginHelp)
61 BeginContextHelp(win);
62 }
63
64 wxContextHelp::~wxContextHelp()
65 {
66 if (m_inHelp)
67 EndContextHelp();
68 }
69
70 // Begin 'context help mode'
71 bool wxContextHelp::BeginContextHelp(wxWindow* win)
72 {
73 if (!win)
74 win = wxTheApp->GetTopWindow();
75 if (!win)
76 return FALSE;
77
78 wxCursor cursor(wxCURSOR_QUESTION_ARROW);
79 wxCursor oldCursor = win->GetCursor();
80 win->SetCursor(cursor);
81 wxSetCursor(cursor);
82
83 win->PushEventHandler(new wxContextHelpEvtHandler(this));
84
85 win->CaptureMouse();
86
87 EventLoop();
88
89 win->ReleaseMouse();
90
91 win->PopEventHandler(TRUE);
92
93 win->SetCursor(oldCursor);
94
95 if (m_status)
96 {
97 wxPoint pt;
98 wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
99 if (winAtPtr)
100 DispatchEvent(winAtPtr, pt);
101 }
102
103 return TRUE;
104 }
105
106 bool wxContextHelp::EndContextHelp()
107 {
108 m_inHelp = FALSE;
109
110 return TRUE;
111 }
112
113 bool wxContextHelp::EventLoop()
114 {
115 m_inHelp = TRUE;
116 while ( m_inHelp )
117 {
118 if (wxTheApp->Pending())
119 {
120 wxTheApp->Dispatch();
121 }
122 else
123 {
124 wxTheApp->ProcessIdle();
125 }
126 }
127 return TRUE;
128 }
129
130 bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
131 {
132 switch (event.GetEventType())
133 {
134 case wxEVT_LEFT_DOWN:
135 {
136 wxMouseEvent& mouseEvent = (wxMouseEvent&) event;
137 m_contextHelp->SetStatus(TRUE);
138 m_contextHelp->EndContextHelp();
139 return TRUE;
140 break;
141 }
142 case wxEVT_CHAR:
143 case wxEVT_KEY_DOWN:
144 case wxEVT_ACTIVATE:
145 case wxEVT_MOUSE_CAPTURE_CHANGED:
146 {
147 m_contextHelp->SetStatus(FALSE);
148 m_contextHelp->EndContextHelp();
149 return TRUE;
150 break;
151 }
152 case wxEVT_PAINT:
153 case wxEVT_ERASE_BACKGROUND:
154 {
155 event.Skip();
156 return FALSE;
157 break;
158 }
159 }
160
161 return TRUE;
162 }
163
164 // Dispatch the help event to the relevant window
165 bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
166 {
167 wxWindow* subjectOfHelp = win;
168 bool eventProcessed = FALSE;
169 while (subjectOfHelp && !eventProcessed)
170 {
171 wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ;
172 helpEvent.SetEventObject(this);
173 eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent);
174
175 // Go up the window hierarchy until the event is handled (or not).
176 // I.e. keep submitting ancestor windows until one is recognised
177 // by the app code that processes the ids and displays help.
178 subjectOfHelp = subjectOfHelp->GetParent();
179 }
180 return eventProcessed;
181 }
182
183 #endif // wxUSE_HELP