]> git.saurik.com Git - wxWidgets.git/blob - src/html/helpfrm.cpp
Revert patch again, as the scrollbars are now always shown.
[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 wxSUNKEN_BORDER |
444 wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT |
445 wxTR_LINES_AT_ROOT);
446
447 m_ContentsBox->AssignImageList(ContentsImageList);
448
449 topsizer->Add(m_ContentsBox, 1,
450 wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT,
451 2);
452
453 m_NavigNotebook->AddPage(dummy, _("Contents"));
454 m_ContentsPage = notebook_page++;
455 }
456
457 // index listbox panel?
458 if ( style & wxHF_INDEX )
459 {
460 wxWindow *dummy = new wxPanel(m_NavigNotebook, wxID_HTML_INDEXPAGE);
461 wxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
462
463 dummy->SetSizer(topsizer);
464
465 m_IndexText = new wxTextCtrl(dummy, wxID_HTML_INDEXTEXT, wxEmptyString,
466 wxDefaultPosition, wxDefaultSize,
467 wxTE_PROCESS_ENTER);
468 m_IndexButton = new wxButton(dummy, wxID_HTML_INDEXBUTTON, _("Find"));
469 m_IndexButtonAll = new wxButton(dummy, wxID_HTML_INDEXBUTTONALL,
470 _("Show all"));
471 m_IndexCountInfo = new wxStaticText(dummy, wxID_HTML_COUNTINFO,
472 wxEmptyString, wxDefaultPosition,
473 wxDefaultSize,
474 wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
475 m_IndexList = new wxListBox(dummy, wxID_HTML_INDEXLIST,
476 wxDefaultPosition, wxDefaultSize,
477 0, NULL, wxLB_SINGLE);
478
479 #if wxUSE_TOOLTIPS
480 m_IndexButton->SetToolTip(_("Display all index items that contain given substring. Search is case insensitive."));
481 m_IndexButtonAll->SetToolTip(_("Show all items in index"));
482 #endif //wxUSE_TOOLTIPS
483
484 topsizer->Add(m_IndexText, 0, wxEXPAND | wxALL, 10);
485 wxSizer *btsizer = new wxBoxSizer(wxHORIZONTAL);
486 btsizer->Add(m_IndexButton, 0, wxRIGHT, 2);
487 btsizer->Add(m_IndexButtonAll);
488 topsizer->Add(btsizer, 0,
489 wxALIGN_RIGHT | wxLEFT | wxRIGHT | wxBOTTOM, 10);
490 topsizer->Add(m_IndexCountInfo, 0, wxEXPAND | wxLEFT | wxRIGHT, 2);
491 topsizer->Add(m_IndexList, 1, wxEXPAND | wxALL, 2);
492
493 m_NavigNotebook->AddPage(dummy, _("Index"));
494 m_IndexPage = notebook_page++;
495 }
496
497 // search list panel?
498 if ( style & wxHF_SEARCH )
499 {
500 wxWindow *dummy = new wxPanel(m_NavigNotebook, wxID_HTML_INDEXPAGE);
501 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
502
503 dummy->SetSizer(sizer);
504
505 m_SearchText = new wxTextCtrl(dummy, wxID_HTML_SEARCHTEXT,
506 wxEmptyString,
507 wxDefaultPosition, wxDefaultSize,
508 wxTE_PROCESS_ENTER);
509 m_SearchChoice = new wxChoice(dummy, wxID_HTML_SEARCHCHOICE,
510 wxDefaultPosition, wxDefaultSize);
511 m_SearchCaseSensitive = new wxCheckBox(dummy, wxID_ANY, _("Case sensitive"));
512 m_SearchWholeWords = new wxCheckBox(dummy, wxID_ANY, _("Whole words only"));
513 m_SearchButton = new wxButton(dummy, wxID_HTML_SEARCHBUTTON, _("Search"));
514 #if wxUSE_TOOLTIPS
515 m_SearchButton->SetToolTip(_("Search contents of help book(s) for all occurences of the text you typed above"));
516 #endif //wxUSE_TOOLTIPS
517 m_SearchList = new wxListBox(dummy, wxID_HTML_SEARCHLIST,
518 wxDefaultPosition, wxDefaultSize,
519 0, NULL, wxLB_SINGLE);
520
521 sizer->Add(m_SearchText, 0, wxEXPAND | wxALL, 10);
522 sizer->Add(m_SearchChoice, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
523 sizer->Add(m_SearchCaseSensitive, 0, wxLEFT | wxRIGHT, 10);
524 sizer->Add(m_SearchWholeWords, 0, wxLEFT | wxRIGHT, 10);
525 sizer->Add(m_SearchButton, 0, wxALL | wxALIGN_RIGHT, 8);
526 sizer->Add(m_SearchList, 1, wxALL | wxEXPAND, 2);
527
528 m_NavigNotebook->AddPage(dummy, _("Search"));
529 m_SearchPage = notebook_page;
530 }
531
532 m_HtmlWin->Show();
533
534 RefreshLists();
535
536 if ( navigSizer )
537 {
538 navigSizer->SetSizeHints(m_NavigPan);
539 m_NavigPan->Layout();
540 }
541
542 // showtime
543 if ( m_NavigPan && m_Splitter )
544 {
545 m_Splitter->SetMinimumPaneSize(20);
546 if ( m_Cfg.navig_on )
547 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
548
549 if ( m_Cfg.navig_on )
550 {
551 m_NavigPan->Show();
552 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
553 }
554 else
555 {
556 m_NavigPan->Show(false);
557 m_Splitter->Initialize(m_HtmlWin);
558 }
559 }
560
561 // Reduce flicker by updating the splitter pane sizes before the
562 // frame is shown
563 wxSizeEvent sizeEvent(GetSize(), GetId());
564 ProcessEvent(sizeEvent);
565
566 m_Splitter->UpdateSize();
567
568 return true;
569 }
570
571 wxHtmlHelpFrame::~wxHtmlHelpFrame()
572 {
573 delete m_mergedIndex;
574
575 // PopEventHandler(); // wxhtmlhelpcontroller (not any more!)
576 if (m_DataCreated)
577 delete m_Data;
578 if (m_NormalFonts) delete m_NormalFonts;
579 if (m_FixedFonts) delete m_FixedFonts;
580 if (m_PagesHash)
581 {
582 WX_CLEAR_HASH_TABLE(*m_PagesHash);
583 delete m_PagesHash;
584 }
585 #if wxUSE_PRINTING_ARCHITECTURE
586 if (m_Printer) delete m_Printer;
587 #endif
588 }
589
590
591 #if wxUSE_TOOLBAR
592 void wxHtmlHelpFrame::AddToolbarButtons(wxToolBar *toolBar, int style)
593 {
594 wxBitmap wpanelBitmap =
595 wxArtProvider::GetBitmap(wxART_HELP_SIDE_PANEL, wxART_TOOLBAR);
596 wxBitmap wbackBitmap =
597 wxArtProvider::GetBitmap(wxART_GO_BACK, wxART_TOOLBAR);
598 wxBitmap wforwardBitmap =
599 wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_TOOLBAR);
600 wxBitmap wupnodeBitmap =
601 wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_TOOLBAR);
602 wxBitmap wupBitmap =
603 wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR);
604 wxBitmap wdownBitmap =
605 wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR);
606 wxBitmap wopenBitmap =
607 wxArtProvider::GetBitmap(wxART_FILE_OPEN, wxART_TOOLBAR);
608 wxBitmap wprintBitmap =
609 wxArtProvider::GetBitmap(wxART_PRINT, wxART_TOOLBAR);
610 wxBitmap woptionsBitmap =
611 wxArtProvider::GetBitmap(wxART_HELP_SETTINGS, wxART_TOOLBAR);
612
613 wxASSERT_MSG( (wpanelBitmap.Ok() && wbackBitmap.Ok() &&
614 wforwardBitmap.Ok() && wupnodeBitmap.Ok() &&
615 wupBitmap.Ok() && wdownBitmap.Ok() &&
616 wopenBitmap.Ok() && wprintBitmap.Ok() &&
617 woptionsBitmap.Ok()),
618 wxT("One or more HTML help frame toolbar bitmap could not be loaded.")) ;
619
620
621 toolBar->AddTool(wxID_HTML_PANEL, wpanelBitmap, wxNullBitmap,
622 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
623 _("Show/hide navigation panel"));
624
625 toolBar->AddSeparator();
626 toolBar->AddTool(wxID_HTML_BACK, wbackBitmap, wxNullBitmap,
627 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
628 _("Go back"));
629 toolBar->AddTool(wxID_HTML_FORWARD, wforwardBitmap, wxNullBitmap,
630 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
631 _("Go forward"));
632 toolBar->AddSeparator();
633
634 toolBar->AddTool(wxID_HTML_UPNODE, wupnodeBitmap, wxNullBitmap,
635 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
636 _("Go one level up in document hierarchy"));
637 toolBar->AddTool(wxID_HTML_UP, wupBitmap, wxNullBitmap,
638 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
639 _("Previous page"));
640 toolBar->AddTool(wxID_HTML_DOWN, wdownBitmap, wxNullBitmap,
641 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
642 _("Next page"));
643
644 if ((style & wxHF_PRINT) || (style & wxHF_OPEN_FILES))
645 toolBar->AddSeparator();
646
647 if (style & wxHF_OPEN_FILES)
648 toolBar->AddTool(wxID_HTML_OPENFILE, wopenBitmap, wxNullBitmap,
649 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
650 _("Open HTML document"));
651
652 #if wxUSE_PRINTING_ARCHITECTURE
653 if (style & wxHF_PRINT)
654 toolBar->AddTool(wxID_HTML_PRINT, wprintBitmap, wxNullBitmap,
655 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
656 _("Print this page"));
657 #endif
658
659 toolBar->AddSeparator();
660 toolBar->AddTool(wxID_HTML_OPTIONS, woptionsBitmap, wxNullBitmap,
661 false, wxDefaultCoord, wxDefaultCoord, (wxObject *) NULL,
662 _("Display options dialog"));
663 }
664 #endif //wxUSE_TOOLBAR
665
666
667 void wxHtmlHelpFrame::SetTitleFormat(const wxString& format)
668 {
669 if (m_HtmlWin)
670 m_HtmlWin->SetRelatedFrame(this, format);
671 m_TitleFormat = format;
672 }
673
674
675 bool wxHtmlHelpFrame::Display(const wxString& x)
676 {
677 wxString url = m_Data->FindPageByName(x);
678 if (!url.IsEmpty())
679 {
680 m_HtmlWin->LoadPage(url);
681 NotifyPageChanged();
682 return true;
683 }
684
685 return false;
686 }
687
688 bool wxHtmlHelpFrame::Display(const int id)
689 {
690 wxString url = m_Data->FindPageById(id);
691 if (!url.IsEmpty())
692 {
693 m_HtmlWin->LoadPage(url);
694 NotifyPageChanged();
695 return true;
696 }
697
698 return false;
699 }
700
701
702
703 bool wxHtmlHelpFrame::DisplayContents()
704 {
705 if (! m_ContentsBox)
706 return false;
707
708 if (!m_Splitter->IsSplit())
709 {
710 m_NavigPan->Show();
711 m_HtmlWin->Show();
712 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
713 m_Cfg.navig_on = true;
714 }
715
716 m_NavigNotebook->SetSelection(0);
717
718 if (m_Data->GetBookRecArray().GetCount() > 0)
719 {
720 wxHtmlBookRecord& book = m_Data->GetBookRecArray()[0];
721 if (!book.GetStart().IsEmpty())
722 m_HtmlWin->LoadPage(book.GetFullPath(book.GetStart()));
723 }
724
725 return true;
726 }
727
728
729
730 bool wxHtmlHelpFrame::DisplayIndex()
731 {
732 if (! m_IndexList)
733 return false;
734
735 if (!m_Splitter->IsSplit())
736 {
737 m_NavigPan->Show();
738 m_HtmlWin->Show();
739 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
740 }
741
742 m_NavigNotebook->SetSelection(1);
743
744 if (m_Data->GetBookRecArray().GetCount() > 0)
745 {
746 wxHtmlBookRecord& book = m_Data->GetBookRecArray()[0];
747 if (!book.GetStart().IsEmpty())
748 m_HtmlWin->LoadPage(book.GetFullPath(book.GetStart()));
749 }
750
751 return true;
752 }
753
754 void wxHtmlHelpFrame::DisplayIndexItem(const wxHtmlHelpMergedIndexItem *it)
755 {
756 if (it->items.size() == 1)
757 {
758 if (!it->items[0]->page.empty())
759 {
760 m_HtmlWin->LoadPage(it->items[0]->GetFullPath());
761 NotifyPageChanged();
762 }
763 }
764 else
765 {
766 wxBusyCursor busy_cursor;
767
768 // more pages associated with this index item -- let the user choose
769 // which one she/he wants from a list:
770 wxArrayString arr;
771 size_t len = it->items.size();
772 for (size_t i = 0; i < len; i++)
773 {
774 wxString page = it->items[i]->page;
775 // try to find page's title in contents:
776 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
777 size_t clen = contents.size();
778 for (size_t j = 0; j < clen; j++)
779 {
780 if (contents[j].page == page)
781 {
782 page = contents[j].name;
783 break;
784 }
785 }
786 arr.push_back(page);
787 }
788
789 wxSingleChoiceDialog dlg(this,
790 _("Please choose the page to display:"),
791 _("Help Topics"),
792 arr, NULL, wxCHOICEDLG_STYLE & ~wxCENTRE);
793 if (dlg.ShowModal() == wxID_OK)
794 {
795 m_HtmlWin->LoadPage(it->items[dlg.GetSelection()]->GetFullPath());
796 NotifyPageChanged();
797 }
798 }
799 }
800
801
802 bool wxHtmlHelpFrame::KeywordSearch(const wxString& keyword,
803 wxHelpSearchMode mode)
804 {
805 if (mode == wxHELP_SEARCH_ALL)
806 {
807 if ( !(m_SearchList &&
808 m_SearchButton && m_SearchText && m_SearchChoice) )
809 return false;
810 }
811 else if (mode == wxHELP_SEARCH_INDEX)
812 {
813 if ( !(m_IndexList &&
814 m_IndexButton && m_IndexButtonAll && m_IndexText) )
815 return false;
816 }
817
818 int foundcnt = 0;
819 wxString foundstr;
820 wxString book = wxEmptyString;
821
822 if (!m_Splitter->IsSplit())
823 {
824 m_NavigPan->Show();
825 m_HtmlWin->Show();
826 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
827 }
828
829 if (mode == wxHELP_SEARCH_ALL)
830 {
831 m_NavigNotebook->SetSelection(m_SearchPage);
832 m_SearchList->Clear();
833 m_SearchText->SetValue(keyword);
834 m_SearchButton->Disable();
835
836 if (m_SearchChoice->GetSelection() != 0)
837 book = m_SearchChoice->GetStringSelection();
838
839 wxHtmlSearchStatus status(m_Data, keyword,
840 m_SearchCaseSensitive->GetValue(),
841 m_SearchWholeWords->GetValue(),
842 book);
843
844 #if wxUSE_PROGRESSDLG
845 wxProgressDialog progress(_("Searching..."),
846 _("No matching page found yet"),
847 status.GetMaxIndex(), this,
848 wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_AUTO_HIDE);
849 #endif
850
851 int curi;
852 while (status.IsActive())
853 {
854 curi = status.GetCurIndex();
855 if (curi % 32 == 0
856 #if wxUSE_PROGRESSDLG
857 && !progress.Update(curi)
858 #endif
859 )
860 break;
861 if (status.Search())
862 {
863 foundstr.Printf(_("Found %i matches"), ++foundcnt);
864 #if wxUSE_PROGRESSDLG
865 progress.Update(status.GetCurIndex(), foundstr);
866 #endif
867 m_SearchList->Append(status.GetName(), (void*)status.GetCurItem());
868 }
869 }
870
871 m_SearchButton->Enable();
872 m_SearchText->SetSelection(0, keyword.Length());
873 m_SearchText->SetFocus();
874 }
875 else if (mode == wxHELP_SEARCH_INDEX)
876 {
877 m_NavigNotebook->SetSelection(m_IndexPage);
878 m_IndexList->Clear();
879 m_IndexButton->Disable();
880 m_IndexButtonAll->Disable();
881 m_IndexText->SetValue(keyword);
882
883 wxCommandEvent dummy;
884 OnIndexFind(dummy); // what a hack...
885 m_IndexButton->Enable();
886 m_IndexButtonAll->Enable();
887 foundcnt = m_IndexList->GetCount();
888 }
889
890 if (foundcnt)
891 {
892 switch ( mode )
893 {
894 default:
895 wxFAIL_MSG( _T("unknown help search mode") );
896 // fall back
897
898 case wxHELP_SEARCH_ALL:
899 {
900 wxHtmlHelpDataItem *it =
901 (wxHtmlHelpDataItem*) m_SearchList->GetClientData(0);
902 if (it)
903 {
904 m_HtmlWin->LoadPage(it->GetFullPath());
905 NotifyPageChanged();
906 }
907 break;
908 }
909
910 case wxHELP_SEARCH_INDEX:
911 {
912 wxHtmlHelpMergedIndexItem* it =
913 (wxHtmlHelpMergedIndexItem*) m_IndexList->GetClientData(0);
914 if (it)
915 DisplayIndexItem(it);
916 break;
917 }
918 }
919
920 }
921
922 return foundcnt > 0;
923 }
924
925 void wxHtmlHelpFrame::CreateContents()
926 {
927 if (! m_ContentsBox)
928 return ;
929
930 if (m_PagesHash)
931 {
932 WX_CLEAR_HASH_TABLE(*m_PagesHash);
933 delete m_PagesHash;
934 }
935
936 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
937
938 size_t cnt = contents.size();
939
940 m_PagesHash = new wxHashTable(wxKEY_STRING, 2 * cnt);
941
942 const int MAX_ROOTS = 64;
943 wxTreeItemId roots[MAX_ROOTS];
944 // VS: this array holds information about whether we've set item icon at
945 // given level. This is neccessary because m_Data has flat structure
946 // and there's no way of recognizing if some item has subitems or not.
947 // We set the icon later: when we find an item with level=n, we know
948 // that the last item with level=n-1 was folder with subitems, so we
949 // set its icon accordingly
950 bool imaged[MAX_ROOTS];
951 m_ContentsBox->DeleteAllItems();
952
953 roots[0] = m_ContentsBox->AddRoot(_("(Help)"));
954 imaged[0] = true;
955
956 for (size_t i = 0; i < cnt; i++)
957 {
958 wxHtmlHelpDataItem *it = &contents[i];
959 // Handle books:
960 if (it->level == 0)
961 {
962 if (m_hfStyle & wxHF_MERGE_BOOKS)
963 // VS: we don't want book nodes, books' content should
964 // appear under tree's root. This line will create "fake"
965 // record about book node so that the rest of this look
966 // will believe there really _is_ book node and will
967 // behave correctly.
968 roots[1] = roots[0];
969 else
970 {
971 roots[1] = m_ContentsBox->AppendItem(roots[0],
972 it->name, IMG_Book, -1,
973 new wxHtmlHelpTreeItemData(i));
974 m_ContentsBox->SetItemBold(roots[1], true);
975 }
976 imaged[1] = true;
977 }
978 // ...and their contents:
979 else
980 {
981 roots[it->level + 1] = m_ContentsBox->AppendItem(
982 roots[it->level], it->name, IMG_Page,
983 -1, new wxHtmlHelpTreeItemData(i));
984 imaged[it->level + 1] = false;
985 }
986
987 m_PagesHash->Put(it->GetFullPath(),
988 new wxHtmlHelpHashData(i, roots[it->level + 1]));
989
990 // Set the icon for the node one level up in the hiearachy,
991 // unless already done (see comment above imaged[] declaration)
992 if (!imaged[it->level])
993 {
994 int image = IMG_Folder;
995 if (m_hfStyle & wxHF_ICONS_BOOK)
996 image = IMG_Book;
997 else if (m_hfStyle & wxHF_ICONS_BOOK_CHAPTER)
998 image = (it->level == 1) ? IMG_Book : IMG_Folder;
999 m_ContentsBox->SetItemImage(roots[it->level], image);
1000 m_ContentsBox->SetItemImage(roots[it->level], image,
1001 wxTreeItemIcon_Selected);
1002 imaged[it->level] = true;
1003 }
1004 }
1005 }
1006
1007
1008 void wxHtmlHelpFrame::CreateIndex()
1009 {
1010 if (! m_IndexList)
1011 return ;
1012
1013 m_IndexList->Clear();
1014
1015 size_t cnt = m_mergedIndex->size();
1016
1017 wxString cnttext;
1018 if (cnt > INDEX_IS_SMALL)
1019 cnttext.Printf(_("%i of %i"), 0, cnt);
1020 else
1021 cnttext.Printf(_("%i of %i"), cnt, cnt);
1022 m_IndexCountInfo->SetLabel(cnttext);
1023 if (cnt > INDEX_IS_SMALL)
1024 return;
1025
1026 for (size_t i = 0; i < cnt; i++)
1027 m_IndexList->Append((*m_mergedIndex)[i].name,
1028 (char*)(&(*m_mergedIndex)[i]));
1029 }
1030
1031 void wxHtmlHelpFrame::CreateSearch()
1032 {
1033 if (! (m_SearchList && m_SearchChoice))
1034 return ;
1035 m_SearchList->Clear();
1036 m_SearchChoice->Clear();
1037 m_SearchChoice->Append(_("Search in all books"));
1038 const wxHtmlBookRecArray& bookrec = m_Data->GetBookRecArray();
1039 int i, cnt = bookrec.GetCount();
1040 for (i = 0; i < cnt; i++)
1041 m_SearchChoice->Append(bookrec[i].GetTitle());
1042 m_SearchChoice->SetSelection(0);
1043 }
1044
1045
1046 void wxHtmlHelpFrame::RefreshLists()
1047 {
1048 // Update m_mergedIndex:
1049 UpdateMergedIndex();
1050 // Update the controls
1051 CreateContents();
1052 CreateIndex();
1053 CreateSearch();
1054 }
1055
1056 void wxHtmlHelpFrame::ReadCustomization(wxConfigBase *cfg, const wxString& path)
1057 {
1058 wxString oldpath;
1059 wxString tmp;
1060
1061 if (path != wxEmptyString)
1062 {
1063 oldpath = cfg->GetPath();
1064 cfg->SetPath(_T("/") + path);
1065 }
1066
1067 m_Cfg.navig_on = cfg->Read(wxT("hcNavigPanel"), m_Cfg.navig_on) != 0;
1068 m_Cfg.sashpos = cfg->Read(wxT("hcSashPos"), m_Cfg.sashpos);
1069 m_Cfg.x = cfg->Read(wxT("hcX"), m_Cfg.x);
1070 m_Cfg.y = cfg->Read(wxT("hcY"), m_Cfg.y);
1071 m_Cfg.w = cfg->Read(wxT("hcW"), m_Cfg.w);
1072 m_Cfg.h = cfg->Read(wxT("hcH"), m_Cfg.h);
1073
1074 m_FixedFace = cfg->Read(wxT("hcFixedFace"), m_FixedFace);
1075 m_NormalFace = cfg->Read(wxT("hcNormalFace"), m_NormalFace);
1076 m_FontSize = cfg->Read(wxT("hcBaseFontSize"), m_FontSize);
1077
1078 {
1079 int i;
1080 int cnt;
1081 wxString val, s;
1082
1083 cnt = cfg->Read(wxT("hcBookmarksCnt"), 0L);
1084 if (cnt != 0)
1085 {
1086 m_BookmarksNames.Clear();
1087 m_BookmarksPages.Clear();
1088 if (m_Bookmarks)
1089 {
1090 m_Bookmarks->Clear();
1091 m_Bookmarks->Append(_("(bookmarks)"));
1092 }
1093
1094 for (i = 0; i < cnt; i++)
1095 {
1096 val.Printf(wxT("hcBookmark_%i"), i);
1097 s = cfg->Read(val);
1098 m_BookmarksNames.Add(s);
1099 if (m_Bookmarks) m_Bookmarks->Append(s);
1100 val.Printf(wxT("hcBookmark_%i_url"), i);
1101 s = cfg->Read(val);
1102 m_BookmarksPages.Add(s);
1103 }
1104 }
1105 }
1106
1107 if (m_HtmlWin)
1108 m_HtmlWin->ReadCustomization(cfg);
1109
1110 if (path != wxEmptyString)
1111 cfg->SetPath(oldpath);
1112 }
1113
1114 void wxHtmlHelpFrame::WriteCustomization(wxConfigBase *cfg, const wxString& path)
1115 {
1116 wxString oldpath;
1117 wxString tmp;
1118
1119 if (path != wxEmptyString)
1120 {
1121 oldpath = cfg->GetPath();
1122 cfg->SetPath(_T("/") + path);
1123 }
1124
1125 cfg->Write(wxT("hcNavigPanel"), m_Cfg.navig_on);
1126 cfg->Write(wxT("hcSashPos"), (long)m_Cfg.sashpos);
1127 if ( !IsIconized() )
1128 {
1129 // Don't write if iconized as this would make the window
1130 // disappear next time it is shown!
1131 cfg->Write(wxT("hcX"), (long)m_Cfg.x);
1132 cfg->Write(wxT("hcY"), (long)m_Cfg.y);
1133 cfg->Write(wxT("hcW"), (long)m_Cfg.w);
1134 cfg->Write(wxT("hcH"), (long)m_Cfg.h);
1135 }
1136 cfg->Write(wxT("hcFixedFace"), m_FixedFace);
1137 cfg->Write(wxT("hcNormalFace"), m_NormalFace);
1138 cfg->Write(wxT("hcBaseFontSize"), (long)m_FontSize);
1139
1140 if (m_Bookmarks)
1141 {
1142 int i;
1143 int cnt = m_BookmarksNames.GetCount();
1144 wxString val;
1145
1146 cfg->Write(wxT("hcBookmarksCnt"), (long)cnt);
1147 for (i = 0; i < cnt; i++)
1148 {
1149 val.Printf(wxT("hcBookmark_%i"), i);
1150 cfg->Write(val, m_BookmarksNames[i]);
1151 val.Printf(wxT("hcBookmark_%i_url"), i);
1152 cfg->Write(val, m_BookmarksPages[i]);
1153 }
1154 }
1155
1156 if (m_HtmlWin)
1157 m_HtmlWin->WriteCustomization(cfg);
1158
1159 if (path != wxEmptyString)
1160 cfg->SetPath(oldpath);
1161 }
1162
1163
1164
1165
1166
1167 static void SetFontsToHtmlWin(wxHtmlWindow *win, wxString scalf, wxString fixf, int size)
1168 {
1169 int f_sizes[7];
1170 f_sizes[0] = int(size * 0.6);
1171 f_sizes[1] = int(size * 0.8);
1172 f_sizes[2] = size;
1173 f_sizes[3] = int(size * 1.2);
1174 f_sizes[4] = int(size * 1.4);
1175 f_sizes[5] = int(size * 1.6);
1176 f_sizes[6] = int(size * 1.8);
1177
1178 win->SetFonts(scalf, fixf, f_sizes);
1179 }
1180
1181
1182 class wxHtmlHelpFrameOptionsDialog : public wxDialog
1183 {
1184 public:
1185 wxComboBox *NormalFont, *FixedFont;
1186 wxSpinCtrl *FontSize;
1187 wxHtmlWindow *TestWin;
1188
1189 wxHtmlHelpFrameOptionsDialog(wxWindow *parent)
1190 : wxDialog(parent, wxID_ANY, wxString(_("Help Browser Options")))
1191 {
1192 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
1193 wxFlexGridSizer *sizer = new wxFlexGridSizer(2, 3, 2, 5);
1194
1195 sizer->Add(new wxStaticText(this, wxID_ANY, _("Normal font:")));
1196 sizer->Add(new wxStaticText(this, wxID_ANY, _("Fixed font:")));
1197 sizer->Add(new wxStaticText(this, wxID_ANY, _("Font size:")));
1198
1199 sizer->Add(NormalFont = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1200 wxSize(200, wxDefaultCoord),
1201 0, NULL, wxCB_DROPDOWN | wxCB_READONLY));
1202
1203 sizer->Add(FixedFont = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1204 wxSize(200, wxDefaultCoord),
1205 0, NULL, wxCB_DROPDOWN | wxCB_READONLY));
1206
1207 sizer->Add(FontSize = new wxSpinCtrl(this, wxID_ANY));
1208 FontSize->SetRange(2, 100);
1209
1210 topsizer->Add(sizer, 0, wxLEFT|wxRIGHT|wxTOP, 10);
1211
1212 topsizer->Add(new wxStaticText(this, wxID_ANY, _("Preview:")),
1213 0, wxLEFT | wxTOP, 10);
1214 topsizer->Add(TestWin = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxSize(20, 150),
1215 wxHW_SCROLLBAR_AUTO | wxSUNKEN_BORDER),
1216 1, wxEXPAND | wxLEFT|wxTOP|wxRIGHT, 10);
1217
1218 wxBoxSizer *sizer2 = new wxBoxSizer(wxHORIZONTAL);
1219 wxButton *ok;
1220 sizer2->Add(ok = new wxButton(this, wxID_OK), 0, wxALL, 10);
1221 ok->SetDefault();
1222 sizer2->Add(new wxButton(this, wxID_CANCEL), 0, wxALL, 10);
1223 topsizer->Add(sizer2, 0, wxALIGN_RIGHT);
1224
1225 SetSizer(topsizer);
1226 topsizer->Fit(this);
1227 Centre(wxBOTH);
1228 }
1229
1230
1231 void UpdateTestWin()
1232 {
1233 wxBusyCursor bcur;
1234 SetFontsToHtmlWin(TestWin,
1235 NormalFont->GetStringSelection(),
1236 FixedFont->GetStringSelection(),
1237 FontSize->GetValue());
1238
1239 wxString content(_("font size"));
1240
1241 content = _T("<font size=-2>") + content + _T(" -2</font><br>")
1242 _T("<font size=-1>") + content + _T(" -1</font><br>")
1243 _T("<font size=+0>") + content + _T(" +0</font><br>")
1244 _T("<font size=+1>") + content + _T(" +1</font><br>")
1245 _T("<font size=+2>") + content + _T(" +2</font><br>")
1246 _T("<font size=+3>") + content + _T(" +3</font><br>")
1247 _T("<font size=+4>") + content + _T(" +4</font><br>") ;
1248
1249 content = wxString( _T("<html><body><table><tr><td>") ) +
1250 _("Normal face<br>and <u>underlined</u>. ") +
1251 _("<i>Italic face.</i> ") +
1252 _("<b>Bold face.</b> ") +
1253 _("<b><i>Bold italic face.</i></b><br>") +
1254 content +
1255 wxString( _T("</td><td><tt>") ) +
1256 _("Fixed size face.<br> <b>bold</b> <i>italic</i> ") +
1257 _("<b><i>bold italic <u>underlined</u></i></b><br>") +
1258 content +
1259 _T("</tt></td></tr></table></body></html>");
1260
1261 TestWin->SetPage( content );
1262 }
1263
1264 void OnUpdate(wxCommandEvent& WXUNUSED(event))
1265 {
1266 UpdateTestWin();
1267 }
1268 void OnUpdateSpin(wxSpinEvent& WXUNUSED(event))
1269 {
1270 UpdateTestWin();
1271 }
1272
1273 DECLARE_EVENT_TABLE()
1274 DECLARE_NO_COPY_CLASS(wxHtmlHelpFrameOptionsDialog)
1275 };
1276
1277 BEGIN_EVENT_TABLE(wxHtmlHelpFrameOptionsDialog, wxDialog)
1278 EVT_COMBOBOX(wxID_ANY, wxHtmlHelpFrameOptionsDialog::OnUpdate)
1279 EVT_SPINCTRL(wxID_ANY, wxHtmlHelpFrameOptionsDialog::OnUpdateSpin)
1280 END_EVENT_TABLE()
1281
1282 void wxHtmlHelpFrame::OptionsDialog()
1283 {
1284 wxHtmlHelpFrameOptionsDialog dlg(this);
1285 unsigned i;
1286
1287 if (m_NormalFonts == NULL)
1288 {
1289 wxFontEnumerator enu;
1290 enu.EnumerateFacenames();
1291 m_NormalFonts = new wxArrayString;
1292 *m_NormalFonts = *enu.GetFacenames();
1293 m_NormalFonts->Sort(); // ascending sort
1294 }
1295 if (m_FixedFonts == NULL)
1296 {
1297 wxFontEnumerator enu;
1298 enu.EnumerateFacenames(wxFONTENCODING_SYSTEM, true /*enum fixed width only*/);
1299 m_FixedFonts = new wxArrayString;
1300 *m_FixedFonts = *enu.GetFacenames();
1301 m_FixedFonts->Sort(); // ascending sort
1302 }
1303
1304 // VS: We want to show the font that is actually used by wxHtmlWindow.
1305 // If customization dialog wasn't used yet, facenames are empty and
1306 // wxHtmlWindow uses default fonts -- let's find out what they
1307 // are so that we can pass them to the dialog:
1308 if (m_NormalFace.empty())
1309 {
1310 wxFont fnt(m_FontSize, wxSWISS, wxNORMAL, wxNORMAL, false);
1311 m_NormalFace = fnt.GetFaceName();
1312 }
1313 if (m_FixedFace.empty())
1314 {
1315 wxFont fnt(m_FontSize, wxMODERN, wxNORMAL, wxNORMAL, false);
1316 m_FixedFace = fnt.GetFaceName();
1317 }
1318
1319 for (i = 0; i < m_NormalFonts->GetCount(); i++)
1320 dlg.NormalFont->Append((*m_NormalFonts)[i]);
1321 for (i = 0; i < m_FixedFonts->GetCount(); i++)
1322 dlg.FixedFont->Append((*m_FixedFonts)[i]);
1323 if (!m_NormalFace.empty())
1324 dlg.NormalFont->SetStringSelection(m_NormalFace);
1325 else
1326 dlg.NormalFont->SetSelection(0);
1327 if (!m_FixedFace.empty())
1328 dlg.FixedFont->SetStringSelection(m_FixedFace);
1329 else
1330 dlg.FixedFont->SetSelection(0);
1331 dlg.FontSize->SetValue(m_FontSize);
1332 dlg.UpdateTestWin();
1333
1334 if (dlg.ShowModal() == wxID_OK)
1335 {
1336 m_NormalFace = dlg.NormalFont->GetStringSelection();
1337 m_FixedFace = dlg.FixedFont->GetStringSelection();
1338 m_FontSize = dlg.FontSize->GetValue();
1339 SetFontsToHtmlWin(m_HtmlWin, m_NormalFace, m_FixedFace, m_FontSize);
1340 }
1341 }
1342
1343
1344
1345 void wxHtmlHelpFrame::NotifyPageChanged()
1346 {
1347 if (m_UpdateContents && m_PagesHash)
1348 {
1349 wxString an = m_HtmlWin->GetOpenedAnchor();
1350 wxHtmlHelpHashData *ha;
1351 if (an.IsEmpty())
1352 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage());
1353 else
1354 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an);
1355 if (ha)
1356 {
1357 bool olduc = m_UpdateContents;
1358 m_UpdateContents = false;
1359 m_ContentsBox->SelectItem(ha->m_Id);
1360 m_ContentsBox->EnsureVisible(ha->m_Id);
1361 m_UpdateContents = olduc;
1362 }
1363 }
1364 }
1365
1366
1367
1368 /*
1369 EVENT HANDLING :
1370 */
1371
1372
1373 void wxHtmlHelpFrame::OnActivate(wxActivateEvent& event)
1374 {
1375 // This saves one mouse click when using the
1376 // wxHTML for context sensitive help systems
1377 #ifndef __WXGTK__
1378 // NB: wxActivateEvent is a bit broken in wxGTK
1379 // and is sometimes sent when it should not be
1380 if (event.GetActive() && m_HtmlWin)
1381 m_HtmlWin->SetFocus();
1382 #endif
1383
1384 event.Skip();
1385 }
1386
1387 void wxHtmlHelpFrame::OnToolbar(wxCommandEvent& event)
1388 {
1389 switch (event.GetId())
1390 {
1391 case wxID_HTML_BACK :
1392 m_HtmlWin->HistoryBack();
1393 NotifyPageChanged();
1394 break;
1395
1396 case wxID_HTML_FORWARD :
1397 m_HtmlWin->HistoryForward();
1398 NotifyPageChanged();
1399 break;
1400
1401 case wxID_HTML_UP :
1402 if (m_PagesHash)
1403 {
1404 wxString an = m_HtmlWin->GetOpenedAnchor();
1405 wxHtmlHelpHashData *ha;
1406 if (an.IsEmpty())
1407 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage());
1408 else
1409 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an);
1410 if (ha && ha->m_Index > 0)
1411 {
1412 const wxHtmlHelpDataItem& it = m_Data->GetContentsArray()[ha->m_Index - 1];
1413 if (!it.page.empty())
1414 {
1415 m_HtmlWin->LoadPage(it.GetFullPath());
1416 NotifyPageChanged();
1417 }
1418 }
1419 }
1420 break;
1421
1422 case wxID_HTML_UPNODE :
1423 if (m_PagesHash)
1424 {
1425 wxString an = m_HtmlWin->GetOpenedAnchor();
1426 wxHtmlHelpHashData *ha;
1427 if (an.IsEmpty())
1428 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage());
1429 else
1430 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(m_HtmlWin->GetOpenedPage() + wxT("#") + an);
1431 if (ha && ha->m_Index > 0)
1432 {
1433 int level =
1434 m_Data->GetContentsArray()[ha->m_Index].level - 1;
1435 int ind = ha->m_Index - 1;
1436
1437 const wxHtmlHelpDataItem *it =
1438 &m_Data->GetContentsArray()[ind];
1439 while (ind >= 0 && it->level != level)
1440 {
1441 ind--;
1442 it = &m_Data->GetContentsArray()[ind];
1443 }
1444 if (ind >= 0)
1445 {
1446 if (!it->page.empty())
1447 {
1448 m_HtmlWin->LoadPage(it->GetFullPath());
1449 NotifyPageChanged();
1450 }
1451 }
1452 }
1453 }
1454 break;
1455
1456 case wxID_HTML_DOWN :
1457 if (m_PagesHash)
1458 {
1459 wxString an = m_HtmlWin->GetOpenedAnchor();
1460 wxString adr;
1461 wxHtmlHelpHashData *ha;
1462
1463 if (an.IsEmpty()) adr = m_HtmlWin->GetOpenedPage();
1464 else adr = m_HtmlWin->GetOpenedPage() + wxT("#") + an;
1465
1466 ha = (wxHtmlHelpHashData*) m_PagesHash->Get(adr);
1467
1468 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
1469 if (ha && ha->m_Index < (int)contents.size() - 1)
1470 {
1471 size_t idx = ha->m_Index + 1;
1472
1473 while (contents[idx].GetFullPath() == adr) idx++;
1474
1475 if (!contents[idx].page.empty())
1476 {
1477 m_HtmlWin->LoadPage(contents[idx].GetFullPath());
1478 NotifyPageChanged();
1479 }
1480 }
1481 }
1482 break;
1483
1484 case wxID_HTML_PANEL :
1485 {
1486 if (! (m_Splitter && m_NavigPan))
1487 return ;
1488 if (m_Splitter->IsSplit())
1489 {
1490 m_Cfg.sashpos = m_Splitter->GetSashPosition();
1491 m_Splitter->Unsplit(m_NavigPan);
1492 m_Cfg.navig_on = false;
1493 }
1494 else
1495 {
1496 m_NavigPan->Show();
1497 m_HtmlWin->Show();
1498 m_Splitter->SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos);
1499 m_Cfg.navig_on = true;
1500 }
1501 }
1502 break;
1503
1504 case wxID_HTML_OPTIONS :
1505 OptionsDialog();
1506 break;
1507
1508 case wxID_HTML_BOOKMARKSADD :
1509 {
1510 wxString item;
1511 wxString url;
1512
1513 item = m_HtmlWin->GetOpenedPageTitle();
1514 url = m_HtmlWin->GetOpenedPage();
1515 if (item == wxEmptyString)
1516 item = url.AfterLast(wxT('/'));
1517 if (m_BookmarksPages.Index(url) == wxNOT_FOUND)
1518 {
1519 m_Bookmarks->Append(item);
1520 m_BookmarksNames.Add(item);
1521 m_BookmarksPages.Add(url);
1522 }
1523 }
1524 break;
1525
1526 case wxID_HTML_BOOKMARKSREMOVE :
1527 {
1528 wxString item;
1529 int pos;
1530
1531 item = m_Bookmarks->GetStringSelection();
1532 pos = m_BookmarksNames.Index(item);
1533 if (pos != wxNOT_FOUND)
1534 {
1535 m_BookmarksNames.RemoveAt(pos);
1536 m_BookmarksPages.RemoveAt(pos);
1537 m_Bookmarks->Delete(m_Bookmarks->GetSelection());
1538 }
1539 }
1540 break;
1541
1542 #if wxUSE_PRINTING_ARCHITECTURE
1543 case wxID_HTML_PRINT :
1544 {
1545 if (m_Printer == NULL)
1546 m_Printer = new wxHtmlEasyPrinting(_("Help Printing"), this);
1547 if (!m_HtmlWin->GetOpenedPage())
1548 wxLogWarning(_("Cannot print empty page."));
1549 else
1550 m_Printer->PrintFile(m_HtmlWin->GetOpenedPage());
1551 }
1552 break;
1553 #endif
1554
1555 case wxID_HTML_OPENFILE :
1556 {
1557 wxString filemask = wxString(
1558 _("HTML files (*.html;*.htm)|*.html;*.htm|")) +
1559 _("Help books (*.htb)|*.htb|Help books (*.zip)|*.zip|") +
1560 _("HTML Help Project (*.hhp)|*.hhp|") +
1561 #if wxUSE_LIBMSPACK
1562 _("Compressed HTML Help file (*.chm)|*.chm|") +
1563 #endif
1564 _("All files (*.*)|*");
1565 wxString s = wxFileSelector(_("Open HTML document"),
1566 wxEmptyString,
1567 wxEmptyString,
1568 wxEmptyString,
1569 filemask,
1570 wxOPEN | wxFILE_MUST_EXIST,
1571 this);
1572 if (!s.IsEmpty())
1573 {
1574 wxString ext = s.Right(4).Lower();
1575 if (ext == _T(".zip") || ext == _T(".htb") ||
1576 #if wxUSE_LIBMSPACK
1577 ext == _T(".chm") ||
1578 #endif
1579 ext == _T(".hhp"))
1580 {
1581 wxBusyCursor bcur;
1582 m_Data->AddBook(s);
1583 RefreshLists();
1584 }
1585 else
1586 m_HtmlWin->LoadPage(s);
1587 }
1588 }
1589 break;
1590 }
1591 }
1592
1593
1594
1595 void wxHtmlHelpFrame::OnContentsSel(wxTreeEvent& event)
1596 {
1597 wxHtmlHelpTreeItemData *pg;
1598
1599 pg = (wxHtmlHelpTreeItemData*) m_ContentsBox->GetItemData(event.GetItem());
1600
1601 if (pg && m_UpdateContents)
1602 {
1603 const wxHtmlHelpDataItems& contents = m_Data->GetContentsArray();
1604 m_UpdateContents = false;
1605 if (!contents[pg->m_Id].page.empty())
1606 m_HtmlWin->LoadPage(contents[pg->m_Id].GetFullPath());
1607 m_UpdateContents = true;
1608 }
1609 }
1610
1611
1612
1613 void wxHtmlHelpFrame::OnIndexSel(wxCommandEvent& WXUNUSED(event))
1614 {
1615 wxHtmlHelpMergedIndexItem *it = (wxHtmlHelpMergedIndexItem*)
1616 m_IndexList->GetClientData(m_IndexList->GetSelection());
1617 if (it)
1618 DisplayIndexItem(it);
1619 }
1620
1621
1622 void wxHtmlHelpFrame::OnIndexFind(wxCommandEvent& event)
1623 {
1624 wxString sr = m_IndexText->GetLineText(0);
1625 sr.MakeLower();
1626 if (sr == wxEmptyString)
1627 {
1628 OnIndexAll(event);
1629 }
1630 else
1631 {
1632 wxBusyCursor bcur;
1633
1634 m_IndexList->Clear();
1635 const wxHtmlHelpMergedIndex& index = *m_mergedIndex;
1636 size_t cnt = index.size();
1637
1638 int displ = 0;
1639 for (size_t i = 0; i < cnt; i++)
1640 {
1641 if (index[i].name.Lower().find(sr) != wxString::npos)
1642 {
1643 int pos = m_IndexList->Append(index[i].name,
1644 (char*)(&index[i]));
1645
1646 if (displ++ == 0)
1647 {
1648 // don't automatically show topic selector if this
1649 // item points to multiple pages:
1650 if (index[i].items.size() == 1)
1651 {
1652 m_IndexList->SetSelection(0);
1653 DisplayIndexItem(&index[i]);
1654 }
1655 }
1656
1657 // if this is nested item of the index, show its parent(s)
1658 // as well, otherwise it would not be clear what entry is
1659 // shown:
1660 wxHtmlHelpMergedIndexItem *parent = index[i].parent;
1661 while (parent)
1662 {
1663 if (pos == 0 ||
1664 (index.Index(*(wxHtmlHelpMergedIndexItem*)m_IndexList->GetClientData(pos-1))) < index.Index(*parent))
1665 {
1666 m_IndexList->Insert(parent->name,
1667 pos, (char*)parent);
1668 parent = parent->parent;
1669 }
1670 else break;
1671 }
1672
1673 // finally, it the item we just added is itself a parent for
1674 // other items, show them as well, because they are refinements
1675 // of the displayed index entry (i.e. it is implicitly contained
1676 // in them: "foo" with parent "bar" reads as "bar, foo"):
1677 int level = index[i].items[0]->level;
1678 i++;
1679 while (i < cnt && index[i].items[0]->level > level)
1680 {
1681 m_IndexList->Append(index[i].name, (char*)(&index[i]));
1682 i++;
1683 }
1684 i--;
1685 }
1686 }
1687
1688 wxString cnttext;
1689 cnttext.Printf(_("%i of %i"), displ, cnt);
1690 m_IndexCountInfo->SetLabel(cnttext);
1691
1692 m_IndexText->SetSelection(0, sr.Length());
1693 m_IndexText->SetFocus();
1694 }
1695 }
1696
1697 void wxHtmlHelpFrame::OnIndexAll(wxCommandEvent& WXUNUSED(event))
1698 {
1699 wxBusyCursor bcur;
1700
1701 m_IndexList->Clear();
1702 const wxHtmlHelpMergedIndex& index = *m_mergedIndex;
1703 size_t cnt = index.size();
1704 bool first = true;
1705
1706 for (size_t i = 0; i < cnt; i++)
1707 {
1708 m_IndexList->Append(index[i].name, (char*)(&index[i]));
1709 if (first)
1710 {
1711 // don't automatically show topic selector if this
1712 // item points to multiple pages:
1713 if (index[i].items.size() == 1)
1714 {
1715 DisplayIndexItem(&index[i]);
1716 }
1717 first = false;
1718 }
1719 }
1720
1721 wxString cnttext;
1722 cnttext.Printf(_("%i of %i"), cnt, cnt);
1723 m_IndexCountInfo->SetLabel(cnttext);
1724 }
1725
1726
1727 void wxHtmlHelpFrame::OnSearchSel(wxCommandEvent& WXUNUSED(event))
1728 {
1729 wxHtmlHelpDataItem *it = (wxHtmlHelpDataItem*) m_SearchList->GetClientData(m_SearchList->GetSelection());
1730 if (it)
1731 {
1732 if (!it->page.empty())
1733 m_HtmlWin->LoadPage(it->GetFullPath());
1734 NotifyPageChanged();
1735 }
1736 }
1737
1738 void wxHtmlHelpFrame::OnSearch(wxCommandEvent& WXUNUSED(event))
1739 {
1740 wxString sr = m_SearchText->GetLineText(0);
1741
1742 if (!sr.empty())
1743 KeywordSearch(sr, wxHELP_SEARCH_ALL);
1744 }
1745
1746 void wxHtmlHelpFrame::OnBookmarksSel(wxCommandEvent& WXUNUSED(event))
1747 {
1748 wxString sr = m_Bookmarks->GetStringSelection();
1749
1750 if (sr != wxEmptyString && sr != _("(bookmarks)"))
1751 {
1752 m_HtmlWin->LoadPage(m_BookmarksPages[m_BookmarksNames.Index(sr)]);
1753 NotifyPageChanged();
1754 }
1755 }
1756
1757 void wxHtmlHelpFrame::OnCloseWindow(wxCloseEvent& evt)
1758 {
1759 GetSize(&m_Cfg.w, &m_Cfg.h);
1760 GetPosition(&m_Cfg.x, &m_Cfg.y);
1761
1762 #ifdef __WXGTK__
1763 if (IsGrabbed())
1764 {
1765 RemoveGrab();
1766 }
1767 #endif
1768
1769 if (m_Splitter && m_Cfg.navig_on) m_Cfg.sashpos = m_Splitter->GetSashPosition();
1770
1771 if (m_Config)
1772 WriteCustomization(m_Config, m_ConfigRoot);
1773
1774 if (m_helpController && m_helpController->IsKindOf(CLASSINFO(wxHtmlHelpController)))
1775 {
1776 ((wxHtmlHelpController*) m_helpController)->OnCloseFrame(evt);
1777 }
1778
1779 evt.Skip();
1780 }
1781
1782 #ifdef __WXMAC__
1783 void wxHtmlHelpFrame::OnClose(wxCommandEvent& event)
1784 {
1785 Close(true);
1786 }
1787
1788 void wxHtmlHelpFrame::OnAbout(wxCommandEvent& event)
1789 {
1790 wxMessageBox(wxT("wxWidgets HTML Help Viewer (c) 1998-2004, Vaclav Slavik et al"), wxT("HelpView"),
1791 wxICON_INFORMATION|wxOK, this);
1792 }
1793 #endif
1794
1795 BEGIN_EVENT_TABLE(wxHtmlHelpFrame, wxFrame)
1796 EVT_ACTIVATE(wxHtmlHelpFrame::OnActivate)
1797 EVT_TOOL_RANGE(wxID_HTML_PANEL, wxID_HTML_OPTIONS, wxHtmlHelpFrame::OnToolbar)
1798 EVT_BUTTON(wxID_HTML_BOOKMARKSREMOVE, wxHtmlHelpFrame::OnToolbar)
1799 EVT_BUTTON(wxID_HTML_BOOKMARKSADD, wxHtmlHelpFrame::OnToolbar)
1800 EVT_TREE_SEL_CHANGED(wxID_HTML_TREECTRL, wxHtmlHelpFrame::OnContentsSel)
1801 EVT_LISTBOX(wxID_HTML_INDEXLIST, wxHtmlHelpFrame::OnIndexSel)
1802 EVT_LISTBOX(wxID_HTML_SEARCHLIST, wxHtmlHelpFrame::OnSearchSel)
1803 EVT_BUTTON(wxID_HTML_SEARCHBUTTON, wxHtmlHelpFrame::OnSearch)
1804 EVT_TEXT_ENTER(wxID_HTML_SEARCHTEXT, wxHtmlHelpFrame::OnSearch)
1805 EVT_BUTTON(wxID_HTML_INDEXBUTTON, wxHtmlHelpFrame::OnIndexFind)
1806 EVT_TEXT_ENTER(wxID_HTML_INDEXTEXT, wxHtmlHelpFrame::OnIndexFind)
1807 EVT_BUTTON(wxID_HTML_INDEXBUTTONALL, wxHtmlHelpFrame::OnIndexAll)
1808 EVT_COMBOBOX(wxID_HTML_BOOKMARKSLIST, wxHtmlHelpFrame::OnBookmarksSel)
1809 EVT_CLOSE(wxHtmlHelpFrame::OnCloseWindow)
1810 #ifdef __WXMAC__
1811 EVT_MENU(wxID_CLOSE, wxHtmlHelpFrame::OnClose)
1812 EVT_MENU(wxID_ABOUT, wxHtmlHelpFrame::OnAbout)
1813 EVT_MENU(wxID_HELP_CONTENTS, wxHtmlHelpFrame::OnAbout)
1814 #endif
1815
1816 END_EVENT_TABLE()
1817
1818 #endif // wxUSE_WXHTML_HELP
1819