]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/cshelp.cpp
Rewind the input stream after failing to load image from it.
[wxWidgets.git] / src / common / cshelp.cpp
index 5d5f7f200f398aea09c541104d2eca86d7ece2e2..5bbdd65f524842f20d1956823d5deb5e569d7ca1 100644 (file)
 // declarations
 // ============================================================================
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "cshelp.h"
-#endif
-
 // ----------------------------------------------------------------------------
 // headers
 // ----------------------------------------------------------------------------
 #if wxUSE_HELP
 
 #ifndef WX_PRECOMP
+    #include "wx/app.h"
+    #include "wx/module.h"
 #endif
 
 #include "wx/tipwin.h"
-#include "wx/app.h"
-#include "wx/module.h"
 #include "wx/cshelp.h"
 
+#if wxUSE_MS_HTML_HELP
+    #include "wx/msw/helpchm.h"     // for ShowContextHelpPopup
+    #include "wx/utils.h"           // for wxGetMousePosition()
+#endif
+
 // ----------------------------------------------------------------------------
 // wxContextHelpEvtHandler private class
 // ----------------------------------------------------------------------------
@@ -57,7 +58,7 @@ public:
 //// Data
     wxContextHelp* m_contextHelp;
 
-    DECLARE_NO_COPY_CLASS(wxContextHelpEvtHandler)
+    wxDECLARE_NO_COPY_CLASS(wxContextHelpEvtHandler);
 };
 
 // ============================================================================
@@ -122,8 +123,8 @@ bool wxContextHelp::BeginContextHelp(wxWindow* win)
     wxCursor oldCursor = win->GetCursor();
     win->SetCursor(cursor);
 
-#ifdef __WXMSW__
-    //    wxSetCursor(cursor);
+#ifdef __WXMAC__
+    wxSetCursor(cursor);
 #endif
 
     m_status = false;
@@ -148,6 +149,10 @@ bool wxContextHelp::BeginContextHelp(wxWindow* win)
 
     win->SetCursor(oldCursor);
 
+#ifdef __WXMAC__
+    wxSetCursor(wxNullCursor);
+#endif
+
     if (m_status)
     {
         wxPoint pt;
@@ -227,21 +232,13 @@ bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
 // 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(subjectOfHelp);
+    wxCHECK_MSG( win, false, wxT("win parameter can't be NULL") );
 
-        eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent);
+    wxHelpEvent helpEvent(wxEVT_HELP, win->GetId(), pt,
+                          wxHelpEvent::Origin_HelpButton);
+    helpEvent.SetEventObject(win);
 
-        // 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;
+    return win->GetEventHandler()->ProcessEvent(helpEvent);
 }
 
 // ----------------------------------------------------------------------------
@@ -254,6 +251,8 @@ bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
  * to put the application into context help mode.
  */
 
+#ifndef __WXPM__
+
 static const char * csquery_xpm[] = {
 "12 11 2 1",
 "  c None",
@@ -270,6 +269,8 @@ static const char * csquery_xpm[] = {
 "     ..     ",
 "            "};
 
+#endif
+
 IMPLEMENT_CLASS(wxContextHelpButton, wxBitmapButton)
 
 BEGIN_EVENT_TABLE(wxContextHelpButton, wxBitmapButton)
@@ -302,7 +303,7 @@ void wxContextHelpButton::OnContextHelp(wxCommandEvent& WXUNUSED(event))
 // wxHelpProvider
 // ----------------------------------------------------------------------------
 
-wxHelpProvider *wxHelpProvider::ms_helpProvider = (wxHelpProvider *)NULL;
+wxHelpProvider *wxHelpProvider::ms_helpProvider = NULL;
 
 // trivial implementation of some methods which we don't want to make pure
 // virtual for convenience
@@ -326,13 +327,34 @@ wxHelpProvider::~wxHelpProvider()
 {
 }
 
+wxString wxHelpProvider::GetHelpTextMaybeAtPoint(wxWindowBase *window)
+{
+    if ( m_helptextAtPoint != wxDefaultPosition ||
+            m_helptextOrigin != wxHelpEvent::Origin_Unknown )
+    {
+        wxCHECK_MSG( window, wxEmptyString, wxT("window must not be NULL") );
+
+        wxPoint pt = m_helptextAtPoint;
+        wxHelpEvent::Origin origin = m_helptextOrigin;
+
+        m_helptextAtPoint = wxDefaultPosition;
+        m_helptextOrigin = wxHelpEvent::Origin_Unknown;
+
+        return window->GetHelpTextAtPoint(pt, origin);
+    }
+
+    return GetHelp(window);
+}
+
 // ----------------------------------------------------------------------------
 // wxSimpleHelpProvider
 // ----------------------------------------------------------------------------
 
+#define WINHASH_KEY(w) wxPtrToUInt(w)
+
 wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
 {
-    wxLongToStringHashMap::iterator it = m_hashWindows.find((long)window);
+    wxSimpleHelpProviderHashMap::iterator it = m_hashWindows.find(WINHASH_KEY(window));
 
     if ( it == m_hashWindows.end() )
     {
@@ -346,13 +368,13 @@ wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window)
 
 void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text)
 {
-    m_hashWindows.erase((long)window);
-    m_hashWindows[(long)window] = text;
+    m_hashWindows.erase(WINHASH_KEY(window));
+    m_hashWindows[WINHASH_KEY(window)] = text;
 }
 
 void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
 {
-    wxLongToStringHashMap::key_type key = (wxLongToStringHashMap::key_type)id;
+    wxSimpleHelpProviderHashMap::key_type key = (wxSimpleHelpProviderHashMap::key_type)id;
     m_hashIds.erase(key);
     m_hashIds[key] = text;
 }
@@ -360,31 +382,56 @@ void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text)
 // removes the association
 void wxSimpleHelpProvider::RemoveHelp(wxWindowBase* window)
 {
-    m_hashWindows.erase((long)window);
+    m_hashWindows.erase(WINHASH_KEY(window));
 }
 
 bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window)
 {
-#if wxUSE_TIPWINDOW
-    static wxTipWindow* s_tipWindow = NULL;
+#if wxUSE_MS_HTML_HELP || wxUSE_TIPWINDOW
+#if wxUSE_MS_HTML_HELP
+    // m_helptextAtPoint will be reset by GetHelpTextMaybeAtPoint(), stash it
+    const wxPoint posTooltip = m_helptextAtPoint;
+#endif // wxUSE_MS_HTML_HELP
 
-    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;
+    const wxString text = GetHelpTextMaybeAtPoint(window);
 
-    wxString text = GetHelp(window);
     if ( !text.empty() )
     {
-        s_tipWindow = new wxTipWindow((wxWindow *)window, text, 100, & s_tipWindow);
+        // use the native help popup style if it's available
+#if wxUSE_MS_HTML_HELP
+        if ( !wxCHMHelpController::ShowContextHelpPopup
+                                   (
+                                        text,
+                                        posTooltip,
+                                        (wxWindow *)window
+                                   ) )
+#endif // wxUSE_MS_HTML_HELP
+        {
+#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 = new wxTipWindow((wxWindow *)window, text,
+                                            100, &s_tipWindow);
+#else // !wxUSE_TIPWINDOW
+            // we tried wxCHMHelpController but it failed and we don't have
+            // wxTipWindow to fall back on, so
+            return false;
+#endif // wxUSE_TIPWINDOW
+        }
 
         return true;
     }
-#endif // wxUSE_TIPWINDOW
+#else // !wxUSE_MS_HTML_HELP && !wxUSE_TIPWINDOW
+    wxUnusedVar(window);
+#endif // wxUSE_MS_HTML_HELP || wxUSE_TIPWINDOW
 
     return false;
 }
@@ -400,35 +447,32 @@ wxHelpControllerHelpProvider::wxHelpControllerHelpProvider(wxHelpControllerBase*
 
 bool wxHelpControllerHelpProvider::ShowHelp(wxWindowBase *window)
 {
-    wxString text = GetHelp(window);
-    if ( !text.empty() )
-    {
-        if (m_helpController)
-        {
-            if (text.IsNumber())
-                return m_helpController->DisplayContextPopup(wxAtoi(text));
+    const wxString text = GetHelpTextMaybeAtPoint(window);
 
-            // 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);
+    if ( text.empty() )
+        return false;
 
+    if ( m_helpController )
+    {
+        // if it's a numeric topic, show it
+        long topic;
+        if ( text.ToLong(&topic) )
+            return m_helpController->DisplayContextPopup(topic);
+
+        // otherwise show the text directly
+        if ( m_helpController->DisplayTextPopup(text, wxGetMousePosition()) )
+            return true;
     }
 
-    return false;
+    // if there is no help controller or it's not capable of showing the help,
+    // fallback to the default method
+    return wxSimpleHelpProvider::ShowHelp(window);
 }
 
 // Convenience function for turning context id into wxString
 wxString wxContextId(int id)
 {
-    return wxString::Format(_T("%d"), id);
+    return wxString::Format(wxT("%d"), id);
 }
 
 // ----------------------------------------------------------------------------