PCH build fixes.
[wxWidgets.git] / src / univ / stdrend.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/stdrend.cpp
3 // Purpose: implementation of wxStdRenderer
4 // Author: Vadim Zeitlin
5 // Created: 2006-09-16
6 // RCS-ID: $Id$
7 // Copyright: (c) 2006 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #ifndef WX_PRECOMP
27 #include "wx/settings.h"
28 #include "wx/brush.h"
29 #include "wx/dc.h"
30 #include "wx/statusbr.h"
31 #include "wx/toplevel.h"
32 #endif //WX_PRECOMP
33
34 #include "wx/univ/stdrend.h"
35 #include "wx/univ/colschem.h"
36
37 // ----------------------------------------------------------------------------
38 // constants
39 // ----------------------------------------------------------------------------
40
41 static const int FRAME_BORDER_THICKNESS = 3;
42 static const int RESIZEABLE_FRAME_BORDER_THICKNESS = 4;
43 static const int FRAME_TITLEBAR_HEIGHT = 18;
44 static const int FRAME_BUTTON_WIDTH = 16;
45 static const int FRAME_BUTTON_HEIGHT = 14;
46
47 // ============================================================================
48 // wxStdRenderer implementation
49 // ============================================================================
50
51 // ----------------------------------------------------------------------------
52 // ctor
53 // ----------------------------------------------------------------------------
54
55 wxStdRenderer::wxStdRenderer(const wxColourScheme *scheme)
56 : m_scheme(scheme)
57 {
58 m_penBlack = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_DARK));
59 m_penDarkGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_OUT));
60 m_penLightGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_IN));
61 m_penHighlight = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT));
62
63 m_titlebarFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
64 m_titlebarFont.SetWeight(wxFONTWEIGHT_BOLD);
65 }
66
67 // ----------------------------------------------------------------------------
68 // helper functions
69 // ----------------------------------------------------------------------------
70
71 void
72 wxStdRenderer::DrawSolidRect(wxDC& dc, const wxColour& col, const wxRect& rect)
73 {
74 wxBrush brush(col, wxSOLID);
75 dc.SetBrush(brush);
76 dc.SetPen(*wxTRANSPARENT_PEN);
77 dc.DrawRectangle(rect);
78 }
79
80 void wxStdRenderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen)
81 {
82 // draw
83 dc.SetPen(pen);
84 dc.SetBrush(*wxTRANSPARENT_BRUSH);
85 dc.DrawRectangle(*rect);
86
87 // adjust the rect
88 rect->Inflate(-1);
89 }
90
91 void wxStdRenderer::DrawShadedRect(wxDC& dc, wxRect *rect,
92 const wxPen& pen1, const wxPen& pen2)
93 {
94 // draw the rectangle
95 dc.SetPen(pen1);
96 dc.DrawLine(rect->GetLeft(), rect->GetTop(),
97 rect->GetLeft(), rect->GetBottom());
98 dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(),
99 rect->GetRight(), rect->GetTop());
100 dc.SetPen(pen2);
101 dc.DrawLine(rect->GetRight(), rect->GetTop(),
102 rect->GetRight(), rect->GetBottom());
103 dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
104 rect->GetRight() + 1, rect->GetBottom());
105
106 // adjust the rect
107 rect->Inflate(-1);
108 }
109
110 // ----------------------------------------------------------------------------
111 // translate various flags into corresponding renderer constants
112 // ----------------------------------------------------------------------------
113
114 /* static */
115 void wxStdRenderer::GetIndicatorsFromFlags(int flags,
116 IndicatorState& state,
117 IndicatorStatus& status)
118 {
119 if ( flags & wxCONTROL_SELECTED )
120 state = flags & wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled
121 : IndicatorState_Selected;
122 else if ( flags & wxCONTROL_DISABLED )
123 state = IndicatorState_Disabled;
124 else if ( flags & wxCONTROL_PRESSED )
125 state = IndicatorState_Pressed;
126 else
127 state = IndicatorState_Normal;
128
129 status = flags & wxCONTROL_CHECKED ? IndicatorStatus_Checked
130 : flags & wxCONTROL_UNDETERMINED
131 ? IndicatorStatus_Undetermined
132 : IndicatorStatus_Unchecked;
133 }
134
135 /* static */
136 wxStdRenderer::ArrowDirection wxStdRenderer::GetArrowDirection(wxDirection dir)
137 {
138 switch ( dir )
139 {
140 case wxLEFT:
141 return Arrow_Left;
142
143 case wxRIGHT:
144 return Arrow_Right;
145
146 case wxUP:
147 return Arrow_Up;
148
149 case wxDOWN:
150 return Arrow_Down;
151
152 default:
153 wxFAIL_MSG(_T("unknown arrow direction"));
154 }
155
156 return Arrow_Max;
157 }
158
159 // ----------------------------------------------------------------------------
160 // background
161 // ----------------------------------------------------------------------------
162
163 void wxStdRenderer::DrawBackground(wxDC& dc,
164 const wxColour& col,
165 const wxRect& rect,
166 int WXUNUSED(flags),
167 wxWindow *window)
168 {
169 wxColour colBg = col.Ok() ? col
170 : window ? m_scheme->GetBackground(window)
171 : wxSCHEME_COLOUR(m_scheme, CONTROL);
172
173 DrawSolidRect(dc, colBg, rect);
174 }
175
176
177 void wxStdRenderer::DrawButtonSurface(wxDC& dc,
178 const wxColour& col,
179 const wxRect& rect,
180 int flags)
181 {
182 DrawBackground(dc, col, rect, flags);
183 }
184
185 // ----------------------------------------------------------------------------
186 // text
187 // ----------------------------------------------------------------------------
188
189 void wxStdRenderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
190 {
191 // draw the pixels manually because the "dots" in wxPen with wxDOT style
192 // may be short traits and not really dots
193 //
194 // note that to behave in the same manner as DrawRect(), we must exclude
195 // the bottom and right borders from the rectangle
196 wxCoord x1 = rect.GetLeft(),
197 y1 = rect.GetTop(),
198 x2 = rect.GetRight(),
199 y2 = rect.GetBottom();
200
201 dc.SetPen(m_penBlack);
202
203 // this seems to be closer than what Windows does than wxINVERT although
204 // I'm still not sure if it's correct
205 dc.SetLogicalFunction(wxAND_REVERSE);
206
207 wxCoord z;
208 for ( z = x1 + 1; z < x2; z += 2 )
209 dc.DrawPoint(z, rect.GetTop());
210
211 wxCoord shift = z == x2 ? 0 : 1;
212 for ( z = y1 + shift; z < y2; z += 2 )
213 dc.DrawPoint(x2, z);
214
215 shift = z == y2 ? 0 : 1;
216 for ( z = x2 - shift; z > x1; z -= 2 )
217 dc.DrawPoint(z, y2);
218
219 shift = z == x1 ? 0 : 1;
220 for ( z = y2 - shift; z > y1; z -= 2 )
221 dc.DrawPoint(x1, z);
222
223 dc.SetLogicalFunction(wxCOPY);
224 }
225
226 void wxStdRenderer::DrawLabel(wxDC& dc,
227 const wxString& label,
228 const wxRect& rect,
229 int flags,
230 int alignment,
231 int indexAccel,
232 wxRect *rectBounds)
233 {
234 DrawButtonLabel(dc, label, wxNullBitmap, rect, flags,
235 alignment, indexAccel, rectBounds);
236 }
237
238 void wxStdRenderer::DrawButtonLabel(wxDC& dc,
239 const wxString& label,
240 const wxBitmap& image,
241 const wxRect& rect,
242 int flags,
243 int alignment,
244 int indexAccel,
245 wxRect *rectBounds)
246 {
247 wxRect rectLabel = rect;
248 if ( !label.empty() && (flags & wxCONTROL_DISABLED) )
249 {
250 if ( flags & wxCONTROL_PRESSED )
251 {
252 // shift the label if a button is pressed
253 rectLabel.Offset(1, 1);
254 }
255
256 // draw shadow of the text
257 dc.SetTextForeground(m_penHighlight.GetColour());
258 wxRect rectShadow = rect;
259 rectShadow.Offset(1, 1);
260 dc.DrawLabel(label, rectShadow, alignment, indexAccel);
261
262 // make the main label text grey
263 dc.SetTextForeground(m_penDarkGrey.GetColour());
264
265 if ( flags & wxCONTROL_FOCUSED )
266 {
267 // leave enough space for the focus rect
268 rectLabel.Inflate(-2);
269 }
270 }
271
272 dc.DrawLabel(label, image, rectLabel, alignment, indexAccel, rectBounds);
273
274 if ( !label.empty() && (flags & wxCONTROL_FOCUSED) )
275 {
276 rectLabel.Inflate(-1);
277
278 DrawFocusRect(dc, rectLabel);
279 }
280 }
281
282 // ----------------------------------------------------------------------------
283 // borders
284 // ----------------------------------------------------------------------------
285
286 /*
287 We implement standard-looking 3D borders which have the following appearance:
288
289 The raised border:
290
291 WWWWWWWWWWWWWWWWWWWWWWB
292 WHHHHHHHHHHHHHHHHHHHHGB
293 WH GB W = white (HILIGHT)
294 WH GB H = light grey (LIGHT)
295 WH GB G = dark grey (SHADOI)
296 WH GB B = black (DKSHADOI)
297 WH GB
298 WH GB
299 WGGGGGGGGGGGGGGGGGGGGGB
300 BBBBBBBBBBBBBBBBBBBBBBB
301
302 The sunken border looks like this:
303
304 GGGGGGGGGGGGGGGGGGGGGGW
305 GBBBBBBBBBBBBBBBBBBBBHW
306 GB HW
307 GB HW
308 GB HW
309 GB HW
310 GB HW
311 GB HW
312 GHHHHHHHHHHHHHHHHHHHHHW
313 WWWWWWWWWWWWWWWWWWWWWWW
314
315 The static border (used for the controls which don't get focus) is like
316 this:
317
318 GGGGGGGGGGGGGGGGGGGGGGW
319 G W
320 G W
321 G W
322 G W
323 G W
324 G W
325 G W
326 WWWWWWWWWWWWWWWWWWWWWWW
327
328 The most complicated is the double border which is a combination of special
329 "anti-sunken" border and an extra border inside it:
330
331 HHHHHHHHHHHHHHHHHHHHHHB
332 HWWWWWWWWWWWWWWWWWWWWGB
333 HWHHHHHHHHHHHHHHHHHHHGB
334 HWH HGB
335 HWH HGB
336 HWH HGB
337 HWH HGB
338 HWHHHHHHHHHHHHHHHHHHHGB
339 HGGGGGGGGGGGGGGGGGGGGGB
340 BBBBBBBBBBBBBBBBBBBBBBB
341
342 And the simple border is, well, simple:
343
344 BBBBBBBBBBBBBBBBBBBBBBB
345 B B
346 B B
347 B B
348 B B
349 B B
350 B B
351 B B
352 B B
353 BBBBBBBBBBBBBBBBBBBBBBB
354 */
355
356 void wxStdRenderer::DrawRaisedBorder(wxDC& dc, wxRect *rect)
357 {
358 DrawShadedRect(dc, rect, m_penHighlight, m_penBlack);
359 DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey);
360 }
361
362 void wxStdRenderer::DrawSunkenBorder(wxDC& dc, wxRect *rect)
363 {
364 DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
365 DrawShadedRect(dc, rect, m_penBlack, m_penLightGrey);
366 }
367
368 void wxStdRenderer::DrawAntiSunkenBorder(wxDC& dc, wxRect *rect)
369 {
370 DrawShadedRect(dc, rect, m_penLightGrey, m_penBlack);
371 DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
372 }
373
374 void wxStdRenderer::DrawBoxBorder(wxDC& dc, wxRect *rect)
375 {
376 DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
377 DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey);
378 }
379
380 void wxStdRenderer::DrawStaticBorder(wxDC& dc, wxRect *rect)
381 {
382 DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
383 }
384
385 void wxStdRenderer::DrawExtraBorder(wxDC& dc, wxRect *rect)
386 {
387 DrawRect(dc, rect, m_penLightGrey);
388 }
389
390 void wxStdRenderer::DrawBorder(wxDC& dc,
391 wxBorder border,
392 const wxRect& rectTotal,
393 int WXUNUSED(flags),
394 wxRect *rectIn)
395 {
396 wxRect rect = rectTotal;
397
398 switch ( border )
399 {
400 case wxBORDER_SUNKEN:
401 DrawSunkenBorder(dc, &rect);
402 break;
403
404 case wxBORDER_DOUBLE:
405 DrawAntiSunkenBorder(dc, &rect);
406 DrawExtraBorder(dc, &rect);
407 break;
408
409 case wxBORDER_STATIC:
410 DrawStaticBorder(dc, &rect);
411 break;
412
413 case wxBORDER_RAISED:
414 DrawRaisedBorder(dc, &rect);
415 break;
416
417 case wxBORDER_SIMPLE:
418 DrawRect(dc, &rect, m_penBlack);
419 break;
420
421 default:
422 wxFAIL_MSG(_T("unknown border type"));
423 // fall through
424
425 case wxBORDER_DEFAULT:
426 case wxBORDER_NONE:
427 break;
428 }
429
430 if ( rectIn )
431 *rectIn = rect;
432 }
433
434 wxRect wxStdRenderer::GetBorderDimensions(wxBorder border) const
435 {
436 wxCoord width;
437 switch ( border )
438 {
439 case wxBORDER_SIMPLE:
440 case wxBORDER_STATIC:
441 width = 1;
442 break;
443
444 case wxBORDER_RAISED:
445 case wxBORDER_SUNKEN:
446 width = 2;
447 break;
448
449 case wxBORDER_DOUBLE:
450 width = 3;
451 break;
452
453 default:
454 wxFAIL_MSG(_T("unknown border type"));
455 // fall through
456
457 case wxBORDER_DEFAULT:
458 case wxBORDER_NONE:
459 width = 0;
460 break;
461 }
462
463 wxRect rect;
464 rect.x =
465 rect.y =
466 rect.width =
467 rect.height = width;
468
469 return rect;
470 }
471
472 void wxStdRenderer::AdjustSize(wxSize *size, const wxWindow *window)
473 {
474 // take into account the border width
475 wxRect rectBorder = GetBorderDimensions(window->GetBorder());
476 size->x += rectBorder.x + rectBorder.width;
477 size->y += rectBorder.y + rectBorder.height;
478 }
479
480 bool wxStdRenderer::AreScrollbarsInsideBorder() const
481 {
482 return false;
483 }
484
485 wxCoord wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight)
486 {
487 return fontHeight + 2;
488 }
489
490 void wxStdRenderer::DrawTextBorder(wxDC& dc,
491 wxBorder border,
492 const wxRect& rect,
493 int flags,
494 wxRect *rectIn)
495 {
496 DrawBorder(dc, border, rect, flags, rectIn);
497 }
498
499 // ----------------------------------------------------------------------------
500 // lines and boxes
501 // ----------------------------------------------------------------------------
502
503 void
504 wxStdRenderer::DrawHorizontalLine(wxDC& dc, wxCoord y, wxCoord x1, wxCoord x2)
505 {
506 dc.SetPen(m_penDarkGrey);
507 dc.DrawLine(x1, y, x2 + 1, y);
508
509 dc.SetPen(m_penHighlight);
510 y++;
511 dc.DrawLine(x1, y, x2 + 1, y);
512 }
513
514 void
515 wxStdRenderer::DrawVerticalLine(wxDC& dc, wxCoord x, wxCoord y1, wxCoord y2)
516 {
517 dc.SetPen(m_penDarkGrey);
518 dc.DrawLine(x, y1, x, y2 + 1);
519
520 dc.SetPen(m_penHighlight);
521 x++;
522 dc.DrawLine(x, y1, x, y2 + 1);
523 }
524
525 void wxStdRenderer::DrawFrameWithoutLabel(wxDC& dc,
526 const wxRect& rectFrame,
527 const wxRect& rectLabel)
528 {
529 // draw left, bottom and right lines entirely
530 DrawVerticalLine(dc, rectFrame.GetLeft(),
531 rectFrame.GetTop(), rectFrame.GetBottom() - 2);
532 DrawHorizontalLine(dc, rectFrame.GetBottom() - 1,
533 rectFrame.GetLeft(), rectFrame.GetRight());
534 DrawVerticalLine(dc, rectFrame.GetRight() - 1,
535 rectFrame.GetTop(), rectFrame.GetBottom() - 1);
536
537 // and 2 parts of the top line
538 DrawHorizontalLine(dc, rectFrame.GetTop(),
539 rectFrame.GetLeft() + 1, rectLabel.GetLeft());
540 DrawHorizontalLine(dc, rectFrame.GetTop(),
541 rectLabel.GetRight(), rectFrame.GetRight() - 2);
542 }
543
544 void wxStdRenderer::DrawFrameWithLabel(wxDC& dc,
545 const wxString& label,
546 const wxRect& rectFrame,
547 const wxRect& rectText,
548 int flags,
549 int alignment,
550 int indexAccel)
551 {
552 wxRect rectLabel;
553 DrawLabel(dc, label, rectText, flags, alignment, indexAccel, &rectLabel);
554
555 DrawFrameWithoutLabel(dc, rectFrame, rectLabel);
556 }
557
558 void wxStdRenderer::DrawFrame(wxDC& dc,
559 const wxString& label,
560 const wxRect& rect,
561 int flags,
562 int alignment,
563 int indexAccel)
564 {
565 wxCoord height = 0; // of the label
566 wxRect rectFrame = rect;
567 if ( !label.empty() )
568 {
569 // the text should touch the top border of the rect, so the frame
570 // itself should be lower
571 dc.GetTextExtent(label, NULL, &height);
572 rectFrame.y += height / 2;
573 rectFrame.height -= height / 2;
574
575 // we have to draw each part of the frame individually as we can't
576 // erase the background beyond the label as it might contain some
577 // pixmap already, so drawing everything and then overwriting part of
578 // the frame with label doesn't work
579
580 // TODO: the +5 shouldn't be hard coded
581 wxRect rectText;
582 rectText.x = rectFrame.x + 5;
583 rectText.y = rect.y;
584 rectText.width = rectFrame.width - 7; // +2 border width
585 rectText.height = height;
586
587 DrawFrameWithLabel(dc, label, rectFrame, rectText, flags,
588 alignment, indexAccel);
589 }
590 else // no label
591 {
592 DrawBoxBorder(dc, &rectFrame);
593 }
594 }
595
596 void wxStdRenderer::DrawItem(wxDC& dc,
597 const wxString& label,
598 const wxRect& rect,
599 int flags)
600 {
601 wxDCTextColourChanger colChanger(dc);
602
603 if ( flags & wxCONTROL_SELECTED )
604 {
605 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
606
607 const wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
608 dc.SetBrush(colBg);
609 dc.SetPen(colBg);
610 dc.DrawRectangle(rect);
611 }
612
613 wxRect rectText = rect;
614 rectText.x += 2;
615 rectText.width -= 2;
616 dc.DrawLabel(label, wxNullBitmap, rectText);
617
618 if ( flags & wxCONTROL_FOCUSED )
619 {
620 DrawFocusRect(dc, rect);
621 }
622 }
623
624 void wxStdRenderer::DrawCheckItemBitmap(wxDC& dc,
625 const wxBitmap& bitmap,
626 const wxRect& rect,
627 int flags)
628 {
629 DrawCheckButton(dc, wxEmptyString, bitmap, rect, flags);
630 }
631
632 void wxStdRenderer::DrawCheckItem(wxDC& dc,
633 const wxString& label,
634 const wxBitmap& bitmap,
635 const wxRect& rect,
636 int flags)
637 {
638 wxRect rectBitmap = rect;
639 rectBitmap.width = GetCheckBitmapSize().x;
640 DrawCheckItemBitmap(dc, bitmap, rectBitmap, flags);
641
642 wxRect rectLabel = rect;
643 wxCoord shift = rectBitmap.width + 2*GetCheckItemMargin();
644 rectLabel.x += shift;
645 rectLabel.width -= shift;
646 DrawItem(dc, label, rectLabel, flags);
647 }
648
649 // ----------------------------------------------------------------------------
650 // check and radio bitmaps
651 // ----------------------------------------------------------------------------
652
653 void wxStdRenderer::DrawCheckButton(wxDC& dc,
654 const wxString& label,
655 const wxBitmap& bitmap,
656 const wxRect& rect,
657 int flags,
658 wxAlignment align,
659 int indexAccel)
660 {
661 wxBitmap bmp(bitmap.Ok() ? bitmap : GetCheckBitmap(flags));
662
663 DrawCheckOrRadioButton(dc, label, bmp, rect, flags, align, indexAccel);
664 }
665
666 void wxStdRenderer::DrawRadioButton(wxDC& dc,
667 const wxString& label,
668 const wxBitmap& bitmap,
669 const wxRect& rect,
670 int flags,
671 wxAlignment align,
672 int indexAccel)
673 {
674 wxBitmap bmp(bitmap.Ok() ? bitmap : GetRadioBitmap(flags));
675
676 DrawCheckOrRadioButton(dc, label, bmp, rect, flags, align, indexAccel);
677 }
678
679 void wxStdRenderer::DrawCheckOrRadioButton(wxDC& dc,
680 const wxString& label,
681 const wxBitmap& bitmap,
682 const wxRect& rect,
683 int flags,
684 wxAlignment align,
685 int indexAccel)
686 {
687 // calculate the position of the bitmap and of the label
688 wxCoord heightBmp = bitmap.GetHeight();
689 wxCoord xBmp,
690 yBmp = rect.y + (rect.height - heightBmp) / 2;
691
692 wxRect rectLabel;
693 dc.GetMultiLineTextExtent(label, NULL, &rectLabel.height);
694 rectLabel.y = rect.y + (rect.height - rectLabel.height) / 2;
695
696 // align label vertically with the bitmap - looks nicer like this
697 rectLabel.y -= (rectLabel.height - heightBmp) % 2;
698
699 // calc horz position
700 if ( align == wxALIGN_RIGHT )
701 {
702 xBmp = rect.GetRight() - bitmap.GetWidth();
703 rectLabel.x = rect.x + 3;
704 rectLabel.SetRight(xBmp);
705 }
706 else // normal (checkbox to the left of the text) case
707 {
708 xBmp = rect.x;
709 rectLabel.x = xBmp + bitmap.GetWidth() + 5;
710 rectLabel.SetRight(rect.GetRight());
711 }
712
713 dc.DrawBitmap(bitmap, xBmp, yBmp, true /* use mask */);
714
715 DrawLabel(dc, label, rectLabel, flags,
716 wxALIGN_LEFT | wxALIGN_TOP, indexAccel);
717 }
718
719 #if wxUSE_TEXTCTRL
720
721 void wxStdRenderer::DrawTextLine(wxDC& dc,
722 const wxString& text,
723 const wxRect& rect,
724 int selStart,
725 int selEnd,
726 int flags)
727 {
728 if ( (selStart == -1) || !(flags & wxCONTROL_FOCUSED) )
729 {
730 // just draw it as is
731 dc.DrawText(text, rect.x, rect.y);
732 }
733 else // we have selection
734 {
735 wxCoord width,
736 x = rect.x;
737
738 // draw the part before selection
739 wxString s(text, (size_t)selStart);
740 if ( !s.empty() )
741 {
742 dc.DrawText(s, x, rect.y);
743
744 dc.GetTextExtent(s, &width, NULL);
745 x += width;
746 }
747
748 // draw the selection itself
749 s = wxString(text.c_str() + selStart, text.c_str() + selEnd);
750 if ( !s.empty() )
751 {
752 wxColour colFg = dc.GetTextForeground(),
753 colBg = dc.GetTextBackground();
754 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
755 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT));
756 dc.SetBackgroundMode(wxSOLID);
757
758 dc.DrawText(s, x, rect.y);
759 dc.GetTextExtent(s, &width, NULL);
760 x += width;
761
762 dc.SetBackgroundMode(wxTRANSPARENT);
763 dc.SetTextBackground(colBg);
764 dc.SetTextForeground(colFg);
765 }
766
767 // draw the final part
768 s = text.c_str() + selEnd;
769 if ( !s.empty() )
770 {
771 dc.DrawText(s, x, rect.y);
772 }
773 }
774 }
775
776 void wxStdRenderer::DrawLineWrapMark(wxDC& WXUNUSED(dc),
777 const wxRect& WXUNUSED(rect))
778 {
779 // nothing by default
780 }
781
782 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl * WXUNUSED(text)) const
783 {
784 return 1;
785 }
786
787 wxRect
788 wxStdRenderer::GetTextTotalArea(const wxTextCtrl *text, const wxRect& rect) const
789 {
790 wxRect rectTotal = rect;
791 rectTotal.Inflate(GetTextBorderWidth(text));
792 return rectTotal;
793 }
794
795 wxRect wxStdRenderer::GetTextClientArea(const wxTextCtrl *text,
796 const wxRect& rect,
797 wxCoord *extraSpaceBeyond) const
798 {
799 wxRect rectText = rect;
800 rectText.Deflate(GetTextBorderWidth(text));
801
802 if ( extraSpaceBeyond )
803 *extraSpaceBeyond = 0;
804
805 return rectText;
806 }
807
808 #endif // wxUSE_TEXTCTRL
809
810 // ----------------------------------------------------------------------------
811 // scrollbars drawing
812 // ----------------------------------------------------------------------------
813
814 void wxStdRenderer::DrawScrollbarArrow(wxDC& dc,
815 wxDirection dir,
816 const wxRect& rect,
817 int flags)
818 {
819 DrawArrow(dc, dir, rect, flags);
820 }
821
822 void wxStdRenderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
823 {
824 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
825 }
826
827 // ----------------------------------------------------------------------------
828 // scrollbars geometry
829 // ----------------------------------------------------------------------------
830
831 #if wxUSE_SCROLLBAR
832
833 /* static */
834 void wxStdRenderer::GetScrollBarThumbSize(wxCoord length,
835 int thumbPos,
836 int thumbSize,
837 int range,
838 wxCoord *thumbStart,
839 wxCoord *thumbEnd)
840 {
841 // the thumb can't be made less than this number of pixels
842 static const wxCoord thumbMinWidth = 8; // FIXME: should be configurable
843
844 *thumbStart = (length*thumbPos) / range;
845 *thumbEnd = (length*(thumbPos + thumbSize)) / range;
846
847 if ( *thumbEnd - *thumbStart < thumbMinWidth )
848 {
849 // adjust the end if possible
850 if ( *thumbStart <= length - thumbMinWidth )
851 {
852 // yes, just make it wider
853 *thumbEnd = *thumbStart + thumbMinWidth;
854 }
855 else // it is at the bottom of the scrollbar
856 {
857 // so move it a bit up
858 *thumbStart = length - thumbMinWidth;
859 *thumbEnd = length;
860 }
861 }
862 }
863
864 wxRect wxStdRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
865 wxScrollBar::Element elem,
866 int thumbPos) const
867 {
868 if ( thumbPos == -1 )
869 {
870 thumbPos = scrollbar->GetThumbPosition();
871 }
872
873 const wxSize sizeArrow = GetScrollbarArrowSize();
874
875 wxSize sizeTotal = scrollbar->GetClientSize();
876 wxCoord *start, *width;
877 wxCoord length, arrow;
878 wxRect rect;
879 if ( scrollbar->IsVertical() )
880 {
881 rect.x = 0;
882 rect.width = sizeTotal.x;
883 length = sizeTotal.y;
884 start = &rect.y;
885 width = &rect.height;
886 arrow = sizeArrow.y;
887 }
888 else // horizontal
889 {
890 rect.y = 0;
891 rect.height = sizeTotal.y;
892 length = sizeTotal.x;
893 start = &rect.x;
894 width = &rect.width;
895 arrow = sizeArrow.x;
896 }
897
898 switch ( elem )
899 {
900 case wxScrollBar::Element_Arrow_Line_1:
901 *start = 0;
902 *width = arrow;
903 break;
904
905 case wxScrollBar::Element_Arrow_Line_2:
906 *start = length - arrow;
907 *width = arrow;
908 break;
909
910 case wxScrollBar::Element_Arrow_Page_1:
911 case wxScrollBar::Element_Arrow_Page_2:
912 // we don't have them at all
913 break;
914
915 case wxScrollBar::Element_Thumb:
916 case wxScrollBar::Element_Bar_1:
917 case wxScrollBar::Element_Bar_2:
918 // we need to calculate the thumb position - do it
919 {
920 length -= 2*arrow;
921 wxCoord thumbStart, thumbEnd;
922 int range = scrollbar->GetRange();
923 if ( !range )
924 {
925 thumbStart =
926 thumbEnd = 0;
927 }
928 else
929 {
930 GetScrollBarThumbSize(length,
931 thumbPos,
932 scrollbar->GetThumbSize(),
933 range,
934 &thumbStart,
935 &thumbEnd);
936 }
937
938 if ( elem == wxScrollBar::Element_Thumb )
939 {
940 *start = thumbStart;
941 *width = thumbEnd - thumbStart;
942 }
943 else if ( elem == wxScrollBar::Element_Bar_1 )
944 {
945 *start = 0;
946 *width = thumbStart;
947 }
948 else // elem == wxScrollBar::Element_Bar_2
949 {
950 *start = thumbEnd;
951 *width = length - thumbEnd;
952 }
953
954 // everything is relative to the start of the shaft so far
955 *start += arrow;
956 }
957 break;
958
959 case wxScrollBar::Element_Max:
960 default:
961 wxFAIL_MSG( _T("unknown scrollbar element") );
962 }
963
964 return rect;
965 }
966
967 wxCoord wxStdRenderer::GetScrollbarSize(const wxScrollBar *scrollbar)
968 {
969 const wxSize sizeArrowSB = GetScrollbarArrowSize();
970
971 wxCoord sizeArrow, sizeTotal;
972 if ( scrollbar->GetWindowStyle() & wxVERTICAL )
973 {
974 sizeArrow = sizeArrowSB.y;
975 sizeTotal = scrollbar->GetSize().y;
976 }
977 else // horizontal
978 {
979 sizeArrow = sizeArrowSB.x;
980 sizeTotal = scrollbar->GetSize().x;
981 }
982
983 return sizeTotal - 2*sizeArrow;
984 }
985
986 wxHitTest
987 wxStdRenderer::HitTestScrollbar(const wxScrollBar *scrollbar, const wxPoint& pt) const
988 {
989 // we only need to work with either x or y coord depending on the
990 // orientation, choose one (but still check the other one to verify if the
991 // mouse is in the window at all)
992 const wxSize sizeArrowSB = GetScrollbarArrowSize();
993
994 wxCoord coord, sizeArrow, sizeTotal;
995 wxSize size = scrollbar->GetSize();
996 if ( scrollbar->GetWindowStyle() & wxVERTICAL )
997 {
998 if ( pt.x < 0 || pt.x > size.x )
999 return wxHT_NOWHERE;
1000
1001 coord = pt.y;
1002 sizeArrow = sizeArrowSB.y;
1003 sizeTotal = size.y;
1004 }
1005 else // horizontal
1006 {
1007 if ( pt.y < 0 || pt.y > size.y )
1008 return wxHT_NOWHERE;
1009
1010 coord = pt.x;
1011 sizeArrow = sizeArrowSB.x;
1012 sizeTotal = size.x;
1013 }
1014
1015 // test for the arrows first as it's faster
1016 if ( coord < 0 || coord > sizeTotal )
1017 {
1018 return wxHT_NOWHERE;
1019 }
1020 else if ( coord < sizeArrow )
1021 {
1022 return wxHT_SCROLLBAR_ARROW_LINE_1;
1023 }
1024 else if ( coord > sizeTotal - sizeArrow )
1025 {
1026 return wxHT_SCROLLBAR_ARROW_LINE_2;
1027 }
1028 else
1029 {
1030 // calculate the thumb position in pixels
1031 sizeTotal -= 2*sizeArrow;
1032 wxCoord thumbStart, thumbEnd;
1033 int range = scrollbar->GetRange();
1034 if ( !range )
1035 {
1036 // clicking the scrollbar without range has no effect
1037 return wxHT_NOWHERE;
1038 }
1039 else
1040 {
1041 GetScrollBarThumbSize(sizeTotal,
1042 scrollbar->GetThumbPosition(),
1043 scrollbar->GetThumbSize(),
1044 range,
1045 &thumbStart,
1046 &thumbEnd);
1047 }
1048
1049 // now compare with the thumb position
1050 coord -= sizeArrow;
1051 if ( coord < thumbStart )
1052 return wxHT_SCROLLBAR_BAR_1;
1053 else if ( coord > thumbEnd )
1054 return wxHT_SCROLLBAR_BAR_2;
1055 else
1056 return wxHT_SCROLLBAR_THUMB;
1057 }
1058 }
1059
1060
1061 wxCoord
1062 wxStdRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar, int thumbPos)
1063 {
1064 int range = scrollbar->GetRange();
1065 if ( !range )
1066 {
1067 // the only valid position anyhow
1068 return 0;
1069 }
1070
1071 if ( thumbPos == -1 )
1072 {
1073 // by default use the current thumb position
1074 thumbPos = scrollbar->GetThumbPosition();
1075 }
1076
1077 const wxSize sizeArrow = GetScrollbarArrowSize();
1078 return (thumbPos*GetScrollbarSize(scrollbar)) / range
1079 + (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x);
1080 }
1081
1082 int wxStdRenderer::PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord)
1083 {
1084 const wxSize sizeArrow = GetScrollbarArrowSize();
1085 return ((coord - (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x)) *
1086 scrollbar->GetRange() ) / GetScrollbarSize(scrollbar);
1087 }
1088
1089 #endif // wxUSE_SCROLLBAR
1090
1091 // ----------------------------------------------------------------------------
1092 // status bar
1093 // ----------------------------------------------------------------------------
1094
1095 #if wxUSE_STATUSBAR
1096
1097 wxSize wxStdRenderer::GetStatusBarBorders(wxCoord *borderBetweenFields) const
1098 {
1099 if ( borderBetweenFields )
1100 *borderBetweenFields = 2;
1101
1102 return wxSize(2, 2);
1103 }
1104
1105 void wxStdRenderer::DrawStatusField(wxDC& dc,
1106 const wxRect& rect,
1107 const wxString& label,
1108 int flags,
1109 int style)
1110 {
1111 wxRect rectIn;
1112
1113 if ( style == wxSB_RAISED )
1114 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn);
1115 else if ( style != wxSB_FLAT )
1116 DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn);
1117
1118 rectIn.Deflate(GetStatusBarBorders(NULL));
1119
1120 wxDCClipper clipper(dc, rectIn);
1121 DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
1122 }
1123
1124 #endif // wxUSE_STATUSBAR
1125
1126 // ----------------------------------------------------------------------------
1127 // top level windows
1128 // ----------------------------------------------------------------------------
1129
1130 int wxStdRenderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const
1131 {
1132 wxRect client = GetFrameClientArea(rect, flags);
1133
1134 if ( client.Contains(pt) )
1135 return wxHT_TOPLEVEL_CLIENT_AREA;
1136
1137 if ( flags & wxTOPLEVEL_TITLEBAR )
1138 {
1139 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1140
1141 if ( flags & wxTOPLEVEL_ICON )
1142 {
1143 if ( wxRect(client.GetPosition(), GetFrameIconSize()).Contains(pt) )
1144 return wxHT_TOPLEVEL_ICON;
1145 }
1146
1147 wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH,
1148 client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2,
1149 FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
1150
1151 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1152 {
1153 if ( btnRect.Contains(pt) )
1154 return wxHT_TOPLEVEL_BUTTON_CLOSE;
1155 btnRect.x -= FRAME_BUTTON_WIDTH + 2;
1156 }
1157 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1158 {
1159 if ( btnRect.Contains(pt) )
1160 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE;
1161 btnRect.x -= FRAME_BUTTON_WIDTH;
1162 }
1163 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1164 {
1165 if ( btnRect.Contains(pt) )
1166 return wxHT_TOPLEVEL_BUTTON_RESTORE;
1167 btnRect.x -= FRAME_BUTTON_WIDTH;
1168 }
1169 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1170 {
1171 if ( btnRect.Contains(pt) )
1172 return wxHT_TOPLEVEL_BUTTON_ICONIZE;
1173 btnRect.x -= FRAME_BUTTON_WIDTH;
1174 }
1175 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1176 {
1177 if ( btnRect.Contains(pt) )
1178 return wxHT_TOPLEVEL_BUTTON_HELP;
1179 btnRect.x -= FRAME_BUTTON_WIDTH;
1180 }
1181
1182 if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT )
1183 return wxHT_TOPLEVEL_TITLEBAR;
1184 }
1185
1186 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1187 {
1188 // we are certainly at one of borders, let's decide which one:
1189
1190 int border = 0;
1191 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
1192 if ( pt.x < client.x )
1193 border |= wxHT_TOPLEVEL_BORDER_W;
1194 else if ( pt.x >= client.width + client.x )
1195 border |= wxHT_TOPLEVEL_BORDER_E;
1196 if ( pt.y < client.y )
1197 border |= wxHT_TOPLEVEL_BORDER_N;
1198 else if ( pt.y >= client.height + client.y )
1199 border |= wxHT_TOPLEVEL_BORDER_S;
1200 return border;
1201 }
1202
1203 return wxHT_NOWHERE;
1204 }
1205
1206 void wxStdRenderer::DrawFrameTitleBar(wxDC& dc,
1207 const wxRect& rect,
1208 const wxString& title,
1209 const wxIcon& icon,
1210 int flags,
1211 int specialButton,
1212 int specialButtonFlags)
1213 {
1214 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1215 {
1216 DrawFrameBorder(dc, rect, flags);
1217 }
1218 if ( flags & wxTOPLEVEL_TITLEBAR )
1219 {
1220 DrawFrameBackground(dc, rect, flags);
1221 if ( flags & wxTOPLEVEL_ICON )
1222 DrawFrameIcon(dc, rect, icon, flags);
1223 DrawFrameTitle(dc, rect, title, flags);
1224
1225 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1226 wxCoord x,y;
1227 x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH;
1228 y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2;
1229
1230 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1231 {
1232 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE,
1233 (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ?
1234 specialButtonFlags : 0);
1235 x -= FRAME_BUTTON_WIDTH + 2;
1236 }
1237 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1238 {
1239 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE,
1240 (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ?
1241 specialButtonFlags : 0);
1242 x -= FRAME_BUTTON_WIDTH;
1243 }
1244 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1245 {
1246 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE,
1247 (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ?
1248 specialButtonFlags : 0);
1249 x -= FRAME_BUTTON_WIDTH;
1250 }
1251 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1252 {
1253 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE,
1254 (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ?
1255 specialButtonFlags : 0);
1256 x -= FRAME_BUTTON_WIDTH;
1257 }
1258 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1259 {
1260 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP,
1261 (specialButton == wxTOPLEVEL_BUTTON_HELP) ?
1262 specialButtonFlags : 0);
1263 }
1264 }
1265 }
1266
1267 void wxStdRenderer::DrawFrameBorder(wxDC& dc, const wxRect& rect, int flags)
1268 {
1269 if ( !(flags & wxTOPLEVEL_BORDER) )
1270 return;
1271
1272 wxRect r(rect);
1273
1274 DrawAntiSunkenBorder(dc, &r);
1275 DrawExtraBorder(dc, &r);
1276 if ( flags & wxTOPLEVEL_RESIZEABLE )
1277 DrawExtraBorder(dc, &r);
1278 }
1279
1280 void wxStdRenderer::DrawFrameBackground(wxDC& dc, const wxRect& rect, int flags)
1281 {
1282 if ( !(flags & wxTOPLEVEL_TITLEBAR) )
1283 return;
1284
1285 wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE
1286 ? wxColourScheme::TITLEBAR_ACTIVE
1287 : wxColourScheme::TITLEBAR);
1288
1289 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1290 r.height = FRAME_TITLEBAR_HEIGHT;
1291
1292 DrawBackground(dc, col, r);
1293 }
1294
1295 void wxStdRenderer::DrawFrameTitle(wxDC& dc,
1296 const wxRect& rect,
1297 const wxString& title,
1298 int flags)
1299 {
1300 wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE
1301 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1302 : wxColourScheme::TITLEBAR_TEXT);
1303 dc.SetTextForeground(col);
1304
1305 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1306 r.height = FRAME_TITLEBAR_HEIGHT;
1307 if ( flags & wxTOPLEVEL_ICON )
1308 {
1309 r.x += FRAME_TITLEBAR_HEIGHT;
1310 r.width -= FRAME_TITLEBAR_HEIGHT + 2;
1311 }
1312 else
1313 {
1314 r.x += 1;
1315 r.width -= 3;
1316 }
1317
1318 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1319 r.width -= FRAME_BUTTON_WIDTH + 2;
1320 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1321 r.width -= FRAME_BUTTON_WIDTH;
1322 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1323 r.width -= FRAME_BUTTON_WIDTH;
1324 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1325 r.width -= FRAME_BUTTON_WIDTH;
1326 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1327 r.width -= FRAME_BUTTON_WIDTH;
1328
1329 dc.SetFont(m_titlebarFont);
1330
1331 wxString s;
1332 wxCoord textW;
1333 dc.GetTextExtent(title, &textW, NULL);
1334 if ( textW > r.width )
1335 {
1336 // text is too big, let's shorten it and add "..." after it:
1337 size_t len = title.length();
1338 wxCoord WSoFar, letterW;
1339
1340 dc.GetTextExtent(wxT("..."), &WSoFar, NULL);
1341 if ( WSoFar > r.width )
1342 {
1343 // not enough space to draw anything
1344 return;
1345 }
1346
1347 s.Alloc(len);
1348 for (size_t i = 0; i < len; i++)
1349 {
1350 dc.GetTextExtent(title[i], &letterW, NULL);
1351 if ( letterW + WSoFar > r.width )
1352 break;
1353 WSoFar += letterW;
1354 s << title[i];
1355 }
1356 s << wxT("...");
1357 }
1358 else // no need to truncate the title
1359 {
1360 s = title;
1361 }
1362
1363 dc.DrawLabel(s, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
1364 }
1365
1366 void wxStdRenderer::DrawFrameIcon(wxDC& dc,
1367 const wxRect& rect,
1368 const wxIcon& icon,
1369 int flags)
1370 {
1371 if ( icon.Ok() )
1372 {
1373 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1374 dc.DrawIcon(icon, r.x, r.y);
1375 }
1376 }
1377
1378 void wxStdRenderer::DrawFrameButton(wxDC& dc,
1379 wxCoord x, wxCoord y,
1380 int button,
1381 int flags)
1382 {
1383 FrameButtonType idx;
1384 switch (button)
1385 {
1386 case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break;
1387 case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break;
1388 case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break;
1389 case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break;
1390 case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break;
1391 default:
1392 wxFAIL_MSG(wxT("incorrect button specification"));
1393 return;
1394 }
1395
1396 wxBitmap bmp = GetFrameButtonBitmap(idx);
1397 if ( !bmp.Ok() )
1398 return;
1399
1400 wxRect rectBtn(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
1401 if ( flags & wxCONTROL_PRESSED )
1402 {
1403 DrawSunkenBorder(dc, &rectBtn);
1404
1405 rectBtn.Offset(1, 1);
1406 }
1407 else
1408 {
1409 DrawRaisedBorder(dc, &rectBtn);
1410 }
1411
1412 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rectBtn);
1413
1414 wxRect rectBmp(0, 0, bmp.GetWidth(), bmp.GetHeight());
1415 dc.DrawBitmap(bmp, rectBmp.CentreIn(rectBtn).GetPosition(), true);
1416 }
1417
1418
1419 wxRect wxStdRenderer::GetFrameClientArea(const wxRect& rect, int flags) const
1420 {
1421 wxRect r(rect);
1422
1423 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1424 {
1425 int border = flags & wxTOPLEVEL_RESIZEABLE
1426 ? RESIZEABLE_FRAME_BORDER_THICKNESS
1427 : FRAME_BORDER_THICKNESS;
1428 r.Inflate(-border);
1429 }
1430
1431 if ( flags & wxTOPLEVEL_TITLEBAR )
1432 {
1433 r.y += FRAME_TITLEBAR_HEIGHT;
1434 r.height -= FRAME_TITLEBAR_HEIGHT;
1435 }
1436
1437 return r;
1438 }
1439
1440 wxSize
1441 wxStdRenderer::GetFrameTotalSize(const wxSize& clientSize, int flags) const
1442 {
1443 wxSize s(clientSize);
1444
1445 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1446 {
1447 int border = flags & wxTOPLEVEL_RESIZEABLE
1448 ? RESIZEABLE_FRAME_BORDER_THICKNESS
1449 : FRAME_BORDER_THICKNESS;
1450 s.x += 2*border;
1451 s.y += 2*border;
1452 }
1453
1454 if ( flags & wxTOPLEVEL_TITLEBAR )
1455 s.y += FRAME_TITLEBAR_HEIGHT;
1456
1457 return s;
1458 }
1459
1460 wxSize wxStdRenderer::GetFrameMinSize(int flags) const
1461 {
1462 wxSize s;
1463
1464 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1465 {
1466 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
1467 RESIZEABLE_FRAME_BORDER_THICKNESS :
1468 FRAME_BORDER_THICKNESS;
1469 s.x += 2*border;
1470 s.y += 2*border;
1471 }
1472
1473 if ( flags & wxTOPLEVEL_TITLEBAR )
1474 {
1475 s.y += FRAME_TITLEBAR_HEIGHT;
1476
1477 if ( flags & wxTOPLEVEL_ICON )
1478 s.x += FRAME_TITLEBAR_HEIGHT + 2;
1479 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1480 s.x += FRAME_BUTTON_WIDTH + 2;
1481 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1482 s.x += FRAME_BUTTON_WIDTH;
1483 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1484 s.x += FRAME_BUTTON_WIDTH;
1485 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1486 s.x += FRAME_BUTTON_WIDTH;
1487 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1488 s.x += FRAME_BUTTON_WIDTH;
1489 }
1490
1491 return s;
1492 }
1493
1494 wxSize wxStdRenderer::GetFrameIconSize() const
1495 {
1496 return wxSize(16, 16);
1497 }