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