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