]> git.saurik.com Git - wxWidgets.git/blob - src/html/htmlwin.cpp
1. wxFrame doesn't show incorrect hints in the status bar for popup items
[wxWidgets.git] / src / html / htmlwin.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: htmlwin.cpp
3 // Purpose: wxHtmlWindow class for parsing & displaying HTML (implementation)
4 // Author: Vaclav Slavik
5 // Copyright: (c) 1999 Vaclav Slavik
6 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
8
9
10 #ifdef __GNUG__
11 #pragma implementation
12 #endif
13
14 #include <wx/wxprec.h>
15
16 #include "wx/defs.h"
17 #if wxUSE_HTML
18
19 #ifdef __BORDLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WXPRECOMP
24 #include <wx/wx.h>
25 #endif
26
27 #include <wx/html/htmlwin.h>
28
29 #include <wx/html/forcelink.h>
30
31 ///// This is my own wxBusyCursor. It works only with one window.
32
33 #if (defined __WXGTK__) && (wxVERSION_NUMBER < 2100)
34 class wxLocalBusyCursor
35 #else
36 class wxLocalBusyCursor : public wxBusyCursor
37 #endif
38 {
39 private:
40 wxWindow *m_Wnd;
41 public:
42 #if (defined __WXGTK__) && (wxVERSION_NUMBER < 2100)
43 wxLocalBusyCursor(wxWindow *w) {m_Wnd = w; m_Wnd -> SetCursor(*wxHOURGLASS_CURSOR);}
44 ~wxLocalBusyCursor() {m_Wnd -> SetCursor(*wxSTANDARD_CURSOR);}
45 #else
46 wxLocalBusyCursor(wxWindow *w) : wxBusyCursor() {}
47 #endif
48 };
49
50
51
52
53 //-----------------------------------------------------------------------------
54 // wxHtmlWindow
55 //-----------------------------------------------------------------------------
56
57
58
59 #include <wx/arrimpl.cpp>
60 WX_DEFINE_OBJARRAY(HtmlHistoryArray)
61
62
63 wxHtmlWindow::wxHtmlWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
64 const wxString& name, bool scrollable) : wxScrolledWindow(parent, id, pos, size, wxVSCROLL, name)
65 {
66 m_tmpMouseMoved = FALSE;
67 m_tmpCanDraw = TRUE;
68 m_FS = new wxFileSystem();
69 m_RelatedStatusBar = -1;
70 m_RelatedFrame = NULL;
71 m_TitleFormat = "%s";
72 m_OpenedPage = m_OpenedAnchor = wxEmptyString;
73 m_Cell = NULL;
74 m_Parser = new wxHtmlWinParser(this);
75 m_Parser -> SetFS(m_FS);
76 SetBorders(10);
77 m_HistoryPos = -1;
78 m_HistoryOn = TRUE;
79 m_Scrollable = scrollable;
80 SetPage("<html><body></body></html>");
81 }
82
83
84
85 wxHtmlWindow::~wxHtmlWindow()
86 {
87 HistoryClear();
88
89 if (m_Cell) delete m_Cell;
90
91 wxList *parser_data = m_Parser -> GetTempData();
92 if (parser_data) delete parser_data;
93
94 delete m_Parser;
95 delete m_FS;
96 }
97
98
99
100 void wxHtmlWindow::SetRelatedFrame(wxFrame* frame, const wxString& format)
101 {
102 m_RelatedFrame = frame;
103 m_TitleFormat = format;
104 }
105
106
107
108 void wxHtmlWindow::SetRelatedStatusBar(int bar)
109 {
110 m_RelatedStatusBar = bar;
111 }
112
113
114
115 void wxHtmlWindow::SetFonts(wxString normal_face, int normal_italic_mode, wxString fixed_face, int fixed_italic_mode, int *sizes)
116 {
117 m_Parser -> SetFonts(normal_face, normal_italic_mode, fixed_face, fixed_italic_mode, sizes);
118 if (!m_OpenedPage.IsEmpty()) LoadPage(m_OpenedPage);
119 }
120
121
122
123 bool wxHtmlWindow::SetPage(const wxString& source)
124 {
125 wxClientDC *dc = new wxClientDC(this);
126
127 dc -> SetMapMode(wxMM_TEXT);
128 SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF));
129 m_OpenedPage = m_OpenedAnchor = wxEmptyString;
130 m_Parser -> SetDC(dc);
131 if (m_Cell) delete m_Cell;
132 m_Cell = (wxHtmlContainerCell*) m_Parser -> Parse(source);
133 delete dc;
134 m_Cell -> SetIndent(m_Borders, HTML_INDENT_ALL, HTML_UNITS_PIXELS);
135 m_Cell -> SetAlignHor(HTML_ALIGN_CENTER);
136 CreateLayout();
137 Refresh();
138 return TRUE;
139 }
140
141
142 bool wxHtmlWindow::LoadPage(const wxString& location)
143 {
144 wxFSFile *f;
145 bool rt_val;
146 wxLocalBusyCursor b(this);
147
148 m_tmpCanDraw = FALSE;
149 if (m_HistoryOn && (m_HistoryPos != -1)) { // store scroll position into history item
150 int x, y;
151 ViewStart(&x, &y);
152 m_History[m_HistoryPos].SetPos(y);
153 }
154
155 if (location[0] == '#') { // local anchor
156 wxString anch = location.Mid(1) /*1 to end*/;
157 m_tmpCanDraw = TRUE;
158 rt_val = ScrollToAnchor(anch);
159 }
160
161 else {
162 // load&display it:
163 if (m_RelatedStatusBar != -1) {
164 m_RelatedFrame -> SetStatusText(_("Connecting..."), m_RelatedStatusBar);
165 Refresh();
166 }
167
168 f = m_FS -> OpenFile(location);
169 if (f == NULL) {
170 wxString err;
171
172 err.Printf(_("The browser is unable to open requested location :\n\n%s"), WXSTRINGCAST location);
173 wxMessageBox(err, "Error");
174 m_tmpCanDraw = TRUE;
175 return FALSE;
176 }
177
178 else {
179 wxNode *node;
180 wxString src = wxEmptyString;
181
182 if (m_RelatedStatusBar != -1) {
183 wxString msg = _("Loading : ") + location;
184 m_RelatedFrame -> SetStatusText(msg, m_RelatedStatusBar);
185 Refresh();
186 }
187
188 node = m_Filters.GetFirst();
189 while (node){
190 wxHtmlFilter *h = (wxHtmlFilter*) node -> GetData();
191 if (h -> CanRead(*f)) {
192 src = h -> ReadFile(*f);
193 break;
194 }
195 node = node -> GetNext();
196 }
197 if (src == wxEmptyString) src = m_DefaultFilter.ReadFile(*f);
198
199 m_FS -> ChangePathTo(f -> GetLocation());
200 rt_val = SetPage(src);
201 m_OpenedPage = f -> GetLocation();
202 if (f -> GetAnchor() != wxEmptyString) {
203 m_tmpCanDraw = TRUE;
204 ScrollToAnchor(f -> GetAnchor());
205 m_tmpCanDraw = FALSE;
206 }
207
208 delete f;
209
210 if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(_("Done"), m_RelatedStatusBar);
211 }
212 }
213
214 if (m_HistoryOn) { // add this page to history there:
215 int c = m_History.GetCount() - (m_HistoryPos + 1);
216
217 m_HistoryPos++;
218 for (int i = 0; i < c; i++)
219 m_History.Remove(m_HistoryPos);
220 m_History.Add(new HtmlHistoryItem(m_OpenedPage, m_OpenedAnchor));
221 }
222
223 m_tmpCanDraw = TRUE;
224 Refresh();
225 return rt_val;
226 }
227
228
229
230 bool wxHtmlWindow::ScrollToAnchor(const wxString& anchor)
231 {
232 const wxHtmlCell *c = m_Cell -> Find(HTML_COND_ISANCHOR, &anchor);
233 if (!c) return FALSE;
234 else {
235 int y;
236
237 for (y = 0; c != NULL; c = c -> GetParent()) y += c -> GetPosY();
238 Scroll(-1, y / HTML_SCROLL_STEP);
239 m_OpenedAnchor = anchor;
240 return TRUE;
241 }
242 }
243
244
245 void wxHtmlWindow::SetTitle(const wxString& title)
246 {
247 if (m_RelatedFrame) {
248 wxString tit;
249 tit.Printf(m_TitleFormat, title.c_str());
250 m_RelatedFrame -> SetTitle(tit);
251 }
252 }
253
254
255
256
257
258 void wxHtmlWindow::CreateLayout()
259 {
260 int ClientWidth, ClientHeight;
261
262 if (!m_Cell) return;
263 GetClientSize(&ClientWidth, &ClientHeight);
264 m_Cell -> Layout(ClientWidth);
265 if (m_Scrollable)
266 SetScrollbars(HTML_SCROLL_STEP, HTML_SCROLL_STEP,
267 m_Cell -> GetWidth() / HTML_SCROLL_STEP,
268 m_Cell -> GetHeight() / HTML_SCROLL_STEP
269 /*cheat: top-level frag is always container*/ );
270 }
271
272
273
274 void wxHtmlWindow::ReadCustomization(wxConfigBase *cfg, wxString path)
275 {
276 wxString oldpath;
277 wxString tmp;
278
279 if (path != wxEmptyString) {
280 oldpath = cfg -> GetPath();
281 cfg -> SetPath(path);
282 }
283
284 m_Borders = cfg -> Read("wxHtmlWindow/Borders", m_Borders);
285 m_Parser -> m_FontFaceFixed = cfg -> Read("wxHtmlWindow/FontFaceFixed", m_Parser -> m_FontFaceFixed);
286 m_Parser -> m_FontFaceNormal = cfg -> Read("wxHtmlWindow/FontFaceNormal", m_Parser -> m_FontFaceNormal);
287 m_Parser -> m_ItalicModeFixed = cfg -> Read("wxHtmlWindow/ItalicModeFixed", m_Parser -> m_ItalicModeFixed);
288 m_Parser -> m_ItalicModeNormal = cfg -> Read("wxHtmlWindow/ItalicModeNormal", m_Parser -> m_ItalicModeNormal);
289 for (int i = 0; i < 7; i++) {
290 tmp.Printf("wxHtmlWindow/FontsSize%i", i);
291 m_Parser -> m_FontsSizes[i] = cfg -> Read(tmp, m_Parser -> m_FontsSizes[i]);
292 }
293
294 if (path != wxEmptyString)
295 cfg -> SetPath(oldpath);
296 }
297
298
299
300 void wxHtmlWindow::WriteCustomization(wxConfigBase *cfg, wxString path)
301 {
302 wxString oldpath;
303 wxString tmp;
304
305 if (path != wxEmptyString) {
306 oldpath = cfg -> GetPath();
307 cfg -> SetPath(path);
308 }
309
310 cfg -> Write("wxHtmlWindow/Borders", (long) m_Borders);
311 cfg -> Write("wxHtmlWindow/FontFaceFixed", m_Parser -> m_FontFaceFixed);
312 cfg -> Write("wxHtmlWindow/FontFaceNormal", m_Parser -> m_FontFaceNormal);
313 cfg -> Write("wxHtmlWindow/ItalicModeFixed", (long) m_Parser -> m_ItalicModeFixed);
314 cfg -> Write("wxHtmlWindow/ItalicModeNormal", (long) m_Parser -> m_ItalicModeNormal);
315 for (int i = 0; i < 7; i++) {
316 tmp.Printf("wxHtmlWindow/FontsSize%i", i);
317 cfg -> Write(tmp, (long) m_Parser -> m_FontsSizes[i]);
318 }
319
320 if (path != wxEmptyString)
321 cfg -> SetPath(oldpath);
322 }
323
324
325
326 bool wxHtmlWindow::HistoryBack()
327 {
328 wxString a, l;
329
330 if (m_HistoryPos < 1) return FALSE;
331
332 m_HistoryPos--;
333
334 l = m_History[m_HistoryPos].GetPage();
335 a = m_History[m_HistoryPos].GetAnchor();
336 m_HistoryOn = FALSE;
337 if (a == wxEmptyString) LoadPage(l);
338 else LoadPage(l + "#" + a);
339 m_HistoryOn = TRUE;
340 Scroll(0, m_History[m_HistoryPos].GetPos());
341 Refresh();
342 return TRUE;
343 }
344
345
346
347 bool wxHtmlWindow::HistoryForward()
348 {
349 wxString a, l;
350
351 if (m_HistoryPos == -1) return FALSE;
352 if (m_HistoryPos >= (int)m_History.GetCount() - 1)return FALSE;
353
354 m_OpenedPage = wxEmptyString; // this will disable adding new entry into history in LoadPage()
355
356 m_HistoryPos++;
357 l = m_History[m_HistoryPos].GetPage();
358 a = m_History[m_HistoryPos].GetAnchor();
359 m_HistoryOn = FALSE;
360 if (a == wxEmptyString) LoadPage(l);
361 else LoadPage(l + "#" + a);
362 m_HistoryOn = TRUE;
363 Scroll(0, m_History[m_HistoryPos].GetPos());
364 Refresh();
365 return TRUE;
366 }
367
368
369
370 void wxHtmlWindow::HistoryClear()
371 {
372 m_History.Empty();
373 m_HistoryPos = -1;
374 }
375
376
377
378 wxList wxHtmlWindow::m_Filters;
379 wxHtmlFilterPlainText wxHtmlWindow::m_DefaultFilter;
380
381 void wxHtmlWindow::AddFilter(wxHtmlFilter *filter)
382 {
383 m_Filters.DeleteContents(TRUE);
384 m_Filters.Append(filter);
385 }
386
387
388
389
390 void wxHtmlWindow::OnLinkClicked(const wxString& link)
391 {
392 LoadPage(link);
393 }
394
395
396
397 void wxHtmlWindow::OnDraw(wxDC& dc)
398 {
399 int x, y;
400 wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
401 int v_y, v_h;
402
403 if (!m_tmpCanDraw) return;
404 dc.SetMapMode(wxMM_TEXT);
405 #if defined(_MSC_VER) && (_MSC_VER == 1200)
406 ::SetMapMode((HDC)dc.GetHDC(), MM_TEXT);
407 #endif
408 dc.SetBackgroundMode(wxTRANSPARENT);
409 ViewStart(&x, &y);
410
411 while (upd) {
412 v_y = upd.GetY();
413 v_h = upd.GetH();
414 if (m_Cell) m_Cell -> Draw(dc, 0, 0, y * HTML_SCROLL_STEP + v_y, y * HTML_SCROLL_STEP + v_h + v_y);
415 upd++;
416 }
417 }
418
419
420
421
422 void wxHtmlWindow::OnSize(wxSizeEvent& event)
423 {
424 wxScrolledWindow::OnSize(event);
425 CreateLayout();
426 }
427
428
429
430 void wxHtmlWindow::OnKeyDown(wxKeyEvent& event)
431 {
432 int dummy;
433 int sty, szy, cliy;
434
435 ViewStart(&dummy, &sty);
436 GetClientSize(&dummy, &cliy); cliy /= HTML_SCROLL_STEP;
437 GetVirtualSize(&dummy, &szy); szy /= HTML_SCROLL_STEP;
438
439 switch (event.KeyCode()) {
440 case WXK_PAGEUP :
441 case WXK_PRIOR :
442 Scroll(-1, sty - cliy);
443 break;
444 case WXK_PAGEDOWN :
445 case WXK_NEXT :
446 Scroll(-1, sty + cliy);
447 break;
448 case WXK_HOME :
449 Scroll(-1, 0);
450 break;
451 case WXK_END :
452 Scroll(-1, szy - cliy);
453 break;
454 case WXK_UP :
455 Scroll(-1, sty - 1);
456 break;
457 case WXK_DOWN :
458 Scroll(-1, sty + 1);
459 break;
460 }
461 }
462
463
464
465 void wxHtmlWindow::OnMouseEvent(wxMouseEvent& event)
466 {
467 m_tmpMouseMoved = TRUE;
468
469 if (event.ButtonDown()) {
470 int sx, sy;
471 wxPoint pos;
472 wxString lnk;
473
474 ViewStart(&sx, &sy); sx *= HTML_SCROLL_STEP; sy *= HTML_SCROLL_STEP;
475 pos = event.GetPosition();
476
477 if (m_Cell)
478 m_Cell -> OnMouseClick(this, sx + pos.x, sy + pos.y, event.ButtonDown(1), event.ButtonDown(2), event.ButtonDown(3));
479 }
480 }
481
482
483
484 void wxHtmlWindow::OnIdle(wxIdleEvent& event)
485 {
486 static wxCursor cur_hand(wxCURSOR_HAND), cur_arrow(wxCURSOR_ARROW);
487
488 if (m_tmpMouseMoved && (m_Cell != NULL)) {
489 int sx, sy;
490 int x, y;
491 wxString lnk;
492
493 ViewStart(&sx, &sy); sx *= HTML_SCROLL_STEP; sy *= HTML_SCROLL_STEP;
494 wxGetMousePosition(&x, &y);
495 ScreenToClient(&x, &y);
496 lnk = m_Cell -> GetLink(sx + x, sy + y);
497
498 if (lnk == wxEmptyString) {
499 SetCursor(cur_arrow);
500 if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(wxEmptyString, m_RelatedStatusBar);
501 }
502 else {
503 SetCursor(cur_hand);
504 if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(lnk, m_RelatedStatusBar);
505 }
506 m_tmpMouseMoved = FALSE;
507 }
508 }
509
510
511
512
513 IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow)
514
515 BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
516 EVT_SIZE(wxHtmlWindow::OnSize)
517 EVT_LEFT_DOWN(wxHtmlWindow::OnMouseEvent)
518 EVT_MOTION(wxHtmlWindow::OnMouseEvent)
519 EVT_IDLE(wxHtmlWindow::OnIdle)
520 EVT_KEY_DOWN(wxHtmlWindow::OnKeyDown)
521 END_EVENT_TABLE()
522
523
524
525
526
527
528
529
530 ///// default mod handlers are forced there:
531
532 FORCE_LINK(mod_layout)
533 FORCE_LINK(mod_fonts)
534 FORCE_LINK(mod_image)
535 FORCE_LINK(mod_list)
536 FORCE_LINK(mod_pre)
537 FORCE_LINK(mod_hline)
538 FORCE_LINK(mod_links)
539 FORCE_LINK(mod_tables)
540
541
542 #endif