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