fixed wxStatusBar size calculations so that the text is not clipped
[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() const
1096 {
1097 // Rendered border may be different depending on field's style, we use
1098 // the largest value so that any field certainly fits into the borders
1099 // we return:
1100 wxRect raised = GetBorderDimensions(wxBORDER_RAISED);
1101 wxRect flat = GetBorderDimensions(wxBORDER_STATIC);
1102 wxASSERT_MSG( raised.x == raised.width && raised.y == raised.height &&
1103 flat.x == flat.width && flat.y == flat.height,
1104 _T("this code expects uniform borders, you must override GetStatusBarBorders") );
1105
1106 // take the larger of flat/raised values:
1107 wxSize border(wxMax(raised.x, flat.x), wxMax(raised.y, flat.y));
1108
1109 return border;
1110 }
1111
1112 wxCoord wxStdRenderer::GetStatusBarBorderBetweenFields() const
1113 {
1114 return 2;
1115 }
1116
1117 wxSize wxStdRenderer::GetStatusBarFieldMargins() const
1118 {
1119 return wxSize(2, 2);
1120 }
1121
1122 void wxStdRenderer::DrawStatusField(wxDC& dc,
1123 const wxRect& rect,
1124 const wxString& label,
1125 int flags,
1126 int style)
1127 {
1128 wxRect rectIn;
1129
1130 if ( style == wxSB_RAISED )
1131 DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn);
1132 else if ( style != wxSB_FLAT )
1133 DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn);
1134
1135 rectIn.Deflate(GetStatusBarFieldMargins());
1136
1137 wxDCClipper clipper(dc, rectIn);
1138 DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
1139 }
1140
1141 #endif // wxUSE_STATUSBAR
1142
1143 // ----------------------------------------------------------------------------
1144 // top level windows
1145 // ----------------------------------------------------------------------------
1146
1147 int wxStdRenderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const
1148 {
1149 wxRect client = GetFrameClientArea(rect, flags);
1150
1151 if ( client.Contains(pt) )
1152 return wxHT_TOPLEVEL_CLIENT_AREA;
1153
1154 if ( flags & wxTOPLEVEL_TITLEBAR )
1155 {
1156 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1157
1158 if ( flags & wxTOPLEVEL_ICON )
1159 {
1160 if ( wxRect(client.GetPosition(), GetFrameIconSize()).Contains(pt) )
1161 return wxHT_TOPLEVEL_ICON;
1162 }
1163
1164 wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH,
1165 client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2,
1166 FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
1167
1168 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1169 {
1170 if ( btnRect.Contains(pt) )
1171 return wxHT_TOPLEVEL_BUTTON_CLOSE;
1172 btnRect.x -= FRAME_BUTTON_WIDTH + 2;
1173 }
1174 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1175 {
1176 if ( btnRect.Contains(pt) )
1177 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE;
1178 btnRect.x -= FRAME_BUTTON_WIDTH;
1179 }
1180 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1181 {
1182 if ( btnRect.Contains(pt) )
1183 return wxHT_TOPLEVEL_BUTTON_RESTORE;
1184 btnRect.x -= FRAME_BUTTON_WIDTH;
1185 }
1186 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1187 {
1188 if ( btnRect.Contains(pt) )
1189 return wxHT_TOPLEVEL_BUTTON_ICONIZE;
1190 btnRect.x -= FRAME_BUTTON_WIDTH;
1191 }
1192 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1193 {
1194 if ( btnRect.Contains(pt) )
1195 return wxHT_TOPLEVEL_BUTTON_HELP;
1196 btnRect.x -= FRAME_BUTTON_WIDTH;
1197 }
1198
1199 if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT )
1200 return wxHT_TOPLEVEL_TITLEBAR;
1201 }
1202
1203 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1204 {
1205 // we are certainly at one of borders, let's decide which one:
1206
1207 int border = 0;
1208 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
1209 if ( pt.x < client.x )
1210 border |= wxHT_TOPLEVEL_BORDER_W;
1211 else if ( pt.x >= client.width + client.x )
1212 border |= wxHT_TOPLEVEL_BORDER_E;
1213 if ( pt.y < client.y )
1214 border |= wxHT_TOPLEVEL_BORDER_N;
1215 else if ( pt.y >= client.height + client.y )
1216 border |= wxHT_TOPLEVEL_BORDER_S;
1217 return border;
1218 }
1219
1220 return wxHT_NOWHERE;
1221 }
1222
1223 void wxStdRenderer::DrawFrameTitleBar(wxDC& dc,
1224 const wxRect& rect,
1225 const wxString& title,
1226 const wxIcon& icon,
1227 int flags,
1228 int specialButton,
1229 int specialButtonFlags)
1230 {
1231 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1232 {
1233 DrawFrameBorder(dc, rect, flags);
1234 }
1235 if ( flags & wxTOPLEVEL_TITLEBAR )
1236 {
1237 DrawFrameBackground(dc, rect, flags);
1238 if ( flags & wxTOPLEVEL_ICON )
1239 DrawFrameIcon(dc, rect, icon, flags);
1240 DrawFrameTitle(dc, rect, title, flags);
1241
1242 wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1243 wxCoord x,y;
1244 x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH;
1245 y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2;
1246
1247 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1248 {
1249 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE,
1250 (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ?
1251 specialButtonFlags : 0);
1252 x -= FRAME_BUTTON_WIDTH + 2;
1253 }
1254 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1255 {
1256 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE,
1257 (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ?
1258 specialButtonFlags : 0);
1259 x -= FRAME_BUTTON_WIDTH;
1260 }
1261 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1262 {
1263 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE,
1264 (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ?
1265 specialButtonFlags : 0);
1266 x -= FRAME_BUTTON_WIDTH;
1267 }
1268 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1269 {
1270 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE,
1271 (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ?
1272 specialButtonFlags : 0);
1273 x -= FRAME_BUTTON_WIDTH;
1274 }
1275 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1276 {
1277 DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP,
1278 (specialButton == wxTOPLEVEL_BUTTON_HELP) ?
1279 specialButtonFlags : 0);
1280 }
1281 }
1282 }
1283
1284 void wxStdRenderer::DrawFrameBorder(wxDC& dc, const wxRect& rect, int flags)
1285 {
1286 if ( !(flags & wxTOPLEVEL_BORDER) )
1287 return;
1288
1289 wxRect r(rect);
1290
1291 DrawAntiSunkenBorder(dc, &r);
1292 DrawExtraBorder(dc, &r);
1293 if ( flags & wxTOPLEVEL_RESIZEABLE )
1294 DrawExtraBorder(dc, &r);
1295 }
1296
1297 void wxStdRenderer::DrawFrameBackground(wxDC& dc, const wxRect& rect, int flags)
1298 {
1299 if ( !(flags & wxTOPLEVEL_TITLEBAR) )
1300 return;
1301
1302 wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE
1303 ? wxColourScheme::TITLEBAR_ACTIVE
1304 : wxColourScheme::TITLEBAR);
1305
1306 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1307 r.height = FRAME_TITLEBAR_HEIGHT;
1308
1309 DrawBackground(dc, col, r);
1310 }
1311
1312 void wxStdRenderer::DrawFrameTitle(wxDC& dc,
1313 const wxRect& rect,
1314 const wxString& title,
1315 int flags)
1316 {
1317 wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE
1318 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1319 : wxColourScheme::TITLEBAR_TEXT);
1320 dc.SetTextForeground(col);
1321
1322 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1323 r.height = FRAME_TITLEBAR_HEIGHT;
1324 if ( flags & wxTOPLEVEL_ICON )
1325 {
1326 r.x += FRAME_TITLEBAR_HEIGHT;
1327 r.width -= FRAME_TITLEBAR_HEIGHT + 2;
1328 }
1329 else
1330 {
1331 r.x += 1;
1332 r.width -= 3;
1333 }
1334
1335 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1336 r.width -= FRAME_BUTTON_WIDTH + 2;
1337 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1338 r.width -= FRAME_BUTTON_WIDTH;
1339 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1340 r.width -= FRAME_BUTTON_WIDTH;
1341 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1342 r.width -= FRAME_BUTTON_WIDTH;
1343 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1344 r.width -= FRAME_BUTTON_WIDTH;
1345
1346 dc.SetFont(m_titlebarFont);
1347
1348 wxString s;
1349 wxCoord textW;
1350 dc.GetTextExtent(title, &textW, NULL);
1351 if ( textW > r.width )
1352 {
1353 // text is too big, let's shorten it and add "..." after it:
1354 size_t len = title.length();
1355 wxCoord WSoFar, letterW;
1356
1357 dc.GetTextExtent(wxT("..."), &WSoFar, NULL);
1358 if ( WSoFar > r.width )
1359 {
1360 // not enough space to draw anything
1361 return;
1362 }
1363
1364 s.Alloc(len);
1365 for (size_t i = 0; i < len; i++)
1366 {
1367 dc.GetTextExtent(title[i], &letterW, NULL);
1368 if ( letterW + WSoFar > r.width )
1369 break;
1370 WSoFar += letterW;
1371 s << title[i];
1372 }
1373 s << wxT("...");
1374 }
1375 else // no need to truncate the title
1376 {
1377 s = title;
1378 }
1379
1380 dc.DrawLabel(s, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
1381 }
1382
1383 void wxStdRenderer::DrawFrameIcon(wxDC& dc,
1384 const wxRect& rect,
1385 const wxIcon& icon,
1386 int flags)
1387 {
1388 if ( icon.Ok() )
1389 {
1390 wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
1391 dc.DrawIcon(icon, r.x, r.y);
1392 }
1393 }
1394
1395 void wxStdRenderer::DrawFrameButton(wxDC& dc,
1396 wxCoord x, wxCoord y,
1397 int button,
1398 int flags)
1399 {
1400 FrameButtonType idx;
1401 switch (button)
1402 {
1403 case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break;
1404 case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break;
1405 case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break;
1406 case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break;
1407 case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break;
1408 default:
1409 wxFAIL_MSG(wxT("incorrect button specification"));
1410 return;
1411 }
1412
1413 wxBitmap bmp = GetFrameButtonBitmap(idx);
1414 if ( !bmp.Ok() )
1415 return;
1416
1417 wxRect rectBtn(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
1418 if ( flags & wxCONTROL_PRESSED )
1419 {
1420 DrawSunkenBorder(dc, &rectBtn);
1421
1422 rectBtn.Offset(1, 1);
1423 }
1424 else
1425 {
1426 DrawRaisedBorder(dc, &rectBtn);
1427 }
1428
1429 DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rectBtn);
1430
1431 wxRect rectBmp(0, 0, bmp.GetWidth(), bmp.GetHeight());
1432 dc.DrawBitmap(bmp, rectBmp.CentreIn(rectBtn).GetPosition(), true);
1433 }
1434
1435 int wxStdRenderer::GetFrameBorderWidth(int flags) const
1436 {
1437 return flags & wxTOPLEVEL_RESIZEABLE ? 4 : 3;
1438 }
1439
1440
1441 wxRect wxStdRenderer::GetFrameClientArea(const wxRect& rect, int flags) const
1442 {
1443 wxRect r(rect);
1444
1445 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1446 {
1447 r.Inflate(-GetFrameBorderWidth(flags));
1448 }
1449
1450 if ( flags & wxTOPLEVEL_TITLEBAR )
1451 {
1452 r.y += FRAME_TITLEBAR_HEIGHT;
1453 r.height -= FRAME_TITLEBAR_HEIGHT;
1454 }
1455
1456 return r;
1457 }
1458
1459 wxSize
1460 wxStdRenderer::GetFrameTotalSize(const wxSize& clientSize, int flags) const
1461 {
1462 wxSize s(clientSize);
1463
1464 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1465 {
1466 s.IncBy(2*GetFrameBorderWidth(flags));
1467 }
1468
1469 if ( flags & wxTOPLEVEL_TITLEBAR )
1470 s.y += FRAME_TITLEBAR_HEIGHT;
1471
1472 return s;
1473 }
1474
1475 wxSize wxStdRenderer::GetFrameMinSize(int flags) const
1476 {
1477 wxSize s;
1478
1479 if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
1480 {
1481 s.IncBy(2*GetFrameBorderWidth(flags));
1482 }
1483
1484 if ( flags & wxTOPLEVEL_TITLEBAR )
1485 {
1486 s.y += FRAME_TITLEBAR_HEIGHT;
1487
1488 if ( flags & wxTOPLEVEL_ICON )
1489 s.x += FRAME_TITLEBAR_HEIGHT + 2;
1490 if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
1491 s.x += FRAME_BUTTON_WIDTH + 2;
1492 if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
1493 s.x += FRAME_BUTTON_WIDTH;
1494 if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
1495 s.x += FRAME_BUTTON_WIDTH;
1496 if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
1497 s.x += FRAME_BUTTON_WIDTH;
1498 if ( flags & wxTOPLEVEL_BUTTON_HELP )
1499 s.x += FRAME_BUTTON_WIDTH;
1500 }
1501
1502 return s;
1503 }
1504
1505 wxSize wxStdRenderer::GetFrameIconSize() const
1506 {
1507 return wxSize(16, 16);
1508 }