]> git.saurik.com Git - wxWidgets.git/blob - src/html/helpctrl.cpp
Applied patch [ 1409971 ] wxX11: fix for DoDrawBitmap() when scaling is set
[wxWidgets.git] / src / html / helpctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        helpctrl.cpp
3 // Purpose:     wxHtmlHelpController
4 // Notes:       Based on htmlhelp.cpp, implementing a monolithic
5 //              HTML Help controller class,  by Vaclav Slavik
6 // Author:      Harm van der Heijden and Vaclav Slavik
7 // RCS-ID:      $Id$
8 // Copyright:   (c) Harm van der Heijden and Vaclav Slavik
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_WXHTML_HELP
20
21 #ifndef WX_PRECOMP
22     #include "wx/app.h"
23     #include "wx/intl.h"
24 #endif // WX_PRECOMP
25
26 #include "wx/busyinfo.h"
27 #include "wx/html/helpctrl.h"
28 #include "wx/html/helpwnd.h"
29 #include "wx/html/helpfrm.h"
30 #include "wx/html/helpdlg.h"
31
32 #if wxUSE_HELP
33     #include "wx/tipwin.h"
34 #endif
35
36 #if wxUSE_LIBMSPACK
37 #include "wx/html/forcelnk.h"
38 FORCE_LINK(wxhtml_chm_support)
39 #endif
40
41 IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpController, wxHelpControllerBase)
42
43 wxHtmlHelpController::wxHtmlHelpController(int style, wxWindow* parentWindow):
44     wxHelpControllerBase(parentWindow)
45 {
46     m_helpWindow = NULL;
47     m_helpFrame = NULL;
48     m_helpDialog = NULL;
49     m_Config = NULL;
50     m_ConfigRoot = wxEmptyString;
51     m_titleFormat = _("Help: %s");
52     m_FrameStyle = style;
53 }
54
55 wxHtmlHelpController::~wxHtmlHelpController()
56 {
57     if (m_Config)
58         WriteCustomization(m_Config, m_ConfigRoot);
59     if (m_helpWindow)
60         DestroyHelpWindow();
61 }
62
63
64 void wxHtmlHelpController::DestroyHelpWindow()
65 {
66     if (m_FrameStyle & wxHF_EMBEDDED)
67         return;
68
69     // Find top-most parent window
70     // If a modal dialog
71     wxWindow* parent = FindTopLevelWindow();
72     if (parent)
73     {
74         wxDialog* dialog = wxDynamicCast(parent, wxDialog);
75         if (dialog && dialog->IsModal())
76         {
77             dialog->EndModal(wxID_OK);
78         }
79         parent->Destroy();
80         m_helpWindow = NULL;
81     }
82     m_helpDialog = NULL;
83     m_helpFrame = NULL;
84 }
85
86 void wxHtmlHelpController::OnCloseFrame(wxCloseEvent& evt)
87 {
88     if (m_Config)
89         WriteCustomization(m_Config, m_ConfigRoot);
90     
91     evt.Skip();
92
93     OnQuit();
94
95     m_helpWindow->SetController(NULL);
96     m_helpWindow = NULL;
97     m_helpDialog = NULL;
98     m_helpFrame = NULL;
99 }
100
101 void wxHtmlHelpController::SetTitleFormat(const wxString& title)
102 {
103     m_titleFormat = title;
104     wxHtmlHelpFrame* frame = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpFrame);
105     wxHtmlHelpDialog* dialog = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpDialog);
106     if (frame)
107     {
108         frame->SetTitleFormat(title);
109     }
110     else if (dialog)
111         dialog->SetTitleFormat(title);
112 }
113
114 // Find the top-most parent window
115 wxWindow* wxHtmlHelpController::FindTopLevelWindow()
116 {
117     wxWindow* parent = m_helpWindow;
118     while (parent && !parent->IsTopLevel())
119     {
120         parent = parent->GetParent();
121     }
122     return parent;
123 }
124
125 bool wxHtmlHelpController::AddBook(const wxFileName& book_file, bool show_wait_msg)
126 {
127     return AddBook(wxFileSystem::FileNameToURL(book_file), show_wait_msg);
128 }
129
130 bool wxHtmlHelpController::AddBook(const wxString& book, bool show_wait_msg)
131 {
132     wxBusyCursor cur;
133 #if wxUSE_BUSYINFO
134     wxBusyInfo* busy = NULL;
135     wxString info;
136     if (show_wait_msg)
137     {
138         info.Printf(_("Adding book %s"), book.c_str());
139         busy = new wxBusyInfo(info);
140     }
141 #endif
142     bool retval = m_helpData.AddBook(book);
143 #if wxUSE_BUSYINFO
144     if (show_wait_msg)
145         delete busy;
146 #else
147     wxUnusedVar(show_wait_msg);
148 #endif
149     if (m_helpWindow)
150         m_helpWindow->RefreshLists();
151     return retval;
152 }
153
154 wxHtmlHelpFrame* wxHtmlHelpController::CreateHelpFrame(wxHtmlHelpData *data)
155 {
156     wxHtmlHelpFrame* frame = new wxHtmlHelpFrame(data);
157     frame->SetController(this);
158     frame->SetTitleFormat(m_titleFormat);    
159     frame->Create(m_parentWindow, -1, wxEmptyString, m_FrameStyle);
160     m_helpFrame = frame;
161     return frame;
162 }
163
164 wxHtmlHelpDialog* wxHtmlHelpController::CreateHelpDialog(wxHtmlHelpData *data)
165 {
166     wxHtmlHelpDialog* dialog = new wxHtmlHelpDialog(data);
167     dialog->SetController(this);
168     dialog->SetTitleFormat(m_titleFormat);    
169     dialog->Create(m_parentWindow, -1, wxEmptyString, m_FrameStyle);
170     m_helpDialog = dialog;
171     return dialog;
172 }
173
174 wxWindow* wxHtmlHelpController::CreateHelpWindow()
175 {
176     if (m_helpWindow)
177     {
178         if (m_FrameStyle & wxHF_EMBEDDED)
179             return m_helpWindow;
180
181         wxWindow* topLevelWindow = FindTopLevelWindow();
182         if (topLevelWindow)
183             topLevelWindow->Raise();
184         return m_helpWindow;
185     }
186
187     if (m_Config == NULL)
188     {
189         m_Config = wxConfigBase::Get(false);
190         if (m_Config != NULL)
191             m_ConfigRoot = _T("wxWindows/wxHtmlHelpController");
192     }
193
194     if (m_FrameStyle & wxHF_DIALOG)
195     {
196         wxHtmlHelpDialog* dialog = CreateHelpDialog(&m_helpData);
197         m_helpWindow = dialog->GetHelpWindow();
198     }
199     else if ((m_FrameStyle & wxHF_EMBEDDED) && m_parentWindow)
200     {
201         m_helpWindow = new wxHtmlHelpWindow(m_parentWindow, -1, wxDefaultPosition, wxDefaultSize,
202             wxTAB_TRAVERSAL|wxNO_BORDER, m_FrameStyle, &m_helpData);
203     }
204     else // wxHF_FRAME
205     {
206         wxHtmlHelpFrame* frame = CreateHelpFrame(&m_helpData);
207         m_helpWindow = frame->GetHelpWindow();
208         frame->Show(true);
209     }
210
211     return m_helpWindow;
212 }
213
214 void wxHtmlHelpController::ReadCustomization(wxConfigBase* cfg, const wxString& path)
215 {
216     /* should not be called by the user; call UseConfig, and the controller
217      * will do the rest */
218     if (m_helpWindow && cfg)
219         m_helpWindow->ReadCustomization(cfg, path);
220 }
221
222 void wxHtmlHelpController::WriteCustomization(wxConfigBase* cfg, const wxString& path)
223 {
224     /* typically called by the controllers OnCloseFrame handler */
225     if (m_helpWindow && cfg)
226         m_helpWindow->WriteCustomization(cfg, path);
227 }
228
229 void wxHtmlHelpController::UseConfig(wxConfigBase *config, const wxString& rootpath)
230 {
231     m_Config = config;
232     m_ConfigRoot = rootpath;
233     if (m_helpWindow) m_helpWindow->UseConfig(config, rootpath);
234     ReadCustomization(config, rootpath);
235 }
236
237 //// Backward compatibility with wxHelpController API
238
239 bool wxHtmlHelpController::Initialize(const wxString& file)
240 {
241     wxString dir, filename, ext;
242     wxSplitPath(file, & dir, & filename, & ext);
243
244     if (!dir.empty())
245         dir = dir + wxFILE_SEP_PATH;
246
247     // Try to find a suitable file
248     wxString actualFilename = dir + filename + wxString(wxT(".zip"));
249     if (!wxFileExists(actualFilename))
250     {
251         actualFilename = dir + filename + wxString(wxT(".htb"));
252         if (!wxFileExists(actualFilename))
253         {
254             actualFilename = dir + filename + wxString(wxT(".hhp"));
255             if (!wxFileExists(actualFilename))
256             {
257 #if wxUSE_LIBMSPACK
258                 actualFilename = dir + filename + wxString(wxT(".chm"));
259                 if (!wxFileExists(actualFilename))
260 #endif
261                     return false;
262             }
263         }
264     }
265     return AddBook(wxFileName(actualFilename));
266 }
267
268 bool wxHtmlHelpController::LoadFile(const wxString& WXUNUSED(file))
269 {
270     // Don't reload the file or we'll have it appear again, presumably.
271     return true;
272 }
273
274 bool wxHtmlHelpController::DisplaySection(int sectionNo)
275 {
276     return Display(sectionNo);
277 }
278
279 bool wxHtmlHelpController::DisplayTextPopup(const wxString& text, const wxPoint& WXUNUSED(pos))
280 {
281 #if wxUSE_TIPWINDOW
282     static wxTipWindow* s_tipWindow = NULL;
283
284     if (s_tipWindow)
285     {
286         // Prevent s_tipWindow being nulled in OnIdle,
287         // thereby removing the chance for the window to be closed by ShowHelp
288         s_tipWindow->SetTipWindowPtr(NULL);
289         s_tipWindow->Close();
290     }
291     s_tipWindow = NULL;
292
293     if ( !text.empty() )
294     {
295         s_tipWindow = new wxTipWindow(wxTheApp->GetTopWindow(), text, 100, & s_tipWindow);
296
297         return true;
298     }
299 #else
300     wxUnusedVar(text);
301 #endif // wxUSE_TIPWINDOW
302
303     return false;
304 }
305
306 void wxHtmlHelpController::SetHelpWindow(wxHtmlHelpWindow* helpWindow)
307 {
308     m_helpWindow = helpWindow;
309     if (helpWindow)
310         helpWindow->SetController(this);
311 }
312
313 void wxHtmlHelpController::SetFrameParameters(const wxString& title,
314                                    const wxSize& size,
315                                    const wxPoint& pos,
316                                    bool WXUNUSED(newFrameEachTime))
317 {
318     SetTitleFormat(title);
319     wxHtmlHelpFrame* frame = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpFrame);
320     wxHtmlHelpDialog* dialog = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpDialog);
321     if (frame)
322         frame->SetSize(pos.x, pos.y, size.x, size.y);
323     else if (dialog)
324         dialog->SetSize(pos.x, pos.y, size.x, size.y);
325 }
326
327 wxFrame* wxHtmlHelpController::GetFrameParameters(wxSize *size,
328                                    wxPoint *pos,
329                                    bool *newFrameEachTime)
330 {
331     if (newFrameEachTime)
332         (* newFrameEachTime) = false;
333
334     wxHtmlHelpFrame* frame = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpFrame);
335     wxHtmlHelpDialog* dialog = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpDialog);
336     if (frame)
337     {
338         if (size)
339             (* size) = frame->GetSize();
340         if (pos)
341             (* pos) = frame->GetPosition();
342         return frame;
343     }
344     else if (dialog)
345     {
346         if (size)
347             (* size) = dialog->GetSize();
348         if (pos)
349             (* pos) = dialog->GetPosition();
350         return NULL;
351     }
352     return NULL;
353 }
354
355 bool wxHtmlHelpController::Quit()
356 {
357     DestroyHelpWindow();
358     return true;
359 }
360
361 // Make the help controller's frame 'modal' if
362 // needed
363 void wxHtmlHelpController::MakeModalIfNeeded()
364 {
365     if ((m_FrameStyle & wxHF_EMBEDDED) == 0)
366     {
367         wxHtmlHelpFrame* frame = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpFrame);
368         wxHtmlHelpDialog* dialog = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpDialog);
369         if (frame)
370             frame->AddGrabIfNeeded();
371         else if (dialog && (m_FrameStyle & wxHF_MODAL))
372         {
373             dialog->ShowModal();
374         }
375     }
376 }
377
378 bool wxHtmlHelpController::Display(const wxString& x)
379 {
380     CreateHelpWindow();
381     bool success = m_helpWindow->Display(x);
382     MakeModalIfNeeded();
383     return success;
384 }
385
386 bool wxHtmlHelpController::Display(int id)
387 {
388     CreateHelpWindow();
389     bool success = m_helpWindow->Display(id);
390     MakeModalIfNeeded();
391     return success;
392 }
393
394 bool wxHtmlHelpController::DisplayContents()
395 {
396     CreateHelpWindow();
397     bool success = m_helpWindow->DisplayContents();
398     MakeModalIfNeeded();
399     return success;
400 }
401
402 bool wxHtmlHelpController::DisplayIndex()
403 {
404     CreateHelpWindow();
405     bool success = m_helpWindow->DisplayIndex();
406     MakeModalIfNeeded();
407     return success;
408 }
409
410 bool wxHtmlHelpController::KeywordSearch(const wxString& keyword,
411                                          wxHelpSearchMode mode)
412 {
413     CreateHelpWindow();
414     bool success = m_helpWindow->KeywordSearch(keyword, mode);
415     MakeModalIfNeeded();
416     return success;
417 }
418
419 /*
420  * wxHtmlModalHelp
421  * A convenience class, to use like this:
422  *
423  * wxHtmlModalHelp help(parent, helpFile, topic);
424  */
425
426 wxHtmlModalHelp::wxHtmlModalHelp(wxWindow* parent, const wxString& helpFile, const wxString& topic, int style)
427 {
428     // Force some mandatory styles
429     style |= wxHF_DIALOG | wxHF_MODAL;
430
431     wxHtmlHelpController controller(style, parent);
432     controller.Initialize(helpFile);
433
434     if (topic.IsEmpty())
435         controller.DisplayContents();
436     else
437         controller.DisplaySection(topic);
438 }
439
440 #endif // wxUSE_WXHTML_HELP
441