1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/cshelp.cpp
3 // Purpose: Context sensitive help class implementation
4 // Author: Julian Smart, Vadim Zeitlin
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"
33 #include "wx/tipwin.h"
34 #include "wx/module.h"
35 #include "wx/cshelp.h"
37 // ----------------------------------------------------------------------------
38 // wxContextHelpEvtHandler private class
39 // ----------------------------------------------------------------------------
41 // This class exists in order to eat events until the left mouse button is
43 class wxContextHelpEvtHandler
: public wxEvtHandler
46 wxContextHelpEvtHandler(wxContextHelp
* contextHelp
)
48 m_contextHelp
= contextHelp
;
51 virtual bool ProcessEvent(wxEvent
& event
);
54 wxContextHelp
* m_contextHelp
;
56 DECLARE_NO_COPY_CLASS(wxContextHelpEvtHandler
)
59 // ============================================================================
61 // ============================================================================
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
68 * Invokes context-sensitive help
72 IMPLEMENT_DYNAMIC_CLASS(wxContextHelp
, wxObject
)
74 wxContextHelp::wxContextHelp(wxWindow
* win
, bool beginHelp
)
79 BeginContextHelp(win
);
82 wxContextHelp::~wxContextHelp()
88 // Not currently needed, but on some systems capture may not work as
89 // expected so we'll leave it here for now.
91 static void wxPushOrPopEventHandlers(wxContextHelp
* help
, wxWindow
* win
, bool push
)
94 win
->PushEventHandler(new wxContextHelpEvtHandler(help
));
96 win
->PopEventHandler(true);
98 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetFirst();
101 wxWindow
* child
= node
->GetData();
102 wxPushOrPopEventHandlers(help
, child
, push
);
104 node
= node
->GetNext();
109 // Begin 'context help mode'
110 bool wxContextHelp::BeginContextHelp(wxWindow
* win
)
113 win
= wxTheApp
->GetTopWindow();
117 wxCursor
cursor(wxCURSOR_QUESTION_ARROW
);
118 wxCursor oldCursor
= win
->GetCursor();
119 win
->SetCursor(cursor
);
122 // wxSetCursor(cursor);
128 wxPushOrPopEventHandlers(this, win
, true);
130 win
->PushEventHandler(new wxContextHelpEvtHandler(this));
140 wxPushOrPopEventHandlers(this, win
, false);
142 win
->PopEventHandler(true);
145 win
->SetCursor(oldCursor
);
150 wxWindow
* winAtPtr
= wxFindWindowAtPointer(pt
);
155 printf("Picked %s (%d)\n", winAtPtr
->GetName().c_str(),
161 DispatchEvent(winAtPtr
, pt
);
167 bool wxContextHelp::EndContextHelp()
174 bool wxContextHelp::EventLoop()
180 if (wxTheApp
->Pending())
182 wxTheApp
->Dispatch();
186 wxTheApp
->ProcessIdle();
193 bool wxContextHelpEvtHandler::ProcessEvent(wxEvent
& event
)
195 if (event
.GetEventType() == wxEVT_LEFT_DOWN
)
197 m_contextHelp
->SetStatus(true);
198 m_contextHelp
->EndContextHelp();
202 if ((event
.GetEventType() == wxEVT_CHAR
) ||
203 (event
.GetEventType() == wxEVT_KEY_DOWN
) ||
204 (event
.GetEventType() == wxEVT_ACTIVATE
) ||
205 (event
.GetEventType() == wxEVT_MOUSE_CAPTURE_CHANGED
))
207 // May have already been set to true by a left-click
208 //m_contextHelp->SetStatus(false);
209 m_contextHelp
->EndContextHelp();
213 if ((event
.GetEventType() == wxEVT_PAINT
) ||
214 (event
.GetEventType() == wxEVT_ERASE_BACKGROUND
))
223 // Dispatch the help event to the relevant window
224 bool wxContextHelp::DispatchEvent(wxWindow
* win
, const wxPoint
& pt
)
226 wxWindow
* subjectOfHelp
= win
;
227 bool eventProcessed
= false;
228 while (subjectOfHelp
&& !eventProcessed
)
230 wxHelpEvent
helpEvent(wxEVT_HELP
, subjectOfHelp
->GetId(), pt
,
231 wxHelpEvent::Origin_HelpButton
);
232 helpEvent
.SetEventObject(subjectOfHelp
);
234 eventProcessed
= win
->GetEventHandler()->ProcessEvent(helpEvent
);
236 // Go up the window hierarchy until the event is handled (or not).
237 // I.e. keep submitting ancestor windows until one is recognised
238 // by the app code that processes the ids and displays help.
239 subjectOfHelp
= subjectOfHelp
->GetParent();
241 return eventProcessed
;
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_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
= (wxHelpProvider
*)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 // ----------------------------------------------------------------------------
331 // wxSimpleHelpProvider
332 // ----------------------------------------------------------------------------
334 #define WINHASH_KEY(w) wxPtrToUInt(w)
336 wxString
wxSimpleHelpProvider::GetHelp(const wxWindowBase
*window
)
338 wxSimpleHelpProviderHashMap::iterator it
= m_hashWindows
.find(WINHASH_KEY(window
));
340 if ( it
== m_hashWindows
.end() )
342 it
= m_hashIds
.find(window
->GetId());
343 if ( it
== m_hashIds
.end() )
344 return wxEmptyString
;
350 void wxSimpleHelpProvider::AddHelp(wxWindowBase
*window
, const wxString
& text
)
352 m_hashWindows
.erase(WINHASH_KEY(window
));
353 m_hashWindows
[WINHASH_KEY(window
)] = text
;
356 void wxSimpleHelpProvider::AddHelp(wxWindowID id
, const wxString
& text
)
358 wxSimpleHelpProviderHashMap::key_type key
= (wxSimpleHelpProviderHashMap::key_type
)id
;
359 m_hashIds
.erase(key
);
360 m_hashIds
[key
] = text
;
363 // removes the association
364 void wxSimpleHelpProvider::RemoveHelp(wxWindowBase
* window
)
366 m_hashWindows
.erase(WINHASH_KEY(window
));
369 bool wxSimpleHelpProvider::ShowHelp(wxWindowBase
*window
)
372 static wxTipWindow
* s_tipWindow
= NULL
;
376 // Prevent s_tipWindow being nulled in OnIdle,
377 // thereby removing the chance for the window to be closed by ShowHelp
378 s_tipWindow
->SetTipWindowPtr(NULL
);
379 s_tipWindow
->Close();
383 wxString text
= GetHelp(window
);
386 s_tipWindow
= new wxTipWindow((wxWindow
*)window
, text
, 100, & s_tipWindow
);
392 #endif // wxUSE_TIPWINDOW
397 // ----------------------------------------------------------------------------
398 // wxHelpControllerHelpProvider
399 // ----------------------------------------------------------------------------
401 wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase
* hc
)
403 m_helpController
= hc
;
406 bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase
*window
)
408 wxString text
= GetHelp(window
);
411 if (m_helpController
)
414 return m_helpController
->DisplayContextPopup(wxAtoi(text
));
416 // If the help controller is capable of popping up the text...
417 else if (m_helpController
->DisplayTextPopup(text
, wxGetMousePosition()))
422 // ...else use the default method.
423 return wxSimpleHelpProvider::ShowHelp(window
);
426 return wxSimpleHelpProvider::ShowHelp(window
);
433 // Convenience function for turning context id into wxString
434 wxString
wxContextId(int id
)
436 return wxString::Format(_T("%d"), id
);
439 // ----------------------------------------------------------------------------
440 // wxHelpProviderModule: module responsible for cleaning up help provider.
441 // ----------------------------------------------------------------------------
443 class wxHelpProviderModule
: public wxModule
450 DECLARE_DYNAMIC_CLASS(wxHelpProviderModule
)
453 IMPLEMENT_DYNAMIC_CLASS(wxHelpProviderModule
, wxModule
)
455 bool wxHelpProviderModule::OnInit()
457 // Probably we don't want to do anything by default,
458 // since it could pull in extra code
459 // wxHelpProvider::Set(new wxSimpleHelpProvider);
464 void wxHelpProviderModule::OnExit()
466 if (wxHelpProvider::Get())
468 delete wxHelpProvider::Get();
469 wxHelpProvider::Set(NULL
);