--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// Name: univ/ctrlrend.cpp
+// Purpose: wxControlRenderer implementation
+// Author: Vadim Zeitlin
+// Modified by:
+// Created: 15.08.00
+// RCS-ID: $Id$
+// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ===========================================================================
+// declarations
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// headers
+// ---------------------------------------------------------------------------
+
+#ifdef __GNUG__
+ #pragma implementation "renderer.h"
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+ #include "wx/control.h"
+ #include "wx/checklst.h"
+ #include "wx/listbox.h"
+ #include "wx/scrolbar.h"
+ #include "wx/dc.h"
+#endif // WX_PRECOMP
+
+#include "wx/image.h"
+#include "wx/log.h"
+
+#include "wx/univ/theme.h"
+#include "wx/univ/renderer.h"
+#include "wx/univ/colschem.h"
+
+#if wxUSE_GAUGE
+#include "wx/gauge.h"
+#endif
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxRenderer: drawing helpers
+// ----------------------------------------------------------------------------
+
+void wxRenderer::StandardDrawFrame(wxDC& dc,
+ const wxRect& rectFrame,
+ const wxRect& rectLabel)
+{
+ // draw left, bottom and right lines entirely
+ DrawVerticalLine(dc, rectFrame.GetLeft(),
+ rectFrame.GetTop(), rectFrame.GetBottom() - 2);
+ DrawHorizontalLine(dc, rectFrame.GetBottom() - 1,
+ rectFrame.GetLeft(), rectFrame.GetRight());
+ DrawVerticalLine(dc, rectFrame.GetRight() - 1,
+ rectFrame.GetTop(), rectFrame.GetBottom() - 1);
+
+ // and 2 parts of the top line
+ DrawHorizontalLine(dc, rectFrame.GetTop(),
+ rectFrame.GetLeft() + 1, rectLabel.GetLeft());
+ DrawHorizontalLine(dc, rectFrame.GetTop(),
+ rectLabel.GetRight(), rectFrame.GetRight() - 2);
+}
+
+/* static */
+void wxRenderer::StandardDrawTextLine(wxDC& dc,
+ const wxString& text,
+ const wxRect& rect,
+ int selStart, int selEnd,
+ int flags)
+{
+ if ( (selStart == -1) || !(flags & wxCONTROL_FOCUSED) )
+ {
+ // just draw it as is
+ dc.DrawText(text, rect.x, rect.y);
+ }
+ else // we have selection
+ {
+ wxCoord width,
+ x = rect.x;
+
+ // draw the part before selection
+ wxString s(text, (size_t)selStart);
+ if ( !s.empty() )
+ {
+ dc.DrawText(s, x, rect.y);
+
+ dc.GetTextExtent(s, &width, NULL);
+ x += width;
+ }
+
+ // draw the selection itself
+ s = wxString(text.c_str() + selStart, text.c_str() + selEnd);
+ if ( !s.empty() )
+ {
+ wxColour colFg = dc.GetTextForeground(),
+ colBg = dc.GetTextBackground();
+ dc.SetTextForeground(wxTHEME_COLOUR(HIGHLIGHT_TEXT));
+ dc.SetTextBackground(wxTHEME_COLOUR(HIGHLIGHT));
+ dc.SetBackgroundMode(wxSOLID);
+
+ dc.DrawText(s, x, rect.y);
+ dc.GetTextExtent(s, &width, NULL);
+ x += width;
+
+ dc.SetBackgroundMode(wxTRANSPARENT);
+ dc.SetTextBackground(colBg);
+ dc.SetTextForeground(colFg);
+ }
+
+ // draw the final part
+ s = text.c_str() + selEnd;
+ if ( !s.empty() )
+ {
+ dc.DrawText(s, x, rect.y);
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// wxRenderer: scrollbar geometry
+// ----------------------------------------------------------------------------
+
+/* static */
+void wxRenderer::StandardScrollBarThumbSize(wxCoord length,
+ int thumbPos,
+ int thumbSize,
+ int range,
+ wxCoord *thumbStart,
+ wxCoord *thumbEnd)
+{
+ // the thumb can't be made less than this number of pixels
+ static const wxCoord thumbMinWidth = 8; // FIXME: should be configurable
+
+ *thumbStart = (length*thumbPos) / range;
+ *thumbEnd = (length*(thumbPos + thumbSize)) / range;
+
+ if ( *thumbEnd - *thumbStart < thumbMinWidth )
+ {
+ // adjust the end if possible
+ if ( *thumbStart <= length - thumbMinWidth )
+ {
+ // yes, just make it wider
+ *thumbEnd = *thumbStart + thumbMinWidth;
+ }
+ else // it is at the bottom of the scrollbar
+ {
+ // so move it a bit up
+ *thumbStart = length - thumbMinWidth;
+ *thumbEnd = length;
+ }
+ }
+}
+
+/* static */
+wxRect wxRenderer::StandardGetScrollbarRect(const wxScrollBar *scrollbar,
+ wxScrollBar::Element elem,
+ int thumbPos,
+ const wxSize& sizeArrow)
+{
+ if ( thumbPos == -1 )
+ {
+ thumbPos = scrollbar->GetThumbPosition();
+ }
+
+ wxSize sizeTotal = scrollbar->GetClientSize();
+ wxCoord *start, *width, length, arrow;
+ wxRect rect;
+ if ( scrollbar->IsVertical() )
+ {
+ rect.x = 0;
+ rect.width = sizeTotal.x;
+ length = sizeTotal.y;
+ start = &rect.y;
+ width = &rect.height;
+ arrow = sizeArrow.y;
+ }
+ else // horizontal
+ {
+ rect.y = 0;
+ rect.height = sizeTotal.y;
+ length = sizeTotal.x;
+ start = &rect.x;
+ width = &rect.width;
+ arrow = sizeArrow.x;
+ }
+
+ switch ( elem )
+ {
+ case wxScrollBar::Element_Arrow_Line_1:
+ *start = 0;
+ *width = arrow;
+ break;
+
+ case wxScrollBar::Element_Arrow_Line_2:
+ *start = length - arrow;
+ *width = arrow;
+ break;
+
+ case wxScrollBar::Element_Arrow_Page_1:
+ case wxScrollBar::Element_Arrow_Page_2:
+ // we don't have them at all
+ break;
+
+ case wxScrollBar::Element_Thumb:
+ case wxScrollBar::Element_Bar_1:
+ case wxScrollBar::Element_Bar_2:
+ // we need to calculate the thumb position - do it
+ {
+ length -= 2*arrow;
+ wxCoord thumbStart, thumbEnd;
+ int range = scrollbar->GetRange();
+ if ( !range )
+ {
+ thumbStart =
+ thumbEnd = 0;
+ }
+ else
+ {
+ StandardScrollBarThumbSize(length,
+ thumbPos,
+ scrollbar->GetThumbSize(),
+ range,
+ &thumbStart,
+ &thumbEnd);
+ }
+
+ if ( elem == wxScrollBar::Element_Thumb )
+ {
+ *start = thumbStart;
+ *width = thumbEnd - thumbStart;
+ }
+ else if ( elem == wxScrollBar::Element_Bar_1 )
+ {
+ *start = 0;
+ *width = thumbStart;
+ }
+ else // elem == wxScrollBar::Element_Bar_2
+ {
+ *start = thumbEnd;
+ *width = length - thumbEnd;
+ }
+
+ // everything is relative to the start of the shaft so far
+ *start += arrow;
+ }
+ break;
+
+ case wxScrollBar::Element_Max:
+ default:
+ wxFAIL_MSG( _T("unknown scrollbar element") );
+ }
+
+ return rect;
+}
+
+/* static */
+wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar,
+ const wxSize& sizeArrowSB)
+{
+ wxCoord sizeArrow, sizeTotal;
+ if ( scrollbar->GetWindowStyle() & wxVERTICAL )
+ {
+ sizeArrow = sizeArrowSB.y;
+ sizeTotal = scrollbar->GetSize().y;
+ }
+ else // horizontal
+ {
+ sizeArrow = sizeArrowSB.x;
+ sizeTotal = scrollbar->GetSize().x;
+ }
+
+ return sizeTotal - 2*sizeArrow;
+}
+
+/* static */
+wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar,
+ int thumbPos,
+ const wxSize& sizeArrow)
+{
+ int range = scrollbar->GetRange();
+ if ( !range )
+ {
+ // the only valid position anyhow
+ return 0;
+ }
+
+ if ( thumbPos == -1 )
+ {
+ // by default use the current thumb position
+ thumbPos = scrollbar->GetThumbPosition();
+ }
+
+ return ( thumbPos*StandardScrollBarSize(scrollbar, sizeArrow) ) / range
+ + (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x);
+}
+
+/* static */
+int wxRenderer::StandardPixelToScrollbar(const wxScrollBar *scrollbar,
+ wxCoord coord,
+ const wxSize& sizeArrow)
+{
+ return ( (coord - (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x)) *
+ scrollbar->GetRange() ) /
+ StandardScrollBarSize(scrollbar, sizeArrow);
+}
+
+/* static */
+wxHitTest wxRenderer::StandardHitTestScrollbar(const wxScrollBar *scrollbar,
+ const wxPoint& pt,
+ const wxSize& sizeArrowSB)
+{
+ // we only need to work with either x or y coord depending on the
+ // orientation, choose one (but still check the other one to verify if the
+ // mouse is in the window at all)
+ wxCoord coord, sizeArrow, sizeTotal;
+ wxSize size = scrollbar->GetSize();
+ if ( scrollbar->GetWindowStyle() & wxVERTICAL )
+ {
+ if ( pt.x < 0 || pt.x > size.x )
+ return wxHT_NOWHERE;
+
+ coord = pt.y;
+ sizeArrow = sizeArrowSB.y;
+ sizeTotal = size.y;
+ }
+ else // horizontal
+ {
+ if ( pt.y < 0 || pt.y > size.y )
+ return wxHT_NOWHERE;
+
+ coord = pt.x;
+ sizeArrow = sizeArrowSB.x;
+ sizeTotal = size.x;
+ }
+
+ // test for the arrows first as it's faster
+ if ( coord < 0 || coord > sizeTotal )
+ {
+ return wxHT_NOWHERE;
+ }
+ else if ( coord < sizeArrow )
+ {
+ return wxHT_SCROLLBAR_ARROW_LINE_1;
+ }
+ else if ( coord > sizeTotal - sizeArrow )
+ {
+ return wxHT_SCROLLBAR_ARROW_LINE_2;
+ }
+ else
+ {
+ // calculate the thumb position in pixels
+ sizeTotal -= 2*sizeArrow;
+ wxCoord thumbStart, thumbEnd;
+ int range = scrollbar->GetRange();
+ if ( !range )
+ {
+ // clicking the scrollbar without range has no effect
+ return wxHT_NOWHERE;
+ }
+ else
+ {
+ StandardScrollBarThumbSize(sizeTotal,
+ scrollbar->GetThumbPosition(),
+ scrollbar->GetThumbSize(),
+ range,
+ &thumbStart,
+ &thumbEnd);
+ }
+
+ // now compare with the thumb position
+ coord -= sizeArrow;
+ if ( coord < thumbStart )
+ return wxHT_SCROLLBAR_BAR_1;
+ else if ( coord > thumbEnd )
+ return wxHT_SCROLLBAR_BAR_2;
+ else
+ return wxHT_SCROLLBAR_THUMB;
+ }
+}
+
+wxRenderer::~wxRenderer()
+{
+}
+
+// ----------------------------------------------------------------------------
+// wxControlRenderer
+// ----------------------------------------------------------------------------
+
+wxControlRenderer::wxControlRenderer(wxWindow *window,
+ wxDC& dc,
+ wxRenderer *renderer)
+ : m_dc(dc)
+{
+ m_window = window;
+ m_renderer = renderer;
+
+ wxSize size = m_window->GetClientSize();
+ m_rect.x =
+ m_rect.y = 0;
+ m_rect.width = size.x;
+ m_rect.height = size.y;
+}
+
+void wxControlRenderer::DrawLabel(const wxBitmap& bitmap,
+ wxCoord marginX, wxCoord marginY)
+{
+ m_dc.SetBackgroundMode(wxTRANSPARENT);
+ m_dc.SetFont(m_window->GetFont());
+ m_dc.SetTextForeground(m_window->GetForegroundColour());
+
+ wxString label = m_window->GetLabel();
+ if ( !label.empty() || bitmap.Ok() )
+ {
+ wxRect rectLabel = m_rect;
+ if ( bitmap.Ok() )
+ {
+ rectLabel.Inflate(-marginX, -marginY);
+ }
+
+ wxControl *ctrl = wxStaticCast(m_window, wxControl);
+
+ m_renderer->DrawButtonLabel(m_dc,
+ label,
+ bitmap,
+ rectLabel,
+ m_window->GetStateFlags(),
+ ctrl->GetAlignment(),
+ ctrl->GetAccelIndex());
+ }
+}
+
+void wxControlRenderer::DrawFrame()
+{
+ m_dc.SetFont(m_window->GetFont());
+ m_dc.SetTextForeground(m_window->GetForegroundColour());
+ m_dc.SetTextBackground(m_window->GetBackgroundColour());
+
+ wxControl *ctrl = wxStaticCast(m_window, wxControl);
+
+ m_renderer->DrawFrame(m_dc,
+ m_window->GetLabel(),
+ m_rect,
+ m_window->GetStateFlags(),
+ ctrl->GetAlignment(),
+ ctrl->GetAccelIndex());
+}
+
+void wxControlRenderer::DrawButtonBorder()
+{
+ int flags = m_window->GetStateFlags();
+
+ m_renderer->DrawButtonBorder(m_dc, m_rect, flags, &m_rect);
+
+ // Why do this here?
+ // m_renderer->DrawButtonSurface(m_dc, wxTHEME_BG_COLOUR(m_window), m_rect, flags );
+}
+
+void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap)
+{
+ int style = m_window->GetWindowStyle();
+ DrawBitmap(m_dc, bitmap, m_rect,
+ style & wxALIGN_MASK,
+ style & wxBI_EXPAND ? wxEXPAND : wxSTRETCH_NOT);
+}
+
+/* static */
+void wxControlRenderer::DrawBitmap(wxDC &dc,
+ const wxBitmap& bitmap,
+ const wxRect& rect,
+ int alignment,
+ wxStretch stretch)
+{
+ // we may change the bitmap if we stretch it
+ wxBitmap bmp = bitmap;
+ if ( !bmp.Ok() )
+ return;
+
+ int width = bmp.GetWidth(),
+ height = bmp.GetHeight();
+
+ wxCoord x = 0,
+ y = 0;
+ if ( stretch & wxTILE )
+ {
+ // tile the bitmap
+ for ( ; x < rect.width; x += width )
+ {
+ for ( y = 0; y < rect.height; y += height )
+ {
+ // no need to use mask here as we cover the entire window area
+ dc.DrawBitmap(bmp, x, y);
+ }
+ }
+ }
+ else if ( stretch & wxEXPAND )
+ {
+ // stretch bitmap to fill the entire control
+ bmp = wxBitmap(wxImage(bmp.ConvertToImage()).Scale(rect.width, rect.height));
+ }
+ else // not stretched, not tiled
+ {
+ if ( alignment & wxALIGN_RIGHT )
+ {
+ x = rect.GetRight() - width;
+ }
+ else if ( alignment & wxALIGN_CENTRE )
+ {
+ x = (rect.GetLeft() + rect.GetRight() - width + 1) / 2;
+ }
+ else // alignment & wxALIGN_LEFT
+ {
+ x = rect.GetLeft();
+ }
+
+ if ( alignment & wxALIGN_BOTTOM )
+ {
+ y = rect.GetBottom() - height;
+ }
+ else if ( alignment & wxALIGN_CENTRE_VERTICAL )
+ {
+ y = (rect.GetTop() + rect.GetBottom() - height + 1) / 2;
+ }
+ else // alignment & wxALIGN_TOP
+ {
+ y = rect.GetTop();
+ }
+ }
+
+ // do draw it
+ dc.DrawBitmap(bmp, x, y, TRUE /* use mask */);
+}
+
+void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
+ int thumbPosOld)
+{
+ // we will only redraw the parts which must be redrawn and not everything
+ wxRegion rgnUpdate = scrollbar->GetUpdateRegion();
+
+ {
+ wxRect rectUpdate = rgnUpdate.GetBox();
+ wxLogTrace(_T("scrollbar"),
+ _T("%s redraw: update box is (%d, %d)-(%d, %d)"),
+ scrollbar->IsVertical() ? _T("vert") : _T("horz"),
+ rectUpdate.GetLeft(),
+ rectUpdate.GetTop(),
+ rectUpdate.GetRight(),
+ rectUpdate.GetBottom());
+
+#if 0 //def WXDEBUG_SCROLLBAR
+ static bool s_refreshDebug = FALSE;
+ if ( s_refreshDebug )
+ {
+ wxClientDC dc(wxConstCast(scrollbar, wxScrollBar));
+ dc.SetBrush(*wxRED_BRUSH);
+ dc.SetPen(*wxTRANSPARENT_PEN);
+ dc.DrawRectangle(rectUpdate);
+
+ // under Unix we use "--sync" X option for this
+ #ifdef __WXMSW__
+ ::GdiFlush();
+ ::Sleep(200);
+ #endif // __WXMSW__
+ }
+#endif // WXDEBUG_SCROLLBAR
+ }
+
+ wxOrientation orient = scrollbar->IsVertical() ? wxVERTICAL
+ : wxHORIZONTAL;
+
+ // the shaft
+ for ( int nBar = 0; nBar < 2; nBar++ )
+ {
+ wxScrollBar::Element elem =
+ (wxScrollBar::Element)(wxScrollBar::Element_Bar_1 + nBar);
+
+ wxRect rectBar = m_renderer->GetScrollbarRect(scrollbar, elem);
+
+ if ( rgnUpdate.Contains(rectBar) )
+ {
+ wxLogTrace(_T("scrollbar"),
+ _T("drawing bar part %d at (%d, %d)-(%d, %d)"),
+ nBar + 1,
+ rectBar.GetLeft(),
+ rectBar.GetTop(),
+ rectBar.GetRight(),
+ rectBar.GetBottom());
+
+ m_renderer->DrawScrollbarShaft(m_dc,
+ orient,
+ rectBar,
+ scrollbar->GetState(elem));
+ }
+ }
+
+ // arrows
+ for ( int nArrow = 0; nArrow < 2; nArrow++ )
+ {
+ wxScrollBar::Element elem =
+ (wxScrollBar::Element)(wxScrollBar::Element_Arrow_Line_1 + nArrow);
+
+ wxRect rectArrow = m_renderer->GetScrollbarRect(scrollbar, elem);
+ if ( rgnUpdate.Contains(rectArrow) )
+ {
+ wxLogTrace(_T("scrollbar"),
+ _T("drawing arrow %d at (%d, %d)-(%d, %d)"),
+ nArrow + 1,
+ rectArrow.GetLeft(),
+ rectArrow.GetTop(),
+ rectArrow.GetRight(),
+ rectArrow.GetBottom());
+
+ scrollbar->GetArrows().DrawArrow
+ (
+ (wxScrollArrows::Arrow)nArrow,
+ m_dc,
+ rectArrow,
+ TRUE // draw a scrollbar arrow, not just an arrow
+ );
+ }
+ }
+
+ // TODO: support for page arrows
+
+ // and the thumb
+ wxScrollBar::Element elem = wxScrollBar::Element_Thumb;
+ wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem);
+ if ( rectThumb.width && rectThumb.height && rgnUpdate.Contains(rectThumb) )
+ {
+ wxLogTrace(_T("scrollbar"),
+ _T("drawing thumb at (%d, %d)-(%d, %d)"),
+ rectThumb.GetLeft(),
+ rectThumb.GetTop(),
+ rectThumb.GetRight(),
+ rectThumb.GetBottom());
+
+ m_renderer->DrawScrollbarThumb(m_dc,
+ orient,
+ rectThumb,
+ scrollbar->GetState(elem));
+ }
+}
+
+void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
+{
+ wxASSERT_MSG( x1 == x2 || y1 == y2,
+ _T("line must be either horizontal or vertical") );
+
+ if ( x1 == x2 )
+ m_renderer->DrawVerticalLine(m_dc, x1, y1, y2);
+ else // horizontal
+ m_renderer->DrawHorizontalLine(m_dc, y1, x1, x2);
+}
+
+#if wxUSE_LISTBOX
+
+void wxControlRenderer::DrawItems(const wxListBox *lbox,
+ size_t itemFirst, size_t itemLast)
+{
+ DoDrawItems(lbox, itemFirst, itemLast);
+}
+
+void wxControlRenderer::DoDrawItems(const wxListBox *lbox,
+ size_t itemFirst, size_t itemLast,
+ bool isCheckLbox)
+{
+ // prepare for the drawing: calc the initial position
+ wxCoord lineHeight = lbox->GetLineHeight();
+
+ // note that SetClippingRegion() needs the physical (unscrolled)
+ // coordinates while we use the logical (scrolled) ones for the drawing
+ // itself
+ wxRect rect;
+ wxSize size = lbox->GetClientSize();
+ rect.width = size.x;
+ rect.height = size.y;
+
+ // keep the text inside the client rect or we will overwrite the vertical
+ // scrollbar for the long strings
+ m_dc.SetClippingRegion(rect.x, rect.y, rect.width + 1, rect.height + 1);
+
+ // adjust the rect position now
+ lbox->CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
+ rect.y += itemFirst*lineHeight;
+ rect.height = lineHeight;
+
+ // the rect should go to the right visible border so adjust the width if x
+ // is shifted (rightmost point should stay the same)
+ rect.width -= rect.x;
+
+ // we'll keep the text colour unchanged
+ m_dc.SetTextForeground(lbox->GetForegroundColour());
+
+ // an item should have the focused rect only when the lbox has focus, so
+ // make sure that we never set wxCONTROL_FOCUSED flag if it doesn't
+ int itemCurrent = wxWindow::FindFocus() == (wxWindow *)lbox // cast needed
+ ? lbox->GetCurrentItem()
+ : -1;
+ for ( size_t n = itemFirst; n < itemLast; n++ )
+ {
+ int flags = 0;
+ if ( (int)n == itemCurrent )
+ flags |= wxCONTROL_FOCUSED;
+ if ( lbox->IsSelected(n) )
+ flags |= wxCONTROL_SELECTED;
+
+#if wxUSE_CHECKLISTBOX
+ if ( isCheckLbox )
+ {
+ wxCheckListBox *checklstbox = wxStaticCast(lbox, wxCheckListBox);
+ if ( checklstbox->IsChecked(n) )
+ flags |= wxCONTROL_CHECKED;
+
+ m_renderer->DrawCheckItem(m_dc, lbox->GetString(n),
+ wxNullBitmap,
+ rect,
+ flags);
+ }
+ else
+#endif // wxUSE_CHECKLISTBOX
+ {
+ m_renderer->DrawItem(m_dc, lbox->GetString(n), rect, flags);
+ }
+
+ rect.y += lineHeight;
+ }
+}
+
+#endif // wxUSE_LISTBOX
+
+#if wxUSE_CHECKLISTBOX
+
+void wxControlRenderer::DrawCheckItems(const wxCheckListBox *lbox,
+ size_t itemFirst, size_t itemLast)
+{
+ DoDrawItems(lbox, itemFirst, itemLast, TRUE);
+}
+
+#endif // wxUSE_CHECKLISTBOX
+
+#if wxUSE_GAUGE
+
+void wxControlRenderer::DrawProgressBar(const wxGauge *gauge)
+{
+ // draw background
+ m_dc.SetBrush(wxBrush(m_window->GetBackgroundColour(), wxSOLID));
+ m_dc.SetPen(*wxTRANSPARENT_PEN);
+ m_dc.DrawRectangle(m_rect);
+
+ int max = gauge->GetRange();
+ if ( !max )
+ {
+ // nothing to draw
+ return;
+ }
+
+ // calc the filled rect
+ int pos = gauge->GetValue();
+ int left = max - pos;
+
+ wxRect rect = m_rect;
+ rect.Deflate(1); // FIXME this depends on the border width
+
+ wxColour col = m_window->UseFgCol() ? m_window->GetForegroundColour()
+ : wxTHEME_COLOUR(GAUGE);
+ m_dc.SetBrush(wxBrush(col, wxSOLID));
+
+ if ( gauge->IsSmooth() )
+ {
+ // just draw the rectangle in one go
+ if ( gauge->IsVertical() )
+ {
+ // vert bars grow from bottom to top
+ wxCoord dy = ((rect.height - 1) * left) / max;
+ rect.y += dy;
+ rect.height -= dy;
+ }
+ else // horizontal
+ {
+ // grow from left to right
+ rect.width -= ((rect.width - 1) * left) / max;
+ }
+
+ m_dc.DrawRectangle(rect);
+ }
+ else // discrete
+ {
+ wxSize sizeStep = m_renderer->GetProgressBarStep();
+ int step = gauge->IsVertical() ? sizeStep.y : sizeStep.x;
+
+ // we divide by it below!
+ wxCHECK_RET( step, _T("invalid wxGauge step") );
+
+ // round up to make the progress appear to start faster
+ int lenTotal = gauge->IsVertical() ? rect.height : rect.width;
+ int steps = ((lenTotal + step - 1) * pos) / (max * step);
+
+ // calc the coords of one small rect
+ wxCoord *px, dx, dy;
+ if ( gauge->IsVertical() )
+ {
+ // draw from bottom to top: so first set y to the bottom
+ rect.y += rect.height - 1;
+
+ // then adjust the height
+ rect.height = step;
+
+ // and then adjust y again to be what it should for the first rect
+ rect.y -= rect.height;
+
+ // we are going up
+ step = -step;
+
+ // remember that this will be the coord which will change
+ px = &rect.y;
+
+ dy = 1;
+ dx = 0;
+ }
+ else // horizontal
+ {
+ // don't leave 2 empty pixels in the beginning
+ rect.x--;
+
+ px = &rect.x;
+ rect.width = step;
+
+ dy = 0;
+ dx = 1;
+ }
+
+ for ( int n = 0; n < steps; n++ )
+ {
+ wxRect rectSegment = rect;
+ rectSegment.Deflate(dx, dy);
+
+ m_dc.DrawRectangle(rectSegment);
+
+ *px += step;
+ if ( *px < 1 )
+ {
+ // this can only happen for the last step of vertical gauge
+ rect.height = *px - step - 1;
+ *px = 1;
+ }
+ else if ( *px > lenTotal - step )
+ {
+ // this can only happen for the last step of horizontal gauge
+ rect.width = lenTotal - *px - 1;
+ }
+ }
+ }
+}
+
+#endif // wxUSE_GAUGE
+
+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////
-// Name: univ/renderer.cpp
-// Purpose: wxControlRenderer implementation
-// Author: Vadim Zeitlin
-// Modified by:
-// Created: 15.08.00
-// RCS-ID: $Id$
-// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
-// Licence: wxWindows licence
-///////////////////////////////////////////////////////////////////////////////
-
-// ===========================================================================
-// declarations
-// ===========================================================================
-
-// ---------------------------------------------------------------------------
-// headers
-// ---------------------------------------------------------------------------
-
-#ifdef __GNUG__
- #pragma implementation "renderer.h"
-#endif
-
-// For compilers that support precompilation, includes "wx.h".
-#include "wx/wxprec.h"
-
-#ifdef __BORLANDC__
- #pragma hdrstop
-#endif
-
-#ifndef WX_PRECOMP
- #include "wx/app.h"
- #include "wx/control.h"
- #include "wx/checklst.h"
- #include "wx/listbox.h"
- #include "wx/scrolbar.h"
- #include "wx/dc.h"
-#endif // WX_PRECOMP
-
-#include "wx/image.h"
-#include "wx/log.h"
-
-#include "wx/univ/theme.h"
-#include "wx/univ/renderer.h"
-#include "wx/univ/colschem.h"
-
-#if wxUSE_GAUGE
-#include "wx/gauge.h"
-#endif
-
-// ============================================================================
-// implementation
-// ============================================================================
-
-// ----------------------------------------------------------------------------
-// wxRenderer: drawing helpers
-// ----------------------------------------------------------------------------
-
-void wxRenderer::StandardDrawFrame(wxDC& dc,
- const wxRect& rectFrame,
- const wxRect& rectLabel)
-{
- // draw left, bottom and right lines entirely
- DrawVerticalLine(dc, rectFrame.GetLeft(),
- rectFrame.GetTop(), rectFrame.GetBottom() - 2);
- DrawHorizontalLine(dc, rectFrame.GetBottom() - 1,
- rectFrame.GetLeft(), rectFrame.GetRight());
- DrawVerticalLine(dc, rectFrame.GetRight() - 1,
- rectFrame.GetTop(), rectFrame.GetBottom() - 1);
-
- // and 2 parts of the top line
- DrawHorizontalLine(dc, rectFrame.GetTop(),
- rectFrame.GetLeft() + 1, rectLabel.GetLeft());
- DrawHorizontalLine(dc, rectFrame.GetTop(),
- rectLabel.GetRight(), rectFrame.GetRight() - 2);
-}
-
-/* static */
-void wxRenderer::StandardDrawTextLine(wxDC& dc,
- const wxString& text,
- const wxRect& rect,
- int selStart, int selEnd,
- int flags)
-{
- if ( (selStart == -1) || !(flags & wxCONTROL_FOCUSED) )
- {
- // just draw it as is
- dc.DrawText(text, rect.x, rect.y);
- }
- else // we have selection
- {
- wxCoord width,
- x = rect.x;
-
- // draw the part before selection
- wxString s(text, (size_t)selStart);
- if ( !s.empty() )
- {
- dc.DrawText(s, x, rect.y);
-
- dc.GetTextExtent(s, &width, NULL);
- x += width;
- }
-
- // draw the selection itself
- s = wxString(text.c_str() + selStart, text.c_str() + selEnd);
- if ( !s.empty() )
- {
- wxColour colFg = dc.GetTextForeground(),
- colBg = dc.GetTextBackground();
- dc.SetTextForeground(wxTHEME_COLOUR(HIGHLIGHT_TEXT));
- dc.SetTextBackground(wxTHEME_COLOUR(HIGHLIGHT));
- dc.SetBackgroundMode(wxSOLID);
-
- dc.DrawText(s, x, rect.y);
- dc.GetTextExtent(s, &width, NULL);
- x += width;
-
- dc.SetBackgroundMode(wxTRANSPARENT);
- dc.SetTextBackground(colBg);
- dc.SetTextForeground(colFg);
- }
-
- // draw the final part
- s = text.c_str() + selEnd;
- if ( !s.empty() )
- {
- dc.DrawText(s, x, rect.y);
- }
- }
-}
-
-// ----------------------------------------------------------------------------
-// wxRenderer: scrollbar geometry
-// ----------------------------------------------------------------------------
-
-/* static */
-void wxRenderer::StandardScrollBarThumbSize(wxCoord length,
- int thumbPos,
- int thumbSize,
- int range,
- wxCoord *thumbStart,
- wxCoord *thumbEnd)
-{
- // the thumb can't be made less than this number of pixels
- static const wxCoord thumbMinWidth = 8; // FIXME: should be configurable
-
- *thumbStart = (length*thumbPos) / range;
- *thumbEnd = (length*(thumbPos + thumbSize)) / range;
-
- if ( *thumbEnd - *thumbStart < thumbMinWidth )
- {
- // adjust the end if possible
- if ( *thumbStart <= length - thumbMinWidth )
- {
- // yes, just make it wider
- *thumbEnd = *thumbStart + thumbMinWidth;
- }
- else // it is at the bottom of the scrollbar
- {
- // so move it a bit up
- *thumbStart = length - thumbMinWidth;
- *thumbEnd = length;
- }
- }
-}
-
-/* static */
-wxRect wxRenderer::StandardGetScrollbarRect(const wxScrollBar *scrollbar,
- wxScrollBar::Element elem,
- int thumbPos,
- const wxSize& sizeArrow)
-{
- if ( thumbPos == -1 )
- {
- thumbPos = scrollbar->GetThumbPosition();
- }
-
- wxSize sizeTotal = scrollbar->GetClientSize();
- wxCoord *start, *width, length, arrow;
- wxRect rect;
- if ( scrollbar->IsVertical() )
- {
- rect.x = 0;
- rect.width = sizeTotal.x;
- length = sizeTotal.y;
- start = &rect.y;
- width = &rect.height;
- arrow = sizeArrow.y;
- }
- else // horizontal
- {
- rect.y = 0;
- rect.height = sizeTotal.y;
- length = sizeTotal.x;
- start = &rect.x;
- width = &rect.width;
- arrow = sizeArrow.x;
- }
-
- switch ( elem )
- {
- case wxScrollBar::Element_Arrow_Line_1:
- *start = 0;
- *width = arrow;
- break;
-
- case wxScrollBar::Element_Arrow_Line_2:
- *start = length - arrow;
- *width = arrow;
- break;
-
- case wxScrollBar::Element_Arrow_Page_1:
- case wxScrollBar::Element_Arrow_Page_2:
- // we don't have them at all
- break;
-
- case wxScrollBar::Element_Thumb:
- case wxScrollBar::Element_Bar_1:
- case wxScrollBar::Element_Bar_2:
- // we need to calculate the thumb position - do it
- {
- length -= 2*arrow;
- wxCoord thumbStart, thumbEnd;
- int range = scrollbar->GetRange();
- if ( !range )
- {
- thumbStart =
- thumbEnd = 0;
- }
- else
- {
- StandardScrollBarThumbSize(length,
- thumbPos,
- scrollbar->GetThumbSize(),
- range,
- &thumbStart,
- &thumbEnd);
- }
-
- if ( elem == wxScrollBar::Element_Thumb )
- {
- *start = thumbStart;
- *width = thumbEnd - thumbStart;
- }
- else if ( elem == wxScrollBar::Element_Bar_1 )
- {
- *start = 0;
- *width = thumbStart;
- }
- else // elem == wxScrollBar::Element_Bar_2
- {
- *start = thumbEnd;
- *width = length - thumbEnd;
- }
-
- // everything is relative to the start of the shaft so far
- *start += arrow;
- }
- break;
-
- case wxScrollBar::Element_Max:
- default:
- wxFAIL_MSG( _T("unknown scrollbar element") );
- }
-
- return rect;
-}
-
-/* static */
-wxCoord wxRenderer::StandardScrollBarSize(const wxScrollBar *scrollbar,
- const wxSize& sizeArrowSB)
-{
- wxCoord sizeArrow, sizeTotal;
- if ( scrollbar->GetWindowStyle() & wxVERTICAL )
- {
- sizeArrow = sizeArrowSB.y;
- sizeTotal = scrollbar->GetSize().y;
- }
- else // horizontal
- {
- sizeArrow = sizeArrowSB.x;
- sizeTotal = scrollbar->GetSize().x;
- }
-
- return sizeTotal - 2*sizeArrow;
-}
-
-/* static */
-wxCoord wxRenderer::StandardScrollbarToPixel(const wxScrollBar *scrollbar,
- int thumbPos,
- const wxSize& sizeArrow)
-{
- int range = scrollbar->GetRange();
- if ( !range )
- {
- // the only valid position anyhow
- return 0;
- }
-
- if ( thumbPos == -1 )
- {
- // by default use the current thumb position
- thumbPos = scrollbar->GetThumbPosition();
- }
-
- return ( thumbPos*StandardScrollBarSize(scrollbar, sizeArrow) ) / range
- + (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x);
-}
-
-/* static */
-int wxRenderer::StandardPixelToScrollbar(const wxScrollBar *scrollbar,
- wxCoord coord,
- const wxSize& sizeArrow)
-{
- return ( (coord - (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x)) *
- scrollbar->GetRange() ) /
- StandardScrollBarSize(scrollbar, sizeArrow);
-}
-
-/* static */
-wxHitTest wxRenderer::StandardHitTestScrollbar(const wxScrollBar *scrollbar,
- const wxPoint& pt,
- const wxSize& sizeArrowSB)
-{
- // we only need to work with either x or y coord depending on the
- // orientation, choose one (but still check the other one to verify if the
- // mouse is in the window at all)
- wxCoord coord, sizeArrow, sizeTotal;
- wxSize size = scrollbar->GetSize();
- if ( scrollbar->GetWindowStyle() & wxVERTICAL )
- {
- if ( pt.x < 0 || pt.x > size.x )
- return wxHT_NOWHERE;
-
- coord = pt.y;
- sizeArrow = sizeArrowSB.y;
- sizeTotal = size.y;
- }
- else // horizontal
- {
- if ( pt.y < 0 || pt.y > size.y )
- return wxHT_NOWHERE;
-
- coord = pt.x;
- sizeArrow = sizeArrowSB.x;
- sizeTotal = size.x;
- }
-
- // test for the arrows first as it's faster
- if ( coord < 0 || coord > sizeTotal )
- {
- return wxHT_NOWHERE;
- }
- else if ( coord < sizeArrow )
- {
- return wxHT_SCROLLBAR_ARROW_LINE_1;
- }
- else if ( coord > sizeTotal - sizeArrow )
- {
- return wxHT_SCROLLBAR_ARROW_LINE_2;
- }
- else
- {
- // calculate the thumb position in pixels
- sizeTotal -= 2*sizeArrow;
- wxCoord thumbStart, thumbEnd;
- int range = scrollbar->GetRange();
- if ( !range )
- {
- // clicking the scrollbar without range has no effect
- return wxHT_NOWHERE;
- }
- else
- {
- StandardScrollBarThumbSize(sizeTotal,
- scrollbar->GetThumbPosition(),
- scrollbar->GetThumbSize(),
- range,
- &thumbStart,
- &thumbEnd);
- }
-
- // now compare with the thumb position
- coord -= sizeArrow;
- if ( coord < thumbStart )
- return wxHT_SCROLLBAR_BAR_1;
- else if ( coord > thumbEnd )
- return wxHT_SCROLLBAR_BAR_2;
- else
- return wxHT_SCROLLBAR_THUMB;
- }
-}
-
-wxRenderer::~wxRenderer()
-{
-}
-
-// ----------------------------------------------------------------------------
-// wxControlRenderer
-// ----------------------------------------------------------------------------
-
-wxControlRenderer::wxControlRenderer(wxWindow *window,
- wxDC& dc,
- wxRenderer *renderer)
- : m_dc(dc)
-{
- m_window = window;
- m_renderer = renderer;
-
- wxSize size = m_window->GetClientSize();
- m_rect.x =
- m_rect.y = 0;
- m_rect.width = size.x;
- m_rect.height = size.y;
-}
-
-void wxControlRenderer::DrawLabel(const wxBitmap& bitmap,
- wxCoord marginX, wxCoord marginY)
-{
- m_dc.SetBackgroundMode(wxTRANSPARENT);
- m_dc.SetFont(m_window->GetFont());
- m_dc.SetTextForeground(m_window->GetForegroundColour());
-
- wxString label = m_window->GetLabel();
- if ( !label.empty() || bitmap.Ok() )
- {
- wxRect rectLabel = m_rect;
- if ( bitmap.Ok() )
- {
- rectLabel.Inflate(-marginX, -marginY);
- }
-
- wxControl *ctrl = wxStaticCast(m_window, wxControl);
-
- m_renderer->DrawButtonLabel(m_dc,
- label,
- bitmap,
- rectLabel,
- m_window->GetStateFlags(),
- ctrl->GetAlignment(),
- ctrl->GetAccelIndex());
- }
-}
-
-void wxControlRenderer::DrawFrame()
-{
- m_dc.SetFont(m_window->GetFont());
- m_dc.SetTextForeground(m_window->GetForegroundColour());
- m_dc.SetTextBackground(m_window->GetBackgroundColour());
-
- wxControl *ctrl = wxStaticCast(m_window, wxControl);
-
- m_renderer->DrawFrame(m_dc,
- m_window->GetLabel(),
- m_rect,
- m_window->GetStateFlags(),
- ctrl->GetAlignment(),
- ctrl->GetAccelIndex());
-}
-
-void wxControlRenderer::DrawButtonBorder()
-{
- int flags = m_window->GetStateFlags();
-
- m_renderer->DrawButtonBorder(m_dc, m_rect, flags, &m_rect);
-
- // Why do this here?
- // m_renderer->DrawButtonSurface(m_dc, wxTHEME_BG_COLOUR(m_window), m_rect, flags );
-}
-
-void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap)
-{
- int style = m_window->GetWindowStyle();
- DrawBitmap(m_dc, bitmap, m_rect,
- style & wxALIGN_MASK,
- style & wxBI_EXPAND ? wxEXPAND : wxSTRETCH_NOT);
-}
-
-/* static */
-void wxControlRenderer::DrawBitmap(wxDC &dc,
- const wxBitmap& bitmap,
- const wxRect& rect,
- int alignment,
- wxStretch stretch)
-{
- // we may change the bitmap if we stretch it
- wxBitmap bmp = bitmap;
- if ( !bmp.Ok() )
- return;
-
- int width = bmp.GetWidth(),
- height = bmp.GetHeight();
-
- wxCoord x = 0,
- y = 0;
- if ( stretch & wxTILE )
- {
- // tile the bitmap
- for ( ; x < rect.width; x += width )
- {
- for ( y = 0; y < rect.height; y += height )
- {
- // no need to use mask here as we cover the entire window area
- dc.DrawBitmap(bmp, x, y);
- }
- }
- }
- else if ( stretch & wxEXPAND )
- {
- // stretch bitmap to fill the entire control
- bmp = wxBitmap(wxImage(bmp.ConvertToImage()).Scale(rect.width, rect.height));
- }
- else // not stretched, not tiled
- {
- if ( alignment & wxALIGN_RIGHT )
- {
- x = rect.GetRight() - width;
- }
- else if ( alignment & wxALIGN_CENTRE )
- {
- x = (rect.GetLeft() + rect.GetRight() - width + 1) / 2;
- }
- else // alignment & wxALIGN_LEFT
- {
- x = rect.GetLeft();
- }
-
- if ( alignment & wxALIGN_BOTTOM )
- {
- y = rect.GetBottom() - height;
- }
- else if ( alignment & wxALIGN_CENTRE_VERTICAL )
- {
- y = (rect.GetTop() + rect.GetBottom() - height + 1) / 2;
- }
- else // alignment & wxALIGN_TOP
- {
- y = rect.GetTop();
- }
- }
-
- // do draw it
- dc.DrawBitmap(bmp, x, y, TRUE /* use mask */);
-}
-
-void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
- int thumbPosOld)
-{
- // we will only redraw the parts which must be redrawn and not everything
- wxRegion rgnUpdate = scrollbar->GetUpdateRegion();
-
- {
- wxRect rectUpdate = rgnUpdate.GetBox();
- wxLogTrace(_T("scrollbar"),
- _T("%s redraw: update box is (%d, %d)-(%d, %d)"),
- scrollbar->IsVertical() ? _T("vert") : _T("horz"),
- rectUpdate.GetLeft(),
- rectUpdate.GetTop(),
- rectUpdate.GetRight(),
- rectUpdate.GetBottom());
-
-#if 0 //def WXDEBUG_SCROLLBAR
- static bool s_refreshDebug = FALSE;
- if ( s_refreshDebug )
- {
- wxClientDC dc(wxConstCast(scrollbar, wxScrollBar));
- dc.SetBrush(*wxRED_BRUSH);
- dc.SetPen(*wxTRANSPARENT_PEN);
- dc.DrawRectangle(rectUpdate);
-
- // under Unix we use "--sync" X option for this
- #ifdef __WXMSW__
- ::GdiFlush();
- ::Sleep(200);
- #endif // __WXMSW__
- }
-#endif // WXDEBUG_SCROLLBAR
- }
-
- wxOrientation orient = scrollbar->IsVertical() ? wxVERTICAL
- : wxHORIZONTAL;
-
- // the shaft
- for ( int nBar = 0; nBar < 2; nBar++ )
- {
- wxScrollBar::Element elem =
- (wxScrollBar::Element)(wxScrollBar::Element_Bar_1 + nBar);
-
- wxRect rectBar = m_renderer->GetScrollbarRect(scrollbar, elem);
-
- if ( rgnUpdate.Contains(rectBar) )
- {
- wxLogTrace(_T("scrollbar"),
- _T("drawing bar part %d at (%d, %d)-(%d, %d)"),
- nBar + 1,
- rectBar.GetLeft(),
- rectBar.GetTop(),
- rectBar.GetRight(),
- rectBar.GetBottom());
-
- m_renderer->DrawScrollbarShaft(m_dc,
- orient,
- rectBar,
- scrollbar->GetState(elem));
- }
- }
-
- // arrows
- for ( int nArrow = 0; nArrow < 2; nArrow++ )
- {
- wxScrollBar::Element elem =
- (wxScrollBar::Element)(wxScrollBar::Element_Arrow_Line_1 + nArrow);
-
- wxRect rectArrow = m_renderer->GetScrollbarRect(scrollbar, elem);
- if ( rgnUpdate.Contains(rectArrow) )
- {
- wxLogTrace(_T("scrollbar"),
- _T("drawing arrow %d at (%d, %d)-(%d, %d)"),
- nArrow + 1,
- rectArrow.GetLeft(),
- rectArrow.GetTop(),
- rectArrow.GetRight(),
- rectArrow.GetBottom());
-
- scrollbar->GetArrows().DrawArrow
- (
- (wxScrollArrows::Arrow)nArrow,
- m_dc,
- rectArrow,
- TRUE // draw a scrollbar arrow, not just an arrow
- );
- }
- }
-
- // TODO: support for page arrows
-
- // and the thumb
- wxScrollBar::Element elem = wxScrollBar::Element_Thumb;
- wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem);
- if ( rectThumb.width && rectThumb.height && rgnUpdate.Contains(rectThumb) )
- {
- wxLogTrace(_T("scrollbar"),
- _T("drawing thumb at (%d, %d)-(%d, %d)"),
- rectThumb.GetLeft(),
- rectThumb.GetTop(),
- rectThumb.GetRight(),
- rectThumb.GetBottom());
-
- m_renderer->DrawScrollbarThumb(m_dc,
- orient,
- rectThumb,
- scrollbar->GetState(elem));
- }
-}
-
-void wxControlRenderer::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
-{
- wxASSERT_MSG( x1 == x2 || y1 == y2,
- _T("line must be either horizontal or vertical") );
-
- if ( x1 == x2 )
- m_renderer->DrawVerticalLine(m_dc, x1, y1, y2);
- else // horizontal
- m_renderer->DrawHorizontalLine(m_dc, y1, x1, x2);
-}
-
-#if wxUSE_LISTBOX
-
-void wxControlRenderer::DrawItems(const wxListBox *lbox,
- size_t itemFirst, size_t itemLast)
-{
- DoDrawItems(lbox, itemFirst, itemLast);
-}
-
-void wxControlRenderer::DoDrawItems(const wxListBox *lbox,
- size_t itemFirst, size_t itemLast,
- bool isCheckLbox)
-{
- // prepare for the drawing: calc the initial position
- wxCoord lineHeight = lbox->GetLineHeight();
-
- // note that SetClippingRegion() needs the physical (unscrolled)
- // coordinates while we use the logical (scrolled) ones for the drawing
- // itself
- wxRect rect;
- wxSize size = lbox->GetClientSize();
- rect.width = size.x;
- rect.height = size.y;
-
- // keep the text inside the client rect or we will overwrite the vertical
- // scrollbar for the long strings
- m_dc.SetClippingRegion(rect.x, rect.y, rect.width + 1, rect.height + 1);
-
- // adjust the rect position now
- lbox->CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
- rect.y += itemFirst*lineHeight;
- rect.height = lineHeight;
-
- // the rect should go to the right visible border so adjust the width if x
- // is shifted (rightmost point should stay the same)
- rect.width -= rect.x;
-
- // we'll keep the text colour unchanged
- m_dc.SetTextForeground(lbox->GetForegroundColour());
-
- // an item should have the focused rect only when the lbox has focus, so
- // make sure that we never set wxCONTROL_FOCUSED flag if it doesn't
- int itemCurrent = wxWindow::FindFocus() == (wxWindow *)lbox // cast needed
- ? lbox->GetCurrentItem()
- : -1;
- for ( size_t n = itemFirst; n < itemLast; n++ )
- {
- int flags = 0;
- if ( (int)n == itemCurrent )
- flags |= wxCONTROL_FOCUSED;
- if ( lbox->IsSelected(n) )
- flags |= wxCONTROL_SELECTED;
-
-#if wxUSE_CHECKLISTBOX
- if ( isCheckLbox )
- {
- wxCheckListBox *checklstbox = wxStaticCast(lbox, wxCheckListBox);
- if ( checklstbox->IsChecked(n) )
- flags |= wxCONTROL_CHECKED;
-
- m_renderer->DrawCheckItem(m_dc, lbox->GetString(n),
- wxNullBitmap,
- rect,
- flags);
- }
- else
-#endif // wxUSE_CHECKLISTBOX
- {
- m_renderer->DrawItem(m_dc, lbox->GetString(n), rect, flags);
- }
-
- rect.y += lineHeight;
- }
-}
-
-#endif // wxUSE_LISTBOX
-
-#if wxUSE_CHECKLISTBOX
-
-void wxControlRenderer::DrawCheckItems(const wxCheckListBox *lbox,
- size_t itemFirst, size_t itemLast)
-{
- DoDrawItems(lbox, itemFirst, itemLast, TRUE);
-}
-
-#endif // wxUSE_CHECKLISTBOX
-
-#if wxUSE_GAUGE
-
-void wxControlRenderer::DrawProgressBar(const wxGauge *gauge)
-{
- // draw background
- m_dc.SetBrush(wxBrush(m_window->GetBackgroundColour(), wxSOLID));
- m_dc.SetPen(*wxTRANSPARENT_PEN);
- m_dc.DrawRectangle(m_rect);
-
- int max = gauge->GetRange();
- if ( !max )
- {
- // nothing to draw
- return;
- }
-
- // calc the filled rect
- int pos = gauge->GetValue();
- int left = max - pos;
-
- wxRect rect = m_rect;
- rect.Deflate(1); // FIXME this depends on the border width
-
- wxColour col = m_window->UseFgCol() ? m_window->GetForegroundColour()
- : wxTHEME_COLOUR(GAUGE);
- m_dc.SetBrush(wxBrush(col, wxSOLID));
-
- if ( gauge->IsSmooth() )
- {
- // just draw the rectangle in one go
- if ( gauge->IsVertical() )
- {
- // vert bars grow from bottom to top
- wxCoord dy = ((rect.height - 1) * left) / max;
- rect.y += dy;
- rect.height -= dy;
- }
- else // horizontal
- {
- // grow from left to right
- rect.width -= ((rect.width - 1) * left) / max;
- }
-
- m_dc.DrawRectangle(rect);
- }
- else // discrete
- {
- wxSize sizeStep = m_renderer->GetProgressBarStep();
- int step = gauge->IsVertical() ? sizeStep.y : sizeStep.x;
-
- // we divide by it below!
- wxCHECK_RET( step, _T("invalid wxGauge step") );
-
- // round up to make the progress appear to start faster
- int lenTotal = gauge->IsVertical() ? rect.height : rect.width;
- int steps = ((lenTotal + step - 1) * pos) / (max * step);
-
- // calc the coords of one small rect
- wxCoord *px, dx, dy;
- if ( gauge->IsVertical() )
- {
- // draw from bottom to top: so first set y to the bottom
- rect.y += rect.height - 1;
-
- // then adjust the height
- rect.height = step;
-
- // and then adjust y again to be what it should for the first rect
- rect.y -= rect.height;
-
- // we are going up
- step = -step;
-
- // remember that this will be the coord which will change
- px = &rect.y;
-
- dy = 1;
- dx = 0;
- }
- else // horizontal
- {
- // don't leave 2 empty pixels in the beginning
- rect.x--;
-
- px = &rect.x;
- rect.width = step;
-
- dy = 0;
- dx = 1;
- }
-
- for ( int n = 0; n < steps; n++ )
- {
- wxRect rectSegment = rect;
- rectSegment.Deflate(dx, dy);
-
- m_dc.DrawRectangle(rectSegment);
-
- *px += step;
- if ( *px < 1 )
- {
- // this can only happen for the last step of vertical gauge
- rect.height = *px - step - 1;
- *px = 1;
- }
- else if ( *px > lenTotal - step )
- {
- // this can only happen for the last step of horizontal gauge
- rect.width = lenTotal - *px - 1;
- }
- }
- }
-}
-
-#endif // wxUSE_GAUGE
-