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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
17 #pragma implementation "cshelp.h"
20 // ----------------------------------------------------------------------------
22 // ----------------------------------------------------------------------------
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
36 #include "wx/tipwin.h"
38 #include "wx/module.h"
39 #include "wx/cshelp.h"
41 // ----------------------------------------------------------------------------
42 // wxContextHelpEvtHandler private class
43 // ----------------------------------------------------------------------------
45 // This class exists in order to eat events until the left mouse button is
47 class wxContextHelpEvtHandler
: public wxEvtHandler
50 wxContextHelpEvtHandler(wxContextHelp
* contextHelp
)
52 m_contextHelp
= contextHelp
;
55 virtual bool ProcessEvent(wxEvent
& event
);
58 wxContextHelp
* m_contextHelp
;
60 DECLARE_NO_COPY_CLASS(wxContextHelpEvtHandler
)
63 // ============================================================================
65 // ============================================================================
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
72 * Invokes context-sensitive help
76 IMPLEMENT_DYNAMIC_CLASS(wxContextHelp
, wxObject
)
78 wxContextHelp::wxContextHelp(wxWindow
* win
, bool beginHelp
)
83 BeginContextHelp(win
);
86 wxContextHelp::~wxContextHelp()
92 // Not currently needed, but on some systems capture may not work as
93 // expected so we'll leave it here for now.
95 static void wxPushOrPopEventHandlers(wxContextHelp
* help
, wxWindow
* win
, bool push
)
98 win
->PushEventHandler(new wxContextHelpEvtHandler(help
));
100 win
->PopEventHandler(true);
102 wxWindowList::compatibility_iterator node
= win
->GetChildren().GetFirst();
105 wxWindow
* child
= node
->GetData();
106 wxPushOrPopEventHandlers(help
, child
, push
);
108 node
= node
->GetNext();
113 // Begin 'context help mode'
114 bool wxContextHelp::BeginContextHelp(wxWindow
* win
)
117 win
= wxTheApp
->GetTopWindow();
121 wxCursor
cursor(wxCURSOR_QUESTION_ARROW
);
122 wxCursor oldCursor
= win
->GetCursor();
123 win
->SetCursor(cursor
);
126 // wxSetCursor(cursor);
132 wxPushOrPopEventHandlers(this, win
, true);
134 win
->PushEventHandler(new wxContextHelpEvtHandler(this));
144 wxPushOrPopEventHandlers(this, win
, false);
146 win
->PopEventHandler(true);
149 win
->SetCursor(oldCursor
);
154 wxWindow
* winAtPtr
= wxFindWindowAtPointer(pt
);
159 printf("Picked %s (%d)\n", winAtPtr
->GetName().c_str(),
165 DispatchEvent(winAtPtr
, pt
);
171 bool wxContextHelp::EndContextHelp()
178 bool wxContextHelp::EventLoop()
184 if (wxTheApp
->Pending())
186 wxTheApp
->Dispatch();
190 wxTheApp
->ProcessIdle();
197 bool wxContextHelpEvtHandler::ProcessEvent(wxEvent
& event
)
199 if (event
.GetEventType() == wxEVT_LEFT_DOWN
)
201 m_contextHelp
->SetStatus(true);
202 m_contextHelp
->EndContextHelp();
206 if ((event
.GetEventType() == wxEVT_CHAR
) ||
207 (event
.GetEventType() == wxEVT_KEY_DOWN
) ||
208 (event
.GetEventType() == wxEVT_ACTIVATE
) ||
209 (event
.GetEventType() == wxEVT_MOUSE_CAPTURE_CHANGED
))
211 // May have already been set to true by a left-click
212 //m_contextHelp->SetStatus(false);
213 m_contextHelp
->EndContextHelp();
217 if ((event
.GetEventType() == wxEVT_PAINT
) ||
218 (event
.GetEventType() == wxEVT_ERASE_BACKGROUND
))
227 // Dispatch the help event to the relevant window
228 bool wxContextHelp::DispatchEvent(wxWindow
* win
, const wxPoint
& pt
)
230 wxWindow
* subjectOfHelp
= win
;
231 bool eventProcessed
= false;
232 while (subjectOfHelp
&& !eventProcessed
)
234 wxHelpEvent
helpEvent(wxEVT_HELP
, subjectOfHelp
->GetId(), pt
) ;
235 helpEvent
.SetEventObject(subjectOfHelp
);
237 eventProcessed
= win
->GetEventHandler()->ProcessEvent(helpEvent
);
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();
244 return eventProcessed
;
247 // ----------------------------------------------------------------------------
248 // wxContextHelpButton
249 // ----------------------------------------------------------------------------
252 * wxContextHelpButton
253 * You can add this to your dialogs (especially on non-Windows platforms)
254 * to put the application into context help mode.
259 static const char * csquery_xpm
[] = {
277 IMPLEMENT_CLASS(wxContextHelpButton
, wxBitmapButton
)
279 BEGIN_EVENT_TABLE(wxContextHelpButton
, wxBitmapButton
)
280 EVT_BUTTON(wxID_CONTEXT_HELP
, wxContextHelpButton::OnContextHelp
)
283 wxContextHelpButton::wxContextHelpButton(wxWindow
* parent
,
288 #if defined(__WXPM__)
289 : wxBitmapButton(parent
, id
, wxBitmap(wxCSQUERY_BITMAP
290 ,wxBITMAP_TYPE_RESOURCE
294 : wxBitmapButton(parent
, id
, wxBitmap(csquery_xpm
),
300 void wxContextHelpButton::OnContextHelp(wxCommandEvent
& WXUNUSED(event
))
302 wxContextHelp
contextHelp(GetParent());
305 // ----------------------------------------------------------------------------
307 // ----------------------------------------------------------------------------
309 wxHelpProvider
*wxHelpProvider::ms_helpProvider
= (wxHelpProvider
*)NULL
;
311 // trivial implementation of some methods which we don't want to make pure
312 // virtual for convenience
314 void wxHelpProvider::AddHelp(wxWindowBase
* WXUNUSED(window
),
315 const wxString
& WXUNUSED(text
))
319 void wxHelpProvider::AddHelp(wxWindowID
WXUNUSED(id
),
320 const wxString
& WXUNUSED(text
))
324 // removes the association
325 void wxHelpProvider::RemoveHelp(wxWindowBase
* WXUNUSED(window
))
329 wxHelpProvider::~wxHelpProvider()
333 // ----------------------------------------------------------------------------
334 // wxSimpleHelpProvider
335 // ----------------------------------------------------------------------------
337 wxString
wxSimpleHelpProvider::GetHelp(const wxWindowBase
*window
)
339 wxLongToStringHashMap::iterator it
= m_hashWindows
.find((long)window
);
341 if ( it
== m_hashWindows
.end() )
343 it
= m_hashIds
.find(window
->GetId());
344 if ( it
== m_hashIds
.end() )
345 return wxEmptyString
;
351 void wxSimpleHelpProvider::AddHelp(wxWindowBase
*window
, const wxString
& text
)
353 m_hashWindows
.erase((long)window
);
354 m_hashWindows
[(long)window
] = text
;
357 void wxSimpleHelpProvider::AddHelp(wxWindowID id
, const wxString
& text
)
359 wxLongToStringHashMap::key_type key
= (wxLongToStringHashMap::key_type
)id
;
360 m_hashIds
.erase(key
);
361 m_hashIds
[key
] = text
;
364 // removes the association
365 void wxSimpleHelpProvider::RemoveHelp(wxWindowBase
* window
)
367 m_hashWindows
.erase((long)window
);
370 bool wxSimpleHelpProvider::ShowHelp(wxWindowBase
*window
)
373 static wxTipWindow
* s_tipWindow
= NULL
;
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();
384 wxString text
= GetHelp(window
);
387 s_tipWindow
= new wxTipWindow((wxWindow
*)window
, text
, 100, & s_tipWindow
);
393 #endif // wxUSE_TIPWINDOW
398 // ----------------------------------------------------------------------------
399 // wxHelpControllerHelpProvider
400 // ----------------------------------------------------------------------------
402 wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase
* hc
)
404 m_helpController
= hc
;
407 bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase
*window
)
409 wxString text
= GetHelp(window
);
412 if (m_helpController
)
415 return m_helpController
->DisplayContextPopup(wxAtoi(text
));
417 // If the help controller is capable of popping up the text...
418 else if (m_helpController
->DisplayTextPopup(text
, wxGetMousePosition()))
423 // ...else use the default method.
424 return wxSimpleHelpProvider::ShowHelp(window
);
427 return wxSimpleHelpProvider::ShowHelp(window
);
434 // Convenience function for turning context id into wxString
435 wxString
wxContextId(int id
)
437 return wxString::Format(_T("%d"), id
);
440 // ----------------------------------------------------------------------------
441 // wxHelpProviderModule: module responsible for cleaning up help provider.
442 // ----------------------------------------------------------------------------
444 class wxHelpProviderModule
: public wxModule
451 DECLARE_DYNAMIC_CLASS(wxHelpProviderModule
)
454 IMPLEMENT_DYNAMIC_CLASS(wxHelpProviderModule
, wxModule
)
456 bool wxHelpProviderModule::OnInit()
458 // Probably we don't want to do anything by default,
459 // since it could pull in extra code
460 // wxHelpProvider::Set(new wxSimpleHelpProvider);
465 void wxHelpProviderModule::OnExit()
467 if (wxHelpProvider::Get())
469 delete wxHelpProvider::Get();
470 wxHelpProvider::Set(NULL
);