git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@20561 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
456 lines
11 KiB
C++
456 lines
11 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/cshelp.cpp
|
|
// Purpose: Context sensitive help class implementation
|
|
// Author: Julian Smart, Vadim Zeitlin
|
|
// Modified by:
|
|
// Created: 08/09/2000
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) 2000 Julian Smart, Vadim Zeitlin
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "cshelp.h"
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_HELP
|
|
|
|
#ifndef WX_PRECOMP
|
|
#endif
|
|
|
|
#include "wx/tipwin.h"
|
|
#include "wx/app.h"
|
|
#include "wx/module.h"
|
|
#include "wx/cshelp.h"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxContextHelpEvtHandler private class
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// This class exists in order to eat events until the left mouse button is
|
|
// pressed
|
|
class wxContextHelpEvtHandler: public wxEvtHandler
|
|
{
|
|
public:
|
|
wxContextHelpEvtHandler(wxContextHelp* contextHelp)
|
|
{
|
|
m_contextHelp = contextHelp;
|
|
}
|
|
|
|
virtual bool ProcessEvent(wxEvent& event);
|
|
|
|
//// Data
|
|
wxContextHelp* m_contextHelp;
|
|
};
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxContextHelp
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/*
|
|
* Invokes context-sensitive help
|
|
*/
|
|
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject)
|
|
|
|
wxContextHelp::wxContextHelp(wxWindow* win, bool beginHelp)
|
|
{
|
|
m_inHelp = FALSE;
|
|
|
|
if (beginHelp)
|
|
BeginContextHelp(win);
|
|
}
|
|
|
|
wxContextHelp::~wxContextHelp()
|
|
{
|
|
if (m_inHelp)
|
|
EndContextHelp();
|
|
}
|
|
|
|
// Not currently needed, but on some systems capture may not work as
|
|
// expected so we'll leave it here for now.
|
|
#if 0
|
|
static void wxPushOrPopEventHandlers(wxContextHelp* help, wxWindow* win, bool push)
|
|
{
|
|
if (push)
|
|
win->PushEventHandler(new wxContextHelpEvtHandler(help));
|
|
else
|
|
win->PopEventHandler();
|
|
|
|
wxNode* node = win->GetChildren().First();
|
|
while (node)
|
|
{
|
|
wxWindow* child = (wxWindow*) node->Data();
|
|
wxPushOrPopEventHandlers(help, child, push);
|
|
|
|
node = node->Next();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Begin 'context help mode'
|
|
bool wxContextHelp::BeginContextHelp(wxWindow* win)
|
|
{
|
|
if (!win)
|
|
win = wxTheApp->GetTopWindow();
|
|
if (!win)
|
|
return FALSE;
|
|
|
|
wxCursor cursor(wxCURSOR_QUESTION_ARROW);
|
|
wxCursor oldCursor = win->GetCursor();
|
|
win->SetCursor(cursor);
|
|
|
|
#ifdef __WXMSW__
|
|
// wxSetCursor(cursor);
|
|
#endif
|
|
|
|
m_status = FALSE;
|
|
|
|
win->PushEventHandler(new wxContextHelpEvtHandler(this));
|
|
//wxPushOrPopEventHandlers(this, win, TRUE);
|
|
|
|
win->CaptureMouse();
|
|
|
|
EventLoop();
|
|
|
|
win->ReleaseMouse();
|
|
|
|
win->PopEventHandler(TRUE);
|
|
//wxPushOrPopEventHandlers(this, win, FALSE);
|
|
|
|
win->SetCursor(oldCursor);
|
|
|
|
if (m_status)
|
|
{
|
|
wxPoint pt;
|
|
wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
|
|
/*
|
|
if (winAtPtr)
|
|
{
|
|
wxString msg;
|
|
msg.Printf("Picked %s (%d)", (const char*) winAtPtr->GetName(), winAtPtr->GetId());
|
|
cout << msg << '\n';
|
|
}
|
|
*/
|
|
|
|
if (winAtPtr)
|
|
DispatchEvent(winAtPtr, pt);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool wxContextHelp::EndContextHelp()
|
|
{
|
|
m_inHelp = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool wxContextHelp::EventLoop()
|
|
{
|
|
m_inHelp = TRUE;
|
|
|
|
while ( m_inHelp )
|
|
{
|
|
if (wxTheApp->Pending())
|
|
{
|
|
wxTheApp->Dispatch();
|
|
}
|
|
else
|
|
{
|
|
wxTheApp->ProcessIdle();
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
|
|
{
|
|
if (event.GetEventType() == wxEVT_LEFT_DOWN)
|
|
{
|
|
m_contextHelp->SetStatus(TRUE);
|
|
m_contextHelp->EndContextHelp();
|
|
return TRUE;
|
|
}
|
|
|
|
if ((event.GetEventType() == wxEVT_CHAR) ||
|
|
(event.GetEventType() == wxEVT_KEY_DOWN) ||
|
|
(event.GetEventType() == wxEVT_ACTIVATE) ||
|
|
(event.GetEventType() == wxEVT_MOUSE_CAPTURE_CHANGED))
|
|
{
|
|
// May have already been set to TRUE by a left-click
|
|
//m_contextHelp->SetStatus(FALSE);
|
|
m_contextHelp->EndContextHelp();
|
|
return TRUE;
|
|
}
|
|
|
|
if ((event.GetEventType() == wxEVT_PAINT) ||
|
|
(event.GetEventType() == wxEVT_ERASE_BACKGROUND))
|
|
{
|
|
event.Skip();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Dispatch the help event to the relevant window
|
|
bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
|
|
{
|
|
wxWindow* subjectOfHelp = win;
|
|
bool eventProcessed = FALSE;
|
|
while (subjectOfHelp && !eventProcessed)
|
|
{
|
|
wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ;
|
|
helpEvent.SetEventObject(this);
|
|
|
|
eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent);
|
|
|
|
// Go up the window hierarchy until the event is handled (or not).
|
|
// I.e. keep submitting ancestor windows until one is recognised
|
|
// by the app code that processes the ids and displays help.
|
|
subjectOfHelp = subjectOfHelp->GetParent();
|
|
}
|
|
return eventProcessed;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxContextHelpButton
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/*
|
|
* wxContextHelpButton
|
|
* You can add this to your dialogs (especially on non-Windows platforms)
|
|
* to put the application into context help mode.
|
|
*/
|
|
|
|
static const char * csquery_xpm[] = {
|
|
"12 11 2 1",
|
|
" c None",
|
|
". c #000000",
|
|
" ",
|
|
" .... ",
|
|
" .. .. ",
|
|
" .. .. ",
|
|
" .. ",
|
|
" .. ",
|
|
" .. ",
|
|
" ",
|
|
" .. ",
|
|
" .. ",
|
|
" "};
|
|
|
|
IMPLEMENT_CLASS(wxContextHelpButton, wxBitmapButton)
|
|
|
|
BEGIN_EVENT_TABLE(wxContextHelpButton, wxBitmapButton)
|
|
EVT_BUTTON(wxID_CONTEXT_HELP, wxContextHelpButton::OnContextHelp)
|
|
END_EVENT_TABLE()
|
|
|
|
wxContextHelpButton::wxContextHelpButton(wxWindow* parent,
|
|
wxWindowID id,
|
|
const wxPoint& pos,
|
|
const wxSize& size,
|
|
long style)
|
|
#if defined(__WXPM__)
|
|
: wxBitmapButton(parent, id, wxBitmap(wxCSQUERY_BITMAP
|
|
,wxBITMAP_TYPE_RESOURCE
|
|
),
|
|
pos, size, style)
|
|
#else
|
|
: wxBitmapButton(parent, id, wxBitmap(csquery_xpm),
|
|
pos, size, style)
|
|
#endif
|
|
{
|
|
}
|
|
|
|
void wxContextHelpButton::OnContextHelp(wxCommandEvent& WXUNUSED(event))
|
|
{
|
|
wxContextHelp contextHelp(GetParent());
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxHelpProvider
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxHelpProvider *wxHelpProvider::ms_helpProvider = (wxHelpProvider *)NULL;
|
|
|
|
// trivial implementation of some methods which we don't want to make pure
|
|
// virtual for convenience
|
|
|
|
void wxHelpProvider::AddHelp(wxWindowBase * WXUNUSED(window),
|
|
const wxString& WXUNUSED(text))
|
|
{
|
|
}
|
|
|
|
void wxHelpProvider::AddHelp(wxWindowID WXUNUSED(id),
|
|
const wxString& WXUNUSED(text))
|
|
{
|
|
}
|
|
|
|
// removes the association
|
|
void wxHelpProvider::RemoveHelp(wxWindowBase* WXUNUSED(window))
|
|
{
|
|
}
|
|
|
|
wxHelpProvider::~wxHelpProvider()
|
|
{
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxSimpleHelpProvider
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
|
|
{
|
|
bool wasFound;
|
|
wxString text = m_hashWindows.Get((long)window, &wasFound);
|
|
if ( !wasFound )
|
|
text = m_hashIds.Get(window->GetId());
|
|
|
|
return text;
|
|
}
|
|
|
|
void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text)
|
|
{
|
|
m_hashWindows.Delete((long)window);
|
|
m_hashWindows.Put((long)window, text);
|
|
}
|
|
|
|
void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
|
|
{
|
|
m_hashIds.Delete((long)id);
|
|
m_hashIds.Put(id, text);
|
|
}
|
|
|
|
// removes the association
|
|
void wxSimpleHelpProvider::RemoveHelp(wxWindowBase* window)
|
|
{
|
|
m_hashWindows.Delete((long)window);
|
|
}
|
|
|
|
bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window)
|
|
{
|
|
#if wxUSE_TIPWINDOW
|
|
static wxTipWindow* s_tipWindow = NULL;
|
|
|
|
if (s_tipWindow)
|
|
{
|
|
// Prevent s_tipWindow being nulled in OnIdle,
|
|
// thereby removing the chance for the window to be closed by ShowHelp
|
|
s_tipWindow->SetTipWindowPtr(NULL);
|
|
s_tipWindow->Close();
|
|
}
|
|
s_tipWindow = NULL;
|
|
|
|
wxString text = GetHelp(window);
|
|
if ( !text.empty() )
|
|
{
|
|
s_tipWindow = new wxTipWindow((wxWindow *)window, text, 100, & s_tipWindow);
|
|
|
|
return TRUE;
|
|
}
|
|
#endif // wxUSE_TIPWINDOW
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxHelpControllerHelpProvider
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase* hc)
|
|
{
|
|
m_helpController = hc;
|
|
}
|
|
|
|
bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase *window)
|
|
{
|
|
wxString text = GetHelp(window);
|
|
if ( !text.empty() )
|
|
{
|
|
if (m_helpController)
|
|
{
|
|
if (text.IsNumber())
|
|
return m_helpController->DisplayContextPopup(wxAtoi(text));
|
|
|
|
// If the help controller is capable of popping up the text...
|
|
else if (m_helpController->DisplayTextPopup(text, wxGetMousePosition()))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
// ...else use the default method.
|
|
return wxSimpleHelpProvider::ShowHelp(window);
|
|
}
|
|
else
|
|
return wxSimpleHelpProvider::ShowHelp(window);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// Convenience function for turning context id into wxString
|
|
wxString wxContextId(int id)
|
|
{
|
|
return wxString(IntToString(id));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxHelpProviderModule: module responsible for cleaning up help provider.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxHelpProviderModule : public wxModule
|
|
{
|
|
public:
|
|
bool OnInit();
|
|
void OnExit();
|
|
|
|
private:
|
|
DECLARE_DYNAMIC_CLASS(wxHelpProviderModule)
|
|
};
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxHelpProviderModule, wxModule)
|
|
|
|
bool wxHelpProviderModule::OnInit()
|
|
{
|
|
// Probably we don't want to do anything by default,
|
|
// since it could pull in extra code
|
|
// wxHelpProvider::Set(new wxSimpleHelpProvider);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void wxHelpProviderModule::OnExit()
|
|
{
|
|
if (wxHelpProvider::Get())
|
|
{
|
|
delete wxHelpProvider::Get();
|
|
wxHelpProvider::Set(NULL);
|
|
}
|
|
}
|
|
|
|
#endif // wxUSE_HELP
|