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