Include wx/settings.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / html / htmlcell.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/html/htmlcell.cpp
3 // Purpose: wxHtmlCell - basic element of HTML output
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id$
6 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #include "wx/wxprec.h"
11
12 #ifdef __BORLANDC__
13 #pragma hdrstop
14 #endif
15
16 #if wxUSE_HTML && wxUSE_STREAMS
17
18 #ifndef WXPRECOMP
19 #include "wx/dynarray.h"
20 #include "wx/brush.h"
21 #include "wx/colour.h"
22 #include "wx/dc.h"
23 #include "wx/settings.h"
24 #endif
25
26 #include "wx/html/htmlcell.h"
27 #include "wx/html/htmlwin.h"
28 #include "wx/module.h"
29
30 #include <stdlib.h>
31
32 //-----------------------------------------------------------------------------
33 // Helper classes
34 //-----------------------------------------------------------------------------
35
36 void wxHtmlSelection::Set(const wxPoint& fromPos, const wxHtmlCell *fromCell,
37 const wxPoint& toPos, const wxHtmlCell *toCell)
38 {
39 m_fromCell = fromCell;
40 m_toCell = toCell;
41 m_fromPos = fromPos;
42 m_toPos = toPos;
43 }
44
45 void wxHtmlSelection::Set(const wxHtmlCell *fromCell, const wxHtmlCell *toCell)
46 {
47 wxPoint p1 = fromCell ? fromCell->GetAbsPos() : wxDefaultPosition;
48 wxPoint p2 = toCell ? toCell->GetAbsPos() : wxDefaultPosition;
49 if ( toCell )
50 {
51 p2.x += toCell->GetWidth();
52 p2.y += toCell->GetHeight();
53 }
54 Set(p1, fromCell, p2, toCell);
55 }
56
57 wxColour
58 wxDefaultHtmlRenderingStyle::
59 GetSelectedTextColour(const wxColour& WXUNUSED(clr))
60 {
61 return wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
62 }
63
64 wxColour
65 wxDefaultHtmlRenderingStyle::
66 GetSelectedTextBgColour(const wxColour& WXUNUSED(clr))
67 {
68 return wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
69 }
70
71
72 //-----------------------------------------------------------------------------
73 // wxHtmlCell
74 //-----------------------------------------------------------------------------
75
76 IMPLEMENT_ABSTRACT_CLASS(wxHtmlCell, wxObject)
77
78 wxHtmlCell::wxHtmlCell() : wxObject()
79 {
80 m_Next = NULL;
81 m_Parent = NULL;
82 m_Width = m_Height = m_Descent = 0;
83 m_ScriptMode = wxHTML_SCRIPT_NORMAL; // <sub> or <sup> mode
84 m_ScriptBaseline = 0; // <sub> or <sup> baseline
85 m_CanLiveOnPagebreak = true;
86 m_Link = NULL;
87 }
88
89 wxHtmlCell::~wxHtmlCell()
90 {
91 delete m_Link;
92 }
93
94 // Update the descent value when whe are in a <sub> or <sup>.
95 // prevbase is the parent base
96 void wxHtmlCell::SetScriptMode(wxHtmlScriptMode mode, long previousBase)
97 {
98 m_ScriptMode = mode;
99
100 if (mode == wxHTML_SCRIPT_SUP)
101 m_ScriptBaseline = previousBase - (m_Height + 1) / 2;
102 else if (mode == wxHTML_SCRIPT_SUB)
103 m_ScriptBaseline = previousBase + (m_Height + 1) / 6;
104 else
105 m_ScriptBaseline = 0;
106
107 m_Descent += m_ScriptBaseline;
108 }
109
110 #if WXWIN_COMPATIBILITY_2_6
111
112 struct wxHtmlCellOnMouseClickCompatHelper;
113
114 static wxHtmlCellOnMouseClickCompatHelper *gs_helperOnMouseClick = NULL;
115
116 // helper for routing calls to new ProcessMouseClick() method to deprecated
117 // OnMouseClick() method
118 struct wxHtmlCellOnMouseClickCompatHelper
119 {
120 wxHtmlCellOnMouseClickCompatHelper(wxHtmlWindowInterface *window_,
121 const wxPoint& pos_,
122 const wxMouseEvent& event_)
123 : window(window_), pos(pos_), event(event_), retval(false)
124 {
125 }
126
127 bool CallOnMouseClick(wxHtmlCell *cell)
128 {
129 wxHtmlCellOnMouseClickCompatHelper *oldHelper = gs_helperOnMouseClick;
130 gs_helperOnMouseClick = this;
131 cell->OnMouseClick
132 (
133 window ? window->GetHTMLWindow() : NULL,
134 pos.x, pos.y,
135 event
136 );
137 gs_helperOnMouseClick = oldHelper;
138 return retval;
139 }
140
141 wxHtmlWindowInterface *window;
142 const wxPoint& pos;
143 const wxMouseEvent& event;
144 bool retval;
145 };
146 #endif // WXWIN_COMPATIBILITY_2_6
147
148 bool wxHtmlCell::ProcessMouseClick(wxHtmlWindowInterface *window,
149 const wxPoint& pos,
150 const wxMouseEvent& event)
151 {
152 wxCHECK_MSG( window, false, _T("window interface must be provided") );
153
154 #if WXWIN_COMPATIBILITY_2_6
155 // NB: this hack puts the body of ProcessMouseClick() into OnMouseClick()
156 // (for which it has to pass the arguments and return value via a
157 // helper variable because these two methods have different
158 // signatures), so that old code overriding OnMouseClick will continue
159 // to work
160 wxHtmlCellOnMouseClickCompatHelper compat(window, pos, event);
161 return compat.CallOnMouseClick(this);
162 }
163
164 void wxHtmlCell::OnMouseClick(wxWindow *, int, int, const wxMouseEvent& event)
165 {
166 wxCHECK_RET( gs_helperOnMouseClick, _T("unexpected call to OnMouseClick") );
167 wxHtmlWindowInterface *window = gs_helperOnMouseClick->window;
168 const wxPoint& pos = gs_helperOnMouseClick->pos;
169 #endif // WXWIN_COMPATIBILITY_2_6
170
171 wxHtmlLinkInfo *lnk = GetLink(pos.x, pos.y);
172 bool retval = false;
173
174 if (lnk)
175 {
176 wxHtmlLinkInfo lnk2(*lnk);
177 lnk2.SetEvent(&event);
178 lnk2.SetHtmlCell(this);
179
180 window->OnHTMLLinkClicked(lnk2);
181 retval = true;
182 }
183
184 #if WXWIN_COMPATIBILITY_2_6
185 gs_helperOnMouseClick->retval = retval;
186 #else
187 return retval;
188 #endif // WXWIN_COMPATIBILITY_2_6
189 }
190
191 #if WXWIN_COMPATIBILITY_2_6
192 wxCursor wxHtmlCell::GetCursor() const
193 {
194 return wxNullCursor;
195 }
196 #endif // WXWIN_COMPATIBILITY_2_6
197
198 wxCursor wxHtmlCell::GetMouseCursor(wxHtmlWindowInterface *window) const
199 {
200 #if WXWIN_COMPATIBILITY_2_6
201 // NB: Older versions of wx used GetCursor() virtual method in place of
202 // GetMouseCursor(interface). This code ensures that user code that
203 // overriden GetCursor() continues to work. The trick is that the base
204 // wxHtmlCell::GetCursor() method simply returns wxNullCursor, so we
205 // know that GetCursor() was overriden iff it returns valid cursor.
206 wxCursor cur = GetCursor();
207 if (cur.Ok())
208 return cur;
209 #endif // WXWIN_COMPATIBILITY_2_6
210
211 if ( GetLink() )
212 {
213 return window->GetHTMLCursor(wxHtmlWindowInterface::HTMLCursor_Link);
214 }
215 else
216 {
217 return window->GetHTMLCursor(wxHtmlWindowInterface::HTMLCursor_Default);
218 }
219 }
220
221
222 bool wxHtmlCell::AdjustPagebreak(int *pagebreak, int* WXUNUSED(known_pagebreaks), int WXUNUSED(number_of_pages)) const
223 {
224 if ((!m_CanLiveOnPagebreak) &&
225 m_PosY < *pagebreak && m_PosY + m_Height > *pagebreak)
226 {
227 *pagebreak = m_PosY;
228 return true;
229 }
230
231 return false;
232 }
233
234
235
236 void wxHtmlCell::SetLink(const wxHtmlLinkInfo& link)
237 {
238 if (m_Link) delete m_Link;
239 m_Link = NULL;
240 if (link.GetHref() != wxEmptyString)
241 m_Link = new wxHtmlLinkInfo(link);
242 }
243
244
245 void wxHtmlCell::Layout(int WXUNUSED(w))
246 {
247 SetPos(0, 0);
248 }
249
250
251
252 const wxHtmlCell* wxHtmlCell::Find(int WXUNUSED(condition), const void* WXUNUSED(param)) const
253 {
254 return NULL;
255 }
256
257
258 wxHtmlCell *wxHtmlCell::FindCellByPos(wxCoord x, wxCoord y,
259 unsigned flags) const
260 {
261 if ( x >= 0 && x < m_Width && y >= 0 && y < m_Height )
262 {
263 return wxConstCast(this, wxHtmlCell);
264 }
265 else
266 {
267 if ((flags & wxHTML_FIND_NEAREST_AFTER) &&
268 (y < 0 || (y < 0+m_Height && x < 0+m_Width)))
269 return wxConstCast(this, wxHtmlCell);
270 else if ((flags & wxHTML_FIND_NEAREST_BEFORE) &&
271 (y >= 0+m_Height || (y >= 0 && x >= 0)))
272 return wxConstCast(this, wxHtmlCell);
273 else
274 return NULL;
275 }
276 }
277
278
279 wxPoint wxHtmlCell::GetAbsPos(wxHtmlCell *rootCell) const
280 {
281 wxPoint p(m_PosX, m_PosY);
282 for (wxHtmlCell *parent = m_Parent; parent && parent != rootCell;
283 parent = parent->m_Parent)
284 {
285 p.x += parent->m_PosX;
286 p.y += parent->m_PosY;
287 }
288 return p;
289 }
290
291 wxHtmlCell *wxHtmlCell::GetRootCell() const
292 {
293 wxHtmlCell *c = wxConstCast(this, wxHtmlCell);
294 while ( c->m_Parent )
295 c = c->m_Parent;
296 return c;
297 }
298
299 unsigned wxHtmlCell::GetDepth() const
300 {
301 unsigned d = 0;
302 for (wxHtmlCell *p = m_Parent; p; p = p->m_Parent)
303 d++;
304 return d;
305 }
306
307 bool wxHtmlCell::IsBefore(wxHtmlCell *cell) const
308 {
309 const wxHtmlCell *c1 = this;
310 const wxHtmlCell *c2 = cell;
311 unsigned d1 = GetDepth();
312 unsigned d2 = cell->GetDepth();
313
314 if ( d1 > d2 )
315 for (; d1 != d2; d1-- )
316 c1 = c1->m_Parent;
317 else if ( d1 < d2 )
318 for (; d1 != d2; d2-- )
319 c2 = c2->m_Parent;
320
321 if ( cell == this )
322 return true;
323
324 while ( c1 && c2 )
325 {
326 if ( c1->m_Parent == c2->m_Parent )
327 {
328 while ( c1 )
329 {
330 if ( c1 == c2 )
331 return true;
332 c1 = c1->GetNext();
333 }
334 return false;
335 }
336 else
337 {
338 c1 = c1->m_Parent;
339 c2 = c2->m_Parent;
340 }
341 }
342
343 wxFAIL_MSG(_T("Cells are in different trees"));
344 return false;
345 }
346
347
348 //-----------------------------------------------------------------------------
349 // wxHtmlWordCell
350 //-----------------------------------------------------------------------------
351
352 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWordCell, wxHtmlCell)
353
354 wxHtmlWordCell::wxHtmlWordCell(const wxString& word, const wxDC& dc) : wxHtmlCell()
355 {
356 m_Word = word;
357 dc.GetTextExtent(m_Word, &m_Width, &m_Height, &m_Descent);
358 SetCanLiveOnPagebreak(false);
359 m_allowLinebreak = true;
360 }
361
362 void wxHtmlWordCell::SetPreviousWord(wxHtmlWordCell *cell)
363 {
364 if ( cell && m_Parent == cell->m_Parent &&
365 !wxIsspace(cell->m_Word.Last()) && !wxIsspace(m_Word[0u]) )
366 {
367 m_allowLinebreak = false;
368 }
369 }
370
371 // Splits m_Word into up to three parts according to selection, returns
372 // substring before, in and after selection and the points (in relative coords)
373 // where s2 and s3 start:
374 void wxHtmlWordCell::Split(const wxDC& dc,
375 const wxPoint& selFrom, const wxPoint& selTo,
376 unsigned& pos1, unsigned& pos2) const
377 {
378 wxPoint pt1 = (selFrom == wxDefaultPosition) ?
379 wxDefaultPosition : selFrom - GetAbsPos();
380 wxPoint pt2 = (selTo == wxDefaultPosition) ?
381 wxPoint(m_Width, wxDefaultCoord) : selTo - GetAbsPos();
382
383 unsigned len = m_Word.length();
384 unsigned i = 0;
385 pos1 = 0;
386
387 // adjust for cases when the start/end position is completely
388 // outside the cell:
389 if ( pt1.y < 0 )
390 pt1.x = 0;
391 if ( pt2.y >= m_Height )
392 pt2.x = m_Width;
393
394 // before selection:
395 #ifdef __WXMAC__
396 // implementation using PartialExtents to support fractional widths
397 wxArrayInt widths ;
398 dc.GetPartialTextExtents(m_Word,widths) ;
399 while( i < len && pt1.x >= widths[i] )
400 i++ ;
401 #else // __WXMAC__
402 wxCoord charW, charH;
403 while ( pt1.x > 0 && i < len )
404 {
405 dc.GetTextExtent(m_Word[i], &charW, &charH);
406 pt1.x -= charW;
407 if ( pt1.x >= 0 )
408 {
409 pos1 += charW;
410 i++;
411 }
412 }
413 #endif // __WXMAC__/!__WXMAC__
414
415 // in selection:
416 unsigned j = i;
417 #ifdef __WXMAC__
418 while( j < len && pt2.x >= widths[j] )
419 j++ ;
420 #else // __WXMAC__
421 pos2 = pos1;
422 pt2.x -= pos2;
423 while ( pt2.x > 0 && j < len )
424 {
425 dc.GetTextExtent(m_Word[j], &charW, &charH);
426 pt2.x -= charW;
427 if ( pt2.x >= 0 )
428 {
429 pos2 += charW;
430 j++;
431 }
432 }
433 #endif // __WXMAC__/!__WXMAC__
434
435 pos1 = i;
436 pos2 = j;
437 }
438
439 void wxHtmlWordCell::SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const
440 {
441 unsigned p1, p2;
442
443 Split(dc,
444 this == s->GetFromCell() ? s->GetFromPos() : wxDefaultPosition,
445 this == s->GetToCell() ? s->GetToPos() : wxDefaultPosition,
446 p1, p2);
447
448 wxPoint p(0, m_Word.length());
449
450 if ( this == s->GetFromCell() )
451 p.x = p1; // selection starts here
452 if ( this == s->GetToCell() )
453 p.y = p2; // selection ends here
454
455 if ( this == s->GetFromCell() )
456 s->SetFromPrivPos(p);
457 if ( this == s->GetToCell() )
458 s->SetToPrivPos(p);
459 }
460
461
462 static void SwitchSelState(wxDC& dc, wxHtmlRenderingInfo& info,
463 bool toSelection)
464 {
465 wxColour fg = info.GetState().GetFgColour();
466 wxColour bg = info.GetState().GetBgColour();
467
468 if ( toSelection )
469 {
470 dc.SetBackgroundMode(wxSOLID);
471 dc.SetTextForeground(info.GetStyle().GetSelectedTextColour(fg));
472 dc.SetTextBackground(info.GetStyle().GetSelectedTextBgColour(bg));
473 dc.SetBackground(wxBrush(info.GetStyle().GetSelectedTextBgColour(bg),
474 wxSOLID));
475 }
476 else
477 {
478 dc.SetBackgroundMode(wxTRANSPARENT);
479 dc.SetTextForeground(fg);
480 dc.SetTextBackground(bg);
481 dc.SetBackground(wxBrush(bg, wxSOLID));
482 }
483 }
484
485
486 void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
487 int WXUNUSED(view_y1), int WXUNUSED(view_y2),
488 wxHtmlRenderingInfo& info)
489 {
490 #if 0 // useful for debugging
491 dc.SetPen(*wxBLACK_PEN);
492 dc.DrawRectangle(x+m_PosX,y+m_PosY,m_Width /* VZ: +1? */ ,m_Height);
493 #endif
494
495 bool drawSelectionAfterCell = false;
496
497 if ( info.GetState().GetSelectionState() == wxHTML_SEL_CHANGING )
498 {
499 // Selection changing, we must draw the word piecewise:
500 wxHtmlSelection *s = info.GetSelection();
501 wxString txt;
502 int w, h;
503 int ofs = 0;
504
505 wxPoint priv = (this == s->GetFromCell()) ?
506 s->GetFromPrivPos() : s->GetToPrivPos();
507
508 // NB: this is quite a hack: in order to compute selection boundaries
509 // (in word's characters) we must know current font, which is only
510 // possible inside rendering code. Therefore we update the
511 // information here and store it in wxHtmlSelection so that
512 // ConvertToText can use it later:
513 if ( priv == wxDefaultPosition )
514 {
515 SetSelectionPrivPos(dc, s);
516 priv = (this == s->GetFromCell()) ?
517 s->GetFromPrivPos() : s->GetToPrivPos();
518 }
519
520 int part1 = priv.x;
521 int part2 = priv.y;
522
523 if ( part1 > 0 )
524 {
525 txt = m_Word.Mid(0, part1);
526 dc.DrawText(txt, x + m_PosX, y + m_PosY);
527 dc.GetTextExtent(txt, &w, &h);
528 ofs += w;
529 }
530
531 SwitchSelState(dc, info, true);
532
533 txt = m_Word.Mid(part1, part2-part1);
534 dc.DrawText(txt, ofs + x + m_PosX, y + m_PosY);
535
536 if ( (size_t)part2 < m_Word.length() )
537 {
538 dc.GetTextExtent(txt, &w, &h);
539 ofs += w;
540 SwitchSelState(dc, info, false);
541 txt = m_Word.Mid(part2);
542 dc.DrawText(txt, ofs + x + m_PosX, y + m_PosY);
543 }
544 else
545 drawSelectionAfterCell = true;
546 }
547 else
548 {
549 wxHtmlSelectionState selstate = info.GetState().GetSelectionState();
550 // Not changing selection state, draw the word in single mode:
551 if ( selstate != wxHTML_SEL_OUT &&
552 dc.GetBackgroundMode() != wxSOLID )
553 {
554 SwitchSelState(dc, info, true);
555 }
556 else if ( selstate == wxHTML_SEL_OUT &&
557 dc.GetBackgroundMode() == wxSOLID )
558 {
559 SwitchSelState(dc, info, false);
560 }
561 dc.DrawText(m_Word, x + m_PosX, y + m_PosY);
562 drawSelectionAfterCell = (selstate != wxHTML_SEL_OUT);
563 }
564
565 // NB: If the text is justified then there is usually some free space
566 // between adjacent cells and drawing the selection only onto cells
567 // would result in ugly unselected spaces. The code below detects
568 // this special case and renders the selection *outside* the sell,
569 // too.
570 if ( m_Parent->GetAlignHor() == wxHTML_ALIGN_JUSTIFY &&
571 drawSelectionAfterCell )
572 {
573 wxHtmlCell *nextCell = m_Next;
574 while ( nextCell && nextCell->IsFormattingCell() )
575 nextCell = nextCell->GetNext();
576 if ( nextCell )
577 {
578 int nextX = nextCell->GetPosX();
579 if ( m_PosX + m_Width < nextX )
580 {
581 dc.SetBrush(dc.GetBackground());
582 dc.SetPen(*wxTRANSPARENT_PEN);
583 dc.DrawRectangle(x + m_PosX + m_Width, y + m_PosY,
584 nextX - m_PosX - m_Width, m_Height);
585 }
586 }
587 }
588 }
589
590
591 wxString wxHtmlWordCell::ConvertToText(wxHtmlSelection *s) const
592 {
593 if ( s && (this == s->GetFromCell() || this == s->GetToCell()) )
594 {
595 wxPoint priv = this == s->GetFromCell() ? s->GetFromPrivPos()
596 : s->GetToPrivPos();
597
598 // VZ: we may be called before we had a chance to re-render ourselves
599 // and in this case GetFrom/ToPrivPos() is not set yet -- assume
600 // that this only happens in case of a double/triple click (which
601 // seems to be the case now) and so it makes sense to select the
602 // entire contents of the cell in this case
603 //
604 // TODO: but this really needs to be fixed in some better way later...
605 if ( priv != wxDefaultPosition )
606 {
607 int part1 = priv.x;
608 int part2 = priv.y;
609 return m_Word.Mid(part1, part2-part1);
610 }
611 //else: return the whole word below
612 }
613
614 return m_Word;
615 }
616
617 wxCursor wxHtmlWordCell::GetMouseCursor(wxHtmlWindowInterface *window) const
618 {
619 if ( !GetLink() )
620 {
621 return window->GetHTMLCursor(wxHtmlWindowInterface::HTMLCursor_Text);
622 }
623 else
624 {
625 return wxHtmlCell::GetMouseCursor(window);
626 }
627 }
628
629
630 //-----------------------------------------------------------------------------
631 // wxHtmlContainerCell
632 //-----------------------------------------------------------------------------
633
634 IMPLEMENT_ABSTRACT_CLASS(wxHtmlContainerCell, wxHtmlCell)
635
636 wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell *parent) : wxHtmlCell()
637 {
638 m_Cells = m_LastCell = NULL;
639 m_Parent = parent;
640 m_MaxTotalWidth = 0;
641 if (m_Parent) m_Parent->InsertCell(this);
642 m_AlignHor = wxHTML_ALIGN_LEFT;
643 m_AlignVer = wxHTML_ALIGN_BOTTOM;
644 m_IndentLeft = m_IndentRight = m_IndentTop = m_IndentBottom = 0;
645 m_WidthFloat = 100; m_WidthFloatUnits = wxHTML_UNITS_PERCENT;
646 m_UseBkColour = false;
647 m_UseBorder = false;
648 m_MinHeight = 0;
649 m_MinHeightAlign = wxHTML_ALIGN_TOP;
650 m_LastLayout = -1;
651 }
652
653 wxHtmlContainerCell::~wxHtmlContainerCell()
654 {
655 wxHtmlCell *cell = m_Cells;
656 while ( cell )
657 {
658 wxHtmlCell *cellNext = cell->GetNext();
659 delete cell;
660 cell = cellNext;
661 }
662 }
663
664
665
666 void wxHtmlContainerCell::SetIndent(int i, int what, int units)
667 {
668 int val = (units == wxHTML_UNITS_PIXELS) ? i : -i;
669 if (what & wxHTML_INDENT_LEFT) m_IndentLeft = val;
670 if (what & wxHTML_INDENT_RIGHT) m_IndentRight = val;
671 if (what & wxHTML_INDENT_TOP) m_IndentTop = val;
672 if (what & wxHTML_INDENT_BOTTOM) m_IndentBottom = val;
673 m_LastLayout = -1;
674 }
675
676
677
678 int wxHtmlContainerCell::GetIndent(int ind) const
679 {
680 if (ind & wxHTML_INDENT_LEFT) return m_IndentLeft;
681 else if (ind & wxHTML_INDENT_RIGHT) return m_IndentRight;
682 else if (ind & wxHTML_INDENT_TOP) return m_IndentTop;
683 else if (ind & wxHTML_INDENT_BOTTOM) return m_IndentBottom;
684 else return -1; /* BUG! Should not be called... */
685 }
686
687
688
689
690 int wxHtmlContainerCell::GetIndentUnits(int ind) const
691 {
692 bool p = false;
693 if (ind & wxHTML_INDENT_LEFT) p = m_IndentLeft < 0;
694 else if (ind & wxHTML_INDENT_RIGHT) p = m_IndentRight < 0;
695 else if (ind & wxHTML_INDENT_TOP) p = m_IndentTop < 0;
696 else if (ind & wxHTML_INDENT_BOTTOM) p = m_IndentBottom < 0;
697 if (p) return wxHTML_UNITS_PERCENT;
698 else return wxHTML_UNITS_PIXELS;
699 }
700
701
702
703 bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak, int* known_pagebreaks, int number_of_pages) const
704 {
705 if (!m_CanLiveOnPagebreak)
706 return wxHtmlCell::AdjustPagebreak(pagebreak, known_pagebreaks, number_of_pages);
707
708 else
709 {
710 wxHtmlCell *c = GetFirstChild();
711 bool rt = false;
712 int pbrk = *pagebreak - m_PosY;
713
714 while (c)
715 {
716 if (c->AdjustPagebreak(&pbrk, known_pagebreaks, number_of_pages))
717 rt = true;
718 c = c->GetNext();
719 }
720 if (rt)
721 *pagebreak = pbrk + m_PosY;
722 return rt;
723 }
724 }
725
726
727
728 void wxHtmlContainerCell::Layout(int w)
729 {
730 wxHtmlCell::Layout(w);
731
732 if (m_LastLayout == w) return;
733
734 // VS: Any attempt to layout with negative or zero width leads to hell,
735 // but we can't ignore such attempts completely, since it sometimes
736 // happen (e.g. when trying how small a table can be). The best thing we
737 // can do is to set the width of child cells to zero
738 if (w < 1)
739 {
740 m_Width = 0;
741 for (wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext())
742 cell->Layout(0);
743 // this does two things: it recursively calls this code on all
744 // child contrainers and resets children's position to (0,0)
745 return;
746 }
747
748 wxHtmlCell *nextCell;
749 long xpos = 0, ypos = m_IndentTop;
750 int xdelta = 0, ybasicpos = 0, ydiff;
751 int s_width, nextWordWidth, s_indent;
752 int ysizeup = 0, ysizedown = 0;
753 int MaxLineWidth = 0;
754 int curLineWidth = 0;
755 m_MaxTotalWidth = 0;
756
757
758 /*
759
760 WIDTH ADJUSTING :
761
762 */
763
764 if (m_WidthFloatUnits == wxHTML_UNITS_PERCENT)
765 {
766 if (m_WidthFloat < 0) m_Width = (100 + m_WidthFloat) * w / 100;
767 else m_Width = m_WidthFloat * w / 100;
768 }
769 else
770 {
771 if (m_WidthFloat < 0) m_Width = w + m_WidthFloat;
772 else m_Width = m_WidthFloat;
773 }
774
775 if (m_Cells)
776 {
777 int l = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft;
778 int r = (m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight;
779 for (wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext())
780 cell->Layout(m_Width - (l + r));
781 }
782
783 /*
784
785 LAYOUTING :
786
787 */
788
789 // adjust indentation:
790 s_indent = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft;
791 s_width = m_Width - s_indent - ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
792
793 // my own layouting:
794 wxHtmlCell *cell = m_Cells,
795 *line = m_Cells;
796 while (cell != NULL)
797 {
798 switch (m_AlignVer)
799 {
800 case wxHTML_ALIGN_TOP : ybasicpos = 0; break;
801 case wxHTML_ALIGN_BOTTOM : ybasicpos = - cell->GetHeight(); break;
802 case wxHTML_ALIGN_CENTER : ybasicpos = - cell->GetHeight() / 2; break;
803 }
804 ydiff = cell->GetHeight() + ybasicpos;
805
806 if (cell->GetDescent() + ydiff > ysizedown) ysizedown = cell->GetDescent() + ydiff;
807 if (ybasicpos + cell->GetDescent() < -ysizeup) ysizeup = - (ybasicpos + cell->GetDescent());
808
809 // layout nonbreakable run of cells:
810 cell->SetPos(xpos, ybasicpos + cell->GetDescent());
811 xpos += cell->GetWidth();
812 if (!cell->IsTerminalCell())
813 {
814 // Container cell indicates new line
815 if (curLineWidth > m_MaxTotalWidth)
816 m_MaxTotalWidth = curLineWidth;
817
818 if (wxMax(cell->GetWidth(), cell->GetMaxTotalWidth()) > m_MaxTotalWidth)
819 m_MaxTotalWidth = cell->GetMaxTotalWidth();
820 curLineWidth = 0;
821 }
822 else
823 // Normal cell, add maximum cell width to line width
824 curLineWidth += cell->GetMaxTotalWidth();
825
826 cell = cell->GetNext();
827
828 // compute length of the next word that would be added:
829 nextWordWidth = 0;
830 if (cell)
831 {
832 nextCell = cell;
833 do
834 {
835 nextWordWidth += nextCell->GetWidth();
836 nextCell = nextCell->GetNext();
837 } while (nextCell && !nextCell->IsLinebreakAllowed());
838 }
839
840 // force new line if occurred:
841 if ((cell == NULL) ||
842 (xpos + nextWordWidth > s_width && cell->IsLinebreakAllowed()))
843 {
844 if (xpos > MaxLineWidth) MaxLineWidth = xpos;
845 if (ysizeup < 0) ysizeup = 0;
846 if (ysizedown < 0) ysizedown = 0;
847 switch (m_AlignHor) {
848 case wxHTML_ALIGN_LEFT :
849 case wxHTML_ALIGN_JUSTIFY :
850 xdelta = 0;
851 break;
852 case wxHTML_ALIGN_RIGHT :
853 xdelta = 0 + (s_width - xpos);
854 break;
855 case wxHTML_ALIGN_CENTER :
856 xdelta = 0 + (s_width - xpos) / 2;
857 break;
858 }
859 if (xdelta < 0) xdelta = 0;
860 xdelta += s_indent;
861
862 ypos += ysizeup;
863
864 if (m_AlignHor != wxHTML_ALIGN_JUSTIFY || cell == NULL)
865 {
866 while (line != cell)
867 {
868 line->SetPos(line->GetPosX() + xdelta,
869 ypos + line->GetPosY());
870 line = line->GetNext();
871 }
872 }
873 else // align == justify
874 {
875 // we have to distribute the extra horz space between the cells
876 // on this line
877
878 // an added complication is that some cells have fixed size and
879 // shouldn't get any increment (it so happens that these cells
880 // also don't allow line break on them which provides with an
881 // easy way to test for this) -- and neither should the cells
882 // adjacent to them as this could result in a visible space
883 // between two cells separated by, e.g. font change, cell which
884 // is wrong
885
886 int step = s_width - xpos;
887 if ( step > 0 )
888 {
889 // first count the cells which will get extra space
890 int total = 0;
891
892 const wxHtmlCell *c;
893 if ( line != cell )
894 {
895 for ( c = line->GetNext(); c != cell; c = c->GetNext() )
896 {
897 if ( c->IsLinebreakAllowed() )
898 {
899 total++;
900 }
901 }
902 }
903
904 // and now extra space to those cells which merit it
905 if ( total )
906 {
907 // first cell on line is not moved:
908 line->SetPos(line->GetPosX() + s_indent,
909 line->GetPosY() + ypos);
910
911 line = line->GetNext();
912 for ( int n = 0; line != cell; line = line->GetNext() )
913 {
914 if ( line->IsLinebreakAllowed() )
915 {
916 // offset the next cell relative to this one
917 // thus increasing our size
918 n++;
919 }
920
921 line->SetPos(line->GetPosX() + s_indent +
922 ((n * step) / total),
923 line->GetPosY() + ypos);
924 }
925 }
926 else
927 {
928 // this will cause the code to enter "else branch" below:
929 step = 0;
930 }
931 }
932 // else branch:
933 if ( step <= 0 ) // no extra space to distribute
934 {
935 // just set the indent properly
936 while (line != cell)
937 {
938 line->SetPos(line->GetPosX() + s_indent,
939 line->GetPosY() + ypos);
940 line = line->GetNext();
941 }
942 }
943 }
944
945 ypos += ysizedown;
946 xpos = 0;
947 ysizeup = ysizedown = 0;
948 line = cell;
949 }
950 }
951
952 // setup height & width, depending on container layout:
953 m_Height = ypos + (ysizedown + ysizeup) + m_IndentBottom;
954
955 if (m_Height < m_MinHeight)
956 {
957 if (m_MinHeightAlign != wxHTML_ALIGN_TOP)
958 {
959 int diff = m_MinHeight - m_Height;
960 if (m_MinHeightAlign == wxHTML_ALIGN_CENTER) diff /= 2;
961 cell = m_Cells;
962 while (cell)
963 {
964 cell->SetPos(cell->GetPosX(), cell->GetPosY() + diff);
965 cell = cell->GetNext();
966 }
967 }
968 m_Height = m_MinHeight;
969 }
970
971 if (curLineWidth > m_MaxTotalWidth)
972 m_MaxTotalWidth = curLineWidth;
973
974 m_MaxTotalWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
975 MaxLineWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
976 if (m_Width < MaxLineWidth) m_Width = MaxLineWidth;
977
978 m_LastLayout = w;
979 }
980
981 void wxHtmlContainerCell::UpdateRenderingStatePre(wxHtmlRenderingInfo& info,
982 wxHtmlCell *cell) const
983 {
984 wxHtmlSelection *s = info.GetSelection();
985 if (!s) return;
986 if (s->GetFromCell() == cell || s->GetToCell() == cell)
987 {
988 info.GetState().SetSelectionState(wxHTML_SEL_CHANGING);
989 }
990 }
991
992 void wxHtmlContainerCell::UpdateRenderingStatePost(wxHtmlRenderingInfo& info,
993 wxHtmlCell *cell) const
994 {
995 wxHtmlSelection *s = info.GetSelection();
996 if (!s) return;
997 if (s->GetToCell() == cell)
998 info.GetState().SetSelectionState(wxHTML_SEL_OUT);
999 else if (s->GetFromCell() == cell)
1000 info.GetState().SetSelectionState(wxHTML_SEL_IN);
1001 }
1002
1003 #define mMin(a, b) (((a) < (b)) ? (a) : (b))
1004 #define mMax(a, b) (((a) < (b)) ? (b) : (a))
1005
1006 void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
1007 wxHtmlRenderingInfo& info)
1008 {
1009 #if 0 // useful for debugging
1010 dc.SetPen(*wxRED_PEN);
1011 dc.DrawRectangle(x+m_PosX,y+m_PosY,m_Width,m_Height);
1012 #endif
1013
1014 int xlocal = x + m_PosX;
1015 int ylocal = y + m_PosY;
1016
1017 if (m_UseBkColour)
1018 {
1019 wxBrush myb = wxBrush(m_BkColour, wxSOLID);
1020
1021 int real_y1 = mMax(ylocal, view_y1);
1022 int real_y2 = mMin(ylocal + m_Height - 1, view_y2);
1023
1024 dc.SetBrush(myb);
1025 dc.SetPen(*wxTRANSPARENT_PEN);
1026 dc.DrawRectangle(xlocal, real_y1, m_Width, real_y2 - real_y1 + 1);
1027 }
1028
1029 if (m_UseBorder)
1030 {
1031 wxPen mypen1(m_BorderColour1, 1, wxSOLID);
1032 wxPen mypen2(m_BorderColour2, 1, wxSOLID);
1033
1034 dc.SetPen(mypen1);
1035 dc.DrawLine(xlocal, ylocal, xlocal, ylocal + m_Height - 1);
1036 dc.DrawLine(xlocal, ylocal, xlocal + m_Width, ylocal);
1037 dc.SetPen(mypen2);
1038 dc.DrawLine(xlocal + m_Width - 1, ylocal, xlocal + m_Width - 1, ylocal + m_Height - 1);
1039 dc.DrawLine(xlocal, ylocal + m_Height - 1, xlocal + m_Width, ylocal + m_Height - 1);
1040 }
1041
1042 if (m_Cells)
1043 {
1044 // draw container's contents:
1045 for (wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext())
1046 {
1047
1048 // optimize drawing: don't render off-screen content:
1049 if ((ylocal + cell->GetPosY() <= view_y2) &&
1050 (ylocal + cell->GetPosY() + cell->GetHeight() > view_y1))
1051 {
1052 // the cell is visible, draw it:
1053 UpdateRenderingStatePre(info, cell);
1054 cell->Draw(dc,
1055 xlocal, ylocal, view_y1, view_y2,
1056 info);
1057 UpdateRenderingStatePost(info, cell);
1058 }
1059 else
1060 {
1061 // the cell is off-screen, proceed with font+color+etc.
1062 // changes only:
1063 cell->DrawInvisible(dc, xlocal, ylocal, info);
1064 }
1065 }
1066 }
1067 }
1068
1069
1070
1071 void wxHtmlContainerCell::DrawInvisible(wxDC& dc, int x, int y,
1072 wxHtmlRenderingInfo& info)
1073 {
1074 if (m_Cells)
1075 {
1076 for (wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext())
1077 {
1078 UpdateRenderingStatePre(info, cell);
1079 cell->DrawInvisible(dc, x + m_PosX, y + m_PosY, info);
1080 UpdateRenderingStatePost(info, cell);
1081 }
1082 }
1083 }
1084
1085
1086 wxColour wxHtmlContainerCell::GetBackgroundColour()
1087 {
1088 if (m_UseBkColour)
1089 return m_BkColour;
1090 else
1091 return wxNullColour;
1092 }
1093
1094
1095
1096 wxHtmlLinkInfo *wxHtmlContainerCell::GetLink(int x, int y) const
1097 {
1098 wxHtmlCell *cell = FindCellByPos(x, y);
1099
1100 // VZ: I don't know if we should pass absolute or relative coords to
1101 // wxHtmlCell::GetLink()? As the base class version just ignores them
1102 // anyhow, it hardly matters right now but should still be clarified
1103 return cell ? cell->GetLink(x, y) : NULL;
1104 }
1105
1106
1107
1108 void wxHtmlContainerCell::InsertCell(wxHtmlCell *f)
1109 {
1110 if (!m_Cells) m_Cells = m_LastCell = f;
1111 else
1112 {
1113 m_LastCell->SetNext(f);
1114 m_LastCell = f;
1115 if (m_LastCell) while (m_LastCell->GetNext()) m_LastCell = m_LastCell->GetNext();
1116 }
1117 f->SetParent(this);
1118 m_LastLayout = -1;
1119 }
1120
1121
1122
1123 void wxHtmlContainerCell::SetAlign(const wxHtmlTag& tag)
1124 {
1125 if (tag.HasParam(wxT("ALIGN")))
1126 {
1127 wxString alg = tag.GetParam(wxT("ALIGN"));
1128 alg.MakeUpper();
1129 if (alg == wxT("CENTER"))
1130 SetAlignHor(wxHTML_ALIGN_CENTER);
1131 else if (alg == wxT("LEFT"))
1132 SetAlignHor(wxHTML_ALIGN_LEFT);
1133 else if (alg == wxT("JUSTIFY"))
1134 SetAlignHor(wxHTML_ALIGN_JUSTIFY);
1135 else if (alg == wxT("RIGHT"))
1136 SetAlignHor(wxHTML_ALIGN_RIGHT);
1137 m_LastLayout = -1;
1138 }
1139 }
1140
1141
1142
1143 void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag& tag, double pixel_scale)
1144 {
1145 if (tag.HasParam(wxT("WIDTH")))
1146 {
1147 int wdi;
1148 wxString wd = tag.GetParam(wxT("WIDTH"));
1149
1150 if (wd[wd.length()-1] == wxT('%'))
1151 {
1152 wxSscanf(wd.c_str(), wxT("%i%%"), &wdi);
1153 SetWidthFloat(wdi, wxHTML_UNITS_PERCENT);
1154 }
1155 else
1156 {
1157 wxSscanf(wd.c_str(), wxT("%i"), &wdi);
1158 SetWidthFloat((int)(pixel_scale * (double)wdi), wxHTML_UNITS_PIXELS);
1159 }
1160 m_LastLayout = -1;
1161 }
1162 }
1163
1164
1165
1166 const wxHtmlCell* wxHtmlContainerCell::Find(int condition, const void* param) const
1167 {
1168 if (m_Cells)
1169 {
1170 for (wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext())
1171 {
1172 const wxHtmlCell *r = cell->Find(condition, param);
1173 if (r) return r;
1174 }
1175 }
1176 return NULL;
1177 }
1178
1179
1180 wxHtmlCell *wxHtmlContainerCell::FindCellByPos(wxCoord x, wxCoord y,
1181 unsigned flags) const
1182 {
1183 if ( flags & wxHTML_FIND_EXACT )
1184 {
1185 for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
1186 {
1187 int cx = cell->GetPosX(),
1188 cy = cell->GetPosY();
1189
1190 if ( (cx <= x) && (cx + cell->GetWidth() > x) &&
1191 (cy <= y) && (cy + cell->GetHeight() > y) )
1192 {
1193 return cell->FindCellByPos(x - cx, y - cy, flags);
1194 }
1195 }
1196 }
1197 else if ( flags & wxHTML_FIND_NEAREST_AFTER )
1198 {
1199 wxHtmlCell *c;
1200 for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
1201 {
1202 if ( cell->IsFormattingCell() )
1203 continue;
1204 int cellY = cell->GetPosY();
1205 if (!( y < cellY || (y < cellY + cell->GetHeight() &&
1206 x < cell->GetPosX() + cell->GetWidth()) ))
1207 continue;
1208
1209 c = cell->FindCellByPos(x - cell->GetPosX(), y - cellY, flags);
1210 if (c) return c;
1211 }
1212 }
1213 else if ( flags & wxHTML_FIND_NEAREST_BEFORE )
1214 {
1215 wxHtmlCell *c2, *c = NULL;
1216 for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
1217 {
1218 if ( cell->IsFormattingCell() )
1219 continue;
1220 int cellY = cell->GetPosY();
1221 if (!( cellY + cell->GetHeight() <= y ||
1222 (y >= cellY && x >= cell->GetPosX()) ))
1223 break;
1224 c2 = cell->FindCellByPos(x - cell->GetPosX(), y - cellY, flags);
1225 if (c2)
1226 c = c2;
1227 }
1228 if (c) return c;
1229 }
1230
1231 return NULL;
1232 }
1233
1234
1235 bool wxHtmlContainerCell::ProcessMouseClick(wxHtmlWindowInterface *window,
1236 const wxPoint& pos,
1237 const wxMouseEvent& event)
1238 {
1239 #if WXWIN_COMPATIBILITY_2_6
1240 wxHtmlCellOnMouseClickCompatHelper compat(window, pos, event);
1241 return compat.CallOnMouseClick(this);
1242 }
1243
1244 void wxHtmlContainerCell::OnMouseClick(wxWindow*,
1245 int, int, const wxMouseEvent& event)
1246 {
1247 wxCHECK_RET( gs_helperOnMouseClick, _T("unexpected call to OnMouseClick") );
1248 wxHtmlWindowInterface *window = gs_helperOnMouseClick->window;
1249 const wxPoint& pos = gs_helperOnMouseClick->pos;
1250 #endif // WXWIN_COMPATIBILITY_2_6
1251
1252 bool retval = false;
1253 wxHtmlCell *cell = FindCellByPos(pos.x, pos.y);
1254 if ( cell )
1255 retval = cell->ProcessMouseClick(window, pos, event);
1256
1257 #if WXWIN_COMPATIBILITY_2_6
1258 gs_helperOnMouseClick->retval = retval;
1259 #else
1260 return retval;
1261 #endif // WXWIN_COMPATIBILITY_2_6
1262 }
1263
1264
1265 wxHtmlCell *wxHtmlContainerCell::GetFirstTerminal() const
1266 {
1267 if ( m_Cells )
1268 {
1269 wxHtmlCell *c2;
1270 for (wxHtmlCell *c = m_Cells; c; c = c->GetNext())
1271 {
1272 c2 = c->GetFirstTerminal();
1273 if ( c2 )
1274 return c2;
1275 }
1276 }
1277 return NULL;
1278 }
1279
1280 wxHtmlCell *wxHtmlContainerCell::GetLastTerminal() const
1281 {
1282 if ( m_Cells )
1283 {
1284 // most common case first:
1285 wxHtmlCell *c = m_LastCell->GetLastTerminal();
1286 if ( c )
1287 return c;
1288
1289 wxHtmlCell *ctmp;
1290 wxHtmlCell *c2 = NULL;
1291 for (c = m_Cells; c; c = c->GetNext())
1292 {
1293 ctmp = c->GetLastTerminal();
1294 if ( ctmp )
1295 c2 = ctmp;
1296 }
1297 return c2;
1298 }
1299 else
1300 return NULL;
1301 }
1302
1303
1304 static bool IsEmptyContainer(wxHtmlContainerCell *cell)
1305 {
1306 for ( wxHtmlCell *c = cell->GetFirstChild(); c; c = c->GetNext() )
1307 {
1308 if ( !c->IsTerminalCell() || !c->IsFormattingCell() )
1309 return false;
1310 }
1311 return true;
1312 }
1313
1314 void wxHtmlContainerCell::RemoveExtraSpacing(bool top, bool bottom)
1315 {
1316 if ( top )
1317 SetIndent(0, wxHTML_INDENT_TOP);
1318 if ( bottom )
1319 SetIndent(0, wxHTML_INDENT_BOTTOM);
1320
1321 if ( m_Cells )
1322 {
1323 wxHtmlCell *c;
1324 wxHtmlContainerCell *cont;
1325 if ( top )
1326 {
1327 for ( c = m_Cells; c; c = c->GetNext() )
1328 {
1329 if ( c->IsTerminalCell() )
1330 {
1331 if ( !c->IsFormattingCell() )
1332 break;
1333 }
1334 else
1335 {
1336 cont = (wxHtmlContainerCell*)c;
1337 if ( IsEmptyContainer(cont) )
1338 {
1339 cont->SetIndent(0, wxHTML_INDENT_VERTICAL);
1340 }
1341 else
1342 {
1343 cont->RemoveExtraSpacing(true, false);
1344 break;
1345 }
1346 }
1347 }
1348 }
1349
1350 if ( bottom )
1351 {
1352 wxArrayPtrVoid arr;
1353 for ( c = m_Cells; c; c = c->GetNext() )
1354 arr.Add((void*)c);
1355
1356 for ( int i = arr.GetCount() - 1; i >= 0; i--)
1357 {
1358 c = (wxHtmlCell*)arr[i];
1359 if ( c->IsTerminalCell() )
1360 {
1361 if ( !c->IsFormattingCell() )
1362 break;
1363 }
1364 else
1365 {
1366 cont = (wxHtmlContainerCell*)c;
1367 if ( IsEmptyContainer(cont) )
1368 {
1369 cont->SetIndent(0, wxHTML_INDENT_VERTICAL);
1370 }
1371 else
1372 {
1373 cont->RemoveExtraSpacing(false, true);
1374 break;
1375 }
1376 }
1377 }
1378 }
1379 }
1380 }
1381
1382
1383
1384
1385 // --------------------------------------------------------------------------
1386 // wxHtmlColourCell
1387 // --------------------------------------------------------------------------
1388
1389 IMPLEMENT_ABSTRACT_CLASS(wxHtmlColourCell, wxHtmlCell)
1390
1391 void wxHtmlColourCell::Draw(wxDC& dc,
1392 int x, int y,
1393 int WXUNUSED(view_y1), int WXUNUSED(view_y2),
1394 wxHtmlRenderingInfo& info)
1395 {
1396 DrawInvisible(dc, x, y, info);
1397 }
1398
1399 void wxHtmlColourCell::DrawInvisible(wxDC& dc,
1400 int WXUNUSED(x), int WXUNUSED(y),
1401 wxHtmlRenderingInfo& info)
1402 {
1403 wxHtmlRenderingState& state = info.GetState();
1404 if (m_Flags & wxHTML_CLR_FOREGROUND)
1405 {
1406 state.SetFgColour(m_Colour);
1407 if (state.GetSelectionState() != wxHTML_SEL_IN)
1408 dc.SetTextForeground(m_Colour);
1409 else
1410 dc.SetTextForeground(
1411 info.GetStyle().GetSelectedTextColour(m_Colour));
1412 }
1413 if (m_Flags & wxHTML_CLR_BACKGROUND)
1414 {
1415 state.SetBgColour(m_Colour);
1416 if (state.GetSelectionState() != wxHTML_SEL_IN)
1417 {
1418 dc.SetTextBackground(m_Colour);
1419 dc.SetBackground(wxBrush(m_Colour, wxSOLID));
1420 }
1421 else
1422 {
1423 wxColour c = info.GetStyle().GetSelectedTextBgColour(m_Colour);
1424 dc.SetTextBackground(c);
1425 dc.SetBackground(wxBrush(c, wxSOLID));
1426 }
1427 }
1428 }
1429
1430
1431
1432
1433 // ---------------------------------------------------------------------------
1434 // wxHtmlFontCell
1435 // ---------------------------------------------------------------------------
1436
1437 IMPLEMENT_ABSTRACT_CLASS(wxHtmlFontCell, wxHtmlCell)
1438
1439 void wxHtmlFontCell::Draw(wxDC& dc,
1440 int WXUNUSED(x), int WXUNUSED(y),
1441 int WXUNUSED(view_y1), int WXUNUSED(view_y2),
1442 wxHtmlRenderingInfo& WXUNUSED(info))
1443 {
1444 dc.SetFont(m_Font);
1445 }
1446
1447 void wxHtmlFontCell::DrawInvisible(wxDC& dc, int WXUNUSED(x), int WXUNUSED(y),
1448 wxHtmlRenderingInfo& WXUNUSED(info))
1449 {
1450 dc.SetFont(m_Font);
1451 }
1452
1453
1454
1455
1456
1457
1458
1459
1460 // ---------------------------------------------------------------------------
1461 // wxHtmlWidgetCell
1462 // ---------------------------------------------------------------------------
1463
1464 IMPLEMENT_ABSTRACT_CLASS(wxHtmlWidgetCell, wxHtmlCell)
1465
1466 wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow *wnd, int w)
1467 {
1468 int sx, sy;
1469 m_Wnd = wnd;
1470 m_Wnd->GetSize(&sx, &sy);
1471 m_Width = sx, m_Height = sy;
1472 m_WidthFloat = w;
1473 }
1474
1475
1476 void wxHtmlWidgetCell::Draw(wxDC& WXUNUSED(dc),
1477 int WXUNUSED(x), int WXUNUSED(y),
1478 int WXUNUSED(view_y1), int WXUNUSED(view_y2),
1479 wxHtmlRenderingInfo& WXUNUSED(info))
1480 {
1481 int absx = 0, absy = 0, stx, sty;
1482 wxHtmlCell *c = this;
1483
1484 while (c)
1485 {
1486 absx += c->GetPosX();
1487 absy += c->GetPosY();
1488 c = c->GetParent();
1489 }
1490
1491 ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
1492 m_Wnd->SetSize(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty, m_Width, m_Height);
1493 }
1494
1495
1496
1497 void wxHtmlWidgetCell::DrawInvisible(wxDC& WXUNUSED(dc),
1498 int WXUNUSED(x), int WXUNUSED(y),
1499 wxHtmlRenderingInfo& WXUNUSED(info))
1500 {
1501 int absx = 0, absy = 0, stx, sty;
1502 wxHtmlCell *c = this;
1503
1504 while (c)
1505 {
1506 absx += c->GetPosX();
1507 absy += c->GetPosY();
1508 c = c->GetParent();
1509 }
1510
1511 ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
1512 m_Wnd->SetSize(absx - wxHTML_SCROLL_STEP * stx, absy - wxHTML_SCROLL_STEP * sty, m_Width, m_Height);
1513 }
1514
1515
1516
1517 void wxHtmlWidgetCell::Layout(int w)
1518 {
1519 if (m_WidthFloat != 0)
1520 {
1521 m_Width = (w * m_WidthFloat) / 100;
1522 m_Wnd->SetSize(m_Width, m_Height);
1523 }
1524
1525 wxHtmlCell::Layout(w);
1526 }
1527
1528
1529
1530 // ----------------------------------------------------------------------------
1531 // wxHtmlTerminalCellsInterator
1532 // ----------------------------------------------------------------------------
1533
1534 const wxHtmlCell* wxHtmlTerminalCellsInterator::operator++()
1535 {
1536 if ( !m_pos )
1537 return NULL;
1538
1539 do
1540 {
1541 if ( m_pos == m_to )
1542 {
1543 m_pos = NULL;
1544 return NULL;
1545 }
1546
1547 if ( m_pos->GetNext() )
1548 m_pos = m_pos->GetNext();
1549 else
1550 {
1551 // we must go up the hierarchy until we reach container where this
1552 // is not the last child, and then go down to first terminal cell:
1553 while ( m_pos->GetNext() == NULL )
1554 {
1555 m_pos = m_pos->GetParent();
1556 if ( !m_pos )
1557 return NULL;
1558 }
1559 m_pos = m_pos->GetNext();
1560 }
1561 while ( m_pos->GetFirstChild() != NULL )
1562 m_pos = m_pos->GetFirstChild();
1563 } while ( !m_pos->IsTerminalCell() );
1564
1565 return m_pos;
1566 }
1567
1568 #endif