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