1
/////////////////////////////////////////////////////////////////////////////
2
// Name: src/common/cshelp.cpp
3
// Purpose: Context sensitive help class implementation
4
// Author: Julian Smart, Vadim Zeitlin
7
// RCS-ID: $Id: cshelp.cpp 68859 2011-08-23 04:55:46Z DS $
8
// Copyright: (c) 2000 Julian Smart, Vadim Zeitlin
9
// Licence: wxWindows licence
10
/////////////////////////////////////////////////////////////////////////////
12
// ============================================================================
14
// ============================================================================
16
// ----------------------------------------------------------------------------
18
// ----------------------------------------------------------------------------
20
// For compilers that support precompilation, includes "wx.h".
21
#include "wx/wxprec.h"
31
#include "wx/module.h"
34
#include "wx/tipwin.h"
35
#include "wx/cshelp.h"
37
#if wxUSE_MS_HTML_HELP
38
#include "wx/msw/helpchm.h" // for ShowContextHelpPopup
39
#include "wx/utils.h" // for wxGetMousePosition()
42
// ----------------------------------------------------------------------------
43
// wxContextHelpEvtHandler private class
44
// ----------------------------------------------------------------------------
46
// This class exists in order to eat events until the left mouse button is
48
class wxContextHelpEvtHandler: public wxEvtHandler
51
wxContextHelpEvtHandler(wxContextHelp* contextHelp)
53
m_contextHelp = contextHelp;
56
virtual bool ProcessEvent(wxEvent& event);
59
wxContextHelp* m_contextHelp;
61
wxDECLARE_NO_COPY_CLASS(wxContextHelpEvtHandler);
64
// ============================================================================
66
// ============================================================================
68
// ----------------------------------------------------------------------------
70
// ----------------------------------------------------------------------------
73
* Invokes context-sensitive help
77
IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject)
79
wxContextHelp::wxContextHelp(wxWindow* win, bool beginHelp)
84
BeginContextHelp(win);
87
wxContextHelp::~wxContextHelp()
93
// Not currently needed, but on some systems capture may not work as
94
// expected so we'll leave it here for now.
96
static void wxPushOrPopEventHandlers(wxContextHelp* help, wxWindow* win, bool push)
99
win->PushEventHandler(new wxContextHelpEvtHandler(help));
101
win->PopEventHandler(true);
103
wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
106
wxWindow* child = node->GetData();
107
wxPushOrPopEventHandlers(help, child, push);
109
node = node->GetNext();
114
// Begin 'context help mode'
115
bool wxContextHelp::BeginContextHelp(wxWindow* win)
118
win = wxTheApp->GetTopWindow();
122
wxCursor cursor(wxCURSOR_QUESTION_ARROW);
123
wxCursor oldCursor = win->GetCursor();
124
win->SetCursor(cursor);
133
wxPushOrPopEventHandlers(this, win, true);
135
win->PushEventHandler(new wxContextHelpEvtHandler(this));
145
wxPushOrPopEventHandlers(this, win, false);
147
win->PopEventHandler(true);
150
win->SetCursor(oldCursor);
153
wxSetCursor(wxNullCursor);
159
wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
164
printf("Picked %s (%d)\n", winAtPtr->GetName().c_str(),
170
DispatchEvent(winAtPtr, pt);
176
bool wxContextHelp::EndContextHelp()
183
bool wxContextHelp::EventLoop()
189
if (wxTheApp->Pending())
191
wxTheApp->Dispatch();
195
wxTheApp->ProcessIdle();
202
bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
204
if (event.GetEventType() == wxEVT_LEFT_DOWN)
206
m_contextHelp->SetStatus(true);
207
m_contextHelp->EndContextHelp();
211
if ((event.GetEventType() == wxEVT_CHAR) ||
212
(event.GetEventType() == wxEVT_KEY_DOWN) ||
213
(event.GetEventType() == wxEVT_ACTIVATE) ||
214
(event.GetEventType() == wxEVT_MOUSE_CAPTURE_CHANGED))
216
// May have already been set to true by a left-click
217
//m_contextHelp->SetStatus(false);
218
m_contextHelp->EndContextHelp();
222
if ((event.GetEventType() == wxEVT_PAINT) ||
223
(event.GetEventType() == wxEVT_ERASE_BACKGROUND))
232
// Dispatch the help event to the relevant window
233
bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
235
wxCHECK_MSG( win, false, wxT("win parameter can't be NULL") );
237
wxHelpEvent helpEvent(wxEVT_HELP, win->GetId(), pt,
238
wxHelpEvent::Origin_HelpButton);
239
helpEvent.SetEventObject(win);
241
return win->GetEventHandler()->ProcessEvent(helpEvent);
244
// ----------------------------------------------------------------------------
245
// wxContextHelpButton
246
// ----------------------------------------------------------------------------
249
* wxContextHelpButton
250
* You can add this to your dialogs (especially on non-Windows platforms)
251
* to put the application into context help mode.
256
static const char * csquery_xpm[] = {
274
IMPLEMENT_CLASS(wxContextHelpButton, wxBitmapButton)
276
BEGIN_EVENT_TABLE(wxContextHelpButton, wxBitmapButton)
277
EVT_BUTTON(wxID_CONTEXT_HELP, wxContextHelpButton::OnContextHelp)
280
wxContextHelpButton::wxContextHelpButton(wxWindow* parent,
285
#if defined(__WXPM__)
286
: wxBitmapButton(parent, id, wxBitmap(wxCSQUERY_BITMAP
287
,wxBITMAP_TYPE_BMP_RESOURCE
291
: wxBitmapButton(parent, id, wxBitmap(csquery_xpm),
297
void wxContextHelpButton::OnContextHelp(wxCommandEvent& WXUNUSED(event))
299
wxContextHelp contextHelp(GetParent());
302
// ----------------------------------------------------------------------------
304
// ----------------------------------------------------------------------------
306
wxHelpProvider *wxHelpProvider::ms_helpProvider = NULL;
308
// trivial implementation of some methods which we don't want to make pure
309
// virtual for convenience
311
void wxHelpProvider::AddHelp(wxWindowBase * WXUNUSED(window),
312
const wxString& WXUNUSED(text))
316
void wxHelpProvider::AddHelp(wxWindowID WXUNUSED(id),
317
const wxString& WXUNUSED(text))
321
// removes the association
322
void wxHelpProvider::RemoveHelp(wxWindowBase* WXUNUSED(window))
326
wxHelpProvider::~wxHelpProvider()
330
wxString wxHelpProvider::GetHelpTextMaybeAtPoint(wxWindowBase *window)
332
if ( m_helptextAtPoint != wxDefaultPosition ||
333
m_helptextOrigin != wxHelpEvent::Origin_Unknown )
335
wxCHECK_MSG( window, wxEmptyString, wxT("window must not be NULL") );
337
wxPoint pt = m_helptextAtPoint;
338
wxHelpEvent::Origin origin = m_helptextOrigin;
340
m_helptextAtPoint = wxDefaultPosition;
341
m_helptextOrigin = wxHelpEvent::Origin_Unknown;
343
return window->GetHelpTextAtPoint(pt, origin);
346
return GetHelp(window);
349
// ----------------------------------------------------------------------------
350
// wxSimpleHelpProvider
351
// ----------------------------------------------------------------------------
353
#define WINHASH_KEY(w) wxPtrToUInt(w)
355
wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
357
wxSimpleHelpProviderHashMap::iterator it = m_hashWindows.find(WINHASH_KEY(window));
359
if ( it == m_hashWindows.end() )
361
it = m_hashIds.find(window->GetId());
362
if ( it == m_hashIds.end() )
363
return wxEmptyString;
369
void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text)
371
m_hashWindows.erase(WINHASH_KEY(window));
372
m_hashWindows[WINHASH_KEY(window)] = text;
375
void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
377
wxSimpleHelpProviderHashMap::key_type key = (wxSimpleHelpProviderHashMap::key_type)id;
378
m_hashIds.erase(key);
379
m_hashIds[key] = text;
382
// removes the association
383
void wxSimpleHelpProvider::RemoveHelp(wxWindowBase* window)
385
m_hashWindows.erase(WINHASH_KEY(window));
388
bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window)
390
#if wxUSE_MS_HTML_HELP || wxUSE_TIPWINDOW
391
#if wxUSE_MS_HTML_HELP
392
// m_helptextAtPoint will be reset by GetHelpTextMaybeAtPoint(), stash it
393
const wxPoint posTooltip = m_helptextAtPoint;
394
#endif // wxUSE_MS_HTML_HELP
396
const wxString text = GetHelpTextMaybeAtPoint(window);
400
// use the native help popup style if it's available
401
#if wxUSE_MS_HTML_HELP
402
if ( !wxCHMHelpController::ShowContextHelpPopup
408
#endif // wxUSE_MS_HTML_HELP
411
static wxTipWindow* s_tipWindow = NULL;
415
// Prevent s_tipWindow being nulled in OnIdle, thereby removing
416
// the chance for the window to be closed by ShowHelp
417
s_tipWindow->SetTipWindowPtr(NULL);
418
s_tipWindow->Close();
421
s_tipWindow = new wxTipWindow((wxWindow *)window, text,
423
#else // !wxUSE_TIPWINDOW
424
// we tried wxCHMHelpController but it failed and we don't have
425
// wxTipWindow to fall back on, so
427
#endif // wxUSE_TIPWINDOW
432
#else // !wxUSE_MS_HTML_HELP && !wxUSE_TIPWINDOW
434
#endif // wxUSE_MS_HTML_HELP || wxUSE_TIPWINDOW
439
// ----------------------------------------------------------------------------
440
// wxHelpControllerHelpProvider
441
// ----------------------------------------------------------------------------
443
wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase* hc)
445
m_helpController = hc;
448
bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase *window)
450
const wxString text = GetHelpTextMaybeAtPoint(window);
455
if ( m_helpController )
457
// if it's a numeric topic, show it
459
if ( text.ToLong(&topic) )
460
return m_helpController->DisplayContextPopup(topic);
462
// otherwise show the text directly
463
if ( m_helpController->DisplayTextPopup(text, wxGetMousePosition()) )
467
// if there is no help controller or it's not capable of showing the help,
468
// fallback to the default method
469
return wxSimpleHelpProvider::ShowHelp(window);
472
// Convenience function for turning context id into wxString
473
wxString wxContextId(int id)
475
return wxString::Format(wxT("%d"), id);
478
// ----------------------------------------------------------------------------
479
// wxHelpProviderModule: module responsible for cleaning up help provider.
480
// ----------------------------------------------------------------------------
482
class wxHelpProviderModule : public wxModule
489
DECLARE_DYNAMIC_CLASS(wxHelpProviderModule)
492
IMPLEMENT_DYNAMIC_CLASS(wxHelpProviderModule, wxModule)
494
bool wxHelpProviderModule::OnInit()
496
// Probably we don't want to do anything by default,
497
// since it could pull in extra code
498
// wxHelpProvider::Set(new wxSimpleHelpProvider);
503
void wxHelpProviderModule::OnExit()
505
if (wxHelpProvider::Get())
507
delete wxHelpProvider::Get();
508
wxHelpProvider::Set(NULL);