X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/567be1875494c4cb90a3bdff691f8545e4f6e41d..cfeafba1328a39299e17a710675d2597f6ef4bf2:/src/univ/ctrlrend.cpp diff --git a/src/univ/ctrlrend.cpp b/src/univ/ctrlrend.cpp new file mode 100644 index 0000000000..a693d45657 --- /dev/null +++ b/src/univ/ctrlrend.cpp @@ -0,0 +1,869 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 +