]> git.saurik.com Git - wxWidgets.git/blame - src/common/cshelp.cpp
fix for assert when setting tooltip for a readonly combo
[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
fb6261e9
JS
9// Licence: wxWindows licence
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
90// Begin 'context help mode'
91bool wxContextHelp::BeginContextHelp(wxWindow* win)
92{
93 if (!win)
94 win = wxTheApp->GetTopWindow();
95 if (!win)
96 return FALSE;
97
98 wxCursor cursor(wxCURSOR_QUESTION_ARROW);
99 wxCursor oldCursor = win->GetCursor();
100 win->SetCursor(cursor);
101
102#ifdef __WXMSW__
103 // wxSetCursor(cursor);
104#endif
105
106 win->PushEventHandler(new wxContextHelpEvtHandler(this));
107
108 win->CaptureMouse();
109
110 EventLoop();
111
112 win->ReleaseMouse();
113
114 win->PopEventHandler(TRUE);
115
116 win->SetCursor(oldCursor);
117
118 if (m_status)
119 {
120 wxPoint pt;
121 wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
d1c8aaa3
JS
122 /*
123 if (winAtPtr)
124 {
125 wxString msg;
126 msg.Printf("Picked %s (%d)", (const char*) winAtPtr->GetName(), winAtPtr->GetId());
127 cout << msg << '\n';
128 }
129 */
130
fb6261e9
JS
131 if (winAtPtr)
132 DispatchEvent(winAtPtr, pt);
133 }
134
135 return TRUE;
136}
137
138bool wxContextHelp::EndContextHelp()
139{
140 m_inHelp = FALSE;
141
142 return TRUE;
143}
144
145bool wxContextHelp::EventLoop()
146{
147 m_inHelp = TRUE;
148 while ( m_inHelp )
149 {
150 if (wxTheApp->Pending())
151 {
152 wxTheApp->Dispatch();
153 }
154 else
155 {
156 wxTheApp->ProcessIdle();
157 }
158 }
159 return TRUE;
160}
161
162bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
163{
164 switch (event.GetEventType())
165 {
166 case wxEVT_LEFT_DOWN:
167 {
168 //wxMouseEvent& mouseEvent = (wxMouseEvent&) event;
169 m_contextHelp->SetStatus(TRUE);
170 m_contextHelp->EndContextHelp();
171 return TRUE;
172 break;
173 }
174 case wxEVT_CHAR:
175 case wxEVT_KEY_DOWN:
176 case wxEVT_ACTIVATE:
177 case wxEVT_MOUSE_CAPTURE_CHANGED:
178 {
179 m_contextHelp->SetStatus(FALSE);
180 m_contextHelp->EndContextHelp();
181 return TRUE;
182 break;
183 }
184 case wxEVT_PAINT:
185 case wxEVT_ERASE_BACKGROUND:
186 {
187 event.Skip();
188 return FALSE;
189 break;
190 }
191 }
192
193 return TRUE;
194}
195
196// Dispatch the help event to the relevant window
197bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
198{
199 wxWindow* subjectOfHelp = win;
200 bool eventProcessed = FALSE;
201 while (subjectOfHelp && !eventProcessed)
202 {
203 wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ;
204 helpEvent.SetEventObject(this);
205 eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent);
206
207 // Go up the window hierarchy until the event is handled (or not).
208 // I.e. keep submitting ancestor windows until one is recognised
209 // by the app code that processes the ids and displays help.
210 subjectOfHelp = subjectOfHelp->GetParent();
211 }
212 return eventProcessed;
213}
214
bd83cb56
VZ
215// ----------------------------------------------------------------------------
216// wxContextHelpButton
217// ----------------------------------------------------------------------------
218
fb6261e9
JS
219/*
220 * wxContextHelpButton
221 * You can add this to your dialogs (especially on non-Windows platforms)
222 * to put the application into context help mode.
223 */
224
225#if !defined(__WXMSW__)
226static char * csquery_xpm[] = {
227"12 11 2 1",
57591e0e
JS
228" c None",
229". c #000000",
fb6261e9
JS
230" ",
231" .... ",
232" .. .. ",
233" .. .. ",
234" .. ",
235" .. ",
236" .. ",
237" ",
238" .. ",
239" .. ",
240" "};
241#endif
242
243IMPLEMENT_CLASS(wxContextHelpButton, wxBitmapButton)
244
245BEGIN_EVENT_TABLE(wxContextHelpButton, wxBitmapButton)
246 EVT_BUTTON(wxID_CONTEXT_HELP, wxContextHelpButton::OnContextHelp)
247END_EVENT_TABLE()
248
84bfc0d5
VZ
249wxContextHelpButton::wxContextHelpButton(wxWindow* parent,
250 wxWindowID id,
251 const wxPoint& pos,
252 const wxSize& size,
253 long style)
254 : wxBitmapButton(parent, id, wxBITMAP(csquery),
255 pos, size, style)
fb6261e9 256{
fb6261e9
JS
257}
258
259void wxContextHelpButton::OnContextHelp(wxCommandEvent& event)
260{
57591e0e 261 wxContextHelp contextHelp(GetParent());
fb6261e9
JS
262}
263
bd83cb56
VZ
264// ----------------------------------------------------------------------------
265// wxHelpProvider
266// ----------------------------------------------------------------------------
267
268wxHelpProvider *wxHelpProvider::ms_helpProvider = (wxHelpProvider *)NULL;
269
270// trivial implementation of some methods which we don't want to make pure
271// virtual for convenience
272
273void wxHelpProvider::AddHelp(wxWindowBase * WXUNUSED(window),
274 const wxString& WXUNUSED(text))
275{
276}
277
278void wxHelpProvider::AddHelp(wxWindowID WXUNUSED(id),
279 const wxString& WXUNUSED(text))
280{
281}
282
283wxHelpProvider::~wxHelpProvider()
284{
285}
286
287// ----------------------------------------------------------------------------
288// wxSimpleHelpProvider
289// ----------------------------------------------------------------------------
290
291wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
292{
293 bool wasFound;
294 wxString text = m_hashWindows.Get((long)window, &wasFound);
295 if ( !wasFound )
296 text = m_hashIds.Get(window->GetId());
297
298 return text;
299}
300
301void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text)
302{
303 m_hashWindows.Put((long)window, text);
304}
305
306void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
307{
308 m_hashIds.Put(id, text);
309}
310
311bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window)
312{
313 wxString text = GetHelp(window);
314 if ( !text.empty() )
315 {
01fa3fe7 316 new wxTipWindow((wxWindow *)window, text);
bd83cb56
VZ
317
318 return TRUE;
319 }
320
321 return FALSE;
322}
323
5100cabf
JS
324// ----------------------------------------------------------------------------
325// wxHelpControllerHelpProvider
326// ----------------------------------------------------------------------------
327
328wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase* hc)
329{
330 m_helpController = hc;
331}
332
333bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase *window)
334{
335 wxString text = GetHelp(window);
336 if ( !text.empty() )
337 {
338 if (m_helpController)
339 {
340 if (text.IsNumber())
341 return m_helpController->DisplayContextPopup(wxAtoi(text));
342
343 // If the help controller is capable of popping up the text...
344 else if (m_helpController->DisplayTextPopup(text, wxGetMousePosition()))
345 {
346 return TRUE;
347 }
348 else
349 // ...else use the default method.
350 return wxSimpleHelpProvider::ShowHelp(window);
351 }
352 else
353 return wxSimpleHelpProvider::ShowHelp(window);
354
355 }
356
357 return FALSE;
358}
359
360// Convenience function for turning context id into wxString
361wxString wxContextId(int id)
362{
363 return wxString(IntToString(id));
364}
365
129caadd
JS
366// ----------------------------------------------------------------------------
367// wxHelpProviderModule: module responsible for cleaning up help provider.
368// ----------------------------------------------------------------------------
369
370class wxHelpProviderModule : public wxModule
371{
372public:
373 bool OnInit();
374 void OnExit();
375
376private:
377 DECLARE_DYNAMIC_CLASS(wxHelpProviderModule)
378};
379
380IMPLEMENT_DYNAMIC_CLASS(wxHelpProviderModule, wxModule)
381
382bool wxHelpProviderModule::OnInit()
383{
384 // Probably we don't want to do anything by default,
385 // since it could pull in extra code
386 // wxHelpProvider::Set(new wxSimpleHelpProvider);
387
388 return TRUE;
389}
390
391void wxHelpProviderModule::OnExit()
392{
393 if (wxHelpProvider::Get())
394 {
395 delete wxHelpProvider::Get();
396 wxHelpProvider::Set(NULL);
397 }
398}
399
fb6261e9 400#endif // wxUSE_HELP