1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/stdrend.cpp
3 // Purpose: implementation of wxStdRenderer
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2006 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
27 #include "wx/settings.h"
30 #include "wx/univ/stdrend.h"
31 #include "wx/univ/colschem.h"
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 static const int FRAME_BORDER_THICKNESS
= 3;
38 static const int RESIZEABLE_FRAME_BORDER_THICKNESS
= 4;
39 static const int FRAME_TITLEBAR_HEIGHT
= 18;
40 static const int FRAME_BUTTON_WIDTH
= 16;
41 static const int FRAME_BUTTON_HEIGHT
= 14;
43 // ============================================================================
44 // wxStdRenderer implementation
45 // ============================================================================
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 wxStdRenderer::wxStdRenderer(const wxColourScheme
*scheme
)
54 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
));
55 m_penDarkGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_OUT
));
56 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
));
57 m_penHighlight
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
));
59 m_titlebarFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
60 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
68 wxStdRenderer::DrawSolidRect(wxDC
& dc
, const wxColour
& col
, const wxRect
& rect
)
70 wxBrush
brush(col
, wxSOLID
);
72 dc
.SetPen(*wxTRANSPARENT_PEN
);
73 dc
.DrawRectangle(rect
);
76 void wxStdRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
80 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
81 dc
.DrawRectangle(*rect
);
87 void wxStdRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
88 const wxPen
& pen1
, const wxPen
& pen2
)
92 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
93 rect
->GetLeft(), rect
->GetBottom());
94 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
95 rect
->GetRight(), rect
->GetTop());
97 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
98 rect
->GetRight(), rect
->GetBottom());
99 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
100 rect
->GetRight() + 1, rect
->GetBottom());
106 // ----------------------------------------------------------------------------
107 // translate various flags into corresponding renderer constants
108 // ----------------------------------------------------------------------------
111 void wxStdRenderer::GetIndicatorsFromFlags(int flags
,
112 IndicatorState
& state
,
113 IndicatorStatus
& status
)
115 if ( flags
& wxCONTROL_SELECTED
)
116 state
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
117 : IndicatorState_Selected
;
118 else if ( flags
& wxCONTROL_DISABLED
)
119 state
= IndicatorState_Disabled
;
120 else if ( flags
& wxCONTROL_PRESSED
)
121 state
= IndicatorState_Pressed
;
123 state
= IndicatorState_Normal
;
125 status
= flags
& wxCONTROL_CHECKED
? IndicatorStatus_Checked
126 : flags
& wxCONTROL_UNDETERMINED
127 ? IndicatorStatus_Undetermined
128 : IndicatorStatus_Unchecked
;
132 wxStdRenderer::ArrowDirection
wxStdRenderer::GetArrowDirection(wxDirection dir
)
149 wxFAIL_MSG(_T("unknown arrow direction"));
155 // ----------------------------------------------------------------------------
157 // ----------------------------------------------------------------------------
159 void wxStdRenderer::DrawBackground(wxDC
& dc
,
165 wxColour colBg
= col
.Ok() ? col
166 : window
? m_scheme
->GetBackground(window
)
167 : wxSCHEME_COLOUR(m_scheme
, CONTROL
);
169 DrawSolidRect(dc
, colBg
, rect
);
173 void wxStdRenderer::DrawButtonSurface(wxDC
& dc
,
178 DrawBackground(dc
, col
, rect
, flags
);
181 // ----------------------------------------------------------------------------
183 // ----------------------------------------------------------------------------
185 void wxStdRenderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
187 // draw the pixels manually because the "dots" in wxPen with wxDOT style
188 // may be short traits and not really dots
190 // note that to behave in the same manner as DrawRect(), we must exclude
191 // the bottom and right borders from the rectangle
192 wxCoord x1
= rect
.GetLeft(),
194 x2
= rect
.GetRight(),
195 y2
= rect
.GetBottom();
197 dc
.SetPen(m_penBlack
);
199 // this seems to be closer than what Windows does than wxINVERT although
200 // I'm still not sure if it's correct
201 dc
.SetLogicalFunction(wxAND_REVERSE
);
204 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
205 dc
.DrawPoint(z
, rect
.GetTop());
207 wxCoord shift
= z
== x2
? 0 : 1;
208 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
211 shift
= z
== y2
? 0 : 1;
212 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
215 shift
= z
== x1
? 0 : 1;
216 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
219 dc
.SetLogicalFunction(wxCOPY
);
222 void wxStdRenderer::DrawLabel(wxDC
& dc
,
223 const wxString
& label
,
230 DrawButtonLabel(dc
, label
, wxNullBitmap
, rect
, flags
,
231 alignment
, indexAccel
, rectBounds
);
234 void wxStdRenderer::DrawButtonLabel(wxDC
& dc
,
235 const wxString
& label
,
236 const wxBitmap
& image
,
243 wxRect rectLabel
= rect
;
244 if ( !label
.empty() && (flags
& wxCONTROL_DISABLED
) )
246 if ( flags
& wxCONTROL_PRESSED
)
248 // shift the label if a button is pressed
249 rectLabel
.Offset(1, 1);
252 // draw shadow of the text
253 dc
.SetTextForeground(m_penHighlight
.GetColour());
254 wxRect rectShadow
= rect
;
255 rectShadow
.Offset(1, 1);
256 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
258 // make the main label text grey
259 dc
.SetTextForeground(m_penDarkGrey
.GetColour());
261 if ( flags
& wxCONTROL_FOCUSED
)
263 // leave enough space for the focus rect
264 rectLabel
.Inflate(-2);
268 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
270 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
272 rectLabel
.Inflate(-1);
274 DrawFocusRect(dc
, rectLabel
);
278 // ----------------------------------------------------------------------------
280 // ----------------------------------------------------------------------------
283 We implement standard-looking 3D borders which have the following appearance:
287 WWWWWWWWWWWWWWWWWWWWWWB
288 WHHHHHHHHHHHHHHHHHHHHGB
289 WH GB W = white (HILIGHT)
290 WH GB H = light grey (LIGHT)
291 WH GB G = dark grey (SHADOI)
292 WH GB B = black (DKSHADOI)
295 WGGGGGGGGGGGGGGGGGGGGGB
296 BBBBBBBBBBBBBBBBBBBBBBB
298 The sunken border looks like this:
300 GGGGGGGGGGGGGGGGGGGGGGW
301 GBBBBBBBBBBBBBBBBBBBBHW
308 GHHHHHHHHHHHHHHHHHHHHHW
309 WWWWWWWWWWWWWWWWWWWWWWW
311 The static border (used for the controls which don't get focus) is like
314 GGGGGGGGGGGGGGGGGGGGGGW
322 WWWWWWWWWWWWWWWWWWWWWWW
324 The most complicated is the double border which is a combination of special
325 "anti-sunken" border and an extra border inside it:
327 HHHHHHHHHHHHHHHHHHHHHHB
328 HWWWWWWWWWWWWWWWWWWWWGB
329 HWHHHHHHHHHHHHHHHHHHHGB
334 HWHHHHHHHHHHHHHHHHHHHGB
335 HGGGGGGGGGGGGGGGGGGGGGB
336 BBBBBBBBBBBBBBBBBBBBBBB
338 And the simple border is, well, simple:
340 BBBBBBBBBBBBBBBBBBBBBBB
349 BBBBBBBBBBBBBBBBBBBBBBB
352 void wxStdRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
354 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
355 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
358 void wxStdRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
360 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
361 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
364 void wxStdRenderer::DrawAntiSunkenBorder(wxDC
& dc
, wxRect
*rect
)
366 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
367 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
370 void wxStdRenderer::DrawBoxBorder(wxDC
& dc
, wxRect
*rect
)
372 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
373 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
376 void wxStdRenderer::DrawStaticBorder(wxDC
& dc
, wxRect
*rect
)
378 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
381 void wxStdRenderer::DrawExtraBorder(wxDC
& dc
, wxRect
*rect
)
383 DrawRect(dc
, rect
, m_penLightGrey
);
386 void wxStdRenderer::DrawBorder(wxDC
& dc
,
388 const wxRect
& rectTotal
,
392 wxRect rect
= rectTotal
;
396 case wxBORDER_SUNKEN
:
397 DrawSunkenBorder(dc
, &rect
);
400 case wxBORDER_DOUBLE
:
401 DrawAntiSunkenBorder(dc
, &rect
);
402 DrawExtraBorder(dc
, &rect
);
405 case wxBORDER_STATIC
:
406 DrawStaticBorder(dc
, &rect
);
409 case wxBORDER_RAISED
:
410 DrawRaisedBorder(dc
, &rect
);
413 case wxBORDER_SIMPLE
:
414 DrawRect(dc
, &rect
, m_penBlack
);
418 wxFAIL_MSG(_T("unknown border type"));
421 case wxBORDER_DEFAULT
:
430 wxRect
wxStdRenderer::GetBorderDimensions(wxBorder border
) const
435 case wxBORDER_SIMPLE
:
436 case wxBORDER_STATIC
:
440 case wxBORDER_RAISED
:
441 case wxBORDER_SUNKEN
:
445 case wxBORDER_DOUBLE
:
450 wxFAIL_MSG(_T("unknown border type"));
453 case wxBORDER_DEFAULT
:
468 void wxStdRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
470 // take into account the border width
471 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
472 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
473 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
476 bool wxStdRenderer::AreScrollbarsInsideBorder() const
481 wxCoord
wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight
)
483 return fontHeight
+ 2;
486 void wxStdRenderer::DrawTextBorder(wxDC
& dc
,
492 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
495 // ----------------------------------------------------------------------------
497 // ----------------------------------------------------------------------------
500 wxStdRenderer::DrawHorizontalLine(wxDC
& dc
, wxCoord y
, wxCoord x1
, wxCoord x2
)
502 dc
.SetPen(m_penDarkGrey
);
503 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
505 dc
.SetPen(m_penHighlight
);
507 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
511 wxStdRenderer::DrawVerticalLine(wxDC
& dc
, wxCoord x
, wxCoord y1
, wxCoord y2
)
513 dc
.SetPen(m_penDarkGrey
);
514 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
516 dc
.SetPen(m_penHighlight
);
518 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
521 void wxStdRenderer::DrawFrameWithoutLabel(wxDC
& dc
,
522 const wxRect
& rectFrame
,
523 const wxRect
& rectLabel
)
525 // draw left, bottom and right lines entirely
526 DrawVerticalLine(dc
, rectFrame
.GetLeft(),
527 rectFrame
.GetTop(), rectFrame
.GetBottom() - 2);
528 DrawHorizontalLine(dc
, rectFrame
.GetBottom() - 1,
529 rectFrame
.GetLeft(), rectFrame
.GetRight());
530 DrawVerticalLine(dc
, rectFrame
.GetRight() - 1,
531 rectFrame
.GetTop(), rectFrame
.GetBottom() - 1);
533 // and 2 parts of the top line
534 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
535 rectFrame
.GetLeft() + 1, rectLabel
.GetLeft());
536 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
537 rectLabel
.GetRight(), rectFrame
.GetRight() - 2);
540 void wxStdRenderer::DrawFrameWithLabel(wxDC
& dc
,
541 const wxString
& label
,
542 const wxRect
& rectFrame
,
543 const wxRect
& rectText
,
549 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
551 DrawFrameWithoutLabel(dc
, rectFrame
, rectLabel
);
554 void wxStdRenderer::DrawFrame(wxDC
& dc
,
555 const wxString
& label
,
561 wxCoord height
= 0; // of the label
562 wxRect rectFrame
= rect
;
563 if ( !label
.empty() )
565 // the text should touch the top border of the rect, so the frame
566 // itself should be lower
567 dc
.GetTextExtent(label
, NULL
, &height
);
568 rectFrame
.y
+= height
/ 2;
569 rectFrame
.height
-= height
/ 2;
571 // we have to draw each part of the frame individually as we can't
572 // erase the background beyond the label as it might contain some
573 // pixmap already, so drawing everything and then overwriting part of
574 // the frame with label doesn't work
576 // TODO: the +5 shouldn't be hard coded
578 rectText
.x
= rectFrame
.x
+ 5;
580 rectText
.width
= rectFrame
.width
- 7; // +2 border width
581 rectText
.height
= height
;
583 DrawFrameWithLabel(dc
, label
, rectFrame
, rectText
, flags
,
584 alignment
, indexAccel
);
588 DrawBoxBorder(dc
, &rectFrame
);
592 void wxStdRenderer::DrawItem(wxDC
& dc
,
593 const wxString
& label
,
597 wxDCTextColourChanger
colChanger(dc
);
599 if ( flags
& wxCONTROL_SELECTED
)
601 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
603 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
606 dc
.DrawRectangle(rect
);
609 wxRect rectText
= rect
;
612 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
614 if ( flags
& wxCONTROL_FOCUSED
)
616 DrawFocusRect(dc
, rect
);
620 void wxStdRenderer::DrawCheckItemBitmap(wxDC
& dc
,
621 const wxBitmap
& bitmap
,
625 DrawCheckButton(dc
, wxEmptyString
, bitmap
, rect
, flags
);
628 void wxStdRenderer::DrawCheckItem(wxDC
& dc
,
629 const wxString
& label
,
630 const wxBitmap
& bitmap
,
634 wxRect rectBitmap
= rect
;
635 rectBitmap
.width
= GetCheckBitmapSize().x
;
636 DrawCheckItemBitmap(dc
, bitmap
, rectBitmap
, flags
);
638 wxRect rectLabel
= rect
;
639 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
640 rectLabel
.x
+= shift
;
641 rectLabel
.width
-= shift
;
642 DrawItem(dc
, label
, rectLabel
, flags
);
645 // ----------------------------------------------------------------------------
646 // check and radio bitmaps
647 // ----------------------------------------------------------------------------
649 void wxStdRenderer::DrawCheckButton(wxDC
& dc
,
650 const wxString
& label
,
651 const wxBitmap
& bitmap
,
657 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
));
659 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
662 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
663 const wxString
& label
,
664 const wxBitmap
& bitmap
,
670 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
));
672 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
675 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
676 const wxString
& label
,
677 const wxBitmap
& bitmap
,
683 // calculate the position of the bitmap and of the label
684 wxCoord heightBmp
= bitmap
.GetHeight();
686 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
689 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
690 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
692 // align label vertically with the bitmap - looks nicer like this
693 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
695 // calc horz position
696 if ( align
== wxALIGN_RIGHT
)
698 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
699 rectLabel
.x
= rect
.x
+ 3;
700 rectLabel
.SetRight(xBmp
);
702 else // normal (checkbox to the left of the text) case
705 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
706 rectLabel
.SetRight(rect
.GetRight());
709 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
711 DrawLabel(dc
, label
, rectLabel
, flags
,
712 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
717 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
718 const wxString
& text
,
724 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
726 // just draw it as is
727 dc
.DrawText(text
, rect
.x
, rect
.y
);
729 else // we have selection
734 // draw the part before selection
735 wxString
s(text
, (size_t)selStart
);
738 dc
.DrawText(s
, x
, rect
.y
);
740 dc
.GetTextExtent(s
, &width
, NULL
);
744 // draw the selection itself
745 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
748 wxColour colFg
= dc
.GetTextForeground(),
749 colBg
= dc
.GetTextBackground();
750 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
751 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
752 dc
.SetBackgroundMode(wxSOLID
);
754 dc
.DrawText(s
, x
, rect
.y
);
755 dc
.GetTextExtent(s
, &width
, NULL
);
758 dc
.SetBackgroundMode(wxTRANSPARENT
);
759 dc
.SetTextBackground(colBg
);
760 dc
.SetTextForeground(colFg
);
763 // draw the final part
764 s
= text
.c_str() + selEnd
;
767 dc
.DrawText(s
, x
, rect
.y
);
772 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
773 const wxRect
& WXUNUSED(rect
))
775 // nothing by default
778 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
784 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
786 wxRect rectTotal
= rect
;
787 rectTotal
.Inflate(GetTextBorderWidth(text
));
791 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
793 wxCoord
*extraSpaceBeyond
) const
795 wxRect rectText
= rect
;
796 rectText
.Deflate(GetTextBorderWidth(text
));
798 if ( extraSpaceBeyond
)
799 *extraSpaceBeyond
= 0;
804 #endif // wxUSE_TEXTCTRL
806 // ----------------------------------------------------------------------------
807 // scrollbars drawing
808 // ----------------------------------------------------------------------------
810 void wxStdRenderer::DrawScrollbarArrow(wxDC
& dc
,
815 DrawArrow(dc
, dir
, rect
, flags
);
818 void wxStdRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
820 DrawSolidRect(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
823 // ----------------------------------------------------------------------------
824 // scrollbars geometry
825 // ----------------------------------------------------------------------------
830 void wxStdRenderer::GetScrollBarThumbSize(wxCoord length
,
837 // the thumb can't be made less than this number of pixels
838 static const wxCoord thumbMinWidth
= 8; // FIXME: should be configurable
840 *thumbStart
= (length
*thumbPos
) / range
;
841 *thumbEnd
= (length
*(thumbPos
+ thumbSize
)) / range
;
843 if ( *thumbEnd
- *thumbStart
< thumbMinWidth
)
845 // adjust the end if possible
846 if ( *thumbStart
<= length
- thumbMinWidth
)
848 // yes, just make it wider
849 *thumbEnd
= *thumbStart
+ thumbMinWidth
;
851 else // it is at the bottom of the scrollbar
853 // so move it a bit up
854 *thumbStart
= length
- thumbMinWidth
;
860 wxRect
wxStdRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
861 wxScrollBar::Element elem
,
864 if ( thumbPos
== -1 )
866 thumbPos
= scrollbar
->GetThumbPosition();
869 const wxSize sizeArrow
= GetScrollbarArrowSize();
871 wxSize sizeTotal
= scrollbar
->GetClientSize();
872 wxCoord
*start
, *width
;
873 wxCoord length
, arrow
;
875 if ( scrollbar
->IsVertical() )
878 rect
.width
= sizeTotal
.x
;
879 length
= sizeTotal
.y
;
881 width
= &rect
.height
;
887 rect
.height
= sizeTotal
.y
;
888 length
= sizeTotal
.x
;
896 case wxScrollBar::Element_Arrow_Line_1
:
901 case wxScrollBar::Element_Arrow_Line_2
:
902 *start
= length
- arrow
;
906 case wxScrollBar::Element_Arrow_Page_1
:
907 case wxScrollBar::Element_Arrow_Page_2
:
908 // we don't have them at all
911 case wxScrollBar::Element_Thumb
:
912 case wxScrollBar::Element_Bar_1
:
913 case wxScrollBar::Element_Bar_2
:
914 // we need to calculate the thumb position - do it
917 wxCoord thumbStart
, thumbEnd
;
918 int range
= scrollbar
->GetRange();
926 GetScrollBarThumbSize(length
,
928 scrollbar
->GetThumbSize(),
934 if ( elem
== wxScrollBar::Element_Thumb
)
937 *width
= thumbEnd
- thumbStart
;
939 else if ( elem
== wxScrollBar::Element_Bar_1
)
944 else // elem == wxScrollBar::Element_Bar_2
947 *width
= length
- thumbEnd
;
950 // everything is relative to the start of the shaft so far
955 case wxScrollBar::Element_Max
:
957 wxFAIL_MSG( _T("unknown scrollbar element") );
963 wxCoord
wxStdRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
965 const wxSize sizeArrowSB
= GetScrollbarArrowSize();
967 wxCoord sizeArrow
, sizeTotal
;
968 if ( scrollbar
->GetWindowStyle() & wxVERTICAL
)
970 sizeArrow
= sizeArrowSB
.y
;
971 sizeTotal
= scrollbar
->GetSize().y
;
975 sizeArrow
= sizeArrowSB
.x
;
976 sizeTotal
= scrollbar
->GetSize().x
;
979 return sizeTotal
- 2*sizeArrow
;
983 wxStdRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
, const wxPoint
& pt
) const
985 // we only need to work with either x or y coord depending on the
986 // orientation, choose one (but still check the other one to verify if the
987 // mouse is in the window at all)
988 const wxSize sizeArrowSB
= GetScrollbarArrowSize();
990 wxCoord coord
, sizeArrow
, sizeTotal
;
991 wxSize size
= scrollbar
->GetSize();
992 if ( scrollbar
->GetWindowStyle() & wxVERTICAL
)
994 if ( pt
.x
< 0 || pt
.x
> size
.x
)
998 sizeArrow
= sizeArrowSB
.y
;
1003 if ( pt
.y
< 0 || pt
.y
> size
.y
)
1004 return wxHT_NOWHERE
;
1007 sizeArrow
= sizeArrowSB
.x
;
1011 // test for the arrows first as it's faster
1012 if ( coord
< 0 || coord
> sizeTotal
)
1014 return wxHT_NOWHERE
;
1016 else if ( coord
< sizeArrow
)
1018 return wxHT_SCROLLBAR_ARROW_LINE_1
;
1020 else if ( coord
> sizeTotal
- sizeArrow
)
1022 return wxHT_SCROLLBAR_ARROW_LINE_2
;
1026 // calculate the thumb position in pixels
1027 sizeTotal
-= 2*sizeArrow
;
1028 wxCoord thumbStart
, thumbEnd
;
1029 int range
= scrollbar
->GetRange();
1032 // clicking the scrollbar without range has no effect
1033 return wxHT_NOWHERE
;
1037 GetScrollBarThumbSize(sizeTotal
,
1038 scrollbar
->GetThumbPosition(),
1039 scrollbar
->GetThumbSize(),
1045 // now compare with the thumb position
1047 if ( coord
< thumbStart
)
1048 return wxHT_SCROLLBAR_BAR_1
;
1049 else if ( coord
> thumbEnd
)
1050 return wxHT_SCROLLBAR_BAR_2
;
1052 return wxHT_SCROLLBAR_THUMB
;
1058 wxStdRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
, int thumbPos
)
1060 int range
= scrollbar
->GetRange();
1063 // the only valid position anyhow
1067 if ( thumbPos
== -1 )
1069 // by default use the current thumb position
1070 thumbPos
= scrollbar
->GetThumbPosition();
1073 const wxSize sizeArrow
= GetScrollbarArrowSize();
1074 return (thumbPos
*GetScrollbarSize(scrollbar
)) / range
1075 + (scrollbar
->IsVertical() ? sizeArrow
.y
: sizeArrow
.x
);
1078 int wxStdRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
)
1080 const wxSize sizeArrow
= GetScrollbarArrowSize();
1081 return ((coord
- (scrollbar
->IsVertical() ? sizeArrow
.y
: sizeArrow
.x
)) *
1082 scrollbar
->GetRange() ) / GetScrollbarSize(scrollbar
);
1085 #endif // wxUSE_SCROLLBAR
1087 // ----------------------------------------------------------------------------
1089 // ----------------------------------------------------------------------------
1093 wxSize
wxStdRenderer::GetStatusBarBorders(wxCoord
*borderBetweenFields
) const
1095 if ( borderBetweenFields
)
1096 *borderBetweenFields
= 2;
1098 return wxSize(2, 2);
1101 void wxStdRenderer::DrawStatusField(wxDC
& dc
,
1103 const wxString
& label
,
1109 if ( style
== wxSB_RAISED
)
1110 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
, &rectIn
);
1111 else if ( style
!= wxSB_FLAT
)
1112 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
1114 rectIn
.Deflate(GetStatusBarBorders(NULL
));
1116 wxDCClipper
clipper(dc
, rectIn
);
1117 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1120 #endif // wxUSE_STATUSBAR
1122 // ----------------------------------------------------------------------------
1123 // top level windows
1124 // ----------------------------------------------------------------------------
1126 int wxStdRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
1128 wxRect client
= GetFrameClientArea(rect
, flags
);
1130 if ( client
.Contains(pt
) )
1131 return wxHT_TOPLEVEL_CLIENT_AREA
;
1133 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1135 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1137 if ( flags
& wxTOPLEVEL_ICON
)
1139 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
1140 return wxHT_TOPLEVEL_ICON
;
1143 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
1144 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
1145 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1147 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1149 if ( btnRect
.Contains(pt
) )
1150 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
1151 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
1153 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1155 if ( btnRect
.Contains(pt
) )
1156 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
1157 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
1159 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1161 if ( btnRect
.Contains(pt
) )
1162 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
1163 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
1165 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1167 if ( btnRect
.Contains(pt
) )
1168 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
1169 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
1171 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1173 if ( btnRect
.Contains(pt
) )
1174 return wxHT_TOPLEVEL_BUTTON_HELP
;
1175 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
1178 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
1179 return wxHT_TOPLEVEL_TITLEBAR
;
1182 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1184 // we are certainly at one of borders, let's decide which one:
1187 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
1188 if ( pt
.x
< client
.x
)
1189 border
|= wxHT_TOPLEVEL_BORDER_W
;
1190 else if ( pt
.x
>= client
.width
+ client
.x
)
1191 border
|= wxHT_TOPLEVEL_BORDER_E
;
1192 if ( pt
.y
< client
.y
)
1193 border
|= wxHT_TOPLEVEL_BORDER_N
;
1194 else if ( pt
.y
>= client
.height
+ client
.y
)
1195 border
|= wxHT_TOPLEVEL_BORDER_S
;
1199 return wxHT_NOWHERE
;
1202 void wxStdRenderer::DrawFrameTitleBar(wxDC
& dc
,
1204 const wxString
& title
,
1208 int specialButtonFlags
)
1210 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1212 DrawFrameBorder(dc
, rect
, flags
);
1214 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1216 DrawFrameBackground(dc
, rect
, flags
);
1217 if ( flags
& wxTOPLEVEL_ICON
)
1218 DrawFrameIcon(dc
, rect
, icon
, flags
);
1219 DrawFrameTitle(dc
, rect
, title
, flags
);
1221 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1223 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
1224 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
1226 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1228 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
1229 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
1230 specialButtonFlags
: 0);
1231 x
-= FRAME_BUTTON_WIDTH
+ 2;
1233 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1235 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
1236 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
1237 specialButtonFlags
: 0);
1238 x
-= FRAME_BUTTON_WIDTH
;
1240 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1242 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
1243 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
1244 specialButtonFlags
: 0);
1245 x
-= FRAME_BUTTON_WIDTH
;
1247 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1249 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
1250 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
1251 specialButtonFlags
: 0);
1252 x
-= FRAME_BUTTON_WIDTH
;
1254 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1256 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
1257 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
1258 specialButtonFlags
: 0);
1263 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, const wxRect
& rect
, int flags
)
1265 if ( !(flags
& wxTOPLEVEL_BORDER
) )
1270 DrawAntiSunkenBorder(dc
, &r
);
1271 DrawExtraBorder(dc
, &r
);
1272 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
1273 DrawExtraBorder(dc
, &r
);
1276 void wxStdRenderer::DrawFrameBackground(wxDC
& dc
, const wxRect
& rect
, int flags
)
1278 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) )
1281 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1282 ? wxColourScheme::TITLEBAR_ACTIVE
1283 : wxColourScheme::TITLEBAR
);
1285 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1286 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1288 DrawBackground(dc
, col
, r
);
1291 void wxStdRenderer::DrawFrameTitle(wxDC
& dc
,
1293 const wxString
& title
,
1296 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1297 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1298 : wxColourScheme::TITLEBAR_TEXT
);
1299 dc
.SetTextForeground(col
);
1301 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1302 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1303 if ( flags
& wxTOPLEVEL_ICON
)
1305 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
1306 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
1314 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1315 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
1316 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1317 r
.width
-= FRAME_BUTTON_WIDTH
;
1318 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1319 r
.width
-= FRAME_BUTTON_WIDTH
;
1320 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1321 r
.width
-= FRAME_BUTTON_WIDTH
;
1322 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1323 r
.width
-= FRAME_BUTTON_WIDTH
;
1325 dc
.SetFont(m_titlebarFont
);
1329 dc
.GetTextExtent(title
, &textW
, NULL
);
1330 if ( textW
> r
.width
)
1332 // text is too big, let's shorten it and add "..." after it:
1333 size_t len
= title
.length();
1334 wxCoord WSoFar
, letterW
;
1336 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
1337 if ( WSoFar
> r
.width
)
1339 // not enough space to draw anything
1344 for (size_t i
= 0; i
< len
; i
++)
1346 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
1347 if ( letterW
+ WSoFar
> r
.width
)
1354 else // no need to truncate the title
1359 dc
.DrawLabel(s
, wxNullBitmap
, r
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1362 void wxStdRenderer::DrawFrameIcon(wxDC
& dc
,
1369 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1370 dc
.DrawIcon(icon
, r
.x
, r
.y
);
1374 void wxStdRenderer::DrawFrameButton(wxDC
& dc
,
1375 wxCoord x
, wxCoord y
,
1379 FrameButtonType idx
;
1382 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
1383 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
1384 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
1385 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
1386 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
1388 wxFAIL_MSG(wxT("incorrect button specification"));
1392 wxBitmap bmp
= GetFrameButtonBitmap(idx
);
1396 wxRect
rectBtn(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1397 if ( flags
& wxCONTROL_PRESSED
)
1399 DrawSunkenBorder(dc
, &rectBtn
);
1401 rectBtn
.Offset(1, 1);
1405 DrawRaisedBorder(dc
, &rectBtn
);
1408 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rectBtn
);
1410 wxRect
rectBmp(0, 0, bmp
.GetWidth(), bmp
.GetHeight());
1411 dc
.DrawBitmap(bmp
, rectBmp
.CentreIn(rectBtn
).GetPosition(), true);
1415 wxRect
wxStdRenderer::GetFrameClientArea(const wxRect
& rect
, int flags
) const
1419 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1421 int border
= flags
& wxTOPLEVEL_RESIZEABLE
1422 ? RESIZEABLE_FRAME_BORDER_THICKNESS
1423 : FRAME_BORDER_THICKNESS
;
1427 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1429 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
1430 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
1437 wxStdRenderer::GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const
1439 wxSize
s(clientSize
);
1441 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1443 int border
= flags
& wxTOPLEVEL_RESIZEABLE
1444 ? RESIZEABLE_FRAME_BORDER_THICKNESS
1445 : FRAME_BORDER_THICKNESS
;
1450 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1451 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1456 wxSize
wxStdRenderer::GetFrameMinSize(int flags
) const
1460 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1462 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
1463 RESIZEABLE_FRAME_BORDER_THICKNESS
:
1464 FRAME_BORDER_THICKNESS
;
1469 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1471 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1473 if ( flags
& wxTOPLEVEL_ICON
)
1474 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
1475 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1476 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
1477 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1478 s
.x
+= FRAME_BUTTON_WIDTH
;
1479 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1480 s
.x
+= FRAME_BUTTON_WIDTH
;
1481 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1482 s
.x
+= FRAME_BUTTON_WIDTH
;
1483 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1484 s
.x
+= FRAME_BUTTON_WIDTH
;
1490 wxSize
wxStdRenderer::GetFrameIconSize() const
1492 return wxSize(16, 16);