]> git.saurik.com Git - wxWidgets.git/blame - src/common/cshelp.cpp
Ambiguous overload fix for gcc
[wxWidgets.git] / src / common / cshelp.cpp
CommitLineData
fb6261e9 1/////////////////////////////////////////////////////////////////////////////
bd83cb56 2// Name: src/common/cshelp.cpp
fb6261e9 3// Purpose: Context sensitive help class implementation
bd83cb56 4// Author: Julian Smart, Vadim Zeitlin
fb6261e9
JS
5// Modified by:
6// Created: 08/09/2000
7// RCS-ID: $Id$
bd83cb56 8// Copyright: (c) 2000 Julian Smart, Vadim Zeitlin
65571936 9// Licence: wxWindows licence
fb6261e9
JS
10/////////////////////////////////////////////////////////////////////////////
11
bd83cb56
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
bd83cb56
VZ
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
fb6261e9
JS
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
bd83cb56 24 #pragma hdrstop
fb6261e9
JS
25#endif
26
bd83cb56
VZ
27#if wxUSE_HELP
28
fb6261e9 29#ifndef WX_PRECOMP
fb6261e9
JS
30#endif
31
afb02ca5 32#include "wx/tipwin.h"
fb6261e9 33#include "wx/app.h"
129caadd 34#include "wx/module.h"
fb6261e9
JS
35#include "wx/cshelp.h"
36
bd83cb56
VZ
37// ----------------------------------------------------------------------------
38// wxContextHelpEvtHandler private class
39// ----------------------------------------------------------------------------
fb6261e9 40
bd83cb56
VZ
41// This class exists in order to eat events until the left mouse button is
42// pressed
fb6261e9
JS
43class wxContextHelpEvtHandler: public wxEvtHandler
44{
45public:
46 wxContextHelpEvtHandler(wxContextHelp* contextHelp)
47 {
48 m_contextHelp = contextHelp;
49 }
50
51 virtual bool ProcessEvent(wxEvent& event);
52
53//// Data
54 wxContextHelp* m_contextHelp;
22f3361e
VZ
55
56 DECLARE_NO_COPY_CLASS(wxContextHelpEvtHandler)
fb6261e9
JS
57};
58
bd83cb56
VZ
59// ============================================================================
60// implementation
61// ============================================================================
62
63// ----------------------------------------------------------------------------
64// wxContextHelp
65// ----------------------------------------------------------------------------
66
67/*
68 * Invokes context-sensitive help
69 */
70
71
fb6261e9
JS
72IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject)
73
74wxContextHelp::wxContextHelp(wxWindow* win, bool beginHelp)
75{
c9d59ee7 76 m_inHelp = false;
fb6261e9
JS
77
78 if (beginHelp)
79 BeginContextHelp(win);
80}
81
82wxContextHelp::~wxContextHelp()
83{
84 if (m_inHelp)
85 EndContextHelp();
86}
87
449d48f9
JS
88// Not currently needed, but on some systems capture may not work as
89// expected so we'll leave it here for now.
ecb9c007 90#ifdef __WXMOTIF__
b8b9d8a7
JS
91static void wxPushOrPopEventHandlers(wxContextHelp* help, wxWindow* win, bool push)
92{
93 if (push)
94 win->PushEventHandler(new wxContextHelpEvtHandler(help));
95 else
c9d59ee7 96 win->PopEventHandler(true);
b8b9d8a7 97
094112e9 98 wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
b8b9d8a7
JS
99 while (node)
100 {
ecb9c007 101 wxWindow* child = node->GetData();
b8b9d8a7
JS
102 wxPushOrPopEventHandlers(help, child, push);
103
ecb9c007 104 node = node->GetNext();
b8b9d8a7
JS
105 }
106}
449d48f9 107#endif
b8b9d8a7 108
fb6261e9
JS
109// Begin 'context help mode'
110bool wxContextHelp::BeginContextHelp(wxWindow* win)
111{
112 if (!win)
113 win = wxTheApp->GetTopWindow();
114 if (!win)
c9d59ee7 115 return false;
fb6261e9
JS
116
117 wxCursor cursor(wxCURSOR_QUESTION_ARROW);
118 wxCursor oldCursor = win->GetCursor();
119 win->SetCursor(cursor);
120
121#ifdef __WXMSW__
122 // wxSetCursor(cursor);
123#endif
124
c9d59ee7 125 m_status = false;
b8b9d8a7 126
ecb9c007 127#ifdef __WXMOTIF__
c9d59ee7 128 wxPushOrPopEventHandlers(this, win, true);
ecb9c007 129#else
449d48f9 130 win->PushEventHandler(new wxContextHelpEvtHandler(this));
ecb9c007 131#endif
fb6261e9
JS
132
133 win->CaptureMouse();
134
135 EventLoop();
136
137 win->ReleaseMouse();
138
ecb9c007 139#ifdef __WXMOTIF__
c9d59ee7 140 wxPushOrPopEventHandlers(this, win, false);
ecb9c007 141#else
c9d59ee7 142 win->PopEventHandler(true);
ecb9c007 143#endif
fb6261e9
JS
144
145 win->SetCursor(oldCursor);
146
147 if (m_status)
148 {
149 wxPoint pt;
150 wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
ecb9c007
MB
151
152#if 0
d1c8aaa3
JS
153 if (winAtPtr)
154 {
ecb9c007
MB
155 printf("Picked %s (%d)\n", winAtPtr->GetName().c_str(),
156 winAtPtr->GetId());
d1c8aaa3 157 }
ecb9c007 158#endif
d1c8aaa3 159
fb6261e9
JS
160 if (winAtPtr)
161 DispatchEvent(winAtPtr, pt);
162 }
163
c9d59ee7 164 return true;
fb6261e9
JS
165}
166
167bool wxContextHelp::EndContextHelp()
168{
c9d59ee7 169 m_inHelp = false;
fb6261e9 170
c9d59ee7 171 return true;
fb6261e9
JS
172}
173
174bool wxContextHelp::EventLoop()
175{
c9d59ee7 176 m_inHelp = true;
dc4211aa 177
fb6261e9
JS
178 while ( m_inHelp )
179 {
180 if (wxTheApp->Pending())
181 {
182 wxTheApp->Dispatch();
183 }
184 else
185 {
186 wxTheApp->ProcessIdle();
187 }
188 }
dc4211aa 189
c9d59ee7 190 return true;
fb6261e9
JS
191}
192
193bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
194{
77d4384e 195 if (event.GetEventType() == wxEVT_LEFT_DOWN)
fb6261e9 196 {
c9d59ee7 197 m_contextHelp->SetStatus(true);
77d4384e 198 m_contextHelp->EndContextHelp();
c9d59ee7 199 return true;
fb6261e9 200 }
33ac7e6f 201
77d4384e
RR
202 if ((event.GetEventType() == wxEVT_CHAR) ||
203 (event.GetEventType() == wxEVT_KEY_DOWN) ||
204 (event.GetEventType() == wxEVT_ACTIVATE) ||
205 (event.GetEventType() == wxEVT_MOUSE_CAPTURE_CHANGED))
206 {
c9d59ee7
WS
207 // May have already been set to true by a left-click
208 //m_contextHelp->SetStatus(false);
77d4384e 209 m_contextHelp->EndContextHelp();
c9d59ee7 210 return true;
77d4384e 211 }
33ac7e6f 212
77d4384e
RR
213 if ((event.GetEventType() == wxEVT_PAINT) ||
214 (event.GetEventType() == wxEVT_ERASE_BACKGROUND))
215 {
216 event.Skip();
c9d59ee7 217 return false;
77d4384e 218 }
33ac7e6f 219
c9d59ee7 220 return true;
fb6261e9
JS
221}
222
223// Dispatch the help event to the relevant window
224bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
225{
226 wxWindow* subjectOfHelp = win;
c9d59ee7 227 bool eventProcessed = false;
fb6261e9
JS
228 while (subjectOfHelp && !eventProcessed)
229 {
230 wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ;
6fefc28d 231 helpEvent.SetEventObject(subjectOfHelp);
dc4211aa 232
fb6261e9 233 eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent);
dc4211aa 234
fb6261e9
JS
235 // Go up the window hierarchy until the event is handled (or not).
236 // I.e. keep submitting ancestor windows until one is recognised
237 // by the app code that processes the ids and displays help.
238 subjectOfHelp = subjectOfHelp->GetParent();
239 }
240 return eventProcessed;
241}
242
bd83cb56
VZ
243// ----------------------------------------------------------------------------
244// wxContextHelpButton
245// ----------------------------------------------------------------------------
246
fb6261e9
JS
247/*
248 * wxContextHelpButton
249 * You can add this to your dialogs (especially on non-Windows platforms)
250 * to put the application into context help mode.
251 */
252
7a893a31
WS
253#ifndef __WXPM__
254
90350682 255static const char * csquery_xpm[] = {
fb6261e9 256"12 11 2 1",
57591e0e
JS
257" c None",
258". c #000000",
fb6261e9
JS
259" ",
260" .... ",
261" .. .. ",
262" .. .. ",
263" .. ",
264" .. ",
265" .. ",
266" ",
267" .. ",
268" .. ",
269" "};
fb6261e9 270
7a893a31
WS
271#endif
272
fb6261e9
JS
273IMPLEMENT_CLASS(wxContextHelpButton, wxBitmapButton)
274
275BEGIN_EVENT_TABLE(wxContextHelpButton, wxBitmapButton)
276 EVT_BUTTON(wxID_CONTEXT_HELP, wxContextHelpButton::OnContextHelp)
277END_EVENT_TABLE()
278
84bfc0d5
VZ
279wxContextHelpButton::wxContextHelpButton(wxWindow* parent,
280 wxWindowID id,
281 const wxPoint& pos,
282 const wxSize& size,
283 long style)
dc4211aa
DW
284#if defined(__WXPM__)
285 : wxBitmapButton(parent, id, wxBitmap(wxCSQUERY_BITMAP
286 ,wxBITMAP_TYPE_RESOURCE
287 ),
288 pos, size, style)
289#else
e0f4c2c8 290 : wxBitmapButton(parent, id, wxBitmap(csquery_xpm),
84bfc0d5 291 pos, size, style)
dc4211aa 292#endif
fb6261e9 293{
fb6261e9
JS
294}
295
33ac7e6f 296void wxContextHelpButton::OnContextHelp(wxCommandEvent& WXUNUSED(event))
fb6261e9 297{
57591e0e 298 wxContextHelp contextHelp(GetParent());
fb6261e9
JS
299}
300
bd83cb56
VZ
301// ----------------------------------------------------------------------------
302// wxHelpProvider
303// ----------------------------------------------------------------------------
304
305wxHelpProvider *wxHelpProvider::ms_helpProvider = (wxHelpProvider *)NULL;
306
307// trivial implementation of some methods which we don't want to make pure
308// virtual for convenience
309
310void wxHelpProvider::AddHelp(wxWindowBase * WXUNUSED(window),
311 const wxString& WXUNUSED(text))
312{
313}
314
315void wxHelpProvider::AddHelp(wxWindowID WXUNUSED(id),
316 const wxString& WXUNUSED(text))
317{
318}
319
53e112a0
JS
320// removes the association
321void wxHelpProvider::RemoveHelp(wxWindowBase* WXUNUSED(window))
322{
323}
324
bd83cb56
VZ
325wxHelpProvider::~wxHelpProvider()
326{
327}
328
329// ----------------------------------------------------------------------------
330// wxSimpleHelpProvider
331// ----------------------------------------------------------------------------
332
333wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
334{
ba8c1601 335 wxLongToStringHashMap::iterator it = m_hashWindows.find((long)window);
bd83cb56 336
ba8c1601
MB
337 if ( it == m_hashWindows.end() )
338 {
339 it = m_hashIds.find(window->GetId());
340 if ( it == m_hashIds.end() )
341 return wxEmptyString;
342 }
343
344 return it->second;
bd83cb56
VZ
345}
346
347void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text)
348{
ba8c1601
MB
349 m_hashWindows.erase((long)window);
350 m_hashWindows[(long)window] = text;
bd83cb56
VZ
351}
352
353void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
354{
c6fbe2f0 355 wxLongToStringHashMap::key_type key = (wxLongToStringHashMap::key_type)id;
65aeb571
WS
356 m_hashIds.erase(key);
357 m_hashIds[key] = text;
bd83cb56
VZ
358}
359
53e112a0
JS
360// removes the association
361void wxSimpleHelpProvider::RemoveHelp(wxWindowBase* window)
362{
ba8c1601 363 m_hashWindows.erase((long)window);
53e112a0
JS
364}
365
bd83cb56
VZ
366bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window)
367{
f38bcae5 368#if wxUSE_TIPWINDOW
173e8bbf
JS
369 static wxTipWindow* s_tipWindow = NULL;
370
371 if (s_tipWindow)
372 {
373 // Prevent s_tipWindow being nulled in OnIdle,
374 // thereby removing the chance for the window to be closed by ShowHelp
375 s_tipWindow->SetTipWindowPtr(NULL);
376 s_tipWindow->Close();
377 }
378 s_tipWindow = NULL;
379
bd83cb56
VZ
380 wxString text = GetHelp(window);
381 if ( !text.empty() )
382 {
173e8bbf 383 s_tipWindow = new wxTipWindow((wxWindow *)window, text, 100, & s_tipWindow);
bd83cb56 384
c9d59ee7 385 return true;
bd83cb56 386 }
ddc80eb4
WS
387#else
388 wxUnusedVar(window);
f38bcae5 389#endif // wxUSE_TIPWINDOW
bd83cb56 390
c9d59ee7 391 return false;
bd83cb56
VZ
392}
393
5100cabf
JS
394// ----------------------------------------------------------------------------
395// wxHelpControllerHelpProvider
396// ----------------------------------------------------------------------------
397
398wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase* hc)
399{
400 m_helpController = hc;
401}
402
403bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase *window)
404{
405 wxString text = GetHelp(window);
406 if ( !text.empty() )
407 {
408 if (m_helpController)
409 {
410 if (text.IsNumber())
411 return m_helpController->DisplayContextPopup(wxAtoi(text));
412
413 // If the help controller is capable of popping up the text...
414 else if (m_helpController->DisplayTextPopup(text, wxGetMousePosition()))
415 {
c9d59ee7 416 return true;
5100cabf
JS
417 }
418 else
419 // ...else use the default method.
420 return wxSimpleHelpProvider::ShowHelp(window);
421 }
422 else
423 return wxSimpleHelpProvider::ShowHelp(window);
424
425 }
426
c9d59ee7 427 return false;
5100cabf
JS
428}
429
430// Convenience function for turning context id into wxString
431wxString wxContextId(int id)
432{
11968fef 433 return wxString::Format(_T("%d"), id);
5100cabf
JS
434}
435
129caadd
JS
436// ----------------------------------------------------------------------------
437// wxHelpProviderModule: module responsible for cleaning up help provider.
438// ----------------------------------------------------------------------------
439
440class wxHelpProviderModule : public wxModule
441{
442public:
443 bool OnInit();
444 void OnExit();
445
446private:
447 DECLARE_DYNAMIC_CLASS(wxHelpProviderModule)
448};
449
450IMPLEMENT_DYNAMIC_CLASS(wxHelpProviderModule, wxModule)
451
452bool wxHelpProviderModule::OnInit()
453{
454 // Probably we don't want to do anything by default,
455 // since it could pull in extra code
456 // wxHelpProvider::Set(new wxSimpleHelpProvider);
457
c9d59ee7 458 return true;
129caadd
JS
459}
460
461void wxHelpProviderModule::OnExit()
462{
463 if (wxHelpProvider::Get())
464 {
465 delete wxHelpProvider::Get();
466 wxHelpProvider::Set(NULL);
467 }
468}
469
fb6261e9 470#endif // wxUSE_HELP