1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/html/helpwnd.cpp
3 // Purpose: wxHtmlHelpWindow
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: helpwnd.cpp 67259 2011-03-20 12:27:35Z JS $
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
14 #include "wx/wxprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #if wxUSE_WXHTML_HELP
21
22 #ifndef WXPRECOMP
23 #include "wx/object.h"
24 #include "wx/dynarray.h"
25 #include "wx/intl.h"
26 #include "wx/log.h"
27 #if wxUSE_STREAMS
28 #include "wx/stream.h"
29 #endif
30
31 #include "wx/sizer.h"
32
33 #include "wx/bmpbuttn.h"
34 #include "wx/statbox.h"
35 #include "wx/radiobox.h"
36 #include "wx/menu.h"
37 #include "wx/settings.h"
38 #include "wx/msgdlg.h"
39 #include "wx/textctrl.h"
40 #include "wx/toolbar.h"
41 #include "wx/choicdlg.h"
42 #include "wx/filedlg.h"
43 #endif // WXPRECOMP
44
45 #include "wx/html/helpfrm.h"
46 #include "wx/html/helpdlg.h"
47 #include "wx/html/helpctrl.h"
48 #include "wx/notebook.h"
49 #include "wx/imaglist.h"
50 #include "wx/treectrl.h"
51 #include "wx/tokenzr.h"
52 #include "wx/wfstream.h"
53 #include "wx/html/htmlwin.h"
54 #include "wx/busyinfo.h"
55 #include "wx/progdlg.h"
56 #include "wx/fontenum.h"
57 #include "wx/artprov.h"
58 #include "wx/spinctrl.h"
59
60 // what is considered "small index"?
61 #define INDEX_IS_SMALL 100
62
63 /* Motif defines this as a macro */
64 #ifdef Below
65 #undef Below
66 #endif
67
68 //--------------------------------------------------------------------------
69 // wxHtmlHelpTreeItemData (private)
70 //--------------------------------------------------------------------------
71
72 class wxHtmlHelpTreeItemData : public wxTreeItemData
73 {
74 public:
75 #if defined(__VISAGECPP__)
76 // VA needs a default ctor for some reason....
wxHtmlHelpTreeItemData()77 wxHtmlHelpTreeItemData() : wxTreeItemData()
78 { m_Id = 0; }
79 #endif
wxHtmlHelpTreeItemData(int id)80 wxHtmlHelpTreeItemData(int id) : wxTreeItemData()
81 { m_Id = id;}
82
83 int m_Id;
84 };
85
86
87 //--------------------------------------------------------------------------
88 // wxHtmlHelpHashData (private)
89 //--------------------------------------------------------------------------
90
91 class wxHtmlHelpHashData : public wxObject
92 {
93 public:
wxHtmlHelpHashData(int index,wxTreeItemId id)94 wxHtmlHelpHashData(int index, wxTreeItemId id) : wxObject()
95 { m_Index = index; m_Id = id;}
~wxHtmlHelpHashData()96 virtual ~wxHtmlHelpHashData() {}
97
98 int m_Index;
99 wxTreeItemId m_Id;
100 };
101
102
103 //--------------------------------------------------------------------------
104 // wxHtmlHelpHtmlWindow (private)
105 //--------------------------------------------------------------------------
106
107
108 class wxHtmlHelpHtmlWindow : public wxHtmlWindow
109 {
110 public:
wxHtmlHelpHtmlWindow(wxHtmlHelpWindow * win,wxWindow * parent,wxWindowID id=wxID_ANY,const wxPoint & pos=wxDefaultPosition,const wxSize & sz=wxDefaultSize,long style=wxHW_DEFAULT_STYLE)111 wxHtmlHelpHtmlWindow(wxHtmlHelpWindow *win, wxWindow *parent, wxWindowID id = wxID_ANY,
112 const wxPoint& pos = wxDefaultPosition, const wxSize& sz = wxDefaultSize, long style = wxHW_DEFAULT_STYLE)
113 : wxHtmlWindow(parent, id, pos, sz, style), m_Window(win)
114 {
115 SetStandardFonts();
116 }
117
OnLink(wxHtmlLinkEvent & ev)118 void OnLink(wxHtmlLinkEvent& ev)
119 {
120 const wxMouseEvent *e = ev.GetLinkInfo().GetEvent();
121 if (e == NULL || e->LeftUp())
122 m_Window->NotifyPageChanged();
123
124 // skip the event so that normal processing (i.e. following the link)
125 // is done:
126 ev.Skip();
127 }
128
129 // Returns full location with anchor (helper)
GetOpenedPageWithAnchor(wxHtmlWindow * win)130 static wxString GetOpenedPageWithAnchor(wxHtmlWindow *win)
131 {
132 if(!win)
133 return wxEmptyString;
134
135 wxString an = win->GetOpenedAnchor();
136 wxString pg = win->GetOpenedPage();
137 if(!an.empty())
138 {
139 pg << wxT("#") << an;
140 }
141 return pg;
142 }
143
144 private:
145 wxHtmlHelpWindow *m_Window;
146
147 DECLARE_NO_COPY_CLASS(wxHtmlHelpHtmlWindow)
148 DECLARE_EVENT_TABLE()
149 };
150
151 BEGIN_EVENT_TABLE(wxHtmlHelpHtmlWindow, wxHtmlWindow)
152 EVT_HTML_LINK_CLICKED(wxID_ANY, wxHtmlHelpHtmlWindow::OnLink)
153 END_EVENT_TABLE()
154
155
156 //---------------------------------------------------------------------------
157 // wxHtmlHelpWindow::m_mergedIndex
158 //---------------------------------------------------------------------------
159
160 WX_DEFINE_ARRAY_PTR(const wxHtmlHelpDataItem*, wxHtmlHelpDataItemPtrArray);
161
162 struct wxHtmlHelpMergedIndexItem
163 {
164 wxHtmlHelpMergedIndexItem *parent;
165 wxString name;
166 wxHtmlHelpDataItemPtrArray items;
167 };
168
169 WX_DECLARE_OBJARRAY(wxHtmlHelpMergedIndexItem, wxHtmlHelpMergedIndex);
170 #include "wx/arrimpl.cpp"
WX_DEFINE_OBJARRAY(wxHtmlHelpMergedIndex)171 WX_DEFINE_OBJARRAY(wxHtmlHelpMergedIndex)
172
173 void wxHtmlHelpWindow::UpdateMergedIndex()
174 {
175 delete m_mergedIndex;
176 m_mergedIndex = new wxHtmlHelpMergedIndex;
177 wxHtmlHelpMergedIndex& merged = *m_mergedIndex;
178
179 const wxHtmlHelpDataItems& items = m_Data->GetIndexArray();
180 size_t len = items.size();
181
182 wxHtmlHelpMergedIndexItem *history[128] = {NULL};
183
184 for (size_t i = 0; i < len; i++)
185 {
186 const wxHtmlHelpDataItem& item = items[i];
187 wxASSERT_MSG( item.level < 128, _T("nested index entries too deep") );
188
189 if (history[item.level] &&
190 history[item.level]->items[0]->name == item.name)
191 {
192 // same index entry as previous one, update list of items
193 history[item.level]->items.Add(&item);
194 }
195 else
196 {
197 // new index entry
198 wxHtmlHelpMergedIndexItem *mi = new wxHtmlHelpMergedIndexItem();
199 mi->name = item.GetIndentedName();
200 mi->items.Add(&item);
201 mi->parent = (item.level == 0) ? NULL : history[item.level - 1];
202 history[item.level] = mi;
203 merged.Add(mi);
204 }
205 }
206 }
207
208 //---------------------------------------------------------------------------
209 // wxHtmlHelpWindow
210 //---------------------------------------------------------------------------
211
IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpWindow,wxWindow)212 IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpWindow, wxWindow)
213
214 BEGIN_EVENT_TABLE(wxHtmlHelpWindow, wxWindow)
215 EVT_TOOL_RANGE(wxID_HTML_PANEL, wxID_HTML_OPTIONS, wxHtmlHelpWindow::OnToolbar)
216 EVT_BUTTON(wxID_HTML_BOOKMARKSREMOVE, wxHtmlHelpWindow::OnToolbar)
217 EVT_BUTTON(wxID_HTML_BOOKMARKSADD, wxHtmlHelpWindow::OnToolbar)
218 EVT_TREE_SEL_CHANGED(wxID_HTML_TREECTRL, wxHtmlHelpWindow::OnContentsSel)
219 EVT_LISTBOX(wxID_HTML_INDEXLIST, wxHtmlHelpWindow::OnIndexSel)
220 EVT_LISTBOX(wxID_HTML_SEARCHLIST, wxHtmlHelpWindow::OnSearchSel)
221 EVT_BUTTON(wxID_HTML_SEARCHBUTTON, wxHtmlHelpWindow::OnSearch)
222 EVT_TEXT_ENTER(wxID_HTML_SEARCHTEXT, wxHtmlHelpWindow::OnSearch)
223 EVT_BUTTON(wxID_HTML_INDEXBUTTON, wxHtmlHelpWindow::OnIndexFind)
224 EVT_TEXT_ENTER(wxID_HTML_INDEXTEXT, wxHtmlHelpWindow::OnIndexFind)
225 EVT_BUTTON(wxID_HTML_INDEXBUTTONALL, wxHtmlHelpWindow::OnIndexAll)
226 EVT_COMBOBOX(wxID_HTML_BOOKMARKSLIST, wxHtmlHelpWindow::OnBookmarksSel)
227 EVT_SIZE(wxHtmlHelpWindow::OnSize)
228 END_EVENT_TABLE()
229
230 wxHtmlHelpWindow::wxHtmlHelpWindow(wxWindow* parent, wxWindowID id,
231 const wxPoint& pos,
232 const wxSize& size,
233 int style, int helpStyle, wxHtmlHelpData* data)
234 {
235 Init(data);
236 Create(parent, id, pos, size, style, helpStyle);
237 }
238
Init(wxHtmlHelpData * data)239 void wxHtmlHelpWindow::Init(wxHtmlHelpData* data)
240 {
241 if (data)
242 {
243 m_Data = data;
244 m_DataCreated = false;
245 }
246 else
247 {
248 m_Data = new wxHtmlHelpData();
249 m_DataCreated = true;
250 }
251
252 m_ContentsPage = 0;
253 m_IndexPage = 0;
254 m_SearchPage = 0;
255
256 m_ContentsBox = NULL;
257 m_IndexList = NULL;
258 m_IndexButton = NULL;
259 m_IndexButtonAll = NULL;
260 m_IndexText = NULL;
261 m_SearchList = NULL;
262 m_SearchButton = NULL;
263 m_SearchText = NULL;
264 m_SearchChoice = NULL;
265 m_IndexCountInfo = NULL;
266 m_Splitter = NULL;
267 m_NavigPan = NULL;
268 m_NavigNotebook = NULL;
269 m_HtmlWin = NULL;
270 m_Bookmarks = NULL;
271 m_SearchCaseSensitive = NULL;
272 m_SearchWholeWords = NULL;
273
274 m_mergedIndex = NULL;
275
276 m_Config = NULL;
277 m_ConfigRoot = wxEmptyString;
278
279 m_Cfg.x = m_Cfg.y = wxDefaultCoord;
280 m_Cfg.w = 700;
281 m_Cfg.h = 480;
282 m_Cfg.sashpos = 240;
283 m_Cfg.navig_on = true;
284
285 m_NormalFonts = m_FixedFonts = NULL;
286 m_NormalFace = m_FixedFace = wxEmptyString;
287 #ifdef __WXMSW__
288 m_FontSize = 10;
289 #else
290 m_FontSize = 14;
291 #endif
292
293 #if wxUSE_PRINTING_ARCHITECTURE
294 m_Printer = NULL;
295 #endif
296
297 m_PagesHash = NULL;
298 m_UpdateContents = true;
299 m_toolBar = NULL;
300 m_helpController = (wxHtmlHelpController*) NULL;
301 }
302
303 // Create: builds the GUI components.
304 // with the style flag it's possible to toggle the toolbar, contents, index and search
305 // controls.
306 // m_HtmlWin will *always* be created, but it's important to realize that
307 // m_ContentsBox, m_IndexList, m_SearchList, m_SearchButton, m_SearchText and
308 // m_SearchButton may be NULL.
309 // moreover, if no contents, index or searchpage is needed, m_Splitter and
310 // m_NavigPan will be NULL too (with m_HtmlWin directly connected to the frame)
311
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,int style,int helpStyle)312 bool wxHtmlHelpWindow::Create(wxWindow* parent, wxWindowID id,
313 const wxPoint& pos, const wxSize& size,
314 int style, int helpStyle)
315 {
316 m_hfStyle = helpStyle;
317
318 // Do the config in two steps. We read the HtmlWindow customization after we
319 // create the window.
320 if (m_Config)
321 ReadCustomization(m_Config, m_ConfigRoot);
322
323 wxWindow::Create(parent, id, pos, size, style, wxT("wxHtmlHelp"));
324
325 SetHelpText(_("Displays help as you browse the books on the left."));
326
327 GetPosition(&m_Cfg.x, &m_Cfg.y);
328
329 int notebook_page = 0;
330
331 // The sizer for the whole top-level window.
332 wxSizer *topWindowSizer = new wxBoxSizer(wxVERTICAL);
333 SetSizer(topWindowSizer);
334 SetAutoLayout(true);
335
336 #if wxUSE_TOOLBAR
337 // toolbar?
338 if (helpStyle & (wxHF_TOOLBAR | wxHF_FLAT_TOOLBAR))
339 {
340 wxToolBar *toolBar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
341 wxNO_BORDER | wxTB_HORIZONTAL |
342 wxTB_DOCKABLE | wxTB_NODIVIDER |
343 (helpStyle & wxHF_FLAT_TOOLBAR ? wxTB_FLAT : 0));
344 toolBar->SetMargins( 2, 2 );
345 AddToolbarButtons(toolBar, helpStyle);
346 toolBar->Realize();
347 topWindowSizer->Add(toolBar, 0, wxEXPAND);
348 m_toolBar = toolBar;
349 }
350 #endif //wxUSE_TOOLBAR
351
352 wxSizer *navigSizer = NULL;
353
354 #ifdef __WXMSW__
355 wxBorder htmlWindowBorder = GetThemedBorderStyle();
356 if (htmlWindowBorder == wxBORDER_SUNKEN)
357 htmlWindowBorder = wxBORDER_SIMPLE;
358 #else
359 wxBorder htmlWindowBorder = wxBORDER_SUNKEN;
360 #endif
361
362 if (helpStyle & (wxHF_CONTENTS | wxHF_INDEX | wxHF_SEARCH))
363 {
364 // traditional help controller; splitter window with html page on the
365 // right and a notebook containing various pages on the left
366 long splitterStyle = wxSP_3D;
367 // Drawing moving sash can cause problems on wxMac
368 #ifdef __WXMAC__
369 splitterStyle |= wxSP_LIVE_UPDATE;
370 #endif
371 m_Splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, splitterStyle);
372
373 topWindowSizer->Add(m_Splitter, 1, wxEXPAND);
374
375 m_HtmlWin = new wxHtmlHelpHtmlWindow(this, m_Splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_DEFAULT_STYLE|htmlWindowBorder);
376 m_NavigPan = new wxPanel(m_Splitter, wxID_ANY);
377 m_NavigNotebook = new wxNotebook(m_NavigPan, wxID_HTML_NOTEBOOK,
378 wxDefaultPosition, wxDefaultSize);
379 #ifdef __WXMAC__
380 m_NavigNotebook->SetWindowVariant(wxWINDOW_VARIANT_SMALL);
381 #endif
382
383 navigSizer = new wxBoxSizer(wxVERTICAL);
384 navigSizer->Add(m_NavigNotebook, 1, wxEXPAND);
385
386 m_NavigPan->SetSizer(navigSizer);
387 }
388 else
389 {
390 // only html window, no notebook with index,contents etc
391 m_HtmlWin = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_DEFAULT_STYLE|htmlWindowBorder);
392 topWindowSizer->Add(m_HtmlWin, 1, wxEXPAND);
393 }
394
395 if ( m_Config )
396 m_HtmlWin->ReadCustomization(m_Config, m_ConfigRoot);
397
398 // contents tree panel?
399 if ( helpStyle & wxHF_CONTENTS )
400 {
401 wxWindow *dummy = new wxPanel(m_NavigNotebook, wxID_HTML_INDEXPAGE);
402 #ifdef __WXMAC__
403 dummy->SetWindowVariant(wxWINDOW_VARIANT_NORMAL);
404 #endif
405 wxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
406
407 topsizer->Add(0, 10);
408
409 dummy->SetSizer(topsizer);
410
411 if ( helpStyle & wxHF_BOOKMARKS )
412 {
413 m_Bookmarks = new wxComboBox(dummy, wxID_HTML_BOOKMARKSLIST,
414 wxEmptyString,
415 wxDefaultPosition, wxDefaultSize,
416 0, NULL, wxCB_READONLY | wxCB_SORT);
417 m_Bookmarks->Append(_("(bookmarks)"));
418 for (unsigned i = 0; i < m_BookmarksNames.GetCount(); i++)
419 m_Bookmarks->Append(m_BookmarksNames[i]);
420 m_Bookmarks->SetSelection(0);
421
422 wxBitmapButton *bmpbt1, *bmpbt2;
423 bmpbt1 = new wxBitmapButton(dummy, wxID_HTML_BOOKMARKSADD,
424 wxArtProvider::GetBitmap(wxART_ADD_BOOKMARK,
425 wxART_BUTTON));
426 bmpbt2 = new wxBitmapButton(dummy, wxID_HTML_BOOKMARKSREMOVE,
427 wxArtProvider::GetBitmap(wxART_DEL_BOOKMARK,
428 wxART_BUTTON));
429 #if wxUSE_TOOLTIPS
430 bmpbt1->SetToolTip(_("Add current page to bookmarks"));
431 bmpbt2->SetToolTip(_("Remove current page from bookmarks"));
432 #endif // wxUSE_TOOLTIPS
433
434 wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
435
436 sizer->Add(m_Bookmarks, 1, wxALIGN_CENTRE_VERTICAL | wxRIGHT, 5);
437 sizer->Add(bmpbt1, 0, wxALIGN_CENTRE_VERTICAL | wxRIGHT, 2);
438 sizer->Add(bmpbt2, 0, wxALIGN_CENTRE_VERTICAL, 0);
439
440 topsizer->Add(sizer, 0, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT, 10);
441 }
442
443 m_ContentsBox = new wxTreeCtrl(dummy, wxID_HTML_TREECTRL,
444 wxDefaultPosition, wxDefaultSize,
445 #ifdef __WXGTK20__
446 wxSUNKEN_BORDER |
447 wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT |
448 wxTR_NO_LINES
449 #else
450 wxSUNKEN_BORDER |
451 wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT |
452 wxTR_LINES_AT_ROOT
453 #endif
454 );
455
456 wxImageList *ContentsImageList = new wxImageList(16, 16);
457 ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_BOOK,
458 wxART_HELP_BROWSER,
459 wxSize(16, 16)));
460 ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_FOLDER,
461 wxART_HELP_BROWSER,
462 wxSize(16, 16)));
463 ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_PAGE,
464 wxART_HELP_BROWSER,
465 wxSize(16, 16)));
466
467 m_ContentsBox->AssignImageList(ContentsImageList);
468
469 topsizer->Add(m_ContentsBox, 1,
470 wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT,
471 2);
472
473 m_NavigNotebook->AddPage(dummy, _("Contents"));
474 m_ContentsPage = notebook_page++;
475 }
476
477 // index listbox panel?
478 if ( helpStyle & wxHF_INDEX )
479 {
480 wxWindow *dummy = new wxPanel(m_NavigNotebook, wxID_HTML_INDEXPAGE);
481 #ifdef __WXMAC__
482 dummy->SetWindowVariant(wxWINDOW_VARIANT_NORMAL);
483 #endif
484 wxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
485
486 dummy->SetSizer(topsizer);
487
488 m_IndexText = new wxTextCtrl(dummy, wxID_HTML_INDEXTEXT, wxEmptyString,
489 wxDefaultPosition, wxDefaultSize,
490 wxTE_PROCESS_ENTER);
491 m_IndexButton = new wxButton(dummy, wxID_HTML_INDEXBUTTON, _("Find"));
492 m_IndexButtonAll = new wxButton(dummy, wxID_HTML_INDEXBUTTONALL,
493 _("Show all"));
494 m_IndexCountInfo = new wxStaticText(dummy, wxID_HTML_COUNTINFO,
495 wxEmptyString, wxDefaultPosition,
496 wxDefaultSize,
497 wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
498 m_IndexList = new wxListBox(dummy, wxID_HTML_INDEXLIST,
499 wxDefaultPosition, wxDefaultSize,
500 0, NULL, wxLB_SINGLE);
501
502 #if wxUSE_TOOLTIPS
503 m_IndexButton->SetToolTip(_("Display all index items that contain given substring. Search is case insensitive."));
504 m_IndexButtonAll->SetToolTip(_("Show all items in index"));
505 #endif //wxUSE_TOOLTIPS
506
507 topsizer->Add(m_IndexText, 0, wxEXPAND | wxALL, 10);
508 wxSizer *btsizer = new wxBoxSizer(wxHORIZONTAL);
509 btsizer->Add(m_IndexButton, 0, wxRIGHT, 2);
510 btsizer->Add(m_IndexButtonAll);
511 topsizer->Add(btsizer, 0,
512 wxALIGN_RIGHT | wxLEFT | wxRIGHT | wxBOTTOM, 10);
513 topsizer->Add(m_IndexCountInfo, 0, wxEXPAND | wxLEFT | wxRIGHT, 2);
514 topsizer->Add(m_IndexList, 1, wxEXPAND | wxALL, 2);
515
516 m_NavigNotebook->AddPage(dummy, _("Index"));
517 m_IndexPage = notebook_page++;
518 }
519
520 // search list panel?
521 if ( helpStyle & wxHF_SEARCH )
522 {
523 wxWindow *dummy = new wxPanel(m_NavigNotebook, wxID_HTML_INDEXPAGE);
524 #ifdef __WXMAC__
525 dummy->SetWindowVariant(wxWINDOW_VARIANT_NORMAL);
526 #endif
527 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
528
529 dummy->SetSizer(sizer);
530
531 m_SearchText = new wxTextCtrl(dummy, wxID_HTML_SEARCHTEXT,
532 wxEmptyString,
533 wxDefaultPosition, wxDefaultSize,
534 wxTE_PROCESS_ENTER);
535 m_SearchChoice = new wxChoice(dummy, wxID_HTML_SEARCHCHOICE,
536 wxDefaultPosition, wxSize(125,wxDefaultCoord));
537 m_SearchCaseSensitive = new wxCheckBox(dummy, wxID_ANY, _("Case sensitive"));
538 m_SearchWholeWords = new wxCheckBox(dummy, wxID_ANY, _("Whole words only"));
539 m_SearchButton = new wxButton(dummy, wxID_HTML_SEARCHBUTTON, _("Search"));
540 #if wxUSE_TOOLTIPS
541 m_SearchButton->SetToolTip(_("Search contents of help book(s) for all occurences of the text you typed above"));
542 #endif //wxUSE_TOOLTIPS
543 m_SearchList = new wxListBox(dummy, wxID_HTML_SEARCHLIST,
544 wxDefaultPosition, wxDefaultSize,
545 0, NULL, wxLB_SINGLE);
546
547 sizer->Add(m_SearchText, 0, wxEXPAND | wxALL, 10);
548 sizer->Add(m_SearchChoice, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
549 sizer->Add(m_SearchCaseSensitive, 0, wxLEFT | wxRIGHT, 10);
550 sizer->Add(m_SearchWholeWords, 0, wxLEFT | wxRIGHT, 10);
551 sizer->Add(m_SearchButton, 0, wxALL | wxALIGN_RIGHT, 8);
552 sizer->Add(m_SearchList, 1, wxALL | wxEXPAND, 2);
553
554 m_NavigNotebook->AddPage(dummy, _("Search"));
555 m_SearchPage = notebook_page;
556 }
557
558 m_HtmlWin->Show();
559
560 RefreshLists();
561
562 if ( navigSizer )
563 {
564 navigSizer->SetSizeHints(m_NavigPan);
565 m_NavigPan->Layout();
566 }
567
568 // showtime
569 if ( m_NavigPan && m_Splitter )
570 {
571 // The panel will have its own min size which the splitter
572 // should respect
573 //if (m_NavigPan)
574 // m_Splitter->SetMinimumPaneSize(m_NavigPan->GetBestSize().x);
575 //else
576 m_Splitter->SetMinimumPaneSize(20);
577
578 if ( m_Cfg.navig_on )
579 {
580 m_NavigPan->Show();
581 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
582 }
583 else
584 {
585 m_NavigPan->Show(false);
586 m_Splitter->Initialize(m_HtmlWin);
587 }
588 }
589
590 // Reduce flicker by updating the splitter pane sizes before the
591 // frame is shown
592 wxSizeEvent sizeEvent(GetSize(), GetId());
593 ProcessEvent(sizeEvent);
594
595 if (m_Splitter)
596 m_Splitter->UpdateSize();
597
598 return true;
599 }
600
~wxHtmlHelpWindow()601 wxHtmlHelpWindow::~wxHtmlHelpWindow()
602 {
603 if ( m_helpController )
604 m_helpController->SetHelpWindow(NULL);
605
606 delete m_mergedIndex;
607
608 // PopEventHandler(); // wxhtmlhelpcontroller (not any more!)
609 if (m_DataCreated)
610 delete m_Data;
611 if (m_NormalFonts) delete m_NormalFonts;
612 if (m_FixedFonts) delete m_FixedFonts;
613 if (m_PagesHash)
614 {
615 WX_CLEAR_HASH_TABLE(*m_PagesHash);
616 delete m_PagesHash;
617 }
618 #if wxUSE_PRINTING_ARCHITECTURE
619 if (m_Printer) delete m_Printer;
620 #endif
621 }
622
SetController(wxHtmlHelpController * controller)623 void wxHtmlHelpWindow::SetController(wxHtmlHelpController* controller)
624 {
625 if (m_DataCreated)
626 delete m_Data;
627 m_helpController = controller;
628 m_Data = controller->GetHelpData();
629 m_DataCreated = false;
630 }
631
632 #if wxUSE_TOOLBAR
AddToolbarButtons(wxToolBar * toolBar,int style)633 void wxHtmlHelpWindow::AddToolbarButtons(wxToolBar *toolBar, int style)
634 {
635 wxBitmap wpanelBitmap =
636 wxArtProvider::GetBitmap(wxART_HELP_SIDE_PANEL, wxART_TOOLBAR);
637 wxBitmap wbackBitmap =
638 wxArtProvider::GetBitmap(wxART_GO_BACK, wxART_TOOLBAR);
639 wxBitmap wforwardBitmap =
640 wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_TOOLBAR);
641 wxBitmap wupnodeBitmap =
642 wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_TOOLBAR);
643 wxBitmap wupBitmap =
644 wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR);
645 wxBitmap wdownBitmap =
646 wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR);
647 wxBitmap wopenBitmap =
648 wxArtProvider::GetBitmap(wxART_FILE_OPEN, wxART_TOOLBAR);
649 wxBitmap wprintBitmap =
650 wxArtProvider::GetBitmap(wxART_PRINT, wxART_TOOLBAR);
651 wxBitmap woptionsBitmap =
652 wxArtProvider::GetBitmap(wxART_HELP_SETTINGS, wxART_TOOLBAR);
653
654 wxASSERT_MSG( (wpanelBitmap.Ok() && wbackBitmap.Ok() &&
655 wforwardBitmap.Ok() && wupnodeBitmap.Ok() &&
656 wupBitmap.Ok() && wdownBitmap.Ok() &&
657 wopenBitmap.Ok() && wprintBitmap.Ok() &&
658 woptionsBitmap.Ok()),
659 wxT("One or more HTML help frame toolbar bitmap could not be loaded.")) ;
660
661
662 toolBar->AddTool(wxID_HTML_PANEL, wpanelBitmap, wxNullBitmap,
663 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
664 _("Show/hide navigation panel"));
665
666 toolBar->AddSeparator();
667 toolBar->AddTool(wxID_HTML_BACK, wbackBitmap, wxNullBitmap,
668 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
669 _("Go back"));
670 toolBar->AddTool(wxID_HTML_FORWARD, wforwardBitmap, wxNullBitmap,
671 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
672 _("Go forward"));
673 toolBar->AddSeparator();
674
675 toolBar->AddTool(wxID_HTML_UPNODE, wupnodeBitmap, wxNullBitmap,
676 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
677 _("Go one level up in document hierarchy"));
678 toolBar->AddTool(wxID_HTML_UP, wupBitmap, wxNullBitmap,
679 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
680 _("Previous page"));
681 toolBar->AddTool(wxID_HTML_DOWN, wdownBitmap, wxNullBitmap,
682 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
683 _("Next page"));
684
685 if ((style & wxHF_PRINT) || (style & wxHF_OPEN_FILES))
686 toolBar->AddSeparator();
687
688 if (style & wxHF_OPEN_FILES)
689 toolBar->AddTool(wxID_HTML_OPENFILE, wopenBitmap, wxNullBitmap,
690 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
691 _("Open HTML document"));
692
693 #if wxUSE_PRINTING_ARCHITECTURE
694 if (style & wxHF_PRINT)
695 toolBar->AddTool(wxID_HTML_PRINT, wprintBitmap, wxNullBitmap,
696 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
697 _("Print this page"));
698 #endif
699
700 toolBar->AddSeparator();
701 toolBar->AddTool(wxID_HTML_OPTIONS, woptionsBitmap, wxNullBitmap,
702 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
703 _("Display options dialog"));
704
705 // Allow application to add custom buttons
706 wxHtmlHelpFrame* parentFrame = wxDynamicCast(GetParent(), wxHtmlHelpFrame);
707 wxHtmlHelpDialog* parentDialog = wxDynamicCast(GetParent(), wxHtmlHelpDialog);
708 if (parentFrame)
709 parentFrame->AddToolbarButtons(toolBar, style);
710 if (parentDialog)
711 parentDialog->AddToolbarButtons(toolBar, style);
712 }
713 #endif //wxUSE_TOOLBAR
714
715
Display(const wxString & x)716 bool wxHtmlHelpWindow::Display(const wxString& x)
717 {
718 wxString url = m_Data->FindPageByName(x);
719 if (!url.empty())
720 {
721 m_HtmlWin->LoadPage(url);
722 NotifyPageChanged();
723 return true;
724 }
725
726 return false;
727 }
728
Display(const int id)729 bool wxHtmlHelpWindow::Display(const int id)
730 {
731 wxString url = m_Data->FindPageById(id);
732 if (!url.empty())
733 {
734 m_HtmlWin->LoadPage(url);
735 NotifyPageChanged();
736 return true;
737 }
738
739 return false;
740 }
741
DisplayContents()742 bool wxHtmlHelpWindow::DisplayContents()
743 {
744 if (! m_ContentsBox)
745 return false;
746
747 if (!m_Splitter->IsSplit())
748 {
749 m_NavigPan->Show();
750 m_HtmlWin->Show();
751 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
752 m_Cfg.navig_on = true;
753 }
754
755 m_NavigNotebook->SetSelection(m_ContentsPage);
756
757 if (m_Data->GetBookRecArray().GetCount() > 0)
758 {
759 wxHtmlBookRecord& book = m_Data->GetBookRecArray()[0];
760 if (!book.GetStart().empty())
761 m_HtmlWin->LoadPage(book.GetFullPath(book.GetStart()));
762 }
763
764 return true;
765 }
766
DisplayIndex()767 bool wxHtmlHelpWindow::DisplayIndex()
768 {
769 if (! m_IndexList)
770 return false;
771
772 if (!m_Splitter->IsSplit())
773 {
774 m_NavigPan->Show();
775 m_HtmlWin->Show();
776 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
777 }
778
779 m_NavigNotebook->SetSelection(m_IndexPage);
780
781 if (m_Data->GetBookRecArray().GetCount() > 0)
782 {
783 wxHtmlBookRecord& book = m_Data->GetBookRecArray()[0];
784 if (!book.GetStart().empty())
785 m_HtmlWin->LoadPage(book.GetFullPath(book.GetStart()));
786 }
787
788 return true;
789 }
790
DisplayIndexItem(const wxHtmlHelpMergedIndexItem * it)791 void wxHtmlHelpWindow::DisplayIndexItem(const wxHtmlHelpMergedIndexItem *it)
792 {
793 if (it->items.size() == 1)
794 {
795 if (!it->items[0]->page.empty())
796 {
797 m_HtmlWin->LoadPage(it->items[0]->GetFullPath());
798 NotifyPageChanged();
799 }
800 }
801 else
802 {
803 wxBusyCursor busy_cursor;
804
805 // more pages associated with this index item -- let the user choose
806 // which one she/he wants from a list:
807 wxArrayString arr;
808 size_t len = it->items.size();
809 for (size_t i = 0; i < len; i++)
810 {
811 wxString page = it->items[i]->page;
812 // try to find page's title in contents:
813 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
814 size_t clen = contents.size();
815 for (size_t j = 0; j < clen; j++)
816 {
817 if (contents[j].page == page)
818 {
819 page = contents[j].name;
820 break;
821 }
822 }
823 arr.push_back(page);
824 }
825
826 wxSingleChoiceDialog dlg(this,
827 _("Please choose the page to display:"),
828 _("Help Topics"),
829 arr, NULL, wxCHOICEDLG_STYLE & ~wxCENTRE);
830 if (dlg.ShowModal() == wxID_OK)
831 {
832 m_HtmlWin->LoadPage(it->items[dlg.GetSelection()]->GetFullPath());
833 NotifyPageChanged();
834 }
835 }
836 }
837
KeywordSearch(const wxString & keyword,wxHelpSearchMode mode)838 bool wxHtmlHelpWindow::KeywordSearch(const wxString& keyword,
839 wxHelpSearchMode mode)
840 {
841 if (mode == wxHELP_SEARCH_ALL)
842 {
843 if ( !(m_SearchList &&
844 m_SearchButton && m_SearchText && m_SearchChoice) )
845 return false;
846 }
847 else if (mode == wxHELP_SEARCH_INDEX)
848 {
849 if ( !(m_IndexList &&
850 m_IndexButton && m_IndexButtonAll && m_IndexText) )
851 return false;
852 }
853
854 int foundcnt = 0;
855 wxString foundstr;
856 wxString book = wxEmptyString;
857
858 if (!m_Splitter->IsSplit())
859 {
860 m_NavigPan->Show();
861 m_HtmlWin->Show();
862 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
863 }
864
865 if (mode == wxHELP_SEARCH_ALL)
866 {
867 m_NavigNotebook->SetSelection(m_SearchPage);
868 m_SearchList->Clear();
869 m_SearchText->SetValue(keyword);
870 m_SearchButton->Disable();
871
872 if (m_SearchChoice->GetSelection() != 0)
873 book = m_SearchChoice->GetStringSelection();
874
875 wxHtmlSearchStatus status(m_Data, keyword,
876 m_SearchCaseSensitive->GetValue(),
877 m_SearchWholeWords->GetValue(),
878 book);
879
880 #if wxUSE_PROGRESSDLG
881 wxProgressDialog progress(_("Searching..."),
882 _("No matching page found yet"),
883 status.GetMaxIndex(), this,
884 wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_AUTO_HIDE);
885 #endif
886
887 int curi;
888 while (status.IsActive())
889 {
890 curi = status.GetCurIndex();
891 if (curi % 32 == 0
892 #if wxUSE_PROGRESSDLG
893 && !progress.Update(curi)
894 #endif
895 )
896 break;
897 if (status.Search())
898 {
899 foundstr.Printf(_("Found %i matches"), ++foundcnt);
900 #if wxUSE_PROGRESSDLG
901 progress.Update(status.GetCurIndex(), foundstr);
902 #endif
903 m_SearchList->Append(status.GetName(), (void*)status.GetCurItem());
904 }
905 }
906
907 m_SearchButton->Enable();
908 m_SearchText->SetSelection(0, keyword.length());
909 m_SearchText->SetFocus();
910 }
911 else if (mode == wxHELP_SEARCH_INDEX)
912 {
913 m_NavigNotebook->SetSelection(m_IndexPage);
914 m_IndexList->Clear();
915 m_IndexButton->Disable();
916 m_IndexButtonAll->Disable();
917 m_IndexText->SetValue(keyword);
918
919 DoIndexFind();
920 m_IndexButton->Enable();
921 m_IndexButtonAll->Enable();
922 foundcnt = m_IndexList->GetCount();
923 }
924
925 if (foundcnt)
926 {
927 switch ( mode )
928 {
929 default:
930 wxFAIL_MSG( _T("unknown help search mode") );
931 // fall back
932
933 case wxHELP_SEARCH_ALL:
934 {
935 wxHtmlHelpDataItem *it =
936 (wxHtmlHelpDataItem*) m_SearchList->GetClientData(0);
937 if (it)
938 {
939 m_HtmlWin->LoadPage(it->GetFullPath());
940 NotifyPageChanged();
941 }
942 break;
943 }
944
945 case wxHELP_SEARCH_INDEX:
946 {
947 wxHtmlHelpMergedIndexItem* it =
948 (wxHtmlHelpMergedIndexItem*) m_IndexList->GetClientData(0);
949 if (it)
950 DisplayIndexItem(it);
951 break;
952 }
953 }
954
955 }
956
957 return foundcnt > 0;
958 }
959
CreateContents()960 void wxHtmlHelpWindow::CreateContents()
961 {
962 if (! m_ContentsBox)
963 return ;
964
965 if (m_PagesHash)
966 {
967 WX_CLEAR_HASH_TABLE(*m_PagesHash);
968 delete m_PagesHash;
969 }
970
971 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
972
973 size_t cnt = contents.size();
974
975 m_PagesHash = new wxHashTable(wxKEY_STRING, 2 * cnt);
976
977 const int MAX_ROOTS = 64;
978 wxTreeItemId roots[MAX_ROOTS];
979 // VS: this array holds information about whether we've set item icon at
980 // given level. This is necessary because m_Data has a flat structure
981 // and there's no way of recognizing if some item has subitems or not.
982 // We set the icon later: when we find an item with level=n, we know
983 // that the last item with level=n-1 was afolder with subitems, so we
984 // set its icon accordingly
985 bool imaged[MAX_ROOTS];
986 m_ContentsBox->DeleteAllItems();
987
988 roots[0] = m_ContentsBox->AddRoot(_("(Help)"));
989 imaged[0] = true;
990
991 for (size_t i = 0; i < cnt; i++)
992 {
993 wxHtmlHelpDataItem *it = &contents[i];
994 // Handle books:
995 if (it->level == 0)
996 {
997 if (m_hfStyle & wxHF_MERGE_BOOKS)
998 // VS: we don't want book nodes, books' content should
999 // appear under tree's root. This line will create a "fake"
1000 // record about book node so that the rest of this look
1001 // will believe there really _is_ a book node and will
1002 // behave correctly.
1003 roots[1] = roots[0];
1004 else
1005 {
1006 roots[1] = m_ContentsBox->AppendItem(roots[0],
1007 it->name, IMG_Book, -1,
1008 new wxHtmlHelpTreeItemData(i));
1009 m_ContentsBox->SetItemBold(roots[1], true);
1010 }
1011 imaged[1] = true;
1012 }
1013 // ...and their contents:
1014 else
1015 {
1016 roots[it->level + 1] = m_ContentsBox->AppendItem(
1017 roots[it->level], it->name, IMG_Page,
1018 -1, new wxHtmlHelpTreeItemData(i));
1019 imaged[it->level + 1] = false;
1020 }
1021
1022 m_PagesHash->Put(it->GetFullPath(),
1023 new wxHtmlHelpHashData(i, roots[it->level + 1]));
1024
1025 // Set the icon for the node one level up in the hierarchy,
1026 // unless already done (see comment above imaged[] declaration)
1027 if (!imaged[it->level])
1028 {
1029 int image = IMG_Folder;
1030 if (m_hfStyle & wxHF_ICONS_BOOK)
1031 image = IMG_Book;
1032 else if (m_hfStyle & wxHF_ICONS_BOOK_CHAPTER)
1033 image = (it->level == 1) ? IMG_Book : IMG_Folder;
1034 m_ContentsBox->SetItemImage(roots[it->level], image);
1035 m_ContentsBox->SetItemImage(roots[it->level], image,
1036 wxTreeItemIcon_Selected);
1037 imaged[it->level] = true;
1038 }
1039 }
1040 }
1041
CreateIndex()1042 void wxHtmlHelpWindow::CreateIndex()
1043 {
1044 if (! m_IndexList)
1045 return ;
1046
1047 m_IndexList->Clear();
1048
1049 size_t cnt = m_mergedIndex->size();
1050
1051 wxString cnttext;
1052 if (cnt > INDEX_IS_SMALL)
1053 cnttext.Printf(_("%i of %i"), 0, cnt);
1054 else
1055 cnttext.Printf(_("%i of %i"), cnt, cnt);
1056 m_IndexCountInfo->SetLabel(cnttext);
1057 if (cnt > INDEX_IS_SMALL)
1058 return;
1059
1060 for (size_t i = 0; i < cnt; i++)
1061 m_IndexList->Append((*m_mergedIndex)[i].name,
1062 (char*)(&(*m_mergedIndex)[i]));
1063 }
1064
CreateSearch()1065 void wxHtmlHelpWindow::CreateSearch()
1066 {
1067 if (! (m_SearchList && m_SearchChoice))
1068 return ;
1069 m_SearchList->Clear();
1070 m_SearchChoice->Clear();
1071 m_SearchChoice->Append(_("Search in all books"));
1072 const wxHtmlBookRecArray& bookrec = m_Data->GetBookRecArray();
1073 int i, cnt = bookrec.GetCount();
1074 for (i = 0; i < cnt; i++)
1075 m_SearchChoice->Append(bookrec[i].GetTitle());
1076 m_SearchChoice->SetSelection(0);
1077 }
1078
RefreshLists()1079 void wxHtmlHelpWindow::RefreshLists()
1080 {
1081 // Update m_mergedIndex:
1082 UpdateMergedIndex();
1083 // Update the controls
1084 CreateContents();
1085 CreateIndex();
1086 CreateSearch();
1087 }
1088
ReadCustomization(wxConfigBase * cfg,const wxString & path)1089 void wxHtmlHelpWindow::ReadCustomization(wxConfigBase *cfg, const wxString& path)
1090 {
1091 wxString oldpath;
1092 wxString tmp;
1093
1094 if (path != wxEmptyString)
1095 {
1096 oldpath = cfg->GetPath();
1097 cfg->SetPath(_T("/") + path);
1098 }
1099
1100 m_Cfg.navig_on = cfg->Read(wxT("hcNavigPanel"), m_Cfg.navig_on) != 0;
1101 m_Cfg.sashpos = cfg->Read(wxT("hcSashPos"), m_Cfg.sashpos);
1102 m_Cfg.x = cfg->Read(wxT("hcX"), m_Cfg.x);
1103 m_Cfg.y = cfg->Read(wxT("hcY"), m_Cfg.y);
1104 m_Cfg.w = cfg->Read(wxT("hcW"), m_Cfg.w);
1105 m_Cfg.h = cfg->Read(wxT("hcH"), m_Cfg.h);
1106
1107 m_FixedFace = cfg->Read(wxT("hcFixedFace"), m_FixedFace);
1108 m_NormalFace = cfg->Read(wxT("hcNormalFace"), m_NormalFace);
1109 m_FontSize = cfg->Read(wxT("hcBaseFontSize"), m_FontSize);
1110
1111 {
1112 int i;
1113 int cnt;
1114 wxString val, s;
1115
1116 cnt = cfg->Read(wxT("hcBookmarksCnt"), 0L);
1117 if (cnt != 0)
1118 {
1119 m_BookmarksNames.Clear();
1120 m_BookmarksPages.Clear();
1121 if (m_Bookmarks)
1122 {
1123 m_Bookmarks->Clear();
1124 m_Bookmarks->Append(_("(bookmarks)"));
1125 }
1126
1127 for (i = 0; i < cnt; i++)
1128 {
1129 val.Printf(wxT("hcBookmark_%i"), i);
1130 s = cfg->Read(val);
1131 m_BookmarksNames.Add(s);
1132 if (m_Bookmarks) m_Bookmarks->Append(s);
1133 val.Printf(wxT("hcBookmark_%i_url"), i);
1134 s = cfg->Read(val);
1135 m_BookmarksPages.Add(s);
1136 }
1137 }
1138 }
1139
1140 if (m_HtmlWin)
1141 m_HtmlWin->ReadCustomization(cfg);
1142
1143 if (path != wxEmptyString)
1144 cfg->SetPath(oldpath);
1145 }
1146
WriteCustomization(wxConfigBase * cfg,const wxString & path)1147 void wxHtmlHelpWindow::WriteCustomization(wxConfigBase *cfg, const wxString& path)
1148 {
1149 wxString oldpath;
1150 wxString tmp;
1151
1152 if (path != wxEmptyString)
1153 {
1154 oldpath = cfg->GetPath();
1155 cfg->SetPath(_T("/") + path);
1156 }
1157
1158 cfg->Write(wxT("hcNavigPanel"), m_Cfg.navig_on);
1159 cfg->Write(wxT("hcSashPos"), (long)m_Cfg.sashpos);
1160
1161 // Don't write if iconized as this would make the window
1162 // disappear next time it is shown!
1163 cfg->Write(wxT("hcX"), (long)m_Cfg.x);
1164 cfg->Write(wxT("hcY"), (long)m_Cfg.y);
1165 cfg->Write(wxT("hcW"), (long)m_Cfg.w);
1166 cfg->Write(wxT("hcH"), (long)m_Cfg.h);
1167
1168 cfg->Write(wxT("hcFixedFace"), m_FixedFace);
1169 cfg->Write(wxT("hcNormalFace"), m_NormalFace);
1170 cfg->Write(wxT("hcBaseFontSize"), (long)m_FontSize);
1171
1172 if (m_Bookmarks)
1173 {
1174 int i;
1175 int cnt = m_BookmarksNames.GetCount();
1176 wxString val;
1177
1178 cfg->Write(wxT("hcBookmarksCnt"), (long)cnt);
1179 for (i = 0; i < cnt; i++)
1180 {
1181 val.Printf(wxT("hcBookmark_%i"), i);
1182 cfg->Write(val, m_BookmarksNames[i]);
1183 val.Printf(wxT("hcBookmark_%i_url"), i);
1184 cfg->Write(val, m_BookmarksPages[i]);
1185 }
1186 }
1187
1188 if (m_HtmlWin)
1189 m_HtmlWin->WriteCustomization(cfg);
1190
1191 if (path != wxEmptyString)
1192 cfg->SetPath(oldpath);
1193 }
1194
SetFontsToHtmlWin(wxHtmlWindow * win,const wxString & scalf,const wxString & fixf,int size)1195 static void SetFontsToHtmlWin(wxHtmlWindow *win, const wxString& scalf, const wxString& fixf, int size)
1196 {
1197 int f_sizes[7];
1198 f_sizes[0] = int(size * 0.6);
1199 f_sizes[1] = int(size * 0.8);
1200 f_sizes[2] = size;
1201 f_sizes[3] = int(size * 1.2);
1202 f_sizes[4] = int(size * 1.4);
1203 f_sizes[5] = int(size * 1.6);
1204 f_sizes[6] = int(size * 1.8);
1205
1206 win->SetFonts(scalf, fixf, f_sizes);
1207 }
1208
1209 class wxHtmlHelpWindowOptionsDialog : public wxDialog
1210 {
1211 public:
1212 wxComboBox *NormalFont, *FixedFont;
1213 wxSpinCtrl *FontSize;
1214 wxHtmlWindow *TestWin;
1215
wxHtmlHelpWindowOptionsDialog(wxWindow * parent)1216 wxHtmlHelpWindowOptionsDialog(wxWindow *parent)
1217 : wxDialog(parent, wxID_ANY, wxString(_("Help Browser Options")))
1218 {
1219 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
1220 wxFlexGridSizer *sizer = new wxFlexGridSizer(2, 3, 2, 5);
1221
1222 sizer->Add(new wxStaticText(this, wxID_ANY, _("Normal font:")));
1223 sizer->Add(new wxStaticText(this, wxID_ANY, _("Fixed font:")));
1224 sizer->Add(new wxStaticText(this, wxID_ANY, _("Font size:")));
1225
1226 sizer->Add(NormalFont = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1227 wxSize(200, wxDefaultCoord),
1228 0, NULL, wxCB_DROPDOWN | wxCB_READONLY));
1229
1230 sizer->Add(FixedFont = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1231 wxSize(200, wxDefaultCoord),
1232 0, NULL, wxCB_DROPDOWN | wxCB_READONLY));
1233
1234 sizer->Add(FontSize = new wxSpinCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1235 wxDefaultSize, wxSP_ARROW_KEYS, 2, 100, 2, _T("wxSpinCtrl")));
1236
1237 topsizer->Add(sizer, 0, wxLEFT|wxRIGHT|wxTOP, 10);
1238
1239 topsizer->Add(new wxStaticText(this, wxID_ANY, _("Preview:")),
1240 0, wxLEFT | wxTOP, 10);
1241
1242 int style = wxHW_SCROLLBAR_AUTO;
1243
1244 #ifdef __WXMSW__
1245 style |= GetThemedBorderStyle();
1246 #else
1247 style |= wxBORDER_SUNKEN;
1248 #endif
1249 topsizer->AddSpacer(5);
1250
1251 topsizer->Add(TestWin = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxSize(20, 150),
1252 style),
1253 1, wxEXPAND | wxLEFT|wxRIGHT, 10);
1254
1255 wxBoxSizer *sizer2 = new wxBoxSizer(wxHORIZONTAL);
1256 wxButton *ok;
1257 sizer2->Add(ok = new wxButton(this, wxID_OK), 0, wxALL, 10);
1258 ok->SetDefault();
1259 sizer2->Add(new wxButton(this, wxID_CANCEL), 0, wxALL, 10);
1260 topsizer->Add(sizer2, 0, wxALIGN_RIGHT);
1261
1262 SetSizer(topsizer);
1263 topsizer->Fit(this);
1264 Centre(wxBOTH);
1265 }
1266
1267
UpdateTestWin()1268 void UpdateTestWin()
1269 {
1270 wxBusyCursor bcur;
1271 SetFontsToHtmlWin(TestWin,
1272 NormalFont->GetStringSelection(),
1273 FixedFont->GetStringSelection(),
1274 FontSize->GetValue());
1275
1276 wxString content(_("font size"));
1277
1278 content = _T("<font size=-2>") + content + _T(" -2</font><br>")
1279 _T("<font size=-1>") + content + _T(" -1</font><br>")
1280 _T("<font size=+0>") + content + _T(" +0</font><br>")
1281 _T("<font size=+1>") + content + _T(" +1</font><br>")
1282 _T("<font size=+2>") + content + _T(" +2</font><br>")
1283 _T("<font size=+3>") + content + _T(" +3</font><br>")
1284 _T("<font size=+4>") + content + _T(" +4</font><br>") ;
1285
1286 content = wxString( _T("<html><body><table><tr><td>") ) +
1287 _("Normal face<br>and <u>underlined</u>. ") +
1288 _("<i>Italic face.</i> ") +
1289 _("<b>Bold face.</b> ") +
1290 _("<b><i>Bold italic face.</i></b><br>") +
1291 content +
1292 wxString( _T("</td><td><tt>") ) +
1293 _("Fixed size face.<br> <b>bold</b> <i>italic</i> ") +
1294 _("<b><i>bold italic <u>underlined</u></i></b><br>") +
1295 content +
1296 _T("</tt></td></tr></table></body></html>");
1297
1298 TestWin->SetPage( content );
1299 }
1300
OnUpdate(wxCommandEvent & WXUNUSED (event))1301 void OnUpdate(wxCommandEvent& WXUNUSED(event))
1302 {
1303 UpdateTestWin();
1304 }
OnUpdateSpin(wxSpinEvent & WXUNUSED (event))1305 void OnUpdateSpin(wxSpinEvent& WXUNUSED(event))
1306 {
1307 UpdateTestWin();
1308 }
1309
1310 DECLARE_EVENT_TABLE()
1311 DECLARE_NO_COPY_CLASS(wxHtmlHelpWindowOptionsDialog)
1312 };
1313
BEGIN_EVENT_TABLE(wxHtmlHelpWindowOptionsDialog,wxDialog)1314 BEGIN_EVENT_TABLE(wxHtmlHelpWindowOptionsDialog, wxDialog)
1315 EVT_COMBOBOX(wxID_ANY, wxHtmlHelpWindowOptionsDialog::OnUpdate)
1316 EVT_SPINCTRL(wxID_ANY, wxHtmlHelpWindowOptionsDialog::OnUpdateSpin)
1317 END_EVENT_TABLE()
1318
1319 void wxHtmlHelpWindow::OptionsDialog()
1320 {
1321 wxHtmlHelpWindowOptionsDialog dlg(this);
1322 unsigned i;
1323
1324 if (m_NormalFonts == NULL)
1325 {
1326 m_NormalFonts = new wxArrayString(wxFontEnumerator::GetFacenames());
1327 m_NormalFonts->Sort(); // ascending sort
1328 }
1329 if (m_FixedFonts == NULL)
1330 {
1331 m_FixedFonts = new wxArrayString(
1332 wxFontEnumerator::GetFacenames(wxFONTENCODING_SYSTEM,
1333 true /*enum fixed width only*/));
1334 m_FixedFonts->Sort(); // ascending sort
1335 }
1336
1337 // VS: We want to show the font that is actually used by wxHtmlWindow.
1338 // If customization dialog wasn't used yet, facenames are empty and
1339 // wxHtmlWindow uses default fonts -- let's find out what they
1340 // are so that we can pass them to the dialog:
1341 if (m_NormalFace.empty())
1342 {
1343 wxFont fnt(m_FontSize, wxSWISS, wxNORMAL, wxNORMAL, false);
1344 m_NormalFace = fnt.GetFaceName();
1345 }
1346 if (m_FixedFace.empty())
1347 {
1348 wxFont fnt(m_FontSize, wxMODERN, wxNORMAL, wxNORMAL, false);
1349 m_FixedFace = fnt.GetFaceName();
1350 }
1351
1352 for (i = 0; i < m_NormalFonts->GetCount(); i++)
1353 dlg.NormalFont->Append((*m_NormalFonts)[i]);
1354 for (i = 0; i < m_FixedFonts->GetCount(); i++)
1355 dlg.FixedFont->Append((*m_FixedFonts)[i]);
1356 if (!m_NormalFace.empty())
1357 dlg.NormalFont->SetStringSelection(m_NormalFace);
1358 else
1359 dlg.NormalFont->SetSelection(0);
1360 if (!m_FixedFace.empty())
1361 dlg.FixedFont->SetStringSelection(m_FixedFace);
1362 else
1363 dlg.FixedFont->SetSelection(0);
1364 dlg.FontSize->SetValue(m_FontSize);
1365 dlg.UpdateTestWin();
1366
1367 if (dlg.ShowModal() == wxID_OK)
1368 {
1369 m_NormalFace = dlg.NormalFont->GetStringSelection();
1370 m_FixedFace = dlg.FixedFont->GetStringSelection();
1371 m_FontSize = dlg.FontSize->GetValue();
1372 SetFontsToHtmlWin(m_HtmlWin, m_NormalFace, m_FixedFace, m_FontSize);
1373 }
1374 }
1375
NotifyPageChanged()1376 void wxHtmlHelpWindow::NotifyPageChanged()
1377 {
1378 if (m_UpdateContents && m_PagesHash)
1379 {
1380 wxString page = wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin);
1381 wxHtmlHelpHashData *ha = NULL;
1382 if (!page.empty())
1383 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(page);
1384
1385 if (ha)
1386 {
1387 bool olduc = m_UpdateContents;
1388 m_UpdateContents = false;
1389 m_ContentsBox->SelectItem(ha->m_Id);
1390 m_ContentsBox->EnsureVisible(ha->m_Id);
1391 m_UpdateContents = olduc;
1392 }
1393 }
1394 }
1395
1396 /*
1397 EVENT HANDLING :
1398 */
1399
1400
OnToolbar(wxCommandEvent & event)1401 void wxHtmlHelpWindow::OnToolbar(wxCommandEvent& event)
1402 {
1403 switch (event.GetId())
1404 {
1405 case wxID_HTML_BACK :
1406 m_HtmlWin->HistoryBack();
1407 NotifyPageChanged();
1408 break;
1409
1410 case wxID_HTML_FORWARD :
1411 m_HtmlWin->HistoryForward();
1412 NotifyPageChanged();
1413 break;
1414
1415 case wxID_HTML_UP :
1416 if (m_PagesHash)
1417 {
1418 wxString page = wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin);
1419 wxHtmlHelpHashData *ha = NULL;
1420 if (!page.empty())
1421 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(page);
1422 if (ha && ha->m_Index > 0)
1423 {
1424 const wxHtmlHelpDataItem& it = m_Data->GetContentsArray()[ha->m_Index - 1];
1425 if (!it.page.empty())
1426 {
1427 m_HtmlWin->LoadPage(it.GetFullPath());
1428 NotifyPageChanged();
1429 }
1430 }
1431 }
1432 break;
1433
1434 case wxID_HTML_UPNODE :
1435 if (m_PagesHash)
1436 {
1437 wxString page = wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin);
1438 wxHtmlHelpHashData *ha = NULL;
1439 if (!page.empty())
1440 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(page);
1441 if (ha && ha->m_Index > 0)
1442 {
1443 int level =
1444 m_Data->GetContentsArray()[ha->m_Index].level - 1;
1445 int ind = ha->m_Index - 1;
1446
1447 const wxHtmlHelpDataItem *it =
1448 &m_Data->GetContentsArray()[ind];
1449 while (ind >= 0 && it->level != level)
1450 {
1451 ind--;
1452 it = &m_Data->GetContentsArray()[ind];
1453 }
1454 if (ind >= 0)
1455 {
1456 if (!it->page.empty())
1457 {
1458 m_HtmlWin->LoadPage(it->GetFullPath());
1459 NotifyPageChanged();
1460 }
1461 }
1462 }
1463 }
1464 break;
1465
1466 case wxID_HTML_DOWN :
1467 if (m_PagesHash)
1468 {
1469 wxString page = wxHtmlHelpHtmlWindow::GetOpenedPageWithAnchor(m_HtmlWin);
1470 wxHtmlHelpHashData *ha = NULL;
1471 if (!page.empty())
1472 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(page);
1473
1474 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
1475 if (ha && ha->m_Index < (int)contents.size() - 1)
1476 {
1477 size_t idx = ha->m_Index + 1;
1478
1479 while (contents[idx].GetFullPath() == page) idx++;
1480
1481 if (!contents[idx].page.empty())
1482 {
1483 m_HtmlWin->LoadPage(contents[idx].GetFullPath());
1484 NotifyPageChanged();
1485 }
1486 }
1487 }
1488 break;
1489
1490 case wxID_HTML_PANEL :
1491 {
1492 if (! (m_Splitter && m_NavigPan))
1493 return ;
1494 if (m_Splitter->IsSplit())
1495 {
1496 m_Cfg.sashpos = m_Splitter->GetSashPosition();
1497 m_Splitter->Unsplit(m_NavigPan);
1498 m_Cfg.navig_on = false;
1499 }
1500 else
1501 {
1502 m_NavigPan->Show();
1503 m_HtmlWin->Show();
1504 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
1505 m_Cfg.navig_on = true;
1506 }
1507 }
1508 break;
1509
1510 case wxID_HTML_OPTIONS :
1511 OptionsDialog();
1512 break;
1513
1514 case wxID_HTML_BOOKMARKSADD :
1515 {
1516 wxString item;
1517 wxString url;
1518
1519 item = m_HtmlWin->GetOpenedPageTitle();
1520 url = m_HtmlWin->GetOpenedPage();
1521 if (item == wxEmptyString)
1522 item = url.AfterLast(wxT('/'));
1523 if (m_BookmarksPages.Index(url) == wxNOT_FOUND)
1524 {
1525 m_Bookmarks->Append(item);
1526 m_BookmarksNames.Add(item);
1527 m_BookmarksPages.Add(url);
1528 }
1529 }
1530 break;
1531
1532 case wxID_HTML_BOOKMARKSREMOVE :
1533 {
1534 wxString item;
1535 int pos;
1536
1537 item = m_Bookmarks->GetStringSelection();
1538 pos = m_BookmarksNames.Index(item);
1539 if (pos != wxNOT_FOUND)
1540 {
1541 m_BookmarksNames.RemoveAt(pos);
1542 m_BookmarksPages.RemoveAt(pos);
1543 pos = m_Bookmarks->GetSelection();
1544 wxASSERT_MSG( pos != wxNOT_FOUND , wxT("Unknown bookmark position") ) ;
1545 m_Bookmarks->Delete((unsigned int)pos);
1546 }
1547 }
1548 break;
1549
1550 #if wxUSE_PRINTING_ARCHITECTURE
1551 case wxID_HTML_PRINT :
1552 {
1553 if (m_Printer == NULL)
1554 m_Printer = new wxHtmlEasyPrinting(_("Help Printing"), this);
1555 if (!m_HtmlWin->GetOpenedPage())
1556 wxLogWarning(_("Cannot print empty page."));
1557 else
1558 m_Printer->PrintFile(m_HtmlWin->GetOpenedPage());
1559 }
1560 break;
1561 #endif
1562
1563 case wxID_HTML_OPENFILE :
1564 {
1565 wxString filemask = wxString(
1566 _("HTML files (*.html;*.htm)|*.html;*.htm|")) +
1567 _("Help books (*.htb)|*.htb|Help books (*.zip)|*.zip|") +
1568 _("HTML Help Project (*.hhp)|*.hhp|") +
1569 #if wxUSE_LIBMSPACK
1570 _("Compressed HTML Help file (*.chm)|*.chm|") +
1571 #endif
1572 _("All files (*.*)|*");
1573 wxString s = wxFileSelector(_("Open HTML document"),
1574 wxEmptyString,
1575 wxEmptyString,
1576 wxEmptyString,
1577 filemask,
1578 wxFD_OPEN | wxFD_FILE_MUST_EXIST,
1579 this);
1580 if (!s.empty())
1581 {
1582 wxString ext = s.Right(4).Lower();
1583 if (ext == _T(".zip") || ext == _T(".htb") ||
1584 #if wxUSE_LIBMSPACK
1585 ext == _T(".chm") ||
1586 #endif
1587 ext == _T(".hhp"))
1588 {
1589 wxBusyCursor bcur;
1590 m_Data->AddBook(s);
1591 RefreshLists();
1592 }
1593 else
1594 m_HtmlWin->LoadPage(s);
1595 }
1596 }
1597 break;
1598 }
1599 }
1600
OnContentsSel(wxTreeEvent & event)1601 void wxHtmlHelpWindow::OnContentsSel(wxTreeEvent& event)
1602 {
1603 wxHtmlHelpTreeItemData *pg;
1604
1605 pg = (wxHtmlHelpTreeItemData*) m_ContentsBox->GetItemData(event.GetItem());
1606
1607 if (pg && m_UpdateContents)
1608 {
1609 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
1610 m_UpdateContents = false;
1611 if (!contents[pg->m_Id].page.empty())
1612 m_HtmlWin->LoadPage(contents[pg->m_Id].GetFullPath());
1613 m_UpdateContents = true;
1614 }
1615 }
1616
OnIndexSel(wxCommandEvent & WXUNUSED (event))1617 void wxHtmlHelpWindow::OnIndexSel(wxCommandEvent& WXUNUSED(event))
1618 {
1619 wxHtmlHelpMergedIndexItem *it = (wxHtmlHelpMergedIndexItem*)
1620 m_IndexList->GetClientData(m_IndexList->GetSelection());
1621 if (it)
1622 DisplayIndexItem(it);
1623 }
1624
OnIndexFind(wxCommandEvent & WXUNUSED (event))1625 void wxHtmlHelpWindow::OnIndexFind(wxCommandEvent& WXUNUSED(event))
1626 {
1627 DoIndexFind();
1628 }
1629
DoIndexFind()1630 void wxHtmlHelpWindow::DoIndexFind()
1631 {
1632 wxString sr = m_IndexText->GetLineText(0);
1633 sr.MakeLower();
1634 if (sr == wxEmptyString)
1635 {
1636 DoIndexAll();
1637 }
1638 else
1639 {
1640 wxBusyCursor bcur;
1641
1642 m_IndexList->Clear();
1643 const wxHtmlHelpMergedIndex& index = *m_mergedIndex;
1644 size_t cnt = index.size();
1645
1646 int displ = 0;
1647 for (size_t i = 0; i < cnt; i++)
1648 {
1649 if (index[i].name.Lower().find(sr) != wxString::npos)
1650 {
1651 int pos = m_IndexList->Append(index[i].name,
1652 (char*)(&index[i]));
1653
1654 if (displ++ == 0)
1655 {
1656 // don't automatically show topic selector if this
1657 // item points to multiple pages:
1658 if (index[i].items.size() == 1)
1659 {
1660 m_IndexList->SetSelection(0);
1661 DisplayIndexItem(&index[i]);
1662 }
1663 }
1664
1665 // if this is nested item of the index, show its parent(s)
1666 // as well, otherwise it would not be clear what entry is
1667 // shown:
1668 wxHtmlHelpMergedIndexItem *parent = index[i].parent;
1669 while (parent)
1670 {
1671 if (pos == 0 ||
1672 (index.Index(*(wxHtmlHelpMergedIndexItem*)m_IndexList->GetClientData(pos-1))) < index.Index(*parent))
1673 {
1674 m_IndexList->Insert(parent->name,
1675 pos, (char*)parent);
1676 parent = parent->parent;
1677 }
1678 else break;
1679 }
1680
1681 // finally, it the item we just added is itself a parent for
1682 // other items, show them as well, because they are refinements
1683 // of the displayed index entry (i.e. it is implicitly contained
1684 // in them: "foo" with parent "bar" reads as "bar, foo"):
1685 int level = index[i].items[0]->level;
1686 i++;
1687 while (i < cnt && index[i].items[0]->level > level)
1688 {
1689 m_IndexList->Append(index[i].name, (char*)(&index[i]));
1690 i++;
1691 }
1692 i--;
1693 }
1694 }
1695
1696 wxString cnttext;
1697 cnttext.Printf(_("%i of %i"), displ, cnt);
1698 m_IndexCountInfo->SetLabel(cnttext);
1699
1700 m_IndexText->SetSelection(0, sr.length());
1701 m_IndexText->SetFocus();
1702 }
1703 }
1704
OnIndexAll(wxCommandEvent & WXUNUSED (event))1705 void wxHtmlHelpWindow::OnIndexAll(wxCommandEvent& WXUNUSED(event))
1706 {
1707 DoIndexAll();
1708 }
1709
DoIndexAll()1710 void wxHtmlHelpWindow::DoIndexAll()
1711 {
1712 wxBusyCursor bcur;
1713
1714 m_IndexList->Clear();
1715 const wxHtmlHelpMergedIndex& index = *m_mergedIndex;
1716 size_t cnt = index.size();
1717 bool first = true;
1718
1719 for (size_t i = 0; i < cnt; i++)
1720 {
1721 m_IndexList->Append(index[i].name, (char*)(&index[i]));
1722 if (first)
1723 {
1724 // don't automatically show topic selector if this
1725 // item points to multiple pages:
1726 if (index[i].items.size() == 1)
1727 {
1728 DisplayIndexItem(&index[i]);
1729 }
1730 first = false;
1731 }
1732 }
1733
1734 wxString cnttext;
1735 cnttext.Printf(_("%i of %i"), cnt, cnt);
1736 m_IndexCountInfo->SetLabel(cnttext);
1737 }
1738
OnSearchSel(wxCommandEvent & WXUNUSED (event))1739 void wxHtmlHelpWindow::OnSearchSel(wxCommandEvent& WXUNUSED(event))
1740 {
1741 wxHtmlHelpDataItem *it = (wxHtmlHelpDataItem*) m_SearchList->GetClientData(m_SearchList->GetSelection());
1742 if (it)
1743 {
1744 if (!it->page.empty())
1745 m_HtmlWin->LoadPage(it->GetFullPath());
1746 NotifyPageChanged();
1747 }
1748 }
1749
OnSearch(wxCommandEvent & WXUNUSED (event))1750 void wxHtmlHelpWindow::OnSearch(wxCommandEvent& WXUNUSED(event))
1751 {
1752 wxString sr = m_SearchText->GetLineText(0);
1753
1754 if (!sr.empty())
1755 KeywordSearch(sr, wxHELP_SEARCH_ALL);
1756 }
1757
OnBookmarksSel(wxCommandEvent & WXUNUSED (event))1758 void wxHtmlHelpWindow::OnBookmarksSel(wxCommandEvent& WXUNUSED(event))
1759 {
1760 wxString str = m_Bookmarks->GetStringSelection();
1761 int idx = m_BookmarksNames.Index(str);
1762 if (!str.empty() && str != _("(bookmarks)") && idx != wxNOT_FOUND)
1763 {
1764 m_HtmlWin->LoadPage(m_BookmarksPages[(size_t)idx]);
1765 NotifyPageChanged();
1766 }
1767 }
1768
OnSize(wxSizeEvent & WXUNUSED (event))1769 void wxHtmlHelpWindow::OnSize(wxSizeEvent& WXUNUSED(event))
1770 {
1771 Layout();
1772 }
1773
1774 #endif // wxUSE_WXHTML_HELP
1775