]> git.saurik.com Git - wxWidgets.git/blame - src/html/helpctrl.cpp
Fix item selection/focus drawing in generic wxListCtrl.
[wxWidgets.git] / src / html / helpctrl.cpp
CommitLineData
8ec2b484
HH
1/////////////////////////////////////////////////////////////////////////////
2// Name: helpctrl.cpp
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;
8ec2b484
HH
55}
56
57wxHtmlHelpController::~wxHtmlHelpController()
58{
b4246849 59#if wxUSE_CONFIG
f6bcfd97
BP
60 if (m_Config)
61 WriteCustomization(m_Config, m_ConfigRoot);
b4246849 62#endif // wxUSE_CONFIG
3755cfa6 63 if (m_helpWindow)
b854b7b8 64 DestroyHelpWindow();
8ec2b484
HH
65}
66
b854b7b8
VS
67
68void wxHtmlHelpController::DestroyHelpWindow()
69{
3755cfa6
JS
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 }
f3e156ef
JS
86 m_helpDialog = NULL;
87 m_helpFrame = NULL;
b854b7b8
VS
88}
89
b4414c1f 90void wxHtmlHelpController::OnCloseFrame(wxCloseEvent& evt)
b854b7b8 91{
b4246849 92#if wxUSE_CONFIG
3755cfa6
JS
93 if (m_Config)
94 WriteCustomization(m_Config, m_ConfigRoot);
b4246849 95#endif // wxUSE_CONFIG
664d1729 96
b4414c1f 97 evt.Skip();
b854b7b8 98
b4414c1f 99 OnQuit();
b854b7b8 100
664d1729
VS
101 if ( m_helpWindow )
102 m_helpWindow->SetController(NULL);
3755cfa6 103 m_helpWindow = NULL;
f3e156ef
JS
104 m_helpDialog = NULL;
105 m_helpFrame = NULL;
b4414c1f 106}
b854b7b8 107
8ec2b484
HH
108void wxHtmlHelpController::SetTitleFormat(const wxString& title)
109{
110 m_titleFormat = title;
3755cfa6
JS
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);
8ec2b484
HH
119}
120
3755cfa6
JS
121// Find the top-most parent window
122wxWindow* wxHtmlHelpController::FindTopLevelWindow()
123{
9df05aab 124 return wxGetTopLevelParent(m_helpWindow);
3755cfa6 125}
d5bb85a0 126
fcf77487
VS
127bool wxHtmlHelpController::AddBook(const wxFileName& book_file, bool show_wait_msg)
128{
129 return AddBook(wxFileSystem::FileNameToURL(book_file), show_wait_msg);
130}
131
8ec2b484
HH
132bool wxHtmlHelpController::AddBook(const wxString& book, bool show_wait_msg)
133{
134 wxBusyCursor cur;
135#if wxUSE_BUSYINFO
69941f05 136 wxBusyInfo* busy = NULL;
8ec2b484 137 wxString info;
33ac7e6f 138 if (show_wait_msg)
4f9297b0 139 {
d5bb85a0
VS
140 info.Printf(_("Adding book %s"), book.c_str());
141 busy = new wxBusyInfo(info);
8ec2b484
HH
142 }
143#endif
144 bool retval = m_helpData.AddBook(book);
145#if wxUSE_BUSYINFO
146 if (show_wait_msg)
d5bb85a0 147 delete busy;
132a5928
WS
148#else
149 wxUnusedVar(show_wait_msg);
33ac7e6f 150#endif
3755cfa6
JS
151 if (m_helpWindow)
152 m_helpWindow->RefreshLists();
8ec2b484
HH
153 return retval;
154}
155
3755cfa6 156wxHtmlHelpFrame* wxHtmlHelpController::CreateHelpFrame(wxHtmlHelpData *data)
b854b7b8 157{
3755cfa6
JS
158 wxHtmlHelpFrame* frame = new wxHtmlHelpFrame(data);
159 frame->SetController(this);
b4246849
VZ
160 frame->Create(m_parentWindow, -1, wxEmptyString, m_FrameStyle
161#if wxUSE_CONFIG
162 , m_Config, m_ConfigRoot
163#endif // wxUSE_CONFIG
164 );
bd365871 165 frame->SetTitleFormat(m_titleFormat);
f3e156ef 166 m_helpFrame = frame;
3755cfa6 167 return frame;
b854b7b8
VS
168}
169
3755cfa6
JS
170wxHtmlHelpDialog* wxHtmlHelpController::CreateHelpDialog(wxHtmlHelpData *data)
171{
172 wxHtmlHelpDialog* dialog = new wxHtmlHelpDialog(data);
173 dialog->SetController(this);
bd365871 174 dialog->SetTitleFormat(m_titleFormat);
3755cfa6 175 dialog->Create(m_parentWindow, -1, wxEmptyString, m_FrameStyle);
f3e156ef 176 m_helpDialog = dialog;
3755cfa6
JS
177 return dialog;
178}
b854b7b8 179
3755cfa6 180wxWindow* wxHtmlHelpController::CreateHelpWindow()
8ec2b484 181{
3755cfa6 182 if (m_helpWindow)
4f9297b0 183 {
3755cfa6
JS
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;
8ec2b484 191 }
d5bb85a0 192
b4246849 193#if wxUSE_CONFIG
33ac7e6f 194 if (m_Config == NULL)
74accc50 195 {
d1da8872 196 m_Config = wxConfigBase::Get(false);
74accc50 197 if (m_Config != NULL)
9a83f860 198 m_ConfigRoot = wxT("wxWindows/wxHtmlHelpController");
74accc50 199 }
b4246849 200#endif // wxUSE_CONFIG
74accc50 201
3755cfa6
JS
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 }
7e521b01 218
3755cfa6 219 return m_helpWindow;
8ec2b484
HH
220}
221
b4246849 222#if wxUSE_CONFIG
8ec2b484
HH
223void 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 */
3755cfa6
JS
227 if (m_helpWindow && cfg)
228 m_helpWindow->ReadCustomization(cfg, path);
8ec2b484
HH
229}
230
231void wxHtmlHelpController::WriteCustomization(wxConfigBase* cfg, const wxString& path)
232{
233 /* typically called by the controllers OnCloseFrame handler */
3755cfa6
JS
234 if (m_helpWindow && cfg)
235 m_helpWindow->WriteCustomization(cfg, path);
8ec2b484
HH
236}
237
721ab905
VS
238void wxHtmlHelpController::UseConfig(wxConfigBase *config, const wxString& rootpath)
239{
240 m_Config = config;
241 m_ConfigRoot = rootpath;
3755cfa6 242 if (m_helpWindow) m_helpWindow->UseConfig(config, rootpath);
721ab905
VS
243 ReadCustomization(config, rootpath);
244}
b4246849 245#endif // wxUSE_CONFIG
721ab905 246
b4414c1f
JS
247//// Backward compatibility with wxHelpController API
248
249bool wxHtmlHelpController::Initialize(const wxString& file)
250{
251 wxString dir, filename, ext;
bd365871 252 wxFileName::SplitPath(file, & dir, & filename, & ext);
b4414c1f 253
ddc80eb4 254 if (!dir.empty())
0222a60b 255 dir = dir + wxFILE_SEP_PATH;
b4414c1f
JS
256
257 // Try to find a suitable file
e81910e0 258 wxString actualFilename = dir + filename + wxString(wxT(".zip"));
b4414c1f
JS
259 if (!wxFileExists(actualFilename))
260 {
e81910e0 261 actualFilename = dir + filename + wxString(wxT(".htb"));
b4414c1f
JS
262 if (!wxFileExists(actualFilename))
263 {
e81910e0 264 actualFilename = dir + filename + wxString(wxT(".hhp"));
b4414c1f 265 if (!wxFileExists(actualFilename))
3527f29c
VS
266 {
267#if wxUSE_LIBMSPACK
268 actualFilename = dir + filename + wxString(wxT(".chm"));
269 if (!wxFileExists(actualFilename))
270#endif
271 return false;
272 }
b4414c1f
JS
273 }
274 }
fcf77487 275 return AddBook(wxFileName(actualFilename));
b4414c1f
JS
276}
277
278bool wxHtmlHelpController::LoadFile(const wxString& WXUNUSED(file))
279{
280 // Don't reload the file or we'll have it appear again, presumably.
d1da8872 281 return true;
b4414c1f
JS
282}
283
284bool wxHtmlHelpController::DisplaySection(int sectionNo)
285{
286 return Display(sectionNo);
287}
288
673dfcfa
JS
289bool wxHtmlHelpController::DisplayTextPopup(const wxString& text, const wxPoint& WXUNUSED(pos))
290{
f38bcae5 291#if wxUSE_TIPWINDOW
673dfcfa
JS
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
d1da8872 307 return true;
673dfcfa 308 }
ddc80eb4
WS
309#else
310 wxUnusedVar(text);
f38bcae5
VZ
311#endif // wxUSE_TIPWINDOW
312
d1da8872 313 return false;
673dfcfa
JS
314}
315
3755cfa6
JS
316void wxHtmlHelpController::SetHelpWindow(wxHtmlHelpWindow* helpWindow)
317{
318 m_helpWindow = helpWindow;
319 if (helpWindow)
320 helpWindow->SetController(this);
321}
322
b4414c1f
JS
323void wxHtmlHelpController::SetFrameParameters(const wxString& title,
324 const wxSize& size,
325 const wxPoint& pos,
326 bool WXUNUSED(newFrameEachTime))
327{
328 SetTitleFormat(title);
3755cfa6
JS
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);
b4414c1f
JS
335}
336
337wxFrame* wxHtmlHelpController::GetFrameParameters(wxSize *size,
338 wxPoint *pos,
339 bool *newFrameEachTime)
340{
341 if (newFrameEachTime)
d1da8872 342 (* newFrameEachTime) = false;
3755cfa6
JS
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;
b4414c1f
JS
363}
364
365bool wxHtmlHelpController::Quit()
366{
367 DestroyHelpWindow();
d1da8872 368 return true;
b4414c1f
JS
369}
370
5152b0e5
JS
371// Make the help controller's frame 'modal' if
372// needed
3755cfa6 373void wxHtmlHelpController::MakeModalIfNeeded()
5152b0e5 374{
3755cfa6 375 if ((m_FrameStyle & wxHF_EMBEDDED) == 0)
5152b0e5 376 {
3755cfa6
JS
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 }
5152b0e5 385 }
5152b0e5
JS
386}
387
388bool wxHtmlHelpController::Display(const wxString& x)
389{
390 CreateHelpWindow();
3755cfa6
JS
391 bool success = m_helpWindow->Display(x);
392 MakeModalIfNeeded();
d1da8872 393 return success;
5152b0e5
JS
394}
395
396bool wxHtmlHelpController::Display(int id)
397{
398 CreateHelpWindow();
3755cfa6
JS
399 bool success = m_helpWindow->Display(id);
400 MakeModalIfNeeded();
5152b0e5
JS
401 return success;
402}
403
404bool wxHtmlHelpController::DisplayContents()
405{
406 CreateHelpWindow();
3755cfa6
JS
407 bool success = m_helpWindow->DisplayContents();
408 MakeModalIfNeeded();
5152b0e5
JS
409 return success;
410}
411
412bool wxHtmlHelpController::DisplayIndex()
413{
414 CreateHelpWindow();
3755cfa6
JS
415 bool success = m_helpWindow->DisplayIndex();
416 MakeModalIfNeeded();
5152b0e5
JS
417 return success;
418}
419
69b5cec2
VS
420bool wxHtmlHelpController::KeywordSearch(const wxString& keyword,
421 wxHelpSearchMode mode)
5152b0e5
JS
422{
423 CreateHelpWindow();
3755cfa6
JS
424 bool success = m_helpWindow->KeywordSearch(keyword, mode);
425 MakeModalIfNeeded();
5152b0e5
JS
426 return success;
427}
428
3755cfa6
JS
429/*
430 * wxHtmlModalHelp
431 * A convenience class, to use like this:
432 *
433 * wxHtmlModalHelp help(parent, helpFile, topic);
434 */
435
436wxHtmlModalHelp::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
3379ed37
VZ
450#endif // wxUSE_WXHTML_HELP
451