Fix HTML help on Mac.
[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 #ifdef __GNUG__
13 #pragma implementation
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/layout.h"
32 #include "wx/sizer.h"
33
34 #include "wx/bmpbuttn.h"
35 #include "wx/statbox.h"
36 #include "wx/radiobox.h"
37 #endif // WXPRECOMP
38
39 #include "wx/html/helpfrm.h"
40 #include "wx/html/helpctrl.h"
41 #include "wx/notebook.h"
42 #include "wx/imaglist.h"
43 #include "wx/treectrl.h"
44 #include "wx/tokenzr.h"
45 #include "wx/wfstream.h"
46 #include "wx/html/htmlwin.h"
47 #include "wx/busyinfo.h"
48 #include "wx/progdlg.h"
49 #include "wx/toolbar.h"
50 #include "wx/fontenum.h"
51 #include "wx/stream.h"
52 #include "wx/filedlg.h"
53
54 // Bitmaps:
55
56 #ifndef __WXMSW__
57 #include "bitmaps/wpanel.xpm"
58 #include "bitmaps/wback.xpm"
59 #include "bitmaps/wforward.xpm"
60 #include "bitmaps/wbook.xpm"
61 #include "bitmaps/woptions.xpm"
62 #include "bitmaps/wfolder.xpm"
63 #include "bitmaps/wpage.xpm"
64 #include "bitmaps/whelp.xpm"
65 #include "bitmaps/whlproot.xpm"
66 #include "bitmaps/wbkadd.xpm"
67 #include "bitmaps/wbkdel.xpm"
68 #include "bitmaps/wup.xpm"
69 #include "bitmaps/wupnode.xpm"
70 #include "bitmaps/wdown.xpm"
71 #include "bitmaps/wopen.xpm"
72 #include "bitmaps/wprint.xpm"
73 #endif
74
75
76 // what is considered "small index"?
77 #define INDEX_IS_SMALL 100
78
79 /* Motif defines this as a macro */
80 #ifdef Below
81 #undef Below
82 #endif
83
84 //--------------------------------------------------------------------------
85 // wxHtmlHelpTreeItemData (private)
86 //--------------------------------------------------------------------------
87
88 class wxHtmlHelpTreeItemData : public wxTreeItemData
89 {
90 public:
91 #if defined(__VISAGECPP__)
92 // VA needs a default ctor for some reason....
93 wxHtmlHelpTreeItemData() : wxTreeItemData()
94 { m_Id = 0; }
95 #endif
96 wxHtmlHelpTreeItemData(int id) : wxTreeItemData()
97 { m_Id = id;}
98
99 int m_Id;
100 };
101
102
103 //--------------------------------------------------------------------------
104 // wxHtmlHelpHashData (private)
105 //--------------------------------------------------------------------------
106
107 class wxHtmlHelpHashData : public wxObject
108 {
109 public:
110 wxHtmlHelpHashData(int index, wxTreeItemId id) : wxObject()
111 { m_Index = index; m_Id = id;}
112 ~wxHtmlHelpHashData() {}
113
114 int m_Index;
115 wxTreeItemId m_Id;
116 };
117
118
119 //--------------------------------------------------------------------------
120 // wxHtmlHelpHtmlWindow (private)
121 //--------------------------------------------------------------------------
122
123 class wxHtmlHelpHtmlWindow : public wxHtmlWindow
124 {
125 public:
126 wxHtmlHelpHtmlWindow(wxHtmlHelpFrame *fr, wxWindow *parent) : wxHtmlWindow(parent), m_Frame(fr) {}
127
128 virtual void OnLinkClicked(const wxHtmlLinkInfo& link)
129 {
130 wxHtmlWindow::OnLinkClicked(link);
131 m_Frame->NotifyPageChanged();
132 }
133
134 private:
135 wxHtmlHelpFrame *m_Frame;
136 };
137
138
139
140 //---------------------------------------------------------------------------
141 // wxHtmlHelpFrame
142 //---------------------------------------------------------------------------
143
144 // Command IDs :
145 enum
146 {
147 //wxID_HTML_HELPFRAME = wxID_HIGHEST + 1,
148 wxID_HTML_PANEL = wxID_HIGHEST + 2,
149 wxID_HTML_BACK,
150 wxID_HTML_FORWARD,
151 wxID_HTML_UPNODE,
152 wxID_HTML_UP,
153 wxID_HTML_DOWN,
154 wxID_HTML_PRINT,
155 wxID_HTML_OPENFILE,
156 wxID_HTML_OPTIONS,
157 wxID_HTML_BOOKMARKSLIST,
158 wxID_HTML_BOOKMARKSADD,
159 wxID_HTML_BOOKMARKSREMOVE,
160 wxID_HTML_TREECTRL,
161 wxID_HTML_INDEXPAGE,
162 wxID_HTML_INDEXLIST,
163 wxID_HTML_INDEXTEXT,
164 wxID_HTML_INDEXBUTTON,
165 wxID_HTML_INDEXBUTTONALL,
166 wxID_HTML_NOTEBOOK,
167 wxID_HTML_SEARCHPAGE,
168 wxID_HTML_SEARCHTEXT,
169 wxID_HTML_SEARCHLIST,
170 wxID_HTML_SEARCHBUTTON,
171 wxID_HTML_SEARCHCHOICE,
172 wxID_HTML_COUNTINFO
173 };
174
175
176 IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpFrame, wxFrame)
177
178 wxHtmlHelpFrame::wxHtmlHelpFrame(wxWindow* parent, wxWindowID id, const wxString& title,
179 int style, wxHtmlHelpData* data)
180 {
181 Init(data);
182 Create(parent, id, title, style);
183 }
184
185 void wxHtmlHelpFrame::Init(wxHtmlHelpData* data)
186 {
187 if (data)
188 {
189 m_Data = data;
190 m_DataCreated = FALSE;
191 } else
192 {
193 m_Data = new wxHtmlHelpData();
194 m_DataCreated = TRUE;
195 }
196
197 m_ContentsBox = NULL;
198 m_IndexList = NULL;
199 m_IndexButton = NULL;
200 m_IndexButtonAll = NULL;
201 m_IndexText = NULL;
202 m_SearchList = NULL;
203 m_SearchButton = NULL;
204 m_SearchText = NULL;
205 m_SearchChoice = NULL;
206 m_IndexCountInfo = NULL;
207 m_Splitter = NULL;
208 m_NavigPan = NULL;
209 m_HtmlWin = NULL;
210 m_Bookmarks = NULL;
211 m_SearchCaseSensitive = NULL;
212 m_SearchWholeWords = NULL;
213
214 m_Config = NULL;
215 m_ConfigRoot = wxEmptyString;
216
217 m_Cfg.x = m_Cfg.y = 0;
218 m_Cfg.w = 700;
219 m_Cfg.h = 480;
220 m_Cfg.sashpos = 240;
221 m_Cfg.navig_on = TRUE;
222
223 m_NormalFonts = m_FixedFonts = NULL;
224 m_NormalFace = m_FixedFace = wxEmptyString;
225 m_FontSize = 1;
226
227 #if wxUSE_PRINTING_ARCHITECTURE
228 m_Printer = NULL;
229 #endif
230
231 m_PagesHash = NULL;
232 m_UpdateContents = TRUE;
233 m_helpController = (wxHelpControllerBase*) NULL;
234 }
235
236 // Create: builds the GUI components.
237 // with the style flag it's possible to toggle the toolbar, contents, index and search
238 // controls.
239 // m_HtmlWin will *always* be created, but it's important to realize that
240 // m_ContentsBox, m_IndexList, m_SearchList, m_SearchButton, m_SearchText and
241 // m_SearchButton may be NULL.
242 // moreover, if no contents, index or searchpage is needed, m_Splitter and
243 // m_NavigPan will be NULL too (with m_HtmlWin directly connected to the frame)
244
245 bool wxHtmlHelpFrame::Create(wxWindow* parent, wxWindowID id,
246 const wxString& WXUNUSED(title), int style)
247 {
248 m_hfStyle = style;
249
250 wxImageList *ContentsImageList = new wxImageList(16, 16);
251 ContentsImageList->Add(wxICON(wbook));
252 ContentsImageList->Add(wxICON(wfolder));
253 ContentsImageList->Add(wxICON(wpage));
254 ContentsImageList->Add(wxICON(whlproot));
255
256 // Do the config in two steps. We read the HtmlWindow customization after we
257 // create the window.
258 if (m_Config)
259 ReadCustomization(m_Config, m_ConfigRoot);
260
261 wxFrame::Create(parent, id, _("Help"), wxPoint(m_Cfg.x, m_Cfg.y), wxSize(m_Cfg.w, m_Cfg.h), wxDEFAULT_FRAME_STYLE, "wxHtmlHelp");
262
263 GetPosition(&m_Cfg.x, &m_Cfg.y);
264
265 SetIcon(wxICON(whelp));
266
267 int notebook_page = 0;
268
269 CreateStatusBar();
270
271 // toolbar?
272 if (style & (wxHF_TOOLBAR | wxHF_FLAT_TOOLBAR))
273 {
274 wxToolBar *toolBar = CreateToolBar(wxNO_BORDER | wxTB_HORIZONTAL |
275 wxTB_DOCKABLE |
276 (style & wxHF_FLAT_TOOLBAR ? wxTB_FLAT : 0));
277 toolBar->SetMargins( 2, 2 );
278 AddToolbarButtons(toolBar, style);
279 toolBar->Realize();
280 }
281
282 if (style & (wxHF_CONTENTS | wxHF_INDEX | wxHF_SEARCH))
283 {
284 // traditional help controller; splitter window with html page on the
285 // right and a notebook containing various pages on the left
286 m_Splitter = new wxSplitterWindow(this);
287
288 m_HtmlWin = new wxHtmlHelpHtmlWindow(this, m_Splitter);
289 m_NavigPan = new wxNotebook(m_Splitter, wxID_HTML_NOTEBOOK,
290 wxDefaultPosition, wxDefaultSize);
291 }
292 else
293 { // only html window, no notebook with index,contents etc
294 m_HtmlWin = new wxHtmlWindow(this);
295 }
296
297 m_HtmlWin->SetRelatedFrame(this, m_TitleFormat);
298 m_HtmlWin->SetRelatedStatusBar(0);
299 if (m_Config)
300 m_HtmlWin->ReadCustomization(m_Config, m_ConfigRoot);
301
302 // contents tree panel?
303 if (style & wxHF_CONTENTS)
304 {
305 wxWindow *dummy = new wxPanel(m_NavigPan, wxID_HTML_INDEXPAGE);
306
307 if (style & wxHF_BOOKMARKS)
308 {
309 wxLayoutConstraints *b1 = new wxLayoutConstraints;
310 wxBitmapButton *bmpbt = new wxBitmapButton(dummy, wxID_HTML_BOOKMARKSREMOVE, wxBITMAP(wbkdel), wxDefaultPosition, wxSize(20,20));
311
312 b1->top.SameAs (dummy, wxTop, 10);
313 b1->right.SameAs (dummy, wxRight, 10);
314 b1->height.AsIs();
315 b1->width.AsIs();
316 bmpbt->SetConstraints(b1);
317
318 wxLayoutConstraints *b2 = new wxLayoutConstraints;
319 wxBitmapButton *bmpbt2 = new wxBitmapButton(dummy, wxID_HTML_BOOKMARKSADD, wxBITMAP(wbkadd), wxDefaultPosition, wxSize(20,20));
320
321 b2->top.SameAs (dummy, wxTop, 10);
322 b2->right.LeftOf (bmpbt, 2);
323 b2->height.AsIs();
324 b2->width.AsIs();
325 bmpbt2->SetConstraints(b2);
326
327 #if wxUSE_TOOLTIPS
328 bmpbt->SetToolTip(_("Remove current page from bookmarks"));
329 bmpbt2->SetToolTip(_("Add current page to bookmarks"));
330 #endif //wxUSE_TOOLTIPS
331
332 wxLayoutConstraints *b3 = new wxLayoutConstraints;
333 m_Bookmarks = new wxComboBox(dummy, wxID_HTML_BOOKMARKSLIST, wxEmptyString,
334 wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY | wxCB_SORT);
335 m_Bookmarks->Append(_("(bookmarks)"));
336 for (unsigned i = 0; i < m_BookmarksNames.GetCount(); i++)
337 m_Bookmarks->Append(m_BookmarksNames[i]);
338 m_Bookmarks->SetSelection(0);
339
340 b3->centreY.SameAs (bmpbt2, wxCentreY);
341 b3->left.SameAs (dummy, wxLeft, 10);
342 b3->right.LeftOf (bmpbt2, 5);
343 b3->height.AsIs();
344 m_Bookmarks->SetConstraints(b3);
345
346
347 wxLayoutConstraints *b4 = new wxLayoutConstraints;
348 m_ContentsBox = new wxTreeCtrl(dummy, wxID_HTML_TREECTRL,
349 wxDefaultPosition, wxDefaultSize,
350 #ifdef __WXMAC__
351 wxSUNKEN_BORDER|wxTR_MAC_BUTTONS|wxTR_NO_LINES|wxTR_ROW_LINES );
352 #else
353 wxSUNKEN_BORDER|wxTR_HAS_BUTTONS );
354 #endif
355 m_ContentsBox->AssignImageList(ContentsImageList);
356
357 b4->top.Below (m_Bookmarks, 10);
358 b4->left.SameAs (dummy, wxLeft, 0);
359 b4->right.SameAs (dummy, wxRight, 0);
360 b4->bottom.SameAs (dummy, wxBottom, 0);
361 m_ContentsBox->SetConstraints(b4);
362
363 dummy->SetAutoLayout(TRUE);
364 dummy->Layout();
365
366 m_NavigPan->AddPage(dummy, _("Contents"));
367 }
368
369 else
370 {
371 m_ContentsBox = new wxTreeCtrl(m_NavigPan, wxID_HTML_TREECTRL,
372 wxDefaultPosition, wxDefaultSize,
373 wxTR_HAS_BUTTONS | wxSUNKEN_BORDER);
374 m_ContentsBox->AssignImageList(ContentsImageList);
375 m_NavigPan->AddPage(m_ContentsBox, _("Contents"));
376 }
377
378 m_ContentsPage = notebook_page++;
379 }
380
381 // index listbox panel?
382 if (style & wxHF_INDEX)
383 {
384 wxWindow *dummy = new wxPanel(m_NavigPan, wxID_HTML_INDEXPAGE);
385
386 wxLayoutConstraints *b1 = new wxLayoutConstraints;
387 m_IndexText = new wxTextCtrl(dummy, wxID_HTML_INDEXTEXT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
388 b1->top.SameAs (dummy, wxTop, 10);
389 b1->left.SameAs (dummy, wxLeft, 10);
390 b1->right.SameAs (dummy, wxRight, 10);
391 b1->height.AsIs();
392 m_IndexText->SetConstraints(b1);
393
394 wxLayoutConstraints *b4 = new wxLayoutConstraints;
395 m_IndexButtonAll = new wxButton(dummy, wxID_HTML_INDEXBUTTONALL, _("Show all"));
396
397 b4->top.Below (m_IndexText, 10);
398 b4->right.SameAs (dummy, wxRight, 10);
399 b4->width.AsIs();
400 b4->height.AsIs();
401 m_IndexButtonAll->SetConstraints(b4);
402
403 wxLayoutConstraints *b2 = new wxLayoutConstraints;
404 m_IndexButton = new wxButton(dummy, wxID_HTML_INDEXBUTTON, _("Find"));
405 b2->top.Below (m_IndexText, 10);
406 b2->right.LeftOf (m_IndexButtonAll, 10);
407 b2->width.AsIs();
408 b2->height.AsIs();
409 m_IndexButton->SetConstraints(b2);
410
411 wxLayoutConstraints *b5 = new wxLayoutConstraints;
412 m_IndexCountInfo = new wxStaticText(dummy, wxID_HTML_COUNTINFO, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
413
414 b5->top.Below (m_IndexButton, 5);
415 b5->right.SameAs (dummy, wxRight, 10);
416 b5->left.SameAs (dummy, wxLeft, 10);
417 b5->height.AsIs();
418 m_IndexCountInfo->SetConstraints(b5);
419
420 wxLayoutConstraints *b3 = new wxLayoutConstraints;
421 m_IndexList = new wxListBox(dummy, wxID_HTML_INDEXLIST, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE);
422 b3->top.Below (m_IndexCountInfo, 5);
423 b3->left.SameAs (dummy, wxLeft, 0);
424 b3->right.SameAs (dummy, wxRight, 0);
425 b3->bottom.SameAs (dummy, wxBottom, 0);
426 m_IndexList->SetConstraints(b3);
427
428 #if wxUSE_TOOLTIPS
429 m_IndexButtonAll->SetToolTip(_("Show all items in index"));
430 m_IndexButton->SetToolTip(_("Display all index items that contain given substring. Search is case insensitive."));
431 #endif //wxUSE_TOOLTIPS
432
433 dummy->SetAutoLayout(TRUE);
434 dummy->Layout();
435
436 m_NavigPan->AddPage(dummy, _("Index"));
437 m_IndexPage = notebook_page++;
438 }
439
440 // search list panel?
441 if (style & wxHF_SEARCH)
442 {
443 wxWindow *dummy = new wxPanel(m_NavigPan, wxID_HTML_SEARCHPAGE);
444
445 wxLayoutConstraints *b1 = new wxLayoutConstraints;
446 m_SearchText = new wxTextCtrl(dummy, wxID_HTML_SEARCHTEXT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
447 b1->top.SameAs (dummy, wxTop, 10);
448 b1->left.SameAs (dummy, wxLeft, 10);
449 b1->right.SameAs (dummy, wxRight, 10);
450 b1->height.AsIs();
451 m_SearchText->SetConstraints(b1);
452
453 wxLayoutConstraints *b4 = new wxLayoutConstraints;
454 m_SearchChoice = new wxChoice(dummy, wxID_HTML_SEARCHCHOICE, wxDefaultPosition,
455 wxDefaultSize);
456 b4->top.Below (m_SearchText, 10);
457 b4->left.SameAs (dummy, wxLeft, 10);
458 b4->right.SameAs (dummy, wxRight, 10);
459 b4->height.AsIs();
460 m_SearchChoice->SetConstraints(b4);
461
462 wxLayoutConstraints *b5 = new wxLayoutConstraints;
463 m_SearchCaseSensitive = new wxCheckBox(dummy, -1, _("Case sensitive"));
464 b5->top.Below (m_SearchChoice, 10);
465 b5->left.SameAs (dummy, wxLeft, 10);
466 b5->width.AsIs();
467 b5->height.AsIs ();
468 m_SearchCaseSensitive->SetConstraints(b5);
469
470 wxLayoutConstraints *b6 = new wxLayoutConstraints;
471 m_SearchWholeWords = new wxCheckBox(dummy, -1, _("Whole words only"));
472 b6->top.Below (m_SearchCaseSensitive, 0);
473 b6->left.SameAs (dummy, wxLeft, 10);
474 b6->width.AsIs();
475 b6->height.AsIs ();
476 m_SearchWholeWords->SetConstraints(b6);
477
478 wxLayoutConstraints *b2 = new wxLayoutConstraints;
479 m_SearchButton = new wxButton(dummy, wxID_HTML_SEARCHBUTTON, _("Search"));
480 #if wxUSE_TOOLTIPS
481 m_SearchButton->SetToolTip(_("Search contents of help book(s) for all occurences of the text you typed above"));
482 #endif //wxUSE_TOOLTIPS
483 b2->top.Below (m_SearchWholeWords, 0);
484 b2->right.SameAs (dummy, wxRight, 10);
485 b2->width.AsIs();
486 b2->height.AsIs();
487 m_SearchButton->SetConstraints(b2);
488
489 wxLayoutConstraints *b3 = new wxLayoutConstraints;
490 m_SearchList = new wxListBox(dummy, wxID_HTML_SEARCHLIST, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE);
491 b3->top.Below (m_SearchButton, 10);
492 b3->left.SameAs (dummy, wxLeft, 0);
493 b3->right.SameAs (dummy, wxRight, 0);
494 b3->bottom.SameAs (dummy, wxBottom, 0);
495 m_SearchList->SetConstraints(b3);
496
497 dummy->SetAutoLayout(TRUE);
498 dummy->Layout();
499 m_NavigPan->AddPage(dummy, _("Search"));
500 m_SearchPage = notebook_page++;
501 }
502 m_HtmlWin->Show(TRUE);
503
504 RefreshLists();
505
506 // showtime
507 if (m_NavigPan && m_Splitter)
508 {
509 m_Splitter->SetMinimumPaneSize(20);
510 if (m_Cfg.navig_on)
511 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
512 else
513 {
514 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
515 m_Splitter->Unsplit();
516 }
517
518 if (m_Cfg.navig_on)
519 {
520 m_NavigPan->Show(TRUE);
521 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
522 }
523 else
524 {
525 m_NavigPan->Show(FALSE);
526 m_Splitter->Initialize(m_HtmlWin);
527 }
528 }
529 return TRUE;
530 }
531
532 wxHtmlHelpFrame::~wxHtmlHelpFrame()
533 {
534 // PopEventHandler(); // wxhtmlhelpcontroller (not any more!)
535 if (m_DataCreated)
536 delete m_Data;
537 if (m_NormalFonts) delete m_NormalFonts;
538 if (m_FixedFonts) delete m_FixedFonts;
539 if (m_PagesHash) delete m_PagesHash;
540 }
541
542
543 void wxHtmlHelpFrame::AddToolbarButtons(wxToolBar *toolBar, int style)
544 {
545 wxBitmap wpanelBitmap = wxBITMAP(wpanel);
546 wxBitmap wbackBitmap = wxBITMAP(wback);
547 wxBitmap wforwardBitmap = wxBITMAP(wforward);
548 wxBitmap wupnodeBitmap = wxBITMAP(wupnode);
549 wxBitmap wupBitmap = wxBITMAP(wup);
550 wxBitmap wdownBitmap = wxBITMAP(wdown);
551 wxBitmap wopenBitmap = wxBITMAP(wopen);
552 wxBitmap wprintBitmap = wxBITMAP(wprint);
553 wxBitmap woptionsBitmap = wxBITMAP(woptions);
554
555 wxASSERT_MSG( (wpanelBitmap.Ok() && wbackBitmap.Ok() &&
556 wforwardBitmap.Ok() && wupnodeBitmap.Ok() &&
557 wupBitmap.Ok() && wdownBitmap.Ok() &&
558 wopenBitmap.Ok() && wprintBitmap.Ok() &&
559 woptionsBitmap.Ok()),
560 wxT("One or more HTML help frame toolbar bitmap could not be loaded.")) ;
561
562
563 toolBar->AddTool(wxID_HTML_PANEL, wpanelBitmap, wxNullBitmap,
564 FALSE, -1, -1, (wxObject *) NULL,
565 _("Show/hide navigation panel"));
566
567 toolBar->AddSeparator();
568 toolBar->AddTool(wxID_HTML_BACK, wbackBitmap, wxNullBitmap,
569 FALSE, -1, -1, (wxObject *) NULL,
570 _("Go back"));
571 toolBar->AddTool(wxID_HTML_FORWARD, wforwardBitmap, wxNullBitmap,
572 FALSE, -1, -1, (wxObject *) NULL,
573 _("Go forward"));
574 toolBar->AddSeparator();
575
576 toolBar->AddTool(wxID_HTML_UPNODE, wupnodeBitmap, wxNullBitmap,
577 FALSE, -1, -1, (wxObject *) NULL,
578 _("Go one level up in document hierarchy"));
579 toolBar->AddTool(wxID_HTML_UP, wupBitmap, wxNullBitmap,
580 FALSE, -1, -1, (wxObject *) NULL,
581 _("Previous page"));
582 toolBar->AddTool(wxID_HTML_DOWN, wdownBitmap, wxNullBitmap,
583 FALSE, -1, -1, (wxObject *) NULL,
584 _("Next page"));
585
586 if ((style & wxHF_PRINT) || (style & wxHF_OPEN_FILES))
587 toolBar->AddSeparator();
588
589 if (style & wxHF_OPEN_FILES)
590 toolBar->AddTool(wxID_HTML_OPENFILE, wopenBitmap, wxNullBitmap,
591 FALSE, -1, -1, (wxObject *) NULL,
592 _("Open HTML document"));
593
594 #if wxUSE_PRINTING_ARCHITECTURE
595 if (style & wxHF_PRINT)
596 toolBar->AddTool(wxID_HTML_PRINT, wprintBitmap, wxNullBitmap,
597 FALSE, -1, -1, (wxObject *) NULL,
598 _("Print this page"));
599 #endif
600
601 toolBar->AddSeparator();
602 toolBar->AddTool(wxID_HTML_OPTIONS, woptionsBitmap, wxNullBitmap,
603 FALSE, -1, -1, (wxObject *) NULL,
604 _("Display options dialog"));
605 }
606
607
608 void wxHtmlHelpFrame::SetTitleFormat(const wxString& format)
609 {
610 if (m_HtmlWin)
611 m_HtmlWin->SetRelatedFrame(this, format);
612 m_TitleFormat = format;
613 }
614
615
616 bool wxHtmlHelpFrame::Display(const wxString& x)
617 {
618 wxString url = m_Data->FindPageByName(x);
619 if (!url.IsEmpty())
620 {
621 m_HtmlWin->LoadPage(url);
622 NotifyPageChanged();
623 return TRUE;
624 }
625 return FALSE;
626 }
627
628 bool wxHtmlHelpFrame::Display(const int id)
629 {
630 wxString url = m_Data->FindPageById(id);
631 if (!url.IsEmpty())
632 {
633 m_HtmlWin->LoadPage(url);
634 NotifyPageChanged();
635 return TRUE;
636 }
637 return FALSE;
638 }
639
640
641
642 bool wxHtmlHelpFrame::DisplayContents()
643 {
644 if (! m_ContentsBox)
645 return FALSE;
646 if (!m_Splitter->IsSplit())
647 {
648 m_NavigPan->Show(TRUE);
649 m_HtmlWin->Show(TRUE);
650 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
651 m_Cfg.navig_on = TRUE;
652 }
653 m_NavigPan->SetSelection(0);
654 if (m_Data->GetBookRecArray().GetCount() > 0)
655 {
656 wxHtmlBookRecord& book = m_Data->GetBookRecArray()[0];
657 if (!book.GetStart().IsEmpty())
658 m_HtmlWin->LoadPage(book.GetFullPath(book.GetStart()));
659 }
660 return TRUE;
661 }
662
663
664
665 bool wxHtmlHelpFrame::DisplayIndex()
666 {
667 if (! m_IndexList)
668 return FALSE;
669 if (!m_Splitter->IsSplit())
670 {
671 m_NavigPan->Show(TRUE);
672 m_HtmlWin->Show(TRUE);
673 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
674 }
675 m_NavigPan->SetSelection(1);
676 if (m_Data->GetBookRecArray().GetCount() > 0)
677 {
678 wxHtmlBookRecord& book = m_Data->GetBookRecArray()[0];
679 if (!book.GetStart().IsEmpty())
680 m_HtmlWin->LoadPage(book.GetFullPath(book.GetStart()));
681 }
682 return TRUE;
683 }
684
685
686
687 bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword)
688 {
689 if (! (m_SearchList && m_SearchButton && m_SearchText && m_SearchChoice))
690 return FALSE;
691
692 int foundcnt = 0, curi;
693 wxString foundstr;
694 wxString book = wxEmptyString;
695
696 if (!m_Splitter->IsSplit())
697 {
698 m_NavigPan->Show(TRUE);
699 m_HtmlWin->Show(TRUE);
700 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
701 }
702 m_NavigPan->SetSelection(m_SearchPage);
703 m_SearchList->Clear();
704 m_SearchText->SetValue(keyword);
705 m_SearchButton->Enable(FALSE);
706
707 if (m_SearchChoice->GetSelection() != 0)
708 book = m_SearchChoice->GetStringSelection();
709
710 wxHtmlSearchStatus status(m_Data, keyword,
711 m_SearchCaseSensitive->GetValue(), m_SearchWholeWords->GetValue(),
712 book);
713
714 wxProgressDialog progress(_("Searching..."), _("No matching page found yet"),
715 status.GetMaxIndex(), this,
716 wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_AUTO_HIDE);
717
718 while (status.IsActive())
719 {
720 curi = status.GetCurIndex();
721 if (curi % 32 == 0 && progress.Update(curi) == FALSE)
722 break;
723 if (status.Search())
724 {
725 foundstr.Printf(_("Found %i matches"), ++foundcnt);
726 progress.Update(status.GetCurIndex(), foundstr);
727 m_SearchList->Append(status.GetName(), status.GetContentsItem());
728 }
729 }
730
731 m_SearchButton->Enable(TRUE);
732 m_SearchText->SetSelection(0, keyword.Length());
733 m_SearchText->SetFocus();
734 if (foundcnt)
735 {
736 wxHtmlContentsItem *it = (wxHtmlContentsItem*) m_SearchList->GetClientData(0);
737 if (it)
738 {
739 m_HtmlWin->LoadPage(it->GetFullPath());
740 NotifyPageChanged();
741 }
742 }
743 return (foundcnt > 0);
744 }
745
746 void wxHtmlHelpFrame::CreateContents()
747 {
748 if (! m_ContentsBox)
749 return ;
750
751 m_ContentsBox->Clear();
752
753 if (m_PagesHash) delete m_PagesHash;
754 m_PagesHash = new wxHashTable(wxKEY_STRING, 2 * m_Data->GetContentsCnt());
755 m_PagesHash->DeleteContents(TRUE);
756
757 int cnt = m_Data->GetContentsCnt();
758 int i;
759 size_t booksCnt = m_Data->GetBookRecArray().GetCount();
760
761 wxHtmlContentsItem *it;
762
763 const int MAX_ROOTS = 64;
764 wxTreeItemId roots[MAX_ROOTS];
765 // VS: this array holds information about whether we've set item icon at
766 // given level. This is neccessary because m_Data has flat structure
767 // and there's no way of recognizing if some item has subitems or not.
768 // We set the icon later: when we find an item with level=n, we know
769 // that the last item with level=n-1 was folder with subitems, so we
770 // set its icon accordingly
771 bool imaged[MAX_ROOTS];
772 m_ContentsBox->DeleteAllItems();
773
774 // Don't show (Help) root if there's only one boook
775 if (booksCnt > 1)
776 {
777 roots[0] = m_ContentsBox->AddRoot(_("(Help)"));
778 m_ContentsBox->SetItemImage(roots[0], IMG_RootFolder);
779 m_ContentsBox->SetItemSelectedImage(roots[0], IMG_RootFolder);
780 imaged[0] = TRUE;
781 }
782
783 for (it = m_Data->GetContents(), i = 0; i < cnt; i++, it++)
784 {
785 // Handle books:
786 if (it->m_Level == 0)
787 {
788 // special case, only one book, make it tree's root:
789 if (booksCnt == 1)
790 {
791 roots[0] = roots[1] = m_ContentsBox->AddRoot(
792 it->m_Name, IMG_Book, -1,
793 new wxHtmlHelpTreeItemData(i));
794 imaged[0] = imaged[1] = TRUE;
795 m_ContentsBox->SetItemBold(roots[1], TRUE);
796 }
797 // multiple books:
798 else
799 {
800 if (m_hfStyle & wxHF_MERGE_BOOKS)
801 // VS: we don't want book nodes, books' content should
802 // appear under tree's root. This line will create "fake"
803 // record about book node so that the rest of this look
804 // will believe there really _is_ book node and will
805 // behave correctly.
806 roots[1] = roots[0];
807 else
808 {
809 roots[1] = m_ContentsBox->AppendItem(roots[0],
810 it->m_Name, IMG_Book, -1,
811 new wxHtmlHelpTreeItemData(i));
812 m_ContentsBox->SetItemBold(roots[1], TRUE);
813 }
814 imaged[1] = TRUE;
815 }
816 }
817 // ...and their contents:
818 else
819 {
820 roots[it->m_Level + 1] = m_ContentsBox->AppendItem(
821 roots[it->m_Level], it->m_Name, IMG_Page,
822 -1, new wxHtmlHelpTreeItemData(i));
823 imaged[it->m_Level + 1] = FALSE;
824 }
825
826 m_PagesHash->Put(it->GetFullPath(),
827 new wxHtmlHelpHashData(i, roots[it->m_Level + 1]));
828
829 // Set the icon for the node one level up in the hiearachy,
830 // unless already done (see comment above imaged[] declaration)
831 if (!imaged[it->m_Level])
832 {
833 int image = IMG_Folder;
834 if (m_hfStyle & wxHF_ICONS_BOOK)
835 image = IMG_Book;
836 else if (m_hfStyle & wxHF_ICONS_BOOK_CHAPTER)
837 image = (it->m_Level == 1) ? IMG_Book : IMG_Folder;
838 m_ContentsBox->SetItemImage(roots[it->m_Level], image);
839 m_ContentsBox->SetItemSelectedImage(roots[it->m_Level], image);
840 imaged[it->m_Level] = TRUE;
841 }
842 }
843
844 m_ContentsBox->Expand(roots[0]);
845 }
846
847
848 void wxHtmlHelpFrame::CreateIndex()
849 {
850 if (! m_IndexList)
851 return ;
852
853 m_IndexList->Clear();
854
855 int cnt = m_Data->GetIndexCnt();
856
857 wxString cnttext;
858 if (cnt > INDEX_IS_SMALL) cnttext.Printf(_("%i of %i"), 0, cnt);
859 else cnttext.Printf(_("%i of %i"), cnt, cnt);
860 m_IndexCountInfo->SetLabel(cnttext);
861 if (cnt > INDEX_IS_SMALL) return;
862
863 wxHtmlContentsItem* index = m_Data->GetIndex();
864
865 for (int i = 0; i < cnt; i++)
866 m_IndexList->Append(index[i].m_Name, (char*)(index + i));
867 }
868
869 void wxHtmlHelpFrame::CreateSearch()
870 {
871 if (! (m_SearchList && m_SearchChoice))
872 return ;
873 m_SearchList->Clear();
874 m_SearchChoice->Clear();
875 m_SearchChoice->Append(_("Search in all books"));
876 const wxHtmlBookRecArray& bookrec = m_Data->GetBookRecArray();
877 int i, cnt = bookrec.GetCount();
878 for (i = 0; i < cnt; i++)
879 m_SearchChoice->Append(bookrec[i].GetTitle());
880 m_SearchChoice->SetSelection(0);
881 }
882
883
884 void wxHtmlHelpFrame::RefreshLists()
885 {
886 CreateContents();
887 CreateIndex();
888 CreateSearch();
889 }
890
891 void wxHtmlHelpFrame::ReadCustomization(wxConfigBase *cfg, const wxString& path)
892 {
893 wxString oldpath;
894 wxString tmp;
895
896 if (path != wxEmptyString)
897 {
898 oldpath = cfg->GetPath();
899 cfg->SetPath(_T("/") + path);
900 }
901
902 m_Cfg.navig_on = cfg->Read(wxT("hcNavigPanel"), m_Cfg.navig_on) != 0;
903 m_Cfg.sashpos = cfg->Read(wxT("hcSashPos"), m_Cfg.sashpos);
904 m_Cfg.x = cfg->Read(wxT("hcX"), m_Cfg.x);
905 m_Cfg.y = cfg->Read(wxT("hcY"), m_Cfg.y);
906 m_Cfg.w = cfg->Read(wxT("hcW"), m_Cfg.w);
907 m_Cfg.h = cfg->Read(wxT("hcH"), m_Cfg.h);
908
909 m_FixedFace = cfg->Read(wxT("hcFixedFace"), m_FixedFace);
910 m_NormalFace = cfg->Read(wxT("hcNormalFace"), m_NormalFace);
911 m_FontSize = cfg->Read(wxT("hcFontSize"), m_FontSize);
912
913 {
914 int i;
915 int cnt;
916 wxString val, s;
917
918 cnt = cfg->Read(wxT("hcBookmarksCnt"), 0L);
919 if (cnt != 0)
920 {
921 m_BookmarksNames.Clear();
922 m_BookmarksPages.Clear();
923 if (m_Bookmarks)
924 {
925 m_Bookmarks->Clear();
926 m_Bookmarks->Append(_("(bookmarks)"));
927 }
928
929 for (i = 0; i < cnt; i++)
930 {
931 val.Printf(wxT("hcBookmark_%i"), i);
932 s = cfg->Read(val);
933 m_BookmarksNames.Add(s);
934 if (m_Bookmarks) m_Bookmarks->Append(s);
935 val.Printf(wxT("hcBookmark_%i_url"), i);
936 s = cfg->Read(val);
937 m_BookmarksPages.Add(s);
938 }
939 }
940 }
941
942 if (m_HtmlWin)
943 m_HtmlWin->ReadCustomization(cfg);
944
945 if (path != wxEmptyString)
946 cfg->SetPath(oldpath);
947 }
948
949 void wxHtmlHelpFrame::WriteCustomization(wxConfigBase *cfg, const wxString& path)
950 {
951 wxString oldpath;
952 wxString tmp;
953
954 if (path != wxEmptyString)
955 {
956 oldpath = cfg->GetPath();
957 cfg->SetPath(_T("/") + path);
958 }
959
960 cfg->Write(wxT("hcNavigPanel"), m_Cfg.navig_on);
961 cfg->Write(wxT("hcSashPos"), (long)m_Cfg.sashpos);
962 cfg->Write(wxT("hcX"), (long)m_Cfg.x);
963 cfg->Write(wxT("hcY"), (long)m_Cfg.y);
964 cfg->Write(wxT("hcW"), (long)m_Cfg.w);
965 cfg->Write(wxT("hcH"), (long)m_Cfg.h);
966 cfg->Write(wxT("hcFixedFace"), m_FixedFace);
967 cfg->Write(wxT("hcNormalFace"), m_NormalFace);
968 cfg->Write(wxT("hcFontSize"), (long)m_FontSize);
969
970 if (m_Bookmarks)
971 {
972 int i;
973 int cnt = m_BookmarksNames.GetCount();
974 wxString val;
975
976 cfg->Write(wxT("hcBookmarksCnt"), (long)cnt);
977 for (i = 0; i < cnt; i++)
978 {
979 val.Printf(wxT("hcBookmark_%i"), i);
980 cfg->Write(val, m_BookmarksNames[i]);
981 val.Printf(wxT("hcBookmark_%i_url"), i);
982 cfg->Write(val, m_BookmarksPages[i]);
983 }
984 }
985
986 if (m_HtmlWin)
987 m_HtmlWin->WriteCustomization(cfg);
988
989 if (path != wxEmptyString)
990 cfg->SetPath(oldpath);
991 }
992
993
994
995
996
997 static void SetFontsToHtmlWin(wxHtmlWindow *win, wxString scalf, wxString fixf, int size)
998 {
999 static int f_sizes[5][7] =
1000 {
1001 { 6, 7, 9, 12, 14, 16, 19},
1002 { 8, 9, 12, 14, 16, 19, 22},
1003 {10, 12, 14, 16, 19, 24, 32},
1004 {14, 16, 18, 24, 32, 38, 45},
1005 {16, 20, 24, 32, 38, 45, 50}
1006 };
1007
1008 win->SetFonts(scalf, fixf, f_sizes[size]);
1009 }
1010
1011
1012 class wxHtmlHelpFrameOptionsDialog : public wxDialog
1013 {
1014 public:
1015 wxComboBox *NormalFont, *FixedFont;
1016 wxRadioBox *RadioBox;
1017 wxHtmlWindow *TestWin;
1018
1019 wxHtmlHelpFrameOptionsDialog(wxWindow *parent) : wxDialog(parent, -1, wxString(_("Help Browser Options")))
1020 {
1021 wxString choices[5] = {_("very small"), _("small"), _("medium"), _("large"), _("very large")};
1022 wxBoxSizer *topsizer, *sizer, *sizer2;
1023
1024 topsizer = new wxBoxSizer(wxVERTICAL);
1025
1026 sizer = new wxBoxSizer(wxHORIZONTAL);
1027
1028 sizer2 = new wxStaticBoxSizer( new wxStaticBox(this, -1, _("Normal font:")), wxVERTICAL);
1029 sizer2->Add(NormalFont = new wxComboBox(this, -1, wxEmptyString, wxDefaultPosition,
1030 wxSize(200, 200),
1031 0, NULL, wxCB_DROPDOWN | wxCB_READONLY),
1032 1, wxEXPAND | wxLEFT | wxRIGHT, 10);
1033
1034 sizer->Add(sizer2, 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10);
1035
1036 sizer2 = new wxStaticBoxSizer( new wxStaticBox(this, -1, _("Fixed font:")), wxVERTICAL);
1037 sizer2->Add(FixedFont = new wxComboBox(this, -1, wxEmptyString, wxDefaultPosition,
1038 wxSize(200, 200),
1039 0, NULL, wxCB_DROPDOWN | wxCB_READONLY),
1040 1, wxEXPAND | wxLEFT | wxRIGHT, 10);
1041
1042 sizer->Add(sizer2, 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10);
1043
1044 topsizer->Add(sizer);
1045
1046 topsizer->Add(RadioBox = new wxRadioBox(this, -1, _("Font size:"),
1047 wxDefaultPosition, wxDefaultSize, 5, choices, 5),
1048 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10);
1049
1050 topsizer->Add(new wxStaticText(this, -1, _("Preview:")),
1051 0, wxLEFT | wxTOP, 10);
1052 topsizer->Add(TestWin = new wxHtmlWindow(this, -1, wxDefaultPosition, wxSize(-1, 150)),
1053 1, wxEXPAND | wxLEFT|wxTOP|wxRIGHT, 10);
1054
1055 sizer = new wxBoxSizer(wxHORIZONTAL);
1056 sizer->Add(new wxButton(this, wxID_OK, _("OK")), 0, wxALL, 10);
1057 sizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 10);
1058 topsizer->Add(sizer, 0, wxALIGN_RIGHT);
1059
1060 SetAutoLayout(TRUE);
1061 SetSizer(topsizer);
1062 topsizer->Fit(this);
1063 Centre(wxBOTH);
1064 }
1065
1066
1067 void UpdateTestWin()
1068 {
1069 wxBusyCursor bcur;
1070 SetFontsToHtmlWin(TestWin,
1071 NormalFont->GetStringSelection(),
1072 FixedFont->GetStringSelection(),
1073 RadioBox->GetSelection());
1074 TestWin->SetPage(_(
1075 "<html><body>\
1076 Normal face<br>(and <u>underlined</u>. <i>Italic face.</i> \
1077 <b>Bold face.</b> <b><i>Bold italic face.</i></b><br>\
1078 <font size=-2>font size -2</font><br>\
1079 <font size=-1>font size -1</font><br>\
1080 <font size=+0>font size +0</font><br>\
1081 <font size=+1>font size +1</font><br>\
1082 <font size=+2>font size +2</font><br>\
1083 <font size=+3>font size +3</font><br>\
1084 <font size=+4>font size +4</font><br>\
1085 \
1086 <p><tt>Fixed size face.<br> <b>bold</b> <i>italic</i> \
1087 <b><i>bold italic <u>underlined</u></i></b><br>\
1088 <font size=-2>font size -2</font><br>\
1089 <font size=-1>font size -1</font><br>\
1090 <font size=+0>font size +0</font><br>\
1091 <font size=+1>font size +1</font><br>\
1092 <font size=+2>font size +2</font><br>\
1093 <font size=+3>font size +3</font><br>\
1094 <font size=+4>font size +4</font></tt>\
1095 </body></html>"
1096 ));
1097 }
1098
1099 void OnUpdate(wxCommandEvent& WXUNUSED(event))
1100 {
1101 UpdateTestWin();
1102 }
1103
1104 DECLARE_EVENT_TABLE()
1105 };
1106
1107 BEGIN_EVENT_TABLE(wxHtmlHelpFrameOptionsDialog, wxDialog)
1108 EVT_COMBOBOX(-1, wxHtmlHelpFrameOptionsDialog::OnUpdate)
1109 EVT_RADIOBOX(-1, wxHtmlHelpFrameOptionsDialog::OnUpdate)
1110 END_EVENT_TABLE()
1111
1112
1113 void wxHtmlHelpFrame::OptionsDialog()
1114 {
1115 wxHtmlHelpFrameOptionsDialog dlg(this);
1116 unsigned i;
1117
1118 if (m_NormalFonts == NULL)
1119 {
1120 wxFontEnumerator enu;
1121 enu.EnumerateFacenames();
1122 m_NormalFonts = new wxArrayString;
1123 *m_NormalFonts = *enu.GetFacenames();
1124 m_NormalFonts->Sort();
1125 }
1126 if (m_FixedFonts == NULL)
1127 {
1128 wxFontEnumerator enu;
1129 enu.EnumerateFacenames(wxFONTENCODING_SYSTEM, TRUE);
1130 m_FixedFonts = new wxArrayString;
1131 *m_FixedFonts = *enu.GetFacenames();
1132 m_FixedFonts->Sort();
1133 }
1134
1135 for (i = 0; i < m_NormalFonts->GetCount(); i++)
1136 dlg.NormalFont->Append((*m_NormalFonts)[i]);
1137 for (i = 0; i < m_FixedFonts->GetCount(); i++)
1138 dlg.FixedFont->Append((*m_FixedFonts)[i]);
1139 if (!m_NormalFace.IsEmpty()) dlg.NormalFont->SetStringSelection(m_NormalFace);
1140 else dlg.NormalFont->SetSelection(0);
1141 if (!m_FixedFace.IsEmpty()) dlg.FixedFont->SetStringSelection(m_FixedFace);
1142 else dlg.FixedFont->SetSelection(0);
1143 dlg.RadioBox->SetSelection(m_FontSize);
1144 dlg.UpdateTestWin();
1145
1146 if (dlg.ShowModal() == wxID_OK)
1147 {
1148 m_NormalFace = dlg.NormalFont->GetStringSelection();
1149 m_FixedFace = dlg.FixedFont->GetStringSelection();
1150 m_FontSize = dlg.RadioBox->GetSelection();
1151 SetFontsToHtmlWin(m_HtmlWin, m_NormalFace, m_FixedFace, m_FontSize);
1152 }
1153 }
1154
1155
1156
1157 void wxHtmlHelpFrame::NotifyPageChanged()
1158 {
1159 if (m_UpdateContents && m_PagesHash)
1160 {
1161 wxString an = m_HtmlWin->GetOpenedAnchor();
1162 wxHtmlHelpHashData *ha;
1163 if (an.IsEmpty())
1164 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage());
1165 else
1166 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an);
1167 if (ha)
1168 {
1169 bool olduc = m_UpdateContents;
1170 m_UpdateContents = FALSE;
1171 m_ContentsBox->SelectItem(ha->m_Id);
1172 m_ContentsBox->EnsureVisible(ha->m_Id);
1173 m_UpdateContents = olduc;
1174 }
1175 }
1176 }
1177
1178
1179
1180 /*
1181 EVENT HANDLING :
1182 */
1183
1184
1185 void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event)
1186 {
1187 switch (event.GetId())
1188 {
1189 case wxID_HTML_BACK :
1190 m_HtmlWin->HistoryBack();
1191 NotifyPageChanged();
1192 break;
1193
1194 case wxID_HTML_FORWARD :
1195 m_HtmlWin->HistoryForward();
1196 NotifyPageChanged();
1197 break;
1198
1199 case wxID_HTML_UP :
1200 if (m_PagesHash)
1201 {
1202 wxString an = m_HtmlWin->GetOpenedAnchor();
1203 wxHtmlHelpHashData *ha;
1204 if (an.IsEmpty())
1205 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage());
1206 else
1207 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an);
1208 if (ha && ha->m_Index > 0)
1209 {
1210 wxHtmlContentsItem *it = m_Data->GetContents() + (ha->m_Index - 1);
1211 if (it->m_Page[0] != 0)
1212 {
1213 m_HtmlWin->LoadPage(it->GetFullPath());
1214 NotifyPageChanged();
1215 }
1216 }
1217 }
1218 break;
1219
1220 case wxID_HTML_UPNODE :
1221 if (m_PagesHash)
1222 {
1223 wxString an = m_HtmlWin->GetOpenedAnchor();
1224 wxHtmlHelpHashData *ha;
1225 if (an.IsEmpty())
1226 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage());
1227 else
1228 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an);
1229 if (ha && ha->m_Index > 0)
1230 {
1231 int level = m_Data->GetContents()[ha->m_Index].m_Level - 1;
1232 wxHtmlContentsItem *it;
1233 int ind = ha->m_Index - 1;
1234
1235 it = m_Data->GetContents() + ind;
1236 while (ind >= 0 && it->m_Level != level) ind--, it--;
1237 if (ind >= 0)
1238 {
1239 if (it->m_Page[0] != 0)
1240 {
1241 m_HtmlWin->LoadPage(it->GetFullPath());
1242 NotifyPageChanged();
1243 }
1244 }
1245 }
1246 }
1247 break;
1248
1249 case wxID_HTML_DOWN :
1250 if (m_PagesHash)
1251 {
1252 wxString an = m_HtmlWin->GetOpenedAnchor();
1253 wxString adr;
1254 wxHtmlHelpHashData *ha;
1255
1256 if (an.IsEmpty()) adr = m_HtmlWin->GetOpenedPage();
1257 else adr = m_HtmlWin->GetOpenedPage() + wxT("#") + an;
1258
1259 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(adr);
1260
1261 if (ha && ha->m_Index < m_Data->GetContentsCnt() - 1)
1262 {
1263 wxHtmlContentsItem *it = m_Data->GetContents() + (ha->m_Index + 1);
1264
1265 while (it->GetFullPath() == adr) it++;
1266
1267 if (it->m_Page[0] != 0)
1268 {
1269 m_HtmlWin->LoadPage(it->GetFullPath());
1270 NotifyPageChanged();
1271 }
1272 }
1273 }
1274 break;
1275
1276 case wxID_HTML_PANEL :
1277 {
1278 if (! (m_Splitter && m_NavigPan))
1279 return ;
1280 if (m_Splitter->IsSplit())
1281 {
1282 m_Cfg.sashpos = m_Splitter->GetSashPosition();
1283 m_Splitter->Unsplit(m_NavigPan);
1284 m_Cfg.navig_on = FALSE;
1285 }
1286 else
1287 {
1288 m_NavigPan->Show(TRUE);
1289 m_HtmlWin->Show(TRUE);
1290 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
1291 m_Cfg.navig_on = TRUE;
1292 }
1293 }
1294 break;
1295
1296 case wxID_HTML_OPTIONS :
1297 OptionsDialog();
1298 break;
1299
1300 case wxID_HTML_BOOKMARKSADD :
1301 {
1302 wxString item;
1303 wxString url;
1304
1305 item = m_HtmlWin->GetOpenedPageTitle();
1306 url = m_HtmlWin->GetOpenedPage();
1307 if (item == wxEmptyString)
1308 item = url.AfterLast(wxT('/'));
1309 if (m_BookmarksPages.Index(url) == wxNOT_FOUND)
1310 {
1311 m_Bookmarks->Append(item);
1312 m_BookmarksNames.Add(item);
1313 m_BookmarksPages.Add(url);
1314 }
1315 }
1316 break;
1317
1318 case wxID_HTML_BOOKMARKSREMOVE :
1319 {
1320 wxString item;
1321 int pos;
1322
1323 item = m_Bookmarks->GetStringSelection();
1324 pos = m_BookmarksNames.Index(item);
1325 if (pos != wxNOT_FOUND)
1326 {
1327 m_BookmarksNames.Remove(pos);
1328 m_BookmarksPages.Remove(pos);
1329 m_Bookmarks->Delete(m_Bookmarks->GetSelection());
1330 }
1331 }
1332 break;
1333
1334 #if wxUSE_PRINTING_ARCHITECTURE
1335 case wxID_HTML_PRINT :
1336 {
1337 if (m_Printer == NULL)
1338 m_Printer = new wxHtmlEasyPrinting(_("Help Printing"), this);
1339 if (!m_HtmlWin->GetOpenedPage())
1340 wxLogWarning(_("Cannot print empty page."));
1341 else
1342 m_Printer->PrintFile(m_HtmlWin->GetOpenedPage());
1343 }
1344 break;
1345 #endif
1346
1347 case wxID_HTML_OPENFILE :
1348 {
1349 wxString s = wxFileSelector(_("Open HTML document"),
1350 wxEmptyString,
1351 wxEmptyString,
1352 wxEmptyString,
1353 _(
1354 "HTML files (*.htm)|*.htm|HTML files (*.html)|*.html|\
1355 Help books (*.htb)|*.htb|Help books (*.zip)|*.zip|\
1356 HTML Help Project (*.hhp)|*.hhp|\
1357 All files (*.*)|*"
1358 ),
1359 wxOPEN | wxFILE_MUST_EXIST,
1360 this);
1361 if (!s.IsEmpty())
1362 {
1363 wxString ext = s.Right(4).Lower();
1364 if (ext == _T(".zip") || ext == _T(".htb") || ext == _T(".hhp"))
1365 {
1366 wxBusyCursor bcur;
1367 m_Data->AddBook(s);
1368 RefreshLists();
1369 }
1370 else
1371 m_HtmlWin->LoadPage(s);
1372 }
1373 }
1374 break;
1375 }
1376 }
1377
1378
1379
1380 void wxHtmlHelpFrame::OnContentsSel(wxTreeEvent& event)
1381 {
1382 wxHtmlHelpTreeItemData *pg;
1383 wxHtmlContentsItem *it;
1384
1385 pg = (wxHtmlHelpTreeItemData*) m_ContentsBox->GetItemData(event.GetItem());
1386
1387 if (pg && m_UpdateContents)
1388 {
1389 it = m_Data->GetContents() + (pg->m_Id);
1390 m_UpdateContents = FALSE;
1391 if (it->m_Page[0] != 0)
1392 m_HtmlWin->LoadPage(it->GetFullPath());
1393 m_UpdateContents = TRUE;
1394 }
1395 }
1396
1397
1398
1399 void wxHtmlHelpFrame::OnIndexSel(wxCommandEvent& WXUNUSED(event))
1400 {
1401 wxHtmlContentsItem *it = (wxHtmlContentsItem*) m_IndexList->GetClientData(m_IndexList->GetSelection());
1402 if (it->m_Page[0] != 0)
1403 m_HtmlWin->LoadPage(it->GetFullPath());
1404 NotifyPageChanged();
1405 }
1406
1407
1408 void wxHtmlHelpFrame::OnIndexFind(wxCommandEvent& event)
1409 {
1410 wxString sr = m_IndexText->GetLineText(0);
1411 sr.MakeLower();
1412 if (sr == wxEmptyString)
1413 {
1414 OnIndexAll(event);
1415 }
1416 else
1417 {
1418 wxBusyCursor bcur;
1419 const wxChar *cstr = sr.c_str();
1420 wxChar mybuff[512];
1421 wxChar *ptr;
1422 bool first = TRUE;
1423
1424 m_IndexList->Clear();
1425 int cnt = m_Data->GetIndexCnt();
1426 wxHtmlContentsItem* index = m_Data->GetIndex();
1427
1428 int displ = 0;
1429 for (int i = 0; i < cnt; i++)
1430 {
1431 wxStrncpy(mybuff, index[i].m_Name, 512);
1432 mybuff[511] = _T('\0');
1433 for (ptr = mybuff; *ptr != 0; ptr++)
1434 if (*ptr >= _T('A') && *ptr <= _T('Z'))
1435 *ptr -= (wxChar)(_T('A') - _T('a'));
1436 if (wxStrstr(mybuff, cstr) != NULL)
1437 {
1438 m_IndexList->Append(index[i].m_Name, (char*)(index + i));
1439 displ++;
1440 if (first)
1441 {
1442 if (index[i].m_Page[0] != 0)
1443 m_HtmlWin->LoadPage(index[i].GetFullPath());
1444 NotifyPageChanged();
1445 first = FALSE;
1446 }
1447 }
1448 }
1449
1450 wxString cnttext;
1451 cnttext.Printf(_("%i of %i"), displ, cnt);
1452 m_IndexCountInfo->SetLabel(cnttext);
1453
1454 m_IndexText->SetSelection(0, sr.Length());
1455 m_IndexText->SetFocus();
1456 }
1457 }
1458
1459 void wxHtmlHelpFrame::OnIndexAll(wxCommandEvent& WXUNUSED(event))
1460 {
1461 wxBusyCursor bcur;
1462
1463 m_IndexList->Clear();
1464 int cnt = m_Data->GetIndexCnt();
1465 bool first = TRUE;
1466 wxHtmlContentsItem* index = m_Data->GetIndex();
1467
1468 for (int i = 0; i < cnt; i++)
1469 {
1470 m_IndexList->Append(index[i].m_Name, (char*)(index + i));
1471 if (first)
1472 {
1473 if (index[i].m_Page[0] != 0)
1474 m_HtmlWin->LoadPage(index[i].GetFullPath());
1475 NotifyPageChanged();
1476 first = FALSE;
1477 }
1478 }
1479
1480 wxString cnttext;
1481 cnttext.Printf(_("%i of %i"), cnt, cnt);
1482 m_IndexCountInfo->SetLabel(cnttext);
1483 }
1484
1485
1486 void wxHtmlHelpFrame::OnSearchSel(wxCommandEvent& WXUNUSED(event))
1487 {
1488 wxHtmlContentsItem *it = (wxHtmlContentsItem*) m_SearchList->GetClientData(m_SearchList->GetSelection());
1489 if (it)
1490 {
1491 if (it->m_Page[0] != 0)
1492 m_HtmlWin->LoadPage(it->GetFullPath());
1493 NotifyPageChanged();
1494 }
1495 }
1496
1497 void wxHtmlHelpFrame::OnSearch(wxCommandEvent& WXUNUSED(event))
1498 {
1499 wxString sr = m_SearchText->GetLineText(0);
1500
1501 if (sr != wxEmptyString) KeywordSearch(sr);
1502 }
1503
1504 void wxHtmlHelpFrame::OnBookmarksSel(wxCommandEvent& WXUNUSED(event))
1505 {
1506 wxString sr = m_Bookmarks->GetStringSelection();
1507
1508 if (sr != wxEmptyString && sr != _("(bookmarks)"))
1509 {
1510 m_HtmlWin->LoadPage(m_BookmarksPages[m_BookmarksNames.Index(sr)]);
1511 NotifyPageChanged();
1512 }
1513 }
1514
1515 void wxHtmlHelpFrame::OnCloseWindow(wxCloseEvent& evt)
1516 {
1517 GetSize(&m_Cfg.w, &m_Cfg.h);
1518 GetPosition(&m_Cfg.x, &m_Cfg.y);
1519
1520 if (m_Splitter && m_Cfg.navig_on) m_Cfg.sashpos = m_Splitter->GetSashPosition();
1521
1522 if (m_Config)
1523 WriteCustomization(m_Config, m_ConfigRoot);
1524
1525 if (m_helpController && m_helpController->IsKindOf(CLASSINFO(wxHtmlHelpController)))
1526 {
1527 ((wxHtmlHelpController*) m_helpController)->OnCloseFrame(evt);
1528 }
1529
1530 evt.Skip();
1531 }
1532
1533 BEGIN_EVENT_TABLE(wxHtmlHelpFrame, wxFrame)
1534 EVT_TOOL_RANGE(wxID_HTML_PANEL, wxID_HTML_OPTIONS, wxHtmlHelpFrame::OnToolbar)
1535 EVT_BUTTON(wxID_HTML_BOOKMARKSREMOVE, wxHtmlHelpFrame::OnToolbar)
1536 EVT_BUTTON(wxID_HTML_BOOKMARKSADD, wxHtmlHelpFrame::OnToolbar)
1537 EVT_TREE_SEL_CHANGED(wxID_HTML_TREECTRL, wxHtmlHelpFrame::OnContentsSel)
1538 EVT_LISTBOX(wxID_HTML_INDEXLIST, wxHtmlHelpFrame::OnIndexSel)
1539 EVT_LISTBOX(wxID_HTML_SEARCHLIST, wxHtmlHelpFrame::OnSearchSel)
1540 EVT_BUTTON(wxID_HTML_SEARCHBUTTON, wxHtmlHelpFrame::OnSearch)
1541 EVT_TEXT_ENTER(wxID_HTML_SEARCHTEXT, wxHtmlHelpFrame::OnSearch)
1542 EVT_BUTTON(wxID_HTML_INDEXBUTTON, wxHtmlHelpFrame::OnIndexFind)
1543 EVT_TEXT_ENTER(wxID_HTML_INDEXTEXT, wxHtmlHelpFrame::OnIndexFind)
1544 EVT_BUTTON(wxID_HTML_INDEXBUTTONALL, wxHtmlHelpFrame::OnIndexAll)
1545 EVT_COMBOBOX(wxID_HTML_BOOKMARKSLIST, wxHtmlHelpFrame::OnBookmarksSel)
1546 EVT_CLOSE(wxHtmlHelpFrame::OnCloseWindow)
1547 END_EVENT_TABLE()
1548
1549 #endif // wxUSE_WXHTML_HELP
1550