]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/cshelp.cpp
Committing in .
[wxWidgets.git] / src / common / cshelp.cpp
index fe75524bb8aa408c5388a5252b79a6e534d0dea9..ae2a282c3a8e0260b37d86acf8ecc2c99b0469b8 100644 (file)
@@ -1,41 +1,45 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        cshelp.cpp
+// Name:        src/common/cshelp.cpp
 // Purpose:     Context sensitive help class implementation
-// Author:      Julian Smart
+// Author:      Julian Smart, Vadim Zeitlin
 // Modified by:
 // Created:     08/09/2000
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart
-// Licence:    wxWindows licence
+// Copyright:   (c) 2000 Julian Smart, Vadim Zeitlin
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "cshelp.h"
-#endif
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
+#if wxUSE_HELP
+
 #ifndef WX_PRECOMP
-#include "wx/defs.h"
 #endif
 
+#include "wx/tipwin.h"
 #include "wx/app.h"
-
-#if wxUSE_HELP
-
+#include "wx/module.h"
 #include "wx/cshelp.h"
 
-/*
- * Invokes context-sensitive help
- */
+// ----------------------------------------------------------------------------
+// wxContextHelpEvtHandler private class
+// ----------------------------------------------------------------------------
 
-// This class exists in order to eat events until the left mouse
-// button is pressed
+// This class exists in order to eat events until the left mouse button is
+// pressed
 class wxContextHelpEvtHandler: public wxEvtHandler
 {
 public:
@@ -48,13 +52,28 @@ public:
 
 //// Data
     wxContextHelp* m_contextHelp;
+
+    DECLARE_NO_COPY_CLASS(wxContextHelpEvtHandler)
 };
 
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxContextHelp
+// ----------------------------------------------------------------------------
+
+/*
+ * Invokes context-sensitive help
+ */
+
+
 IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject)
 
 wxContextHelp::wxContextHelp(wxWindow* win, bool beginHelp)
 {
-    m_inHelp = FALSE;
+    m_inHelp = false;
 
     if (beginHelp)
         BeginContextHelp(win);
@@ -66,13 +85,34 @@ wxContextHelp::~wxContextHelp()
         EndContextHelp();
 }
 
+// Not currently needed, but on some systems capture may not work as
+// expected so we'll leave it here for now.
+#ifdef __WXMOTIF__
+static void wxPushOrPopEventHandlers(wxContextHelp* help, wxWindow* win, bool push)
+{
+    if (push)
+        win->PushEventHandler(new wxContextHelpEvtHandler(help));
+    else
+        win->PopEventHandler(true);
+
+    wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
+    while (node)
+    {
+        wxWindow* child = node->GetData();
+        wxPushOrPopEventHandlers(help, child, push);
+
+        node = node->GetNext();
+    }
+}
+#endif
+
 // Begin 'context help mode'
 bool wxContextHelp::BeginContextHelp(wxWindow* win)
 {
     if (!win)
         win = wxTheApp->GetTopWindow();
     if (!win)
-        return FALSE;
+        return false;
 
     wxCursor cursor(wxCURSOR_QUESTION_ARROW);
     wxCursor oldCursor = win->GetCursor();
@@ -82,7 +122,13 @@ bool wxContextHelp::BeginContextHelp(wxWindow* win)
     //    wxSetCursor(cursor);
 #endif
 
+    m_status = false;
+
+#ifdef __WXMOTIF__
+    wxPushOrPopEventHandlers(this, win, true);
+#else
     win->PushEventHandler(new wxContextHelpEvtHandler(this));
+#endif
 
     win->CaptureMouse();
 
@@ -90,7 +136,11 @@ bool wxContextHelp::BeginContextHelp(wxWindow* win)
 
     win->ReleaseMouse();
 
-    win->PopEventHandler(TRUE);
+#ifdef __WXMOTIF__
+    wxPushOrPopEventHandlers(this, win, false);
+#else
+    win->PopEventHandler(true);
+#endif
 
     win->SetCursor(oldCursor);
 
@@ -98,23 +148,33 @@ bool wxContextHelp::BeginContextHelp(wxWindow* win)
     {
         wxPoint pt;
         wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
+
+#if 0
+        if (winAtPtr)
+        {
+            printf("Picked %s (%d)\n", winAtPtr->GetName().c_str(),
+                   winAtPtr->GetId());
+        }
+#endif
+
         if (winAtPtr)
             DispatchEvent(winAtPtr, pt);
     }
 
-    return TRUE;
+    return true;
 }
 
 bool wxContextHelp::EndContextHelp()
 {
-    m_inHelp = FALSE;
+    m_inHelp = false;
 
-    return TRUE;
+    return true;
 }
 
 bool wxContextHelp::EventLoop()
 {
-    m_inHelp = TRUE;
+    m_inHelp = true;
+
     while ( m_inHelp )
     {
         if (wxTheApp->Pending())
@@ -126,54 +186,52 @@ bool wxContextHelp::EventLoop()
             wxTheApp->ProcessIdle();
         }
     }
-    return TRUE;
+
+    return true;
 }
 
 bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
 {
-    switch (event.GetEventType())
+    if (event.GetEventType() == wxEVT_LEFT_DOWN)
     {
-        case wxEVT_LEFT_DOWN:
-        {
-         //wxMouseEvent& mouseEvent = (wxMouseEvent&) event;
-            m_contextHelp->SetStatus(TRUE);
-            m_contextHelp->EndContextHelp();
-            return TRUE;
-            break;
-        }
-        case wxEVT_CHAR:
-        case wxEVT_KEY_DOWN:
-        case wxEVT_ACTIVATE:
-        case wxEVT_MOUSE_CAPTURE_CHANGED:
-        {
-            m_contextHelp->SetStatus(FALSE);
-            m_contextHelp->EndContextHelp();
-            return TRUE;
-            break;
-        }
-        case wxEVT_PAINT:
-        case wxEVT_ERASE_BACKGROUND:
-        {
-            event.Skip();
-            return FALSE;
-            break;
-        }
+        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;
+    return true;
 }
 
 // Dispatch the help event to the relevant window
 bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
 {
     wxWindow* subjectOfHelp = win;
-    bool eventProcessed = FALSE;
+    bool eventProcessed = false;
     while (subjectOfHelp && !eventProcessed)
     {
         wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ;
-        helpEvent.SetEventObject(this);
+        helpEvent.SetEventObject(subjectOfHelp);
+
         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.
@@ -182,17 +240,22 @@ bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
     return eventProcessed;
 }
 
+// ----------------------------------------------------------------------------
+// wxContextHelpButton
+// ----------------------------------------------------------------------------
+
 /*
  * wxContextHelpButton
  * You can add this to your dialogs (especially on non-Windows platforms)
  * to put the application into context help mode.
  */
 
-#if !defined(__WXMSW__)
-static char * csquery_xpm[] = {
+#ifndef __WXPM__
+
+static const char * csquery_xpm[] = {
 "12 11 2 1",
-"      c None",
-".     c Black",
+"  c None",
+". c #000000",
 "            ",
 "    ....    ",
 "   ..  ..   ",
@@ -204,6 +267,7 @@ static char * csquery_xpm[] = {
 "     ..     ",
 "     ..     ",
 "            "};
+
 #endif
 
 IMPLEMENT_CLASS(wxContextHelpButton, wxBitmapButton)
@@ -212,23 +276,197 @@ 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):
-   wxBitmapButton(parent, id, wxNullBitmap, pos, size, style)
-{
-#ifdef __WXMSW__
-    wxBitmap bitmap(wxT("csquery_bmp"), wxBITMAP_TYPE_BMP_RESOURCE);
+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
-    wxBitmap bitmap(csquery_xpm);
+                   : 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
+// ----------------------------------------------------------------------------
+
+#define WINHASH_KEY(w) wxPtrToUInt(w)
+
+wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
+{
+    wxSimpleHelpProviderHashMap::iterator it = m_hashWindows.find(WINHASH_KEY(window));
+
+    if ( it == m_hashWindows.end() )
+    {
+        it = m_hashIds.find(window->GetId());
+        if ( it == m_hashIds.end() )
+            return wxEmptyString;
+    }
+
+    return it->second;
+}
+
+void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text)
+{
+    m_hashWindows.erase(WINHASH_KEY(window));
+    m_hashWindows[WINHASH_KEY(window)] = text;
+}
+
+void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
+{
+    wxSimpleHelpProviderHashMap::key_type key = (wxSimpleHelpProviderHashMap::key_type)id;
+    m_hashIds.erase(key);
+    m_hashIds[key] = text;
+}
+
+// removes the association
+void wxSimpleHelpProvider::RemoveHelp(wxWindowBase* window)
+{
+    m_hashWindows.erase(WINHASH_KEY(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;
+    }
+#else
+    wxUnusedVar(window);
+#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);
+
+    }
 
-    SetBitmapLabel(bitmap);
+    return false;
 }
 
-void wxContextHelpButton::OnContextHelp(wxCommandEvent& event)
+// Convenience function for turning context id into wxString
+wxString wxContextId(int id)
+{
+    return wxString::Format(_T("%d"), id);
+}
+
+// ----------------------------------------------------------------------------
+// wxHelpProviderModule: module responsible for cleaning up help provider.
+// ----------------------------------------------------------------------------
+
+class wxHelpProviderModule : public wxModule
 {
-    wxContextHelp contextHelp;
+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