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