]> git.saurik.com Git - wxWidgets.git/blob - src/common/cshelp.cpp
attempt to fix crash in tree ctrl
[wxWidgets.git] / src / common / cshelp.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/cshelp.cpp
3 // Purpose: Context sensitive help class implementation
4 // Author: Julian Smart, Vadim Zeitlin
5 // Modified by:
6 // Created: 08/09/2000
7 // RCS-ID: $Id$
8 // Copyright: (c) 2000 Julian Smart, Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 #ifdef __GNUG__
17 #pragma implementation "cshelp.h"
18 #endif
19
20 // ----------------------------------------------------------------------------
21 // headers
22 // ----------------------------------------------------------------------------
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if wxUSE_HELP
32
33 #ifndef WX_PRECOMP
34 #endif
35
36 #include "wx/tipwin.h"
37 #include "wx/app.h"
38 #include "wx/module.h"
39 #include "wx/cshelp.h"
40
41 // ----------------------------------------------------------------------------
42 // wxContextHelpEvtHandler private class
43 // ----------------------------------------------------------------------------
44
45 // This class exists in order to eat events until the left mouse button is
46 // pressed
47 class wxContextHelpEvtHandler: public wxEvtHandler
48 {
49 public:
50 wxContextHelpEvtHandler(wxContextHelp* contextHelp)
51 {
52 m_contextHelp = contextHelp;
53 }
54
55 virtual bool ProcessEvent(wxEvent& event);
56
57 //// Data
58 wxContextHelp* m_contextHelp;
59 };
60
61 // ============================================================================
62 // implementation
63 // ============================================================================
64
65 // ----------------------------------------------------------------------------
66 // wxContextHelp
67 // ----------------------------------------------------------------------------
68
69 /*
70 * Invokes context-sensitive help
71 */
72
73
74 IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject)
75
76 wxContextHelp::wxContextHelp(wxWindow* win, bool beginHelp)
77 {
78 m_inHelp = FALSE;
79
80 if (beginHelp)
81 BeginContextHelp(win);
82 }
83
84 wxContextHelp::~wxContextHelp()
85 {
86 if (m_inHelp)
87 EndContextHelp();
88 }
89
90 // Begin 'context help mode'
91 bool wxContextHelp::BeginContextHelp(wxWindow* win)
92 {
93 if (!win)
94 win = wxTheApp->GetTopWindow();
95 if (!win)
96 return FALSE;
97
98 wxCursor cursor(wxCURSOR_QUESTION_ARROW);
99 wxCursor oldCursor = win->GetCursor();
100 win->SetCursor(cursor);
101
102 #ifdef __WXMSW__
103 // wxSetCursor(cursor);
104 #endif
105
106 win->PushEventHandler(new wxContextHelpEvtHandler(this));
107
108 win->CaptureMouse();
109
110 EventLoop();
111
112 win->ReleaseMouse();
113
114 win->PopEventHandler(TRUE);
115
116 win->SetCursor(oldCursor);
117
118 if (m_status)
119 {
120 wxPoint pt;
121 wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
122 if (winAtPtr)
123 DispatchEvent(winAtPtr, pt);
124 }
125
126 return TRUE;
127 }
128
129 bool wxContextHelp::EndContextHelp()
130 {
131 m_inHelp = FALSE;
132
133 return TRUE;
134 }
135
136 bool wxContextHelp::EventLoop()
137 {
138 m_inHelp = TRUE;
139 while ( m_inHelp )
140 {
141 if (wxTheApp->Pending())
142 {
143 wxTheApp->Dispatch();
144 }
145 else
146 {
147 wxTheApp->ProcessIdle();
148 }
149 }
150 return TRUE;
151 }
152
153 bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
154 {
155 switch (event.GetEventType())
156 {
157 case wxEVT_LEFT_DOWN:
158 {
159 //wxMouseEvent& mouseEvent = (wxMouseEvent&) event;
160 m_contextHelp->SetStatus(TRUE);
161 m_contextHelp->EndContextHelp();
162 return TRUE;
163 break;
164 }
165 case wxEVT_CHAR:
166 case wxEVT_KEY_DOWN:
167 case wxEVT_ACTIVATE:
168 case wxEVT_MOUSE_CAPTURE_CHANGED:
169 {
170 m_contextHelp->SetStatus(FALSE);
171 m_contextHelp->EndContextHelp();
172 return TRUE;
173 break;
174 }
175 case wxEVT_PAINT:
176 case wxEVT_ERASE_BACKGROUND:
177 {
178 event.Skip();
179 return FALSE;
180 break;
181 }
182 }
183
184 return TRUE;
185 }
186
187 // Dispatch the help event to the relevant window
188 bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
189 {
190 wxWindow* subjectOfHelp = win;
191 bool eventProcessed = FALSE;
192 while (subjectOfHelp && !eventProcessed)
193 {
194 wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ;
195 helpEvent.SetEventObject(this);
196 eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent);
197
198 // Go up the window hierarchy until the event is handled (or not).
199 // I.e. keep submitting ancestor windows until one is recognised
200 // by the app code that processes the ids and displays help.
201 subjectOfHelp = subjectOfHelp->GetParent();
202 }
203 return eventProcessed;
204 }
205
206 // ----------------------------------------------------------------------------
207 // wxContextHelpButton
208 // ----------------------------------------------------------------------------
209
210 /*
211 * wxContextHelpButton
212 * You can add this to your dialogs (especially on non-Windows platforms)
213 * to put the application into context help mode.
214 */
215
216 #if !defined(__WXMSW__)
217 static char * csquery_xpm[] = {
218 "12 11 2 1",
219 " c None",
220 ". c #000000",
221 " ",
222 " .... ",
223 " .. .. ",
224 " .. .. ",
225 " .. ",
226 " .. ",
227 " .. ",
228 " ",
229 " .. ",
230 " .. ",
231 " "};
232 #endif
233
234 IMPLEMENT_CLASS(wxContextHelpButton, wxBitmapButton)
235
236 BEGIN_EVENT_TABLE(wxContextHelpButton, wxBitmapButton)
237 EVT_BUTTON(wxID_CONTEXT_HELP, wxContextHelpButton::OnContextHelp)
238 END_EVENT_TABLE()
239
240 wxContextHelpButton::wxContextHelpButton(wxWindow* parent,
241 wxWindowID id,
242 const wxPoint& pos,
243 const wxSize& size,
244 long style)
245 : wxBitmapButton(parent, id, wxBITMAP(csquery),
246 pos, size, style)
247 {
248 }
249
250 void wxContextHelpButton::OnContextHelp(wxCommandEvent& event)
251 {
252 wxContextHelp contextHelp(GetParent());
253 }
254
255 // ----------------------------------------------------------------------------
256 // wxHelpProvider
257 // ----------------------------------------------------------------------------
258
259 wxHelpProvider *wxHelpProvider::ms_helpProvider = (wxHelpProvider *)NULL;
260
261 // trivial implementation of some methods which we don't want to make pure
262 // virtual for convenience
263
264 void wxHelpProvider::AddHelp(wxWindowBase * WXUNUSED(window),
265 const wxString& WXUNUSED(text))
266 {
267 }
268
269 void wxHelpProvider::AddHelp(wxWindowID WXUNUSED(id),
270 const wxString& WXUNUSED(text))
271 {
272 }
273
274 wxHelpProvider::~wxHelpProvider()
275 {
276 }
277
278 // ----------------------------------------------------------------------------
279 // wxSimpleHelpProvider
280 // ----------------------------------------------------------------------------
281
282 wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
283 {
284 bool wasFound;
285 wxString text = m_hashWindows.Get((long)window, &wasFound);
286 if ( !wasFound )
287 text = m_hashIds.Get(window->GetId());
288
289 return text;
290 }
291
292 void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text)
293 {
294 m_hashWindows.Put((long)window, text);
295 }
296
297 void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
298 {
299 m_hashIds.Put(id, text);
300 }
301
302 bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window)
303 {
304 wxString text = GetHelp(window);
305 if ( !text.empty() )
306 {
307 new wxTipWindow((wxWindow *)window, text);
308
309 return TRUE;
310 }
311
312 return FALSE;
313 }
314
315 // ----------------------------------------------------------------------------
316 // wxHelpControllerHelpProvider
317 // ----------------------------------------------------------------------------
318
319 wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase* hc)
320 {
321 m_helpController = hc;
322 }
323
324 bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase *window)
325 {
326 wxString text = GetHelp(window);
327 if ( !text.empty() )
328 {
329 if (m_helpController)
330 {
331 if (text.IsNumber())
332 return m_helpController->DisplayContextPopup(wxAtoi(text));
333
334 // If the help controller is capable of popping up the text...
335 else if (m_helpController->DisplayTextPopup(text, wxGetMousePosition()))
336 {
337 return TRUE;
338 }
339 else
340 // ...else use the default method.
341 return wxSimpleHelpProvider::ShowHelp(window);
342 }
343 else
344 return wxSimpleHelpProvider::ShowHelp(window);
345
346 }
347
348 return FALSE;
349 }
350
351 // Convenience function for turning context id into wxString
352 wxString wxContextId(int id)
353 {
354 return wxString(IntToString(id));
355 }
356
357 // ----------------------------------------------------------------------------
358 // wxHelpProviderModule: module responsible for cleaning up help provider.
359 // ----------------------------------------------------------------------------
360
361 class wxHelpProviderModule : public wxModule
362 {
363 public:
364 bool OnInit();
365 void OnExit();
366
367 private:
368 DECLARE_DYNAMIC_CLASS(wxHelpProviderModule)
369 };
370
371 IMPLEMENT_DYNAMIC_CLASS(wxHelpProviderModule, wxModule)
372
373 bool wxHelpProviderModule::OnInit()
374 {
375 // Probably we don't want to do anything by default,
376 // since it could pull in extra code
377 // wxHelpProvider::Set(new wxSimpleHelpProvider);
378
379 return TRUE;
380 }
381
382 void wxHelpProviderModule::OnExit()
383 {
384 if (wxHelpProvider::Get())
385 {
386 delete wxHelpProvider::Get();
387 wxHelpProvider::Set(NULL);
388 }
389 }
390
391 #endif // wxUSE_HELP