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