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