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