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