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