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