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