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