~ubuntu-dev/wxwidgets2.6/upstream-debian

« back to all changes in this revision

Viewing changes to src/common/cshelp.cpp

  • Committer: Daniel T Chen
  • Date: 2006-06-26 10:15:11 UTC
  • Revision ID: crimsun@ubuntu.com-20060626101511-a4436cec4c6d9b35
ImportĀ DebianĀ 2.6.3.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/common/cshelp.cpp
 
3
// Purpose:     Context sensitive help class implementation
 
4
// Author:      Julian Smart, Vadim Zeitlin
 
5
// Modified by:
 
6
// Created:     08/09/2000
 
7
// RCS-ID:      $Id: cshelp.cpp,v 1.35 2005/07/21 16:19:39 ABX Exp $
 
8
// Copyright:   (c) 2000 Julian Smart, Vadim Zeitlin
 
9
// Licence:     wxWindows licence
 
10
/////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
// ============================================================================
 
13
// declarations
 
14
// ============================================================================
 
15
 
 
16
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
 
17
    #pragma implementation "cshelp.h"
 
18
#endif
 
19
 
 
20
// ----------------------------------------------------------------------------
 
21
// headers
 
22
// ----------------------------------------------------------------------------
 
23
 
 
24
// For compilers that support precompilation, includes "wx.h".
 
25
#include "wx/wxprec.h"
 
26
 
 
27
#ifdef __BORLANDC__
 
28
    #pragma hdrstop
 
29
#endif
 
30
 
 
31
#if wxUSE_HELP
 
32
 
 
33
#ifndef WX_PRECOMP
 
34
#endif
 
35
 
 
36
#include "wx/tipwin.h"
 
37
#include "wx/app.h"
 
38
#include "wx/module.h"
 
39
#include "wx/cshelp.h"
 
40
 
 
41
// ----------------------------------------------------------------------------
 
42
// wxContextHelpEvtHandler private class
 
43
// ----------------------------------------------------------------------------
 
44
 
 
45
// This class exists in order to eat events until the left mouse button is
 
46
// pressed
 
47
class wxContextHelpEvtHandler: public wxEvtHandler
 
48
{
 
49
public:
 
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
    DECLARE_NO_COPY_CLASS(wxContextHelpEvtHandler)
 
61
};
 
62
 
 
63
// ============================================================================
 
64
// implementation
 
65
// ============================================================================
 
66
 
 
67
// ----------------------------------------------------------------------------
 
68
// wxContextHelp
 
69
// ----------------------------------------------------------------------------
 
70
 
 
71
/*
 
72
 * Invokes context-sensitive help
 
73
 */
 
74
 
 
75
 
 
76
IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject)
 
77
 
 
78
wxContextHelp::wxContextHelp(wxWindow* win, bool beginHelp)
 
79
{
 
80
    m_inHelp = false;
 
81
 
 
82
    if (beginHelp)
 
83
        BeginContextHelp(win);
 
84
}
 
85
 
 
86
wxContextHelp::~wxContextHelp()
 
87
{
 
88
    if (m_inHelp)
 
89
        EndContextHelp();
 
90
}
 
91
 
 
92
// Not currently needed, but on some systems capture may not work as
 
93
// expected so we'll leave it here for now.
 
94
#ifdef __WXMOTIF__
 
95
static void wxPushOrPopEventHandlers(wxContextHelp* help, wxWindow* win, bool push)
 
96
{
 
97
    if (push)
 
98
        win->PushEventHandler(new wxContextHelpEvtHandler(help));
 
99
    else
 
100
        win->PopEventHandler(true);
 
101
 
 
102
    wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
 
103
    while (node)
 
104
    {
 
105
        wxWindow* child = node->GetData();
 
106
        wxPushOrPopEventHandlers(help, child, push);
 
107
 
 
108
        node = node->GetNext();
 
109
    }
 
110
}
 
111
#endif
 
112
 
 
113
// Begin 'context help mode'
 
114
bool wxContextHelp::BeginContextHelp(wxWindow* win)
 
115
{
 
116
    if (!win)
 
117
        win = wxTheApp->GetTopWindow();
 
118
    if (!win)
 
119
        return false;
 
120
 
 
121
    wxCursor cursor(wxCURSOR_QUESTION_ARROW);
 
122
    wxCursor oldCursor = win->GetCursor();
 
123
    win->SetCursor(cursor);
 
124
 
 
125
#ifdef __WXMSW__
 
126
    //    wxSetCursor(cursor);
 
127
#endif
 
128
 
 
129
    m_status = false;
 
130
 
 
131
#ifdef __WXMOTIF__
 
132
    wxPushOrPopEventHandlers(this, win, true);
 
133
#else
 
134
    win->PushEventHandler(new wxContextHelpEvtHandler(this));
 
135
#endif
 
136
 
 
137
    win->CaptureMouse();
 
138
 
 
139
    EventLoop();
 
140
 
 
141
    win->ReleaseMouse();
 
142
 
 
143
#ifdef __WXMOTIF__
 
144
    wxPushOrPopEventHandlers(this, win, false);
 
145
#else
 
146
    win->PopEventHandler(true);
 
147
#endif
 
148
 
 
149
    win->SetCursor(oldCursor);
 
150
 
 
151
    if (m_status)
 
152
    {
 
153
        wxPoint pt;
 
154
        wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
 
155
 
 
156
#if 0
 
157
        if (winAtPtr)
 
158
        {
 
159
            printf("Picked %s (%d)\n", winAtPtr->GetName().c_str(),
 
160
                   winAtPtr->GetId());
 
161
        }
 
162
#endif
 
163
 
 
164
        if (winAtPtr)
 
165
            DispatchEvent(winAtPtr, pt);
 
166
    }
 
167
 
 
168
    return true;
 
169
}
 
170
 
 
171
bool wxContextHelp::EndContextHelp()
 
172
{
 
173
    m_inHelp = false;
 
174
 
 
175
    return true;
 
176
}
 
177
 
 
178
bool wxContextHelp::EventLoop()
 
179
{
 
180
    m_inHelp = true;
 
181
 
 
182
    while ( m_inHelp )
 
183
    {
 
184
        if (wxTheApp->Pending())
 
185
        {
 
186
            wxTheApp->Dispatch();
 
187
        }
 
188
        else
 
189
        {
 
190
            wxTheApp->ProcessIdle();
 
191
        }
 
192
    }
 
193
 
 
194
    return true;
 
195
}
 
196
 
 
197
bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
 
198
{
 
199
    if (event.GetEventType() == wxEVT_LEFT_DOWN)
 
200
    {
 
201
        m_contextHelp->SetStatus(true);
 
202
        m_contextHelp->EndContextHelp();
 
203
        return true;
 
204
    }
 
205
 
 
206
    if ((event.GetEventType() == wxEVT_CHAR) ||
 
207
        (event.GetEventType() == wxEVT_KEY_DOWN) ||
 
208
        (event.GetEventType() == wxEVT_ACTIVATE) ||
 
209
        (event.GetEventType() == wxEVT_MOUSE_CAPTURE_CHANGED))
 
210
    {
 
211
        // May have already been set to true by a left-click
 
212
        //m_contextHelp->SetStatus(false);
 
213
        m_contextHelp->EndContextHelp();
 
214
        return true;
 
215
    }
 
216
 
 
217
    if ((event.GetEventType() == wxEVT_PAINT) ||
 
218
        (event.GetEventType() == wxEVT_ERASE_BACKGROUND))
 
219
    {
 
220
        event.Skip();
 
221
        return false;
 
222
    }
 
223
 
 
224
    return true;
 
225
}
 
226
 
 
227
// Dispatch the help event to the relevant window
 
228
bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
 
229
{
 
230
    wxWindow* subjectOfHelp = win;
 
231
    bool eventProcessed = false;
 
232
    while (subjectOfHelp && !eventProcessed)
 
233
    {
 
234
        wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ;
 
235
        helpEvent.SetEventObject(subjectOfHelp);
 
236
 
 
237
        eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent);
 
238
 
 
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();
 
243
    }
 
244
    return eventProcessed;
 
245
}
 
246
 
 
247
// ----------------------------------------------------------------------------
 
248
// wxContextHelpButton
 
249
// ----------------------------------------------------------------------------
 
250
 
 
251
/*
 
252
 * wxContextHelpButton
 
253
 * You can add this to your dialogs (especially on non-Windows platforms)
 
254
 * to put the application into context help mode.
 
255
 */
 
256
 
 
257
#ifndef __WXPM__
 
258
 
 
259
static const char * csquery_xpm[] = {
 
260
"12 11 2 1",
 
261
"  c None",
 
262
". c #000000",
 
263
"            ",
 
264
"    ....    ",
 
265
"   ..  ..   ",
 
266
"   ..  ..   ",
 
267
"      ..    ",
 
268
"     ..     ",
 
269
"     ..     ",
 
270
"            ",
 
271
"     ..     ",
 
272
"     ..     ",
 
273
"            "};
 
274
 
 
275
#endif
 
276
 
 
277
IMPLEMENT_CLASS(wxContextHelpButton, wxBitmapButton)
 
278
 
 
279
BEGIN_EVENT_TABLE(wxContextHelpButton, wxBitmapButton)
 
280
    EVT_BUTTON(wxID_CONTEXT_HELP, wxContextHelpButton::OnContextHelp)
 
281
END_EVENT_TABLE()
 
282
 
 
283
wxContextHelpButton::wxContextHelpButton(wxWindow* parent,
 
284
                                         wxWindowID id,
 
285
                                         const wxPoint& pos,
 
286
                                         const wxSize& size,
 
287
                                         long style)
 
288
#if defined(__WXPM__)
 
289
                   : wxBitmapButton(parent, id, wxBitmap(wxCSQUERY_BITMAP
 
290
                                                         ,wxBITMAP_TYPE_RESOURCE
 
291
                                                        ),
 
292
                                    pos, size, style)
 
293
#else
 
294
                   : wxBitmapButton(parent, id, wxBitmap(csquery_xpm),
 
295
                                    pos, size, style)
 
296
#endif
 
297
{
 
298
}
 
299
 
 
300
void wxContextHelpButton::OnContextHelp(wxCommandEvent& WXUNUSED(event))
 
301
{
 
302
    wxContextHelp contextHelp(GetParent());
 
303
}
 
304
 
 
305
// ----------------------------------------------------------------------------
 
306
// wxHelpProvider
 
307
// ----------------------------------------------------------------------------
 
308
 
 
309
wxHelpProvider *wxHelpProvider::ms_helpProvider = (wxHelpProvider *)NULL;
 
310
 
 
311
// trivial implementation of some methods which we don't want to make pure
 
312
// virtual for convenience
 
313
 
 
314
void wxHelpProvider::AddHelp(wxWindowBase * WXUNUSED(window),
 
315
                             const wxString& WXUNUSED(text))
 
316
{
 
317
}
 
318
 
 
319
void wxHelpProvider::AddHelp(wxWindowID WXUNUSED(id),
 
320
                             const wxString& WXUNUSED(text))
 
321
{
 
322
}
 
323
 
 
324
// removes the association
 
325
void wxHelpProvider::RemoveHelp(wxWindowBase* WXUNUSED(window))
 
326
{
 
327
}
 
328
 
 
329
wxHelpProvider::~wxHelpProvider()
 
330
{
 
331
}
 
332
 
 
333
// ----------------------------------------------------------------------------
 
334
// wxSimpleHelpProvider
 
335
// ----------------------------------------------------------------------------
 
336
 
 
337
wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
 
338
{
 
339
    wxLongToStringHashMap::iterator it = m_hashWindows.find((long)window);
 
340
 
 
341
    if ( it == m_hashWindows.end() )
 
342
    {
 
343
        it = m_hashIds.find(window->GetId());
 
344
        if ( it == m_hashIds.end() )
 
345
            return wxEmptyString;
 
346
    }
 
347
 
 
348
    return it->second;
 
349
}
 
350
 
 
351
void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text)
 
352
{
 
353
    m_hashWindows.erase((long)window);
 
354
    m_hashWindows[(long)window] = text;
 
355
}
 
356
 
 
357
void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
 
358
{
 
359
    wxLongToStringHashMap::key_type key = (wxLongToStringHashMap::key_type)id;
 
360
    m_hashIds.erase(key);
 
361
    m_hashIds[key] = text;
 
362
}
 
363
 
 
364
// removes the association
 
365
void wxSimpleHelpProvider::RemoveHelp(wxWindowBase* window)
 
366
{
 
367
    m_hashWindows.erase((long)window);
 
368
}
 
369
 
 
370
bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window)
 
371
{
 
372
#if wxUSE_TIPWINDOW
 
373
    static wxTipWindow* s_tipWindow = NULL;
 
374
 
 
375
    if (s_tipWindow)
 
376
    {
 
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();
 
381
    }
 
382
    s_tipWindow = NULL;
 
383
 
 
384
    wxString text = GetHelp(window);
 
385
    if ( !text.empty() )
 
386
    {
 
387
        s_tipWindow = new wxTipWindow((wxWindow *)window, text, 100, & s_tipWindow);
 
388
 
 
389
        return true;
 
390
    }
 
391
#else
 
392
    wxUnusedVar(window);
 
393
#endif // wxUSE_TIPWINDOW
 
394
 
 
395
    return false;
 
396
}
 
397
 
 
398
// ----------------------------------------------------------------------------
 
399
// wxHelpControllerHelpProvider
 
400
// ----------------------------------------------------------------------------
 
401
 
 
402
wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase* hc)
 
403
{
 
404
    m_helpController = hc;
 
405
}
 
406
 
 
407
bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase *window)
 
408
{
 
409
    wxString text = GetHelp(window);
 
410
    if ( !text.empty() )
 
411
    {
 
412
        if (m_helpController)
 
413
        {
 
414
            if (text.IsNumber())
 
415
                return m_helpController->DisplayContextPopup(wxAtoi(text));
 
416
 
 
417
            // If the help controller is capable of popping up the text...
 
418
            else if (m_helpController->DisplayTextPopup(text, wxGetMousePosition()))
 
419
            {
 
420
                return true;
 
421
            }
 
422
            else
 
423
            // ...else use the default method.
 
424
                return wxSimpleHelpProvider::ShowHelp(window);
 
425
        }
 
426
        else
 
427
            return wxSimpleHelpProvider::ShowHelp(window);
 
428
 
 
429
    }
 
430
 
 
431
    return false;
 
432
}
 
433
 
 
434
// Convenience function for turning context id into wxString
 
435
wxString wxContextId(int id)
 
436
{
 
437
    return wxString::Format(_T("%d"), id);
 
438
}
 
439
 
 
440
// ----------------------------------------------------------------------------
 
441
// wxHelpProviderModule: module responsible for cleaning up help provider.
 
442
// ----------------------------------------------------------------------------
 
443
 
 
444
class wxHelpProviderModule : public wxModule
 
445
{
 
446
public:
 
447
    bool OnInit();
 
448
    void OnExit();
 
449
 
 
450
private:
 
451
    DECLARE_DYNAMIC_CLASS(wxHelpProviderModule)
 
452
};
 
453
 
 
454
IMPLEMENT_DYNAMIC_CLASS(wxHelpProviderModule, wxModule)
 
455
 
 
456
bool wxHelpProviderModule::OnInit()
 
457
{
 
458
    // Probably we don't want to do anything by default,
 
459
    // since it could pull in extra code
 
460
    // wxHelpProvider::Set(new wxSimpleHelpProvider);
 
461
 
 
462
    return true;
 
463
}
 
464
 
 
465
void wxHelpProviderModule::OnExit()
 
466
{
 
467
    if (wxHelpProvider::Get())
 
468
    {
 
469
        delete wxHelpProvider::Get();
 
470
        wxHelpProvider::Set(NULL);
 
471
    }
 
472
}
 
473
 
 
474
#endif // wxUSE_HELP