]>
git.saurik.com Git - wxWidgets.git/blob - src/univ/ctrlrend.cpp
27d9b1e80907cfa841b70edc55c4fcd018393efd
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/ctrlrend.cpp
3 // Purpose: wxControlRenderer implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/control.h"
30 #include "wx/checklst.h"
31 #include "wx/listbox.h"
32 #include "wx/scrolbar.h"
39 #include "wx/univ/theme.h"
40 #include "wx/univ/renderer.h"
41 #include "wx/univ/colschem.h"
43 // ============================================================================
45 // ============================================================================
47 wxRenderer::~wxRenderer()
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 wxControlRenderer::wxControlRenderer(wxWindow
*window
,
61 m_renderer
= renderer
;
63 wxSize size
= m_window
->GetClientSize();
66 m_rect
.width
= size
.x
;
67 m_rect
.height
= size
.y
;
70 void wxControlRenderer::DrawLabel()
72 m_dc
.SetBackgroundMode(wxTRANSPARENT
);
73 m_dc
.SetFont(m_window
->GetFont());
74 m_dc
.SetTextForeground(m_window
->GetForegroundColour());
76 wxString label
= m_window
->GetLabel();
79 wxControl
*ctrl
= wxStaticCast(m_window
, wxControl
);
81 m_renderer
->DrawLabel(m_dc
,
84 m_window
->GetStateFlags(),
86 ctrl
->GetAccelIndex());
90 void wxControlRenderer::DrawButtonLabel(const wxBitmap
& bitmap
,
91 wxCoord marginX
, wxCoord marginY
)
93 m_dc
.SetBackgroundMode(wxTRANSPARENT
);
94 m_dc
.SetFont(m_window
->GetFont());
95 m_dc
.SetTextForeground(m_window
->GetForegroundColour());
97 wxString label
= m_window
->GetLabel();
98 if ( !label
.empty() || bitmap
.IsOk() )
100 wxRect rectLabel
= m_rect
;
103 rectLabel
.Inflate(-marginX
, -marginY
);
106 wxControl
*ctrl
= wxStaticCast(m_window
, wxControl
);
108 m_renderer
->DrawButtonLabel(m_dc
,
112 m_window
->GetStateFlags(),
113 ctrl
->GetAlignment(),
114 ctrl
->GetAccelIndex());
118 void wxControlRenderer::DrawFrame()
120 m_dc
.SetFont(m_window
->GetFont());
121 m_dc
.SetTextForeground(m_window
->GetForegroundColour());
122 m_dc
.SetTextBackground(m_window
->GetBackgroundColour());
124 wxControl
*ctrl
= wxStaticCast(m_window
, wxControl
);
126 m_renderer
->DrawFrame(m_dc
,
127 m_window
->GetLabel(),
129 m_window
->GetStateFlags(),
130 ctrl
->GetAlignment(),
131 ctrl
->GetAccelIndex());
134 void wxControlRenderer::DrawButtonBorder()
136 int flags
= m_window
->GetStateFlags();
138 m_renderer
->DrawButtonBorder(m_dc
, m_rect
, flags
, &m_rect
);
141 // m_renderer->DrawButtonSurface(m_dc, wxTHEME_BG_COLOUR(m_window), m_rect, flags );
144 void wxControlRenderer::DrawBitmap(const wxBitmap
& bitmap
)
146 int style
= m_window
->GetWindowStyle();
147 DrawBitmap(m_dc
, bitmap
, m_rect
,
148 style
& wxALIGN_MASK
,
149 style
& wxBI_EXPAND
? wxEXPAND
: wxSTRETCH_NOT
);
153 void wxControlRenderer::DrawBitmap(wxDC
&dc
,
154 const wxBitmap
& bitmap
,
159 // we may change the bitmap if we stretch it
160 wxBitmap bmp
= bitmap
;
164 int width
= bmp
.GetWidth(),
165 height
= bmp
.GetHeight();
169 if ( stretch
& wxTILE
)
172 for ( ; x
< rect
.width
; x
+= width
)
174 for ( y
= 0; y
< rect
.height
; y
+= height
)
176 // no need to use mask here as we cover the entire window area
177 dc
.DrawBitmap(bmp
, x
, y
);
182 else if ( stretch
& wxEXPAND
)
184 // stretch bitmap to fill the entire control
185 bmp
= wxBitmap(wxImage(bmp
.ConvertToImage()).Scale(rect
.width
, rect
.height
));
187 #endif // wxUSE_IMAGE
188 else // not stretched, not tiled
190 if ( alignment
& wxALIGN_RIGHT
)
192 x
= rect
.GetRight() - width
;
194 else if ( alignment
& wxALIGN_CENTRE
)
196 x
= (rect
.GetLeft() + rect
.GetRight() - width
+ 1) / 2;
198 else // alignment & wxALIGN_LEFT
203 if ( alignment
& wxALIGN_BOTTOM
)
205 y
= rect
.GetBottom() - height
;
207 else if ( alignment
& wxALIGN_CENTRE_VERTICAL
)
209 y
= (rect
.GetTop() + rect
.GetBottom() - height
+ 1) / 2;
211 else // alignment & wxALIGN_TOP
218 dc
.DrawBitmap(bmp
, x
, y
, true /* use mask */);
223 void wxControlRenderer::DrawScrollbar(const wxScrollBar
*scrollbar
,
224 int WXUNUSED(thumbPosOld
))
226 // we will only redraw the parts which must be redrawn and not everything
227 wxRegion rgnUpdate
= scrollbar
->GetUpdateRegion();
230 wxRect rectUpdate
= rgnUpdate
.GetBox();
231 wxLogTrace(wxT("scrollbar"),
232 wxT("%s redraw: update box is (%d, %d)-(%d, %d)"),
233 scrollbar
->IsVertical() ? wxT("vert") : wxT("horz"),
234 rectUpdate
.GetLeft(),
236 rectUpdate
.GetRight(),
237 rectUpdate
.GetBottom());
239 #if 0 //def WXDEBUG_SCROLLBAR
240 static bool s_refreshDebug
= false;
241 if ( s_refreshDebug
)
243 wxClientDC
dc(wxConstCast(scrollbar
, wxScrollBar
));
244 dc
.SetBrush(*wxRED_BRUSH
);
245 dc
.SetPen(*wxTRANSPARENT_PEN
);
246 dc
.DrawRectangle(rectUpdate
);
248 // under Unix we use "--sync" X option for this
254 #endif // WXDEBUG_SCROLLBAR
257 wxOrientation orient
= scrollbar
->IsVertical() ? wxVERTICAL
261 for ( int nBar
= 0; nBar
< 2; nBar
++ )
263 wxScrollBar::Element elem
=
264 (wxScrollBar::Element
)(wxScrollBar::Element_Bar_1
+ nBar
);
266 wxRect rectBar
= scrollbar
->GetScrollbarRect(elem
);
268 if ( rgnUpdate
.Contains(rectBar
) )
270 wxLogTrace(wxT("scrollbar"),
271 wxT("drawing bar part %d at (%d, %d)-(%d, %d)"),
276 rectBar
.GetBottom());
278 m_renderer
->DrawScrollbarShaft(m_dc
,
281 scrollbar
->GetState(elem
));
286 for ( int nArrow
= 0; nArrow
< 2; nArrow
++ )
288 wxScrollBar::Element elem
=
289 (wxScrollBar::Element
)(wxScrollBar::Element_Arrow_Line_1
+ nArrow
);
291 wxRect rectArrow
= scrollbar
->GetScrollbarRect(elem
);
292 if ( rgnUpdate
.Contains(rectArrow
) )
294 wxLogTrace(wxT("scrollbar"),
295 wxT("drawing arrow %d at (%d, %d)-(%d, %d)"),
299 rectArrow
.GetRight(),
300 rectArrow
.GetBottom());
302 scrollbar
->GetArrows().DrawArrow
304 (wxScrollArrows::Arrow
)nArrow
,
307 true // draw a scrollbar arrow, not just an arrow
312 // TODO: support for page arrows
315 wxScrollBar::Element elem
= wxScrollBar::Element_Thumb
;
316 wxRect rectThumb
= scrollbar
->GetScrollbarRect(elem
);
317 if ( rectThumb
.width
&& rectThumb
.height
&& rgnUpdate
.Contains(rectThumb
) )
319 wxLogTrace(wxT("scrollbar"),
320 wxT("drawing thumb at (%d, %d)-(%d, %d)"),
323 rectThumb
.GetRight(),
324 rectThumb
.GetBottom());
326 m_renderer
->DrawScrollbarThumb(m_dc
,
329 scrollbar
->GetState(elem
));
333 #endif // wxUSE_SCROLLBAR
335 void wxControlRenderer::DrawLine(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
337 wxASSERT_MSG( x1
== x2
|| y1
== y2
,
338 wxT("line must be either horizontal or vertical") );
341 m_renderer
->DrawVerticalLine(m_dc
, x1
, y1
, y2
);
343 m_renderer
->DrawHorizontalLine(m_dc
, y1
, x1
, x2
);
348 void wxControlRenderer::DrawItems(const wxListBox
*lbox
,
349 size_t itemFirst
, size_t itemLast
)
351 DoDrawItems(lbox
, itemFirst
, itemLast
);
354 void wxControlRenderer::DoDrawItems(const wxListBox
*lbox
,
355 size_t itemFirst
, size_t itemLast
,
356 #if wxUSE_CHECKLISTBOX
359 bool WXUNUSED(isCheckLbox
)
363 // prepare for the drawing: calc the initial position
364 wxCoord lineHeight
= lbox
->GetLineHeight();
366 // note that SetClippingRegion() needs the physical (unscrolled)
367 // coordinates while we use the logical (scrolled) ones for the drawing
370 wxSize size
= lbox
->GetClientSize();
372 rect
.height
= size
.y
;
374 // keep the text inside the client rect or we will overwrite the vertical
375 // scrollbar for the long strings
376 m_dc
.SetClippingRegion(rect
.x
, rect
.y
, rect
.width
+ 1, rect
.height
+ 1);
378 // adjust the rect position now
379 lbox
->CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
380 rect
.y
+= itemFirst
*lineHeight
;
381 rect
.height
= lineHeight
;
383 // the rect should go to the right visible border so adjust the width if x
384 // is shifted (rightmost point should stay the same)
385 rect
.width
-= rect
.x
;
387 // we'll keep the text colour unchanged
388 m_dc
.SetTextForeground(lbox
->GetForegroundColour());
390 // an item should have the focused rect only when the lbox has focus, so
391 // make sure that we never set wxCONTROL_FOCUSED flag if it doesn't
392 int itemCurrent
= wxWindow::FindFocus() == (wxWindow
*)lbox
// cast needed
393 ? lbox
->GetCurrentItem()
395 for ( size_t n
= itemFirst
; n
< itemLast
; n
++ )
398 if ( (int)n
== itemCurrent
)
399 flags
|= wxCONTROL_FOCUSED
;
400 if ( lbox
->IsSelected(n
) )
401 flags
|= wxCONTROL_SELECTED
;
403 #if wxUSE_CHECKLISTBOX
406 wxCheckListBox
*checklstbox
= wxStaticCast(lbox
, wxCheckListBox
);
407 if ( checklstbox
->IsChecked(n
) )
408 flags
|= wxCONTROL_CHECKED
;
410 m_renderer
->DrawCheckItem(m_dc
, lbox
->GetString(n
),
416 #endif // wxUSE_CHECKLISTBOX
418 m_renderer
->DrawItem(m_dc
, lbox
->GetString(n
), rect
, flags
);
421 rect
.y
+= lineHeight
;
425 #endif // wxUSE_LISTBOX
427 #if wxUSE_CHECKLISTBOX
429 void wxControlRenderer::DrawCheckItems(const wxCheckListBox
*lbox
,
430 size_t itemFirst
, size_t itemLast
)
432 DoDrawItems(lbox
, itemFirst
, itemLast
, true);
435 #endif // wxUSE_CHECKLISTBOX
439 void wxControlRenderer::DrawProgressBar(const wxGauge
*gauge
)
442 m_dc
.SetBrush(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
443 m_dc
.SetPen(*wxTRANSPARENT_PEN
);
444 m_dc
.DrawRectangle(m_rect
);
446 int max
= gauge
->GetRange();
453 // calc the filled rect
454 int pos
= gauge
->GetValue();
455 int left
= max
- pos
;
457 wxRect rect
= m_rect
;
458 rect
.Deflate(1); // FIXME this depends on the border width
460 wxColour col
= m_window
->UseFgCol() ? m_window
->GetForegroundColour()
461 : wxTHEME_COLOUR(GAUGE
);
462 m_dc
.SetBrush(wxBrush(col
, wxSOLID
));
464 if ( gauge
->IsSmooth() )
466 // just draw the rectangle in one go
467 if ( gauge
->IsVertical() )
469 // vert bars grow from bottom to top
470 wxCoord dy
= ((rect
.height
- 1) * left
) / max
;
476 // grow from left to right
477 rect
.width
-= ((rect
.width
- 1) * left
) / max
;
480 m_dc
.DrawRectangle(rect
);
484 wxSize sizeStep
= m_renderer
->GetProgressBarStep();
485 int step
= gauge
->IsVertical() ? sizeStep
.y
: sizeStep
.x
;
487 // we divide by it below!
488 wxCHECK_RET( step
, wxT("invalid wxGauge step") );
490 // round up to make the progress appear to start faster
491 int lenTotal
= gauge
->IsVertical() ? rect
.height
: rect
.width
;
492 int steps
= ((lenTotal
+ step
- 1) * pos
) / (max
* step
);
494 // calc the coords of one small rect
497 if ( gauge
->IsVertical() )
499 // draw from bottom to top: so first set y to the bottom
500 rect
.y
+= rect
.height
- 1;
502 // then adjust the height
505 // and then adjust y again to be what it should for the first rect
506 rect
.y
-= rect
.height
;
511 // remember that this will be the coord which will change
519 // don't leave 2 empty pixels in the beginning
529 for ( int n
= 0; n
< steps
; n
++ )
531 wxRect rectSegment
= rect
;
532 rectSegment
.Deflate(dx
, dy
);
534 m_dc
.DrawRectangle(rectSegment
);
539 // this can only happen for the last step of vertical gauge
540 rect
.height
= *px
- step
- 1;
543 else if ( *px
> lenTotal
- step
)
545 // this can only happen for the last step of horizontal gauge
546 rect
.width
= lenTotal
- *px
- 1;
552 #endif // wxUSE_GAUGE