| 1 | ///////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: helpwxht.cpp |
| 3 | // Purpose: A help controller using the wxHTML classes |
| 4 | // Author: Karsten Ballueder |
| 5 | // Modified by: |
| 6 | // Created: 04/01/98 |
| 7 | // RCS-ID: $Id$ |
| 8 | // Copyright: (c) Karsten Ballueder |
| 9 | // Licence: wxWindows licence |
| 10 | ///////////////////////////////////////////////////////////////////////////// |
| 11 | |
| 12 | #ifdef __GNUG__ |
| 13 | # pragma implementation "helpwxht.h" |
| 14 | #endif |
| 15 | |
| 16 | #include "wx/wxprec.h" |
| 17 | |
| 18 | #ifdef __BORLANDC__ |
| 19 | # pragma hdrstop |
| 20 | #endif |
| 21 | |
| 22 | #if wxUSE_WXHTML_HELP |
| 23 | |
| 24 | #ifndef WX_PRECOMP |
| 25 | #include "wx/string.h" |
| 26 | #include "wx/utils.h" |
| 27 | #include "wx/list.h" |
| 28 | #include "wx/intl.h" |
| 29 | #include "wx/layout.h" |
| 30 | #include "wx/combobox.h" |
| 31 | #include "wx/button.h" |
| 32 | #endif |
| 33 | |
| 34 | #include "wx/helpbase.h" |
| 35 | #include "wx/generic/helpwxht.h" |
| 36 | #include "wx/html/htmlwin.h" |
| 37 | |
| 38 | #include <stdio.h> |
| 39 | #include <ctype.h> |
| 40 | #ifndef __MWERKS__ |
| 41 | #include <sys/stat.h> |
| 42 | #endif |
| 43 | |
| 44 | #if !defined(__WINDOWS__) && !defined(__OS2__) |
| 45 | # include <unistd.h> |
| 46 | #endif |
| 47 | |
| 48 | IMPLEMENT_CLASS(wxHelpControllerHtml, wxHTMLHelpControllerBase) |
| 49 | |
| 50 | /** |
| 51 | This class implements help via wxHTML. |
| 52 | It requires the name of a directory containing the documentation |
| 53 | and a file mapping numerical Section numbers to relative URLS. |
| 54 | */ |
| 55 | |
| 56 | class wxForceHtmlFilter : public wxHtmlFilter |
| 57 | { |
| 58 | public: |
| 59 | virtual wxString ReadFile(const wxFSFile& file) const |
| 60 | { |
| 61 | wxInputStream *s = file.GetStream(); |
| 62 | char *src; |
| 63 | wxString doc; |
| 64 | |
| 65 | if (s == NULL) return wxEmptyString; |
| 66 | src = new char[s -> GetSize()+1]; |
| 67 | src[s -> GetSize()] = 0; |
| 68 | s -> Read(src, s -> GetSize()); |
| 69 | doc = src; |
| 70 | delete [] src; |
| 71 | return doc; |
| 72 | } |
| 73 | |
| 74 | virtual bool CanRead(const wxFSFile& file) const |
| 75 | { |
| 76 | wxString filename = file.GetLocation(); |
| 77 | if(filename.Length() >= 5 && |
| 78 | ( |
| 79 | filename.Right(4).MakeUpper() == ".HTM" || |
| 80 | filename.Right(5).MakeUpper() == ".HTML")) |
| 81 | return TRUE; |
| 82 | else |
| 83 | return FALSE; |
| 84 | } |
| 85 | }; |
| 86 | |
| 87 | #define FRAME_WIDTH 500 |
| 88 | #define FRAME_HEIGHT 400 |
| 89 | #define LAYOUT_X_MARGIN 2 |
| 90 | #define LAYOUT_Y_MARGIN 2 |
| 91 | #define OFFSET 10 |
| 92 | #define BUTTON_WIDTH 70 |
| 93 | #define MAX_COMBO_ENTRIES 25 |
| 94 | |
| 95 | class wxHelpFrame : public wxFrame |
| 96 | { |
| 97 | public: |
| 98 | wxHelpFrame(wxWindow *parent, int id, const wxString &title, |
| 99 | const wxPoint &pos, const wxSize &size, |
| 100 | wxHelpControllerHtml *controller); |
| 101 | ~wxHelpFrame(); |
| 102 | void OnClose(wxCloseEvent &ev); |
| 103 | void OnButton(wxCommandEvent &ev); |
| 104 | bool LoadPage(const wxString &url) { return m_htmlwin->LoadPage(url); } |
| 105 | private: |
| 106 | wxHelpControllerHtml *m_controller; |
| 107 | wxHtmlWindow *m_htmlwin; |
| 108 | wxHtmlFilter *m_filter; |
| 109 | wxComboBox *m_combo; |
| 110 | long m_IdBack, m_IdFwd, m_IdContents, m_IdCombo, m_IdSearch; |
| 111 | DECLARE_EVENT_TABLE() |
| 112 | }; |
| 113 | |
| 114 | BEGIN_EVENT_TABLE(wxHelpFrame, wxFrame) |
| 115 | EVT_CLOSE(wxHelpFrame::OnClose) |
| 116 | EVT_BUTTON(-1, wxHelpFrame::OnButton) |
| 117 | END_EVENT_TABLE() |
| 118 | |
| 119 | |
| 120 | void |
| 121 | wxHelpFrame::OnButton(wxCommandEvent &ev) |
| 122 | { |
| 123 | long id =ev.GetId(); |
| 124 | |
| 125 | if(id == m_IdBack) |
| 126 | m_htmlwin->HistoryBack(); |
| 127 | else if(id == m_IdFwd) |
| 128 | m_htmlwin->HistoryForward(); |
| 129 | else if(id == m_IdContents) |
| 130 | m_controller->DisplayContents(); |
| 131 | else if(id == m_IdSearch) |
| 132 | { |
| 133 | wxString str = m_combo->GetValue(); |
| 134 | if(m_combo->FindString(str) == -1 && m_combo->GetCount() < MAX_COMBO_ENTRIES) |
| 135 | m_combo->Append(str); |
| 136 | m_controller->KeywordSearch(str); |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | wxHelpFrame::wxHelpFrame(wxWindow *parent, int id, |
| 141 | const wxString &title, |
| 142 | const wxPoint &pos, const wxSize &size, |
| 143 | wxHelpControllerHtml *controller) |
| 144 | : wxFrame(parent, id, title, pos, size) |
| 145 | { |
| 146 | |
| 147 | m_controller = controller; |
| 148 | m_htmlwin = new wxHtmlWindow(this,-1,wxDefaultPosition,wxSize(FRAME_WIDTH, |
| 149 | FRAME_HEIGHT)); |
| 150 | |
| 151 | m_IdBack = wxWindow::NewControlId(); |
| 152 | m_IdFwd = wxWindow::NewControlId(); |
| 153 | m_IdContents = wxWindow::NewControlId(); |
| 154 | m_IdCombo = wxWindow::NewControlId(); |
| 155 | m_IdSearch = wxWindow::NewControlId(); |
| 156 | |
| 157 | wxButton *btn_back = new wxButton(this, m_IdBack, _("Back")); |
| 158 | wxButton *btn_fwd = new wxButton(this, m_IdFwd, _("Forward")); |
| 159 | wxButton *btn_contents = new wxButton(this, m_IdContents, _("Contents")); |
| 160 | m_combo = new wxComboBox(this, m_IdCombo); |
| 161 | wxButton *btn_search = new wxButton(this, m_IdSearch, _("Search")); |
| 162 | |
| 163 | m_filter = new wxForceHtmlFilter; |
| 164 | |
| 165 | wxLayoutConstraints *c; |
| 166 | |
| 167 | c = new wxLayoutConstraints; |
| 168 | c->left.SameAs(this, wxLeft, 2*LAYOUT_X_MARGIN); |
| 169 | c->width.Absolute(BUTTON_WIDTH); |
| 170 | c->top.SameAs(this, wxTop, 2*LAYOUT_Y_MARGIN); |
| 171 | c->height.AsIs(); |
| 172 | btn_back->SetConstraints(c); |
| 173 | |
| 174 | c = new wxLayoutConstraints; |
| 175 | c->left.SameAs(btn_back, wxRight, 2*LAYOUT_X_MARGIN); |
| 176 | c->width.Absolute(BUTTON_WIDTH); |
| 177 | c->top.SameAs(this, wxTop, 2*LAYOUT_Y_MARGIN); |
| 178 | c->height.AsIs(); |
| 179 | btn_fwd->SetConstraints(c); |
| 180 | |
| 181 | c = new wxLayoutConstraints; |
| 182 | c->left.SameAs(btn_fwd, wxRight, 2*LAYOUT_X_MARGIN); |
| 183 | c->width.Absolute(BUTTON_WIDTH); |
| 184 | c->top.SameAs(this, wxTop, 2*LAYOUT_Y_MARGIN); |
| 185 | c->height.AsIs(); |
| 186 | btn_contents->SetConstraints(c); |
| 187 | |
| 188 | c = new wxLayoutConstraints; |
| 189 | c->left.SameAs(btn_contents, wxRight, 2*LAYOUT_X_MARGIN); |
| 190 | c->width.Absolute(3*BUTTON_WIDTH); |
| 191 | c->top.SameAs(this, wxTop, 2*LAYOUT_Y_MARGIN); |
| 192 | c->height.AsIs(); |
| 193 | m_combo->SetConstraints(c); |
| 194 | |
| 195 | c = new wxLayoutConstraints; |
| 196 | c->left.SameAs(m_combo, wxRight, 2*LAYOUT_X_MARGIN); |
| 197 | c->width.Absolute(BUTTON_WIDTH); |
| 198 | c->top.SameAs(this, wxTop, 2*LAYOUT_Y_MARGIN); |
| 199 | c->height.AsIs(); |
| 200 | btn_search->SetConstraints(c); |
| 201 | |
| 202 | |
| 203 | c = new wxLayoutConstraints; |
| 204 | c->left.SameAs(this, wxLeft, 2*LAYOUT_X_MARGIN); |
| 205 | c->right.SameAs(this, wxRight, 2*LAYOUT_X_MARGIN); |
| 206 | c->top.SameAs(btn_back, wxBottom, 2*LAYOUT_Y_MARGIN); |
| 207 | c->bottom.SameAs(this, wxBottom, 2*LAYOUT_Y_MARGIN); |
| 208 | m_htmlwin->SetConstraints(c); |
| 209 | SetAutoLayout(TRUE); |
| 210 | CreateStatusBar(); |
| 211 | |
| 212 | m_htmlwin->SetRelatedFrame(this, title); |
| 213 | m_htmlwin->SetRelatedStatusBar(0); |
| 214 | m_htmlwin->AddFilter(m_filter); |
| 215 | |
| 216 | #ifdef __WXMOTIF__ |
| 217 | // Motif needs a nudge to get it to resize properly |
| 218 | // when shown |
| 219 | wxSizeEvent event(size, GetId()); |
| 220 | GetEventHandler()->ProcessEvent(event); |
| 221 | #endif |
| 222 | |
| 223 | Show(TRUE); |
| 224 | } |
| 225 | |
| 226 | wxHelpFrame::~wxHelpFrame() |
| 227 | { |
| 228 | } |
| 229 | |
| 230 | void |
| 231 | wxHelpFrame::OnClose(wxCloseEvent &WXUNUSED(ev)) |
| 232 | { |
| 233 | wxASSERT(m_controller); |
| 234 | m_controller->m_Frame = NULL; |
| 235 | bool newFrame; |
| 236 | int x,y; |
| 237 | GetPosition(&x,&y); |
| 238 | |
| 239 | m_controller->GetFrameParameters(NULL, NULL, &newFrame); |
| 240 | m_controller->SetFrameParameters(GetTitle(), GetSize(), |
| 241 | wxPoint(x,y), |
| 242 | newFrame); |
| 243 | Destroy(); |
| 244 | } |
| 245 | |
| 246 | wxHelpControllerHtml::wxHelpControllerHtml(void) |
| 247 | { |
| 248 | m_Frame = NULL; |
| 249 | m_offset = 0; |
| 250 | |
| 251 | SetFrameParameters(_("Help: %s"), |
| 252 | wxSize(FRAME_WIDTH, FRAME_HEIGHT), |
| 253 | wxDefaultPosition); |
| 254 | } |
| 255 | |
| 256 | wxHelpControllerHtml::~wxHelpControllerHtml(void) |
| 257 | { |
| 258 | if(m_Frame && ! m_NewFrameEachTime) |
| 259 | m_Frame->Close(); |
| 260 | } |
| 261 | |
| 262 | |
| 263 | #ifdef __WXMSW__ |
| 264 | # define SEP '\\' |
| 265 | #else |
| 266 | # define SEP '/' |
| 267 | #endif |
| 268 | |
| 269 | bool |
| 270 | wxHelpControllerHtml::DisplayHelp(const wxString &relativeURL) |
| 271 | { |
| 272 | wxBusyCursor b; // display a busy cursor |
| 273 | |
| 274 | wxString url; |
| 275 | url << m_MapFile << SEP<< relativeURL; |
| 276 | if(! m_Frame || m_NewFrameEachTime) |
| 277 | { |
| 278 | m_Frame = new wxHelpFrame(NULL, -1, m_FrameTitle, |
| 279 | m_FramePosition+wxPoint(m_offset,m_offset), |
| 280 | m_FrameSize, |
| 281 | this); |
| 282 | if(m_NewFrameEachTime) |
| 283 | { |
| 284 | m_offset += OFFSET; |
| 285 | if(m_offset > 200) |
| 286 | m_offset = 0; |
| 287 | } |
| 288 | |
| 289 | } |
| 290 | m_Frame->Raise(); |
| 291 | return m_Frame->LoadPage(url); |
| 292 | } |
| 293 | |
| 294 | |
| 295 | void |
| 296 | wxHelpControllerHtml::SetFrameParameters(const wxString &title, |
| 297 | const wxSize &size, |
| 298 | const wxPoint &pos, |
| 299 | bool newFrame) |
| 300 | { |
| 301 | m_FrameTitle = title; |
| 302 | m_FrameSize = size; |
| 303 | m_FramePosition = pos; |
| 304 | m_NewFrameEachTime = newFrame; |
| 305 | } |
| 306 | |
| 307 | wxFrame * |
| 308 | wxHelpControllerHtml::GetFrameParameters(wxSize *size, |
| 309 | wxPoint *pos, |
| 310 | bool *newframe) |
| 311 | { |
| 312 | if(size) *size = m_FrameSize; |
| 313 | if(pos) *pos = m_FramePosition; |
| 314 | if(newframe) *newframe = m_NewFrameEachTime; |
| 315 | return m_Frame; |
| 316 | } |
| 317 | |
| 318 | #endif // wxUSE_WXHTML_HELP |
| 319 | |