add more virtual border drawing functions used by frame decorations code
[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::DrawBoxBorder(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::DrawStaticBorder(wxDC& dc, wxRect *rect)
376 {
377 DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight);
378 }
379
380 void wxStdRenderer::DrawExtraBorder(wxDC& dc, wxRect *rect)
381 {
382 DrawRect(dc, rect, m_penLightGrey);
383 }
384
385 void wxStdRenderer::DrawBorder(wxDC& dc,
386 wxBorder border,
387 const wxRect& rectTotal,
388 int WXUNUSED(flags),
389 wxRect *rectIn)
390 {
391 wxRect rect = rectTotal;
392
393 switch ( border )
394 {
395 case wxBORDER_SUNKEN:
396 DrawSunkenBorder(dc, &rect);
397 break;
398
399 case wxBORDER_DOUBLE:
400 DrawAntiSunkenBorder(dc, &rect);
401 DrawExtraBorder(dc, &rect);
402 break;
403
404 case wxBORDER_STATIC:
405 DrawStaticBorder(dc, &rect);
406 break;
407
408 case wxBORDER_RAISED:
409 DrawRaisedBorder(dc, &rect);
410 break;
411
412 case wxBORDER_SIMPLE:
413 DrawRect(dc, &rect, m_penBlack);
414 break;
415
416 default:
417 wxFAIL_MSG(_T("unknown border type"));
418 // fall through
419
420 case wxBORDER_DEFAULT:
421 case wxBORDER_NONE:
422 break;
423 }
424
425 if ( rectIn )
426 *rectIn = rect;
427 }
428
429 wxRect wxStdRenderer::GetBorderDimensions(wxBorder border) const
430 {
431 wxCoord width;
432 switch ( border )
433 {
434 case wxBORDER_SIMPLE:
435 case wxBORDER_STATIC:
436 width = 1;
437 break;
438
439 case wxBORDER_RAISED:
440 case wxBORDER_SUNKEN:
441 width = 2;
442 break;
443
444 case wxBORDER_DOUBLE:
445 width = 3;
446 break;
447
448 default:
449 wxFAIL_MSG(_T("unknown border type"));
450 // fall through
451
452 case wxBORDER_DEFAULT:
453 case wxBORDER_NONE:
454 width = 0;
455 break;
456 }
457
458 wxRect rect;
459 rect.x =
460 rect.y =
461 rect.width =
462 rect.height = width;
463
464 return rect;
465 }
466
467 void wxStdRenderer::AdjustSize(wxSize *size, const wxWindow *window)
468 {
469 // take into account the border width
470 wxRect rectBorder = GetBorderDimensions(window->GetBorder());
471 size->x += rectBorder.x + rectBorder.width;
472 size->y += rectBorder.y + rectBorder.height;
473 }
474
475 bool wxStdRenderer::AreScrollbarsInsideBorder() const
476 {
477 return false;
478 }
479
480 wxCoord wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight)
481 {
482 return fontHeight + 2;
483 }
484
485 void wxStdRenderer::DrawTextBorder(wxDC& dc,
486 wxBorder border,
487 const wxRect& rect,
488 int flags,
489 wxRect *rectIn)
490 {
491 DrawBorder(dc, border, rect, flags, rectIn);
492 }
493
494 // ----------------------------------------------------------------------------
495 // lines and boxes
496 // ----------------------------------------------------------------------------
497
498 void
499 wxStdRenderer::DrawHorizontalLine(wxDC& dc, wxCoord y, wxCoord x1, wxCoord x2)
500 {
501 dc.SetPen(m_penDarkGrey);
502 dc.DrawLine(x1, y, x2 + 1, y);
503
504 dc.SetPen(m_penHighlight);
505 y++;
506 dc.DrawLine(x1, y, x2 + 1, y);
507 }
508
509 void
510 wxStdRenderer::DrawVerticalLine(wxDC& dc, wxCoord x, wxCoord y1, wxCoord y2)
511 {
512 dc.SetPen(m_penDarkGrey);
513 dc.DrawLine(x, y1, x, y2 + 1);
514
515 dc.SetPen(m_penHighlight);
516 x++;
517 dc.DrawLine(x, y1, x, y2 + 1);
518 }
519
520 void wxStdRenderer::DrawFrameWithoutLabel(wxDC& dc,
521 const wxRect& rectFrame,
522 const wxRect& rectLabel)
523 {
524 // draw left, bottom and right lines entirely
525 DrawVerticalLine(dc, rectFrame.GetLeft(),
526 rectFrame.GetTop(), rectFrame.GetBottom() - 2);
527 DrawHorizontalLine(dc, rectFrame.GetBottom() - 1,
528 rectFrame.GetLeft(), rectFrame.GetRight());
529 DrawVerticalLine(dc, rectFrame.GetRight() - 1,
530 rectFrame.GetTop(), rectFrame.GetBottom() - 1);
531
532 // and 2 parts of the top line
533 DrawHorizontalLine(dc, rectFrame.GetTop(),
534 rectFrame.GetLeft() + 1, rectLabel.GetLeft());
535 DrawHorizontalLine(dc, rectFrame.GetTop(),
536 rectLabel.GetRight(), rectFrame.GetRight() - 2);
537 }
538
539 void wxStdRenderer::DrawFrameWithLabel(wxDC& dc,
540 const wxString& label,
541 const wxRect& rectFrame,
542 const wxRect& rectText,
543 int flags,
544 int alignment,
545 int indexAccel)
546 {
547 wxRect rectLabel;
548 DrawLabel(dc, label, rectText, flags, alignment, indexAccel, &rectLabel);
549
550 DrawFrameWithoutLabel(dc, rectFrame, rectLabel);
551 }
552
553 void wxStdRenderer::DrawFrame(wxDC& dc,
554 const wxString& label,
555 const wxRect& rect,
556 int flags,
557 int alignment,
558 int indexAccel)
559 {
560 wxCoord height = 0; // of the label
561 wxRect rectFrame = rect;
562 if ( !label.empty() )
563 {
564 // the text should touch the top border of the rect, so the frame
565 // itself should be lower
566 dc.GetTextExtent(label, NULL, &height);
567 rectFrame.y += height / 2;
568 rectFrame.height -= height / 2;
569
570 // we have to draw each part of the frame individually as we can't
571 // erase the background beyond the label as it might contain some
572 // pixmap already, so drawing everything and then overwriting part of
573 // the frame with label doesn't work
574
575 // TODO: the +5 shouldn't be hard coded
576 wxRect rectText;
577 rectText.x = rectFrame.x + 5;
578 rectText.y = rect.y;
579 rectText.width = rectFrame.width - 7; // +2 border width
580 rectText.height = height;
581
582 DrawFrameWithLabel(dc, label, rectFrame, rectText, flags,
583 alignment, indexAccel);
584 }
585 else // no label
586 {
587 DrawBoxBorder(dc, &rectFrame);
588 }
589 }
590
591 void wxStdRenderer::DrawItem(wxDC& dc,
592 const wxString& label,
593 const wxRect& rect,
594 int flags)
595 {
596 wxDCTextColourChanger colChanger(dc);
597
598 if ( flags & wxCONTROL_SELECTED )
599 {
600 colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
601
602 const wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
603 dc.SetBrush(colBg);
604 dc.SetPen(colBg);
605 dc.DrawRectangle(rect);
606 }
607
608 wxRect rectText = rect;
609 rectText.x += 2;
610 rectText.width -= 2;
611 dc.DrawLabel(label, wxNullBitmap, rectText);
612
613 if ( flags & wxCONTROL_FOCUSED )
614 {
615 DrawFocusRect(dc, rect);
616 }
617 }
618
619 void wxStdRenderer::DrawCheckItemBitmap(wxDC& dc,
620 const wxBitmap& bitmap,
621 const wxRect& rect,
622 int flags)
623 {
624 DrawCheckButton(dc, wxEmptyString, bitmap, rect, flags);
625 }
626
627 void wxStdRenderer::DrawCheckItem(wxDC& dc,
628 const wxString& label,
629 const wxBitmap& bitmap,
630 const wxRect& rect,
631 int flags)
632 {
633 wxRect rectBitmap = rect;
634 rectBitmap.width = GetCheckBitmapSize().x;
635 DrawCheckItemBitmap(dc, bitmap, rectBitmap, flags);
636
637 wxRect rectLabel = rect;
638 wxCoord shift = rectBitmap.width + 2*GetCheckItemMargin();
639 rectLabel.x += shift;
640 rectLabel.width -= shift;
641 DrawItem(dc, label, rectLabel, flags);
642 }
643
644 // ----------------------------------------------------------------------------
645 // check and radio bitmaps
646 // ----------------------------------------------------------------------------
647
648 void wxStdRenderer::DrawCheckButton(wxDC& dc,
649 const wxString& label,
650 const wxBitmap& bitmap,
651 const wxRect& rect,
652 int flags,
653 wxAlignment align,
654 int indexAccel)
655 {
656 wxBitmap bmp(bitmap.Ok() ? bitmap : GetCheckBitmap(flags));
657
658 DrawCheckOrRadioButton(dc, label, bmp, rect, flags, align, indexAccel);
659 }
660
661 void wxStdRenderer::DrawRadioButton(wxDC& dc,
662 const wxString& label,
663 const wxBitmap& bitmap,
664 const wxRect& rect,
665 int flags,
666 wxAlignment align,
667 int indexAccel)
668 {
669 wxBitmap bmp(bitmap.Ok() ? bitmap : GetRadioBitmap(flags));
670
671 DrawCheckOrRadioButton(dc, label, bmp, rect, flags, align, indexAccel);
672 }
673
674 void wxStdRenderer::DrawCheckOrRadioButton(wxDC& dc,
675 const wxString& label,
676 const wxBitmap& bitmap,
677 const wxRect& rect,
678 int flags,
679 wxAlignment align,
680 int indexAccel)
681 {
682 // calculate the position of the bitmap and of the label
683 wxCoord heightBmp = bitmap.GetHeight();
684 wxCoord xBmp,
685 yBmp = rect.y + (rect.height - heightBmp) / 2;
686
687 wxRect rectLabel;
688 dc.GetMultiLineTextExtent(label, NULL, &rectLabel.height);
689 rectLabel.y = rect.y + (rect.height - rectLabel.height) / 2;
690
691 // align label vertically with the bitmap - looks nicer like this
692 rectLabel.y -= (rectLabel.height - heightBmp) % 2;
693
694 // calc horz position
695 if ( align == wxALIGN_RIGHT )
696 {
697 xBmp = rect.GetRight() - bitmap.GetWidth();
698 rectLabel.x = rect.x + 3;
699 rectLabel.SetRight(xBmp);
700 }
701 else // normal (checkbox to the left of the text) case
702 {
703 xBmp = rect.x;
704 rectLabel.x = xBmp + bitmap.GetWidth() + 5;
705 rectLabel.SetRight(rect.GetRight());
706 }
707
708 dc.DrawBitmap(bitmap, xBmp, yBmp, true /* use mask */);
709
710 DrawLabel(dc, label, rectLabel, flags,
711 wxALIGN_LEFT | wxALIGN_TOP, indexAccel);
712 }
713
714 #if wxUSE_TEXTCTRL
715
716 void wxStdRenderer::DrawTextLine(wxDC& dc,
717 const wxString& text,
718 const wxRect& rect,
719 int selStart,
720 int selEnd,
721 int flags)
722 {
723 if ( (selStart == -1) || !(flags & wxCONTROL_FOCUSED) )
724 {
725 // just draw it as is
726 dc.DrawText(text, rect.x, rect.y);
727 }
728 else // we have selection
729 {
730 wxCoord width,
731 x = rect.x;
732
733 // draw the part before selection
734 wxString s(text, (size_t)selStart);
735 if ( !s.empty() )
736 {
737 dc.DrawText(s, x, rect.y);
738
739 dc.GetTextExtent(s, &width, NULL);
740 x += width;
741 }
742
743 // draw the selection itself
744 s = wxString(text.c_str() + selStart, text.c_str() + selEnd);
745 if ( !s.empty() )
746 {
747 wxColour colFg = dc.GetTextForeground(),
748 colBg = dc.GetTextBackground();
749 dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
750 dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT));
751 dc.SetBackgroundMode(wxSOLID);
752
753 dc.DrawText(s, x, rect.y);
754 dc.GetTextExtent(s, &width, NULL);
755 x += width;
756
757 dc.SetBackgroundMode(wxTRANSPARENT);
758 dc.SetTextBackground(colBg);
759 dc.SetTextForeground(colFg);
760 }
761
762 // draw the final part
763 s = text.c_str() + selEnd;
764 if ( !s.empty() )
765 {
766 dc.DrawText(s, x, rect.y);
767 }
768 }
769 }
770
771 void wxStdRenderer::DrawLineWrapMark(wxDC& WXUNUSED(dc),
772 const wxRect& WXUNUSED(rect))
773 {
774 // nothing by default
775 }
776
777 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl * WXUNUSED(text)) const
778 {
779 return 1;
780 }
781
782 wxRect
783 wxStdRenderer::GetTextTotalArea(const wxTextCtrl *text, const wxRect& rect) const
784 {
785 wxRect rectTotal = rect;
786 rectTotal.Inflate(GetTextBorderWidth(text));
787 return rectTotal;
788 }
789
790 wxRect wxStdRenderer::GetTextClientArea(const wxTextCtrl *text,
791 const wxRect& rect,
792 wxCoord *extraSpaceBeyond) const
793 {
794 wxRect rectText = rect;
795 rectText.Deflate(GetTextBorderWidth(text));
796
797 if ( extraSpaceBeyond )
798 *extraSpaceBeyond = 0;
799
800 return rectText;
801 }
802
803 #endif // wxUSE_TEXTCTRL
804
805 // ----------------------------------------------------------------------------
806 // scrollbars drawing
807 // ----------------------------------------------------------------------------
808
809 void wxStdRenderer::DrawScrollbarArrow(wxDC& dc,
810 wxDirection dir,
811 const wxRect& rect,
812 int flags)
813 {
814 DrawArrow(dc, dir, rect, flags);
815 }
816
817 void wxStdRenderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
818 {
819 DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
820 }
821
822 // ----------------------------------------------------------------------------
823 // scrollbars geometry
824 // ----------------------------------------------------------------------------
825
826 #if wxUSE_SCROLLBAR
827
828 /* static */
829 void wxStdRenderer::GetScrollBarThumbSize(wxCoord length,
830 int thumbPos,
831 int thumbSize,
832 int range,
833 wxCoord *thumbStart,
834 wxCoord *thumbEnd)
835 {
836 // the thumb can't be made less than this number of pixels
837 static const wxCoord thumbMinWidth = 8; // FIXME: should be configurable
838
839 *thumbStart = (length*thumbPos) / range;
840 *thumbEnd = (length*(thumbPos + thumbSize)) / range;
841
842 if ( *thumbEnd - *thumbStart < thumbMinWidth )
843 {
844 // adjust the end if possible
845 if ( *thumbStart <= length - thumbMinWidth )
846 {
847 // yes, just make it wider
848 *thumbEnd = *thumbStart + thumbMinWidth;
849 }
850 else // it is at the bottom of the scrollbar
851 {
852 // so move it a bit up
853 *thumbStart = length - thumbMinWidth;
854 *thumbEnd = length;
855 }
856 }
857 }
858
859 wxRect wxStdRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
860 wxScrollBar::Element elem,
861 int thumbPos) const
862 {
863 if ( thumbPos == -1 )
864 {
865 thumbPos = scrollbar->GetThumbPosition();
866 }
867
868 const wxSize sizeArrow = GetScrollbarArrowSize();
869
870 wxSize sizeTotal = scrollbar->GetClientSize();
871 wxCoord *start, *width;
872 wxCoord length, arrow;
873 wxRect rect;
874 if ( scrollbar->IsVertical() )
875 {
876 rect.x = 0;
877 rect.width = sizeTotal.x;
878 length = sizeTotal.y;
879 start = &rect.y;
880 width = &rect.height;
881 arrow = sizeArrow.y;
882 }
883 else // horizontal
884 {
885 rect.y = 0;
886 rect.height = sizeTotal.y;
887 length = sizeTotal.x;
888 start = &rect.x;
889 width = &rect.width;
890 arrow = sizeArrow.x;
891 }
892
893 switch ( elem )
894 {
895 case wxScrollBar::Element_Arrow_Line_1:
896 *start = 0;
897 *width = arrow;
898 break;
899
900 case wxScrollBar::Element_Arrow_Line_2:
901 *start = length - arrow;
902 *width = arrow;
903 break;
904
905 case wxScrollBar::Element_Arrow_Page_1:
906 case wxScrollBar::Element_Arrow_Page_2:
907 // we don't have them at all
908 break;
909
910 case wxScrollBar::Element_Thumb:
911 case wxScrollBar::Element_Bar_1:
912 case wxScrollBar::Element_Bar_2:
913 // we need to calculate the thumb position - do it
914 {
915 length -= 2*arrow;
916 wxCoord thumbStart, thumbEnd;
917 int range = scrollbar->GetRange();
918 if ( !range )
919 {
920 thumbStart =
921 thumbEnd = 0;
922 }
923 else
924 {
925 GetScrollBarThumbSize(length,
926 thumbPos,
927 scrollbar->GetThumbSize(),
928 range,
929 &thumbStart,
930 &thumbEnd);
931 }
932
933 if ( elem == wxScrollBar::Element_Thumb )
934 {
935 *start = thumbStart;
936 *width = thumbEnd - thumbStart;
937 }
938 else if ( elem == wxScrollBar::Element_Bar_1 )
939 {
940 *start = 0;
941 *width = thumbStart;
942 }
943 else // elem == wxScrollBar::Element_Bar_2
944 {
945 *start = thumbEnd;
946 *width = length - thumbEnd;
947 }
948
949 // everything is relative to the start of the shaft so far
950 *start += arrow;
951 }
952 break;
953
954 case wxScrollBar::Element_Max:
955 default:
956 wxFAIL_MSG( _T("unknown scrollbar element") );
957 }
958
959 return rect;
960 }
961
962 wxCoord wxStdRenderer::GetScrollbarSize(const wxScrollBar *scrollbar)
963 {
964 const wxSize sizeArrowSB = GetScrollbarArrowSize();
965
966 wxCoord sizeArrow, sizeTotal;
967 if ( scrollbar->GetWindowStyle() & wxVERTICAL )
968 {
969 sizeArrow = sizeArrowSB.y;
970 sizeTotal = scrollbar->GetSize().y;
971 }
972 else // horizontal
973 {
974 sizeArrow = sizeArrowSB.x;
975 sizeTotal = scrollbar->GetSize().x;
976 }
977
978 return sizeTotal - 2*sizeArrow;
979 }
980
981 wxHitTest
982 wxStdRenderer::HitTestScrollbar(const wxScrollBar *scrollbar, const wxPoint& pt) const
983 {
984 // we only need to work with either x or y coord depending on the
985 // orientation, choose one (but still check the other one to verify if the
986 // mouse is in the window at all)
987 const wxSize sizeArrowSB = GetScrollbarArrowSize();
988
989 wxCoord coord, sizeArrow, sizeTotal;
990 wxSize size = scrollbar->GetSize();
991 if ( scrollbar->GetWindowStyle() & wxVERTICAL )
992 {
993 if ( pt.x < 0 || pt.x > size.x )
994 return wxHT_NOWHERE;
995
996 coord = pt.y;
997 sizeArrow = sizeArrowSB.y;
998 sizeTotal = size.y;
999 }
1000 else // horizontal
1001 {
1002 if ( pt.y < 0 || pt.y > size.y )
1003 return wxHT_NOWHERE;
1004
1005 coord = pt.x;
1006 sizeArrow = sizeArrowSB.x;
1007 sizeTotal = size.x;
1008 }
1009
1010 // test for the arrows first as it's faster
1011 if ( coord < 0 || coord > sizeTotal )
1012 {
1013 return wxHT_NOWHERE;
1014 }
1015 else if ( coord < sizeArrow )
1016 {
1017 return wxHT_SCROLLBAR_ARROW_LINE_1;
1018 }
1019 else if ( coord > sizeTotal - sizeArrow )
1020 {
1021 return wxHT_SCROLLBAR_ARROW_LINE_2;
1022 }
1023 else
1024 {
1025 // calculate the thumb position in pixels
1026 sizeTotal -= 2*sizeArrow;
1027 wxCoord thumbStart, thumbEnd;
1028 int range = scrollbar->GetRange();
1029 if ( !range )
1030 {
1031 // clicking the scrollbar without range has no effect
1032 return wxHT_NOWHERE;
1033 }
1034 else
1035 {
1036 GetScrollBarThumbSize(sizeTotal,
1037 scrollbar->GetThumbPosition(),
1038 scrollbar->GetThumbSize(),
1039 range,
1040 &thumbStart,
1041 &thumbEnd);
1042 }
1043
1044 // now compare with the thumb position
1045 coord -= sizeArrow;
1046 if ( coord < thumbStart )
1047 return wxHT_SCROLLBAR_BAR_1;
1048 else if ( coord > thumbEnd )
1049 return wxHT_SCROLLBAR_BAR_2;
1050 else
1051 return wxHT_SCROLLBAR_THUMB;
1052 }
1053 }
1054
1055
1056 wxCoord
1057 wxStdRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar, int thumbPos)
1058 {
1059 int range = scrollbar->GetRange();
1060 if ( !range )
1061 {
1062 // the only valid position anyhow
1063 return 0;
1064 }
1065
1066 if ( thumbPos == -1 )
1067 {
1068 // by default use the current thumb position
1069 thumbPos = scrollbar->GetThumbPosition();
1070 }
1071
1072 const wxSize sizeArrow = GetScrollbarArrowSize();
1073 return (thumbPos*GetScrollbarSize(scrollbar)) / range
1074 + (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x);
1075 }
1076
1077 int wxStdRenderer::PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord)
1078 {
1079 const wxSize sizeArrow = GetScrollbarArrowSize();
1080 return ((coord - (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x)) *
1081 scrollbar->GetRange() ) / GetScrollbarSize(scrollbar);
1082 }
1083
1084 #endif // wxUSE_SCROLLBAR
1085
1086 // ----------------------------------------------------------------------------
1087 // status bar
1088 // ----------------------------------------------------------------------------
1089
1090 #if wxUSE_STATUSBAR
1091
1092 wxSize wxStdRenderer::GetStatusBarBorders(wxCoord *borderBetweenFields) const
1093 {
1094 if ( borderBetweenFields )
1095 *borderBetweenFields = 2;
1096
1097 return wxSize(2, 2);
1098 }
1099
1100 void wxStdRenderer::DrawStatusField(wxDC& dc,
1101 const wxRect& rect,
1102 const wxString& label,
1103 int flags,
1104 int style)
1105 {
1106 wxRect rectIn;
1107
1108 if ( style == wxSB_RAISED )
1109 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn);
1110 else if ( style != wxSB_FLAT )
1111 DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn);
1112
1113 rectIn.Deflate(GetStatusBarBorders(NULL));
1114
1115 wxDCClipper clipper(dc, rectIn);
1116 DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
1117 }
1118
1119 #endif // wxUSE_STATUSBAR
1120
1121 // ----------------------------------------------------------------------------
1122 // top level windows
1123 // ----------------------------------------------------------------------------
1124
1125 int wxStdRenderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const
1126 {
1127 wxRect client = GetFrameClientArea(rect, flags);
1128
1129 if ( client.Contains(pt) )
1130 return wxHT_TOPLEVEL_CLIENT_AREA;
1131
1132 if ( flags & wxTOPLEVEL_TITLEBAR )
1133 {
1134 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1135
1136 if ( flags & wxTOPLEVEL_ICON )
1137 {
1138 if ( wxRect(client.GetPosition(), GetFrameIconSize()).Contains(pt) )
1139 return wxHT_TOPLEVEL_ICON;
1140 }
1141
1142 wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH,
1143 client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2,
1144 FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
1145
1146 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1147 {
1148 if ( btnRect.Contains(pt) )
1149 return wxHT_TOPLEVEL_BUTTON_CLOSE;
1150 btnRect.x -= FRAME_BUTTON_WIDTH + 2;
1151 }
1152 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1153 {
1154 if ( btnRect.Contains(pt) )
1155 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE;
1156 btnRect.x -= FRAME_BUTTON_WIDTH;
1157 }
1158 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1159 {
1160 if ( btnRect.Contains(pt) )
1161 return wxHT_TOPLEVEL_BUTTON_RESTORE;
1162 btnRect.x -= FRAME_BUTTON_WIDTH;
1163 }
1164 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1165 {
1166 if ( btnRect.Contains(pt) )
1167 return wxHT_TOPLEVEL_BUTTON_ICONIZE;
1168 btnRect.x -= FRAME_BUTTON_WIDTH;
1169 }
1170 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1171 {
1172 if ( btnRect.Contains(pt) )
1173 return wxHT_TOPLEVEL_BUTTON_HELP;
1174 btnRect.x -= FRAME_BUTTON_WIDTH;
1175 }
1176
1177 if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT )
1178 return wxHT_TOPLEVEL_TITLEBAR;
1179 }
1180
1181 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1182 {
1183 // we are certainly at one of borders, let's decide which one:
1184
1185 int border = 0;
1186 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
1187 if ( pt.x < client.x )
1188 border |= wxHT_TOPLEVEL_BORDER_W;
1189 else if ( pt.x >= client.width + client.x )
1190 border |= wxHT_TOPLEVEL_BORDER_E;
1191 if ( pt.y < client.y )
1192 border |= wxHT_TOPLEVEL_BORDER_N;
1193 else if ( pt.y >= client.height + client.y )
1194 border |= wxHT_TOPLEVEL_BORDER_S;
1195 return border;
1196 }
1197
1198 return wxHT_NOWHERE;
1199 }
1200
1201 void wxStdRenderer::DrawFrameTitleBar(wxDC& dc,
1202 const wxRect& rect,
1203 const wxString& title,
1204 const wxIcon& icon,
1205 int flags,
1206 int specialButton,
1207 int specialButtonFlags)
1208 {
1209 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1210 {
1211 DrawFrameBorder(dc, rect, flags);
1212 }
1213 if ( flags & wxTOPLEVEL_TITLEBAR )
1214 {
1215 DrawFrameBackground(dc, rect, flags);
1216 if ( flags & wxTOPLEVEL_ICON )
1217 DrawFrameIcon(dc, rect, icon, flags);
1218 DrawFrameTitle(dc, rect, title, flags);
1219
1220 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1221 wxCoord x,y;
1222 x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH;
1223 y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2;
1224
1225 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1226 {
1227 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE,
1228 (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ?
1229 specialButtonFlags : 0);
1230 x -= FRAME_BUTTON_WIDTH + 2;
1231 }
1232 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1233 {
1234 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE,
1235 (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ?
1236 specialButtonFlags : 0);
1237 x -= FRAME_BUTTON_WIDTH;
1238 }
1239 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1240 {
1241 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE,
1242 (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ?
1243 specialButtonFlags : 0);
1244 x -= FRAME_BUTTON_WIDTH;
1245 }
1246 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1247 {
1248 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE,
1249 (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ?
1250 specialButtonFlags : 0);
1251 x -= FRAME_BUTTON_WIDTH;
1252 }
1253 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1254 {
1255 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP,
1256 (specialButton == wxTOPLEVEL_BUTTON_HELP) ?
1257 specialButtonFlags : 0);
1258 }
1259 }
1260 }
1261
1262 void wxStdRenderer::DrawFrameBorder(wxDC& dc, const wxRect& rect, int flags)
1263 {
1264 if ( !(flags & wxTOPLEVEL_BORDER) )
1265 return;
1266
1267 wxRect r(rect);
1268
1269 DrawAntiSunkenBorder(dc, &r);
1270 DrawExtraBorder(dc, &r);
1271 if ( flags & wxTOPLEVEL_RESIZEABLE )
1272 DrawExtraBorder(dc, &r);
1273 }
1274
1275 void wxStdRenderer::DrawFrameBackground(wxDC& dc, const wxRect& rect, int flags)
1276 {
1277 if ( !(flags & wxTOPLEVEL_TITLEBAR) )
1278 return;
1279
1280 wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE
1281 ? wxColourScheme::TITLEBAR_ACTIVE
1282 : wxColourScheme::TITLEBAR);
1283
1284 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1285 r.height = FRAME_TITLEBAR_HEIGHT;
1286
1287 DrawBackground(dc, col, r);
1288 }
1289
1290 void wxStdRenderer::DrawFrameTitle(wxDC& dc,
1291 const wxRect& rect,
1292 const wxString& title,
1293 int flags)
1294 {
1295 wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE
1296 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1297 : wxColourScheme::TITLEBAR_TEXT);
1298 dc.SetTextForeground(col);
1299
1300 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1301 r.height = FRAME_TITLEBAR_HEIGHT;
1302 if ( flags & wxTOPLEVEL_ICON )
1303 {
1304 r.x += FRAME_TITLEBAR_HEIGHT;
1305 r.width -= FRAME_TITLEBAR_HEIGHT + 2;
1306 }
1307 else
1308 {
1309 r.x += 1;
1310 r.width -= 3;
1311 }
1312
1313 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1314 r.width -= FRAME_BUTTON_WIDTH + 2;
1315 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1316 r.width -= FRAME_BUTTON_WIDTH;
1317 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1318 r.width -= FRAME_BUTTON_WIDTH;
1319 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1320 r.width -= FRAME_BUTTON_WIDTH;
1321 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1322 r.width -= FRAME_BUTTON_WIDTH;
1323
1324 dc.SetFont(m_titlebarFont);
1325
1326 wxString s;
1327 wxCoord textW;
1328 dc.GetTextExtent(title, &textW, NULL);
1329 if ( textW > r.width )
1330 {
1331 // text is too big, let's shorten it and add "..." after it:
1332 size_t len = title.length();
1333 wxCoord WSoFar, letterW;
1334
1335 dc.GetTextExtent(wxT("..."), &WSoFar, NULL);
1336 if ( WSoFar > r.width )
1337 {
1338 // not enough space to draw anything
1339 return;
1340 }
1341
1342 s.Alloc(len);
1343 for (size_t i = 0; i < len; i++)
1344 {
1345 dc.GetTextExtent(title[i], &letterW, NULL);
1346 if ( letterW + WSoFar > r.width )
1347 break;
1348 WSoFar += letterW;
1349 s << title[i];
1350 }
1351 s << wxT("...");
1352 }
1353 else // no need to truncate the title
1354 {
1355 s = title;
1356 }
1357
1358 dc.DrawLabel(s, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
1359 }
1360
1361 void wxStdRenderer::DrawFrameIcon(wxDC& dc,
1362 const wxRect& rect,
1363 const wxIcon& icon,
1364 int flags)
1365 {
1366 if ( icon.Ok() )
1367 {
1368 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1369 dc.DrawIcon(icon, r.x, r.y);
1370 }
1371 }
1372
1373 void wxStdRenderer::DrawFrameButton(wxDC& dc,
1374 wxCoord x, wxCoord y,
1375 int button,
1376 int flags)
1377 {
1378 FrameButtonType idx;
1379 switch (button)
1380 {
1381 case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break;
1382 case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break;
1383 case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break;
1384 case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break;
1385 case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break;
1386 default:
1387 wxFAIL_MSG(wxT("incorrect button specification"));
1388 return;
1389 }
1390
1391 wxBitmap bmp = GetFrameButtonBitmap(idx);
1392 if ( !bmp.Ok() )
1393 return;
1394
1395 wxRect rectBtn(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
1396 if ( flags & wxCONTROL_PRESSED )
1397 {
1398 DrawSunkenBorder(dc, &rectBtn);
1399
1400 rectBtn.Offset(1, 1);
1401 }
1402 else
1403 {
1404 DrawRaisedBorder(dc, &rectBtn);
1405 }
1406
1407 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rectBtn);
1408
1409 wxRect rectBmp(0, 0, bmp.GetWidth(), bmp.GetHeight());
1410 dc.DrawBitmap(bmp, rectBmp.CentreIn(rectBtn).GetPosition(), true);
1411 }
1412
1413
1414 wxRect wxStdRenderer::GetFrameClientArea(const wxRect& rect, int flags) const
1415 {
1416 wxRect r(rect);
1417
1418 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1419 {
1420 int border = flags & wxTOPLEVEL_RESIZEABLE
1421 ? RESIZEABLE_FRAME_BORDER_THICKNESS
1422 : FRAME_BORDER_THICKNESS;
1423 r.Inflate(-border);
1424 }
1425
1426 if ( flags & wxTOPLEVEL_TITLEBAR )
1427 {
1428 r.y += FRAME_TITLEBAR_HEIGHT;
1429 r.height -= FRAME_TITLEBAR_HEIGHT;
1430 }
1431
1432 return r;
1433 }
1434
1435 wxSize
1436 wxStdRenderer::GetFrameTotalSize(const wxSize& clientSize, int flags) const
1437 {
1438 wxSize s(clientSize);
1439
1440 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1441 {
1442 int border = flags & wxTOPLEVEL_RESIZEABLE
1443 ? RESIZEABLE_FRAME_BORDER_THICKNESS
1444 : FRAME_BORDER_THICKNESS;
1445 s.x += 2*border;
1446 s.y += 2*border;
1447 }
1448
1449 if ( flags & wxTOPLEVEL_TITLEBAR )
1450 s.y += FRAME_TITLEBAR_HEIGHT;
1451
1452 return s;
1453 }
1454
1455 wxSize wxStdRenderer::GetFrameMinSize(int flags) const
1456 {
1457 wxSize s;
1458
1459 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1460 {
1461 int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
1462 RESIZEABLE_FRAME_BORDER_THICKNESS :
1463 FRAME_BORDER_THICKNESS;
1464 s.x += 2*border;
1465 s.y += 2*border;
1466 }
1467
1468 if ( flags & wxTOPLEVEL_TITLEBAR )
1469 {
1470 s.y += FRAME_TITLEBAR_HEIGHT;
1471
1472 if ( flags & wxTOPLEVEL_ICON )
1473 s.x += FRAME_TITLEBAR_HEIGHT + 2;
1474 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1475 s.x += FRAME_BUTTON_WIDTH + 2;
1476 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1477 s.x += FRAME_BUTTON_WIDTH;
1478 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1479 s.x += FRAME_BUTTON_WIDTH;
1480 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1481 s.x += FRAME_BUTTON_WIDTH;
1482 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1483 s.x += FRAME_BUTTON_WIDTH;
1484 }
1485
1486 return s;
1487 }
1488
1489 wxSize wxStdRenderer::GetFrameIconSize() const
1490 {
1491 return wxSize(16, 16);
1492 }
1493