Include wx/gauge.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / univ / ctrlrend.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/ctrlrend.cpp
3 // Purpose: wxControlRenderer implementation
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 15.08.00
7 // RCS-ID: $Id$
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/app.h"
29 #include "wx/control.h"
30 #include "wx/checklst.h"
31 #include "wx/listbox.h"
32 #include "wx/scrolbar.h"
33 #include "wx/dc.h"
34 #include "wx/log.h"
35 #include "wx/gauge.h"
36 #endif // WX_PRECOMP
37
38 #include "wx/image.h"
39
40 #include "wx/univ/theme.h"
41 #include "wx/univ/renderer.h"
42 #include "wx/univ/colschem.h"
43
44 // ============================================================================
45 // implementation
46 // ============================================================================
47
48 // ----------------------------------------------------------------------------
49 // wxRenderer: drawing helpers
50 // ----------------------------------------------------------------------------
51
52 void wxRenderer::StandardDrawFrame(wxDC& dc,
53 const wxRect& rectFrame,
54 const wxRect& rectLabel)
55 {
56 // draw left, bottom and right lines entirely
57 DrawVerticalLine(dc, rectFrame.GetLeft(),
58 rectFrame.GetTop(), rectFrame.GetBottom() - 2);
59 DrawHorizontalLine(dc, rectFrame.GetBottom() - 1,
60 rectFrame.GetLeft(), rectFrame.GetRight());
61 DrawVerticalLine(dc, rectFrame.GetRight() - 1,
62 rectFrame.GetTop(), rectFrame.GetBottom() - 1);
63
64 // and 2 parts of the top line
65 DrawHorizontalLine(dc, rectFrame.GetTop(),
66 rectFrame.GetLeft() + 1, rectLabel.GetLeft());
67 DrawHorizontalLine(dc, rectFrame.GetTop(),
68 rectLabel.GetRight(), rectFrame.GetRight() - 2);
69 }
70
71 /* static */
72 void wxRenderer::StandardDrawTextLine(wxDC& dc,
73 const wxString& text,
74 const wxRect& rect,
75 int selStart, int selEnd,
76 int flags)
77 {
78 if ( (selStart == -1) || !(flags & wxCONTROL_FOCUSED) )
79 {
80 // just draw it as is
81 dc.DrawText(text, rect.x, rect.y);
82 }
83 else // we have selection
84 {
85 wxCoord width,
86 x = rect.x;
87
88 // draw the part before selection
89 wxString s(text, (size_t)selStart);
90 if ( !s.empty() )
91 {
92 dc.DrawText(s, x, rect.y);
93
94 dc.GetTextExtent(s, &width, NULL);
95 x += width;
96 }
97
98 // draw the selection itself
99 s = wxString(text.c_str() + selStart, text.c_str() + selEnd);
100 if ( !s.empty() )
101 {
102 wxColour colFg = dc.GetTextForeground(),
103 colBg = dc.GetTextBackground();
104 dc.SetTextForeground(wxTHEME_COLOUR(HIGHLIGHT_TEXT));
105 dc.SetTextBackground(wxTHEME_COLOUR(HIGHLIGHT));
106 dc.SetBackgroundMode(wxSOLID);
107
108 dc.DrawText(s, x, rect.y);
109 dc.GetTextExtent(s, &width, NULL);
110 x += width;
111
112 dc.SetBackgroundMode(wxTRANSPARENT);
113 dc.SetTextBackground(colBg);
114 dc.SetTextForeground(colFg);
115 }
116
117 // draw the final part
118 s = text.c_str() + selEnd;
119 if ( !s.empty() )
120 {
121 dc.DrawText(s, x, rect.y);
122 }
123 }
124 }
125
126 // ----------------------------------------------------------------------------
127 // wxRenderer: scrollbar geometry
128 // ----------------------------------------------------------------------------
129
130 /* static */
131 void wxRenderer::StandardScrollBarThumbSize(wxCoord length,
132 int thumbPos,
133 int thumbSize,
134 int range,
135 wxCoord *thumbStart,
136 wxCoord *thumbEnd)
137 {
138 // the thumb can't be made less than this number of pixels
139 static const wxCoord thumbMinWidth = 8; // FIXME: should be configurable
140
141 *thumbStart = (length*thumbPos) / range;
142 *thumbEnd = (length*(thumbPos + thumbSize)) / range;
143
144 if ( *thumbEnd - *thumbStart < thumbMinWidth )
145 {
146 // adjust the end if possible
147 if ( *thumbStart <= length - thumbMinWidth )
148 {
149 // yes, just make it wider
150 *thumbEnd = *thumbStart + thumbMinWidth;
151 }
152 else // it is at the bottom of the scrollbar
153 {
154 // so move it a bit up
155 *thumbStart = length - thumbMinWidth;
156 *thumbEnd = length;
157 }
158 }
159 }
160
161 /* static */
162 wxRect wxRenderer::StandardGetScrollbarRect(const wxScrollBar *scrollbar,
163 wxScrollBar::Element elem,
164 int thumbPos,
165 const wxSize& sizeArrow)
166 {
167 if ( thumbPos == -1 )
168 {
169 thumbPos = scrollbar->GetThumbPosition();
170 }
171
172 wxSize sizeTotal = scrollbar->GetClientSize();
173 wxCoord *start, *width;
174 wxCoord length, arrow;
175 wxRect rect;
176 if ( scrollbar->IsVertical() )
177 {
178 rect.x = 0;
179 rect.width = sizeTotal.x;
180 length = sizeTotal.y;
181 start = &rect.y;
182 width = &rect.height;
183 arrow = sizeArrow.y;
184 }
185 else // horizontal
186 {
187 rect.y = 0;
188 rect.height = sizeTotal.y;
189 length = sizeTotal.x;
190 start = &rect.x;
191 width = &rect.width;
192 arrow = sizeArrow.x;
193 }
194
195 switch ( elem )
196 {
197 case wxScrollBar::Element_Arrow_Line_1:
198 *start = 0;
199 *width = arrow;
200 break;
201
202 case wxScrollBar::Element_Arrow_Line_2:
203 *start = length - arrow;
204 *width = arrow;
205 break;
206
207 case wxScrollBar::Element_Arrow_Page_1:
208 case wxScrollBar::Element_Arrow_Page_2:
209 // we don't have them at all
210 break;
211
212 case wxScrollBar::Element_Thumb:
213 case wxScrollBar::Element_Bar_1:
214 case wxScrollBar::Element_Bar_2:
215 // we need to calculate the thumb position - do it
216 {
217 length -= 2*arrow;
218 wxCoord thumbStart, thumbEnd;
219 int range = scrollbar->GetRange();
220 if ( !range )
221 {
222 thumbStart =
223 thumbEnd = 0;
224 }
225 else
226 {
227 StandardScrollBarThumbSize(length,
228 thumbPos,
229 scrollbar->GetThumbSize(),
230 range,
231 &thumbStart,
232 &thumbEnd);
233 }
234
235 if ( elem == wxScrollBar::Element_Thumb )
236 {
237 *start = thumbStart;
238 *width = thumbEnd - thumbStart;
239 }
240 else if ( elem == wxScrollBar::Element_Bar_1 )
241 {
242 *start = 0;
243 *width = thumbStart;
244 }
245 else // elem == wxScrollBar::Element_Bar_2
246 {
247 *start = thumbEnd;
248 *width = length - thumbEnd;
249 }
250
251 // everything is relative to the start of the shaft so far
252 *start += arrow;
253 }
254 break;
255
256 case wxScrollBar::Element_Max:
257 default:
258 wxFAIL_MSG( _T("unknown scrollbar element") );
259 }
260
261 return rect;
262 }
263
264 /* static */
265 wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar,
266 const wxSize& sizeArrowSB)
267 {
268 wxCoord sizeArrow, sizeTotal;
269 if ( scrollbar->GetWindowStyle() & wxVERTICAL )
270 {
271 sizeArrow = sizeArrowSB.y;
272 sizeTotal = scrollbar->GetSize().y;
273 }
274 else // horizontal
275 {
276 sizeArrow = sizeArrowSB.x;
277 sizeTotal = scrollbar->GetSize().x;
278 }
279
280 return sizeTotal - 2*sizeArrow;
281 }
282
283 /* static */
284 wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar,
285 int thumbPos,
286 const wxSize& sizeArrow)
287 {
288 int range = scrollbar->GetRange();
289 if ( !range )
290 {
291 // the only valid position anyhow
292 return 0;
293 }
294
295 if ( thumbPos == -1 )
296 {
297 // by default use the current thumb position
298 thumbPos = scrollbar->GetThumbPosition();
299 }
300
301 return ( thumbPos*StandardScrollBarSize(scrollbar, sizeArrow) ) / range
302 + (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x);
303 }
304
305 /* static */
306 int wxRenderer::StandardPixelToScrollbar(const wxScrollBar *scrollbar,
307 wxCoord coord,
308 const wxSize& sizeArrow)
309 {
310 return ( (coord - (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x)) *
311 scrollbar->GetRange() ) /
312 StandardScrollBarSize(scrollbar, sizeArrow);
313 }
314
315 /* static */
316 wxHitTest wxRenderer::StandardHitTestScrollbar(const wxScrollBar *scrollbar,
317 const wxPoint& pt,
318 const wxSize& sizeArrowSB)
319 {
320 // we only need to work with either x or y coord depending on the
321 // orientation, choose one (but still check the other one to verify if the
322 // mouse is in the window at all)
323 wxCoord coord, sizeArrow, sizeTotal;
324 wxSize size = scrollbar->GetSize();
325 if ( scrollbar->GetWindowStyle() & wxVERTICAL )
326 {
327 if ( pt.x < 0 || pt.x > size.x )
328 return wxHT_NOWHERE;
329
330 coord = pt.y;
331 sizeArrow = sizeArrowSB.y;
332 sizeTotal = size.y;
333 }
334 else // horizontal
335 {
336 if ( pt.y < 0 || pt.y > size.y )
337 return wxHT_NOWHERE;
338
339 coord = pt.x;
340 sizeArrow = sizeArrowSB.x;
341 sizeTotal = size.x;
342 }
343
344 // test for the arrows first as it's faster
345 if ( coord < 0 || coord > sizeTotal )
346 {
347 return wxHT_NOWHERE;
348 }
349 else if ( coord < sizeArrow )
350 {
351 return wxHT_SCROLLBAR_ARROW_LINE_1;
352 }
353 else if ( coord > sizeTotal - sizeArrow )
354 {
355 return wxHT_SCROLLBAR_ARROW_LINE_2;
356 }
357 else
358 {
359 // calculate the thumb position in pixels
360 sizeTotal -= 2*sizeArrow;
361 wxCoord thumbStart, thumbEnd;
362 int range = scrollbar->GetRange();
363 if ( !range )
364 {
365 // clicking the scrollbar without range has no effect
366 return wxHT_NOWHERE;
367 }
368 else
369 {
370 StandardScrollBarThumbSize(sizeTotal,
371 scrollbar->GetThumbPosition(),
372 scrollbar->GetThumbSize(),
373 range,
374 &thumbStart,
375 &thumbEnd);
376 }
377
378 // now compare with the thumb position
379 coord -= sizeArrow;
380 if ( coord < thumbStart )
381 return wxHT_SCROLLBAR_BAR_1;
382 else if ( coord > thumbEnd )
383 return wxHT_SCROLLBAR_BAR_2;
384 else
385 return wxHT_SCROLLBAR_THUMB;
386 }
387 }
388
389 wxRenderer::~wxRenderer()
390 {
391 }
392
393 // ----------------------------------------------------------------------------
394 // wxControlRenderer
395 // ----------------------------------------------------------------------------
396
397 wxControlRenderer::wxControlRenderer(wxWindow *window,
398 wxDC& dc,
399 wxRenderer *renderer)
400 : m_dc(dc)
401 {
402 m_window = window;
403 m_renderer = renderer;
404
405 wxSize size = m_window->GetClientSize();
406 m_rect.x =
407 m_rect.y = 0;
408 m_rect.width = size.x;
409 m_rect.height = size.y;
410 }
411
412 void wxControlRenderer::DrawLabel(const wxBitmap& bitmap,
413 wxCoord marginX, wxCoord marginY)
414 {
415 m_dc.SetBackgroundMode(wxTRANSPARENT);
416 m_dc.SetFont(m_window->GetFont());
417 m_dc.SetTextForeground(m_window->GetForegroundColour());
418
419 wxString label = m_window->GetLabel();
420 if ( !label.empty() || bitmap.Ok() )
421 {
422 wxRect rectLabel = m_rect;
423 if ( bitmap.Ok() )
424 {
425 rectLabel.Inflate(-marginX, -marginY);
426 }
427
428 wxControl *ctrl = wxStaticCast(m_window, wxControl);
429
430 m_renderer->DrawButtonLabel(m_dc,
431 label,
432 bitmap,
433 rectLabel,
434 m_window->GetStateFlags(),
435 ctrl->GetAlignment(),
436 ctrl->GetAccelIndex());
437 }
438 }
439
440 void wxControlRenderer::DrawFrame()
441 {
442 m_dc.SetFont(m_window->GetFont());
443 m_dc.SetTextForeground(m_window->GetForegroundColour());
444 m_dc.SetTextBackground(m_window->GetBackgroundColour());
445
446 wxControl *ctrl = wxStaticCast(m_window, wxControl);
447
448 m_renderer->DrawFrame(m_dc,
449 m_window->GetLabel(),
450 m_rect,
451 m_window->GetStateFlags(),
452 ctrl->GetAlignment(),
453 ctrl->GetAccelIndex());
454 }
455
456 void wxControlRenderer::DrawButtonBorder()
457 {
458 int flags = m_window->GetStateFlags();
459
460 m_renderer->DrawButtonBorder(m_dc, m_rect, flags, &m_rect);
461
462 // Why do this here?
463 // m_renderer->DrawButtonSurface(m_dc, wxTHEME_BG_COLOUR(m_window), m_rect, flags );
464 }
465
466 void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap)
467 {
468 int style = m_window->GetWindowStyle();
469 DrawBitmap(m_dc, bitmap, m_rect,
470 style & wxALIGN_MASK,
471 style & wxBI_EXPAND ? wxEXPAND : wxSTRETCH_NOT);
472 }
473
474 /* static */
475 void wxControlRenderer::DrawBitmap(wxDC &dc,
476 const wxBitmap& bitmap,
477 const wxRect& rect,
478 int alignment,
479 wxStretch stretch)
480 {
481 // we may change the bitmap if we stretch it
482 wxBitmap bmp = bitmap;
483 if ( !bmp.Ok() )
484 return;
485
486 int width = bmp.GetWidth(),
487 height = bmp.GetHeight();
488
489 wxCoord x = 0,
490 y = 0;
491 if ( stretch & wxTILE )
492 {
493 // tile the bitmap
494 for ( ; x < rect.width; x += width )
495 {
496 for ( y = 0; y < rect.height; y += height )
497 {
498 // no need to use mask here as we cover the entire window area
499 dc.DrawBitmap(bmp, x, y);
500 }
501 }
502 }
503 else if ( stretch & wxEXPAND )
504 {
505 // stretch bitmap to fill the entire control
506 bmp = wxBitmap(wxImage(bmp.ConvertToImage()).Scale(rect.width, rect.height));
507 }
508 else // not stretched, not tiled
509 {
510 if ( alignment & wxALIGN_RIGHT )
511 {
512 x = rect.GetRight() - width;
513 }
514 else if ( alignment & wxALIGN_CENTRE )
515 {
516 x = (rect.GetLeft() + rect.GetRight() - width + 1) / 2;
517 }
518 else // alignment & wxALIGN_LEFT
519 {
520 x = rect.GetLeft();
521 }
522
523 if ( alignment & wxALIGN_BOTTOM )
524 {
525 y = rect.GetBottom() - height;
526 }
527 else if ( alignment & wxALIGN_CENTRE_VERTICAL )
528 {
529 y = (rect.GetTop() + rect.GetBottom() - height + 1) / 2;
530 }
531 else // alignment & wxALIGN_TOP
532 {
533 y = rect.GetTop();
534 }
535 }
536
537 // do draw it
538 dc.DrawBitmap(bmp, x, y, true /* use mask */);
539 }
540
541 void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
542 int WXUNUSED(thumbPosOld))
543 {
544 // we will only redraw the parts which must be redrawn and not everything
545 wxRegion rgnUpdate = scrollbar->GetUpdateRegion();
546
547 {
548 wxRect rectUpdate = rgnUpdate.GetBox();
549 wxLogTrace(_T("scrollbar"),
550 _T("%s redraw: update box is (%d, %d)-(%d, %d)"),
551 scrollbar->IsVertical() ? _T("vert") : _T("horz"),
552 rectUpdate.GetLeft(),
553 rectUpdate.GetTop(),
554 rectUpdate.GetRight(),
555 rectUpdate.GetBottom());
556
557 #if 0 //def WXDEBUG_SCROLLBAR
558 static bool s_refreshDebug = false;
559 if ( s_refreshDebug )
560 {
561 wxClientDC dc(wxConstCast(scrollbar, wxScrollBar));
562 dc.SetBrush(*wxRED_BRUSH);
563 dc.SetPen(*wxTRANSPARENT_PEN);
564 dc.DrawRectangle(rectUpdate);
565
566 // under Unix we use "--sync" X option for this
567 #ifdef __WXMSW__
568 ::GdiFlush();
569 ::Sleep(200);
570 #endif // __WXMSW__
571 }
572 #endif // WXDEBUG_SCROLLBAR
573 }
574
575 wxOrientation orient = scrollbar->IsVertical() ? wxVERTICAL
576 : wxHORIZONTAL;
577
578 // the shaft
579 for ( int nBar = 0; nBar < 2; nBar++ )
580 {
581 wxScrollBar::Element elem =
582 (wxScrollBar::Element)(wxScrollBar::Element_Bar_1 + nBar);
583
584 wxRect rectBar = m_renderer->GetScrollbarRect(scrollbar, elem);
585
586 if ( rgnUpdate.Contains(rectBar) )
587 {
588 wxLogTrace(_T("scrollbar"),
589 _T("drawing bar part %d at (%d, %d)-(%d, %d)"),
590 nBar + 1,
591 rectBar.GetLeft(),
592 rectBar.GetTop(),
593 rectBar.GetRight(),
594 rectBar.GetBottom());
595
596 m_renderer->DrawScrollbarShaft(m_dc,
597 orient,
598 rectBar,
599 scrollbar->GetState(elem));
600 }
601 }
602
603 // arrows
604 for ( int nArrow = 0; nArrow < 2; nArrow++ )
605 {
606 wxScrollBar::Element elem =
607 (wxScrollBar::Element)(wxScrollBar::Element_Arrow_Line_1 + nArrow);
608
609 wxRect rectArrow = m_renderer->GetScrollbarRect(scrollbar, elem);
610 if ( rgnUpdate.Contains(rectArrow) )
611 {
612 wxLogTrace(_T("scrollbar"),
613 _T("drawing arrow %d at (%d, %d)-(%d, %d)"),
614 nArrow + 1,
615 rectArrow.GetLeft(),
616 rectArrow.GetTop(),
617 rectArrow.GetRight(),
618 rectArrow.GetBottom());
619
620 scrollbar->GetArrows().DrawArrow
621 (
622 (wxScrollArrows::Arrow)nArrow,
623 m_dc,
624 rectArrow,
625 true // draw a scrollbar arrow, not just an arrow
626 );
627 }
628 }
629
630 // TODO: support for page arrows
631
632 // and the thumb
633 wxScrollBar::Element elem = wxScrollBar::Element_Thumb;
634 wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem);
635 if ( rectThumb.width && rectThumb.height && rgnUpdate.Contains(rectThumb) )
636 {
637 wxLogTrace(_T("scrollbar"),
638 _T("drawing thumb at (%d, %d)-(%d, %d)"),
639 rectThumb.GetLeft(),
640 rectThumb.GetTop(),
641 rectThumb.GetRight(),
642 rectThumb.GetBottom());
643
644 m_renderer->DrawScrollbarThumb(m_dc,
645 orient,
646 rectThumb,
647 scrollbar->GetState(elem));
648 }
649 }
650
651 void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
652 {
653 wxASSERT_MSG( x1 == x2 || y1 == y2,
654 _T("line must be either horizontal or vertical") );
655
656 if ( x1 == x2 )
657 m_renderer->DrawVerticalLine(m_dc, x1, y1, y2);
658 else // horizontal
659 m_renderer->DrawHorizontalLine(m_dc, y1, x1, x2);
660 }
661
662 #if wxUSE_LISTBOX
663
664 void wxControlRenderer::DrawItems(const wxListBox *lbox,
665 size_t itemFirst, size_t itemLast)
666 {
667 DoDrawItems(lbox, itemFirst, itemLast);
668 }
669
670 void wxControlRenderer::DoDrawItems(const wxListBox *lbox,
671 size_t itemFirst, size_t itemLast,
672 #if wxUSE_CHECKLISTBOX
673 bool isCheckLbox)
674 #else
675 bool WXUNUSED(isCheckLbox))
676 #endif
677 {
678 // prepare for the drawing: calc the initial position
679 wxCoord lineHeight = lbox->GetLineHeight();
680
681 // note that SetClippingRegion() needs the physical (unscrolled)
682 // coordinates while we use the logical (scrolled) ones for the drawing
683 // itself
684 wxRect rect;
685 wxSize size = lbox->GetClientSize();
686 rect.width = size.x;
687 rect.height = size.y;
688
689 // keep the text inside the client rect or we will overwrite the vertical
690 // scrollbar for the long strings
691 m_dc.SetClippingRegion(rect.x, rect.y, rect.width + 1, rect.height + 1);
692
693 // adjust the rect position now
694 lbox->CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
695 rect.y += itemFirst*lineHeight;
696 rect.height = lineHeight;
697
698 // the rect should go to the right visible border so adjust the width if x
699 // is shifted (rightmost point should stay the same)
700 rect.width -= rect.x;
701
702 // we'll keep the text colour unchanged
703 m_dc.SetTextForeground(lbox->GetForegroundColour());
704
705 // an item should have the focused rect only when the lbox has focus, so
706 // make sure that we never set wxCONTROL_FOCUSED flag if it doesn't
707 int itemCurrent = wxWindow::FindFocus() == (wxWindow *)lbox // cast needed
708 ? lbox->GetCurrentItem()
709 : -1;
710 for ( size_t n = itemFirst; n < itemLast; n++ )
711 {
712 int flags = 0;
713 if ( (int)n == itemCurrent )
714 flags |= wxCONTROL_FOCUSED;
715 if ( lbox->IsSelected(n) )
716 flags |= wxCONTROL_SELECTED;
717
718 #if wxUSE_CHECKLISTBOX
719 if ( isCheckLbox )
720 {
721 wxCheckListBox *checklstbox = wxStaticCast(lbox, wxCheckListBox);
722 if ( checklstbox->IsChecked(n) )
723 flags |= wxCONTROL_CHECKED;
724
725 m_renderer->DrawCheckItem(m_dc, lbox->GetString(n),
726 wxNullBitmap,
727 rect,
728 flags);
729 }
730 else
731 #endif // wxUSE_CHECKLISTBOX
732 {
733 m_renderer->DrawItem(m_dc, lbox->GetString(n), rect, flags);
734 }
735
736 rect.y += lineHeight;
737 }
738 }
739
740 #endif // wxUSE_LISTBOX
741
742 #if wxUSE_CHECKLISTBOX
743
744 void wxControlRenderer::DrawCheckItems(const wxCheckListBox *lbox,
745 size_t itemFirst, size_t itemLast)
746 {
747 DoDrawItems(lbox, itemFirst, itemLast, true);
748 }
749
750 #endif // wxUSE_CHECKLISTBOX
751
752 #if wxUSE_GAUGE
753
754 void wxControlRenderer::DrawProgressBar(const wxGauge *gauge)
755 {
756 // draw background
757 m_dc.SetBrush(wxBrush(m_window->GetBackgroundColour(), wxSOLID));
758 m_dc.SetPen(*wxTRANSPARENT_PEN);
759 m_dc.DrawRectangle(m_rect);
760
761 int max = gauge->GetRange();
762 if ( !max )
763 {
764 // nothing to draw
765 return;
766 }
767
768 // calc the filled rect
769 int pos = gauge->GetValue();
770 int left = max - pos;
771
772 wxRect rect = m_rect;
773 rect.Deflate(1); // FIXME this depends on the border width
774
775 wxColour col = m_window->UseFgCol() ? m_window->GetForegroundColour()
776 : wxTHEME_COLOUR(GAUGE);
777 m_dc.SetBrush(wxBrush(col, wxSOLID));
778
779 if ( gauge->IsSmooth() )
780 {
781 // just draw the rectangle in one go
782 if ( gauge->IsVertical() )
783 {
784 // vert bars grow from bottom to top
785 wxCoord dy = ((rect.height - 1) * left) / max;
786 rect.y += dy;
787 rect.height -= dy;
788 }
789 else // horizontal
790 {
791 // grow from left to right
792 rect.width -= ((rect.width - 1) * left) / max;
793 }
794
795 m_dc.DrawRectangle(rect);
796 }
797 else // discrete
798 {
799 wxSize sizeStep = m_renderer->GetProgressBarStep();
800 int step = gauge->IsVertical() ? sizeStep.y : sizeStep.x;
801
802 // we divide by it below!
803 wxCHECK_RET( step, _T("invalid wxGauge step") );
804
805 // round up to make the progress appear to start faster
806 int lenTotal = gauge->IsVertical() ? rect.height : rect.width;
807 int steps = ((lenTotal + step - 1) * pos) / (max * step);
808
809 // calc the coords of one small rect
810 wxCoord *px;
811 wxCoord dx, dy;
812 if ( gauge->IsVertical() )
813 {
814 // draw from bottom to top: so first set y to the bottom
815 rect.y += rect.height - 1;
816
817 // then adjust the height
818 rect.height = step;
819
820 // and then adjust y again to be what it should for the first rect
821 rect.y -= rect.height;
822
823 // we are going up
824 step = -step;
825
826 // remember that this will be the coord which will change
827 px = &rect.y;
828
829 dy = 1;
830 dx = 0;
831 }
832 else // horizontal
833 {
834 // don't leave 2 empty pixels in the beginning
835 rect.x--;
836
837 px = &rect.x;
838 rect.width = step;
839
840 dy = 0;
841 dx = 1;
842 }
843
844 for ( int n = 0; n < steps; n++ )
845 {
846 wxRect rectSegment = rect;
847 rectSegment.Deflate(dx, dy);
848
849 m_dc.DrawRectangle(rectSegment);
850
851 *px += step;
852 if ( *px < 1 )
853 {
854 // this can only happen for the last step of vertical gauge
855 rect.height = *px - step - 1;
856 *px = 1;
857 }
858 else if ( *px > lenTotal - step )
859 {
860 // this can only happen for the last step of horizontal gauge
861 rect.width = lenTotal - *px - 1;
862 }
863 }
864 }
865 }
866
867 #endif // wxUSE_GAUGE
868