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