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