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