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