X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/147b8a4ab5ef1546015c9f1c40cf701d1ac4376a..cc4d5638c66a409e421420ed7110917755a66788:/src/univ/stdrend.cpp diff --git a/src/univ/stdrend.cpp b/src/univ/stdrend.cpp index fa8b77dfe0..7f5451855d 100644 --- a/src/univ/stdrend.cpp +++ b/src/univ/stdrend.cpp @@ -3,7 +3,6 @@ // Purpose: implementation of wxStdRenderer // Author: Vadim Zeitlin // Created: 2006-09-16 -// RCS-ID: $Id$ // Copyright: (c) 2006 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -24,11 +23,27 @@ #endif #ifndef WX_PRECOMP + #include "wx/settings.h" + #include "wx/brush.h" + #include "wx/dc.h" + #include "wx/statusbr.h" + #include "wx/toplevel.h" #endif //WX_PRECOMP #include "wx/univ/stdrend.h" #include "wx/univ/colschem.h" +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +static const int FRAME_TITLEBAR_HEIGHT = 18; +static const int FRAME_BUTTON_WIDTH = 16; +static const int FRAME_BUTTON_HEIGHT = 14; + +// the margin between listbox item text and its rectangle +static const int ITEM_MARGIN = 1; + // ============================================================================ // wxStdRenderer implementation // ============================================================================ @@ -44,6 +59,9 @@ wxStdRenderer::wxStdRenderer(const wxColourScheme *scheme) m_penDarkGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_OUT)); m_penLightGrey = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_IN)); m_penHighlight = wxPen(wxSCHEME_COLOUR(scheme, SHADOW_HIGHLIGHT)); + + m_titlebarFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + m_titlebarFont.SetWeight(wxFONTWEIGHT_BOLD); } // ---------------------------------------------------------------------------- @@ -89,6 +107,55 @@ void wxStdRenderer::DrawShadedRect(wxDC& dc, wxRect *rect, rect->Inflate(-1); } +// ---------------------------------------------------------------------------- +// translate various flags into corresponding renderer constants +// ---------------------------------------------------------------------------- + +/* static */ +void wxStdRenderer::GetIndicatorsFromFlags(int flags, + IndicatorState& state, + IndicatorStatus& status) +{ + if ( flags & wxCONTROL_SELECTED ) + state = flags & wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled + : IndicatorState_Selected; + else if ( flags & wxCONTROL_DISABLED ) + state = IndicatorState_Disabled; + else if ( flags & wxCONTROL_PRESSED ) + state = IndicatorState_Pressed; + else + state = IndicatorState_Normal; + + status = flags & wxCONTROL_CHECKED ? IndicatorStatus_Checked + : flags & wxCONTROL_UNDETERMINED + ? IndicatorStatus_Undetermined + : IndicatorStatus_Unchecked; +} + +/* static */ +wxStdRenderer::ArrowDirection wxStdRenderer::GetArrowDirection(wxDirection dir) +{ + switch ( dir ) + { + case wxLEFT: + return Arrow_Left; + + case wxRIGHT: + return Arrow_Right; + + case wxUP: + return Arrow_Up; + + case wxDOWN: + return Arrow_Down; + + default: + wxFAIL_MSG(wxT("unknown arrow direction")); + } + + return Arrow_Max; +} + // ---------------------------------------------------------------------------- // background // ---------------------------------------------------------------------------- @@ -99,9 +166,20 @@ void wxStdRenderer::DrawBackground(wxDC& dc, int WXUNUSED(flags), wxWindow *window) { - wxColour colBg = col.Ok() ? col - : window ? m_scheme->GetBackground(window) - : wxSCHEME_COLOUR(m_scheme, CONTROL); + wxColour colBg; + + if (col.IsOk()) + { + colBg = col; + } + else if (window) + { + colBg = m_scheme->GetBackground(window); + } + else + { + colBg = wxSCHEME_COLOUR(m_scheme, CONTROL); + } DrawSolidRect(dc, colBg, rect); } @@ -119,7 +197,8 @@ void wxStdRenderer::DrawButtonSurface(wxDC& dc, // text // ---------------------------------------------------------------------------- -void wxStdRenderer::DrawFocusRect(wxDC& dc, const wxRect& rect) +void +wxStdRenderer::DrawFocusRect(wxWindow* WXUNUSED(win), wxDC& dc, const wxRect& rect, int WXUNUSED(flags)) { // draw the pixels manually because the "dots" in wxPen with wxDOT style // may be short traits and not really dots @@ -177,6 +256,8 @@ void wxStdRenderer::DrawButtonLabel(wxDC& dc, int indexAccel, wxRect *rectBounds) { + wxDCTextColourChanger clrChanger(dc); + wxRect rectLabel = rect; if ( !label.empty() && (flags & wxCONTROL_DISABLED) ) { @@ -187,13 +268,13 @@ void wxStdRenderer::DrawButtonLabel(wxDC& dc, } // draw shadow of the text - dc.SetTextForeground(m_penHighlight.GetColour()); + clrChanger.Set(m_penHighlight.GetColour()); wxRect rectShadow = rect; rectShadow.Offset(1, 1); dc.DrawLabel(label, rectShadow, alignment, indexAccel); // make the main label text grey - dc.SetTextForeground(m_penDarkGrey.GetColour()); + clrChanger.Set(m_penDarkGrey.GetColour()); if ( flags & wxCONTROL_FOCUSED ) { @@ -208,7 +289,7 @@ void wxStdRenderer::DrawButtonLabel(wxDC& dc, { rectLabel.Inflate(-1); - DrawFocusRect(dc, rectLabel); + DrawFocusRect(NULL, dc, rectLabel); } } @@ -304,6 +385,22 @@ void wxStdRenderer::DrawAntiSunkenBorder(wxDC& dc, wxRect *rect) DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey); } +void wxStdRenderer::DrawBoxBorder(wxDC& dc, wxRect *rect) +{ + DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight); + DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey); +} + +void wxStdRenderer::DrawStaticBorder(wxDC& dc, wxRect *rect) +{ + DrawShadedRect(dc, rect, m_penDarkGrey, m_penHighlight); +} + +void wxStdRenderer::DrawExtraBorder(wxDC& dc, wxRect *rect) +{ + DrawRect(dc, rect, m_penLightGrey); +} + void wxStdRenderer::DrawBorder(wxDC& dc, wxBorder border, const wxRect& rectTotal, @@ -315,16 +412,20 @@ void wxStdRenderer::DrawBorder(wxDC& dc, switch ( border ) { case wxBORDER_SUNKEN: + case wxBORDER_THEME: DrawSunkenBorder(dc, &rect); break; + // wxBORDER_DOUBLE and wxBORDER_THEME are currently the same value. +#if 0 case wxBORDER_DOUBLE: DrawAntiSunkenBorder(dc, &rect); - DrawRect(dc, &rect, m_penLightGrey); + DrawExtraBorder(dc, &rect); break; +#endif case wxBORDER_STATIC: - DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + DrawStaticBorder(dc, &rect); break; case wxBORDER_RAISED: @@ -336,7 +437,7 @@ void wxStdRenderer::DrawBorder(wxDC& dc, break; default: - wxFAIL_MSG(_T("unknown border type")); + wxFAIL_MSG(wxT("unknown border type")); // fall through case wxBORDER_DEFAULT: @@ -360,15 +461,16 @@ wxRect wxStdRenderer::GetBorderDimensions(wxBorder border) const case wxBORDER_RAISED: case wxBORDER_SUNKEN: + case wxBORDER_THEME: width = 2; break; - +#if 0 case wxBORDER_DOUBLE: width = 3; break; - +#endif default: - wxFAIL_MSG(_T("unknown border type")); + wxFAIL_MSG(wxT("unknown border type")); // fall through case wxBORDER_DEFAULT: @@ -386,11 +488,24 @@ wxRect wxStdRenderer::GetBorderDimensions(wxBorder border) const return rect; } +void wxStdRenderer::AdjustSize(wxSize *size, const wxWindow *window) +{ + // take into account the border width + wxRect rectBorder = GetBorderDimensions(window->GetBorder()); + size->x += rectBorder.x + rectBorder.width; + size->y += rectBorder.y + rectBorder.height; +} + bool wxStdRenderer::AreScrollbarsInsideBorder() const { return false; } +wxCoord wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight) +{ + return fontHeight + 2*ITEM_MARGIN; +} + void wxStdRenderer::DrawTextBorder(wxDC& dc, wxBorder border, const wxRect& rect, @@ -493,9 +608,7 @@ void wxStdRenderer::DrawFrame(wxDC& dc, } else // no label { - // just draw the complete frame - DrawShadedRect(dc, &rectFrame, m_penDarkGrey, m_penHighlight); - DrawShadedRect(dc, &rectFrame, m_penHighlight, m_penDarkGrey); + DrawBoxBorder(dc, &rectFrame); } } @@ -516,42 +629,46 @@ void wxStdRenderer::DrawItem(wxDC& dc, dc.DrawRectangle(rect); } + // horizontal adjustment is arbitrary wxRect rectText = rect; - rectText.x += 2; - rectText.width -= 2; + rectText.Deflate(2, ITEM_MARGIN); dc.DrawLabel(label, wxNullBitmap, rectText); if ( flags & wxCONTROL_FOCUSED ) { - DrawFocusRect(dc, rect); + DrawFocusRect(NULL, dc, rect, flags); } } -// ---------------------------------------------------------------------------- -// check and radio bitmaps -// ---------------------------------------------------------------------------- +void wxStdRenderer::DrawCheckItemBitmap(wxDC& dc, + const wxBitmap& bitmap, + const wxRect& rect, + int flags) +{ + DrawCheckButton(dc, wxEmptyString, bitmap, rect, flags); +} -/* static */ -void wxStdRenderer::GetIndicatorsFromFlags(int flags, - IndicatorState& state, - IndicatorStatus& status) +void wxStdRenderer::DrawCheckItem(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rect, + int flags) { - if ( flags & wxCONTROL_SELECTED ) - state = flags & wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled - : IndicatorState_Selected; - else if ( flags & wxCONTROL_DISABLED ) - state = IndicatorState_Disabled; - else if ( flags & wxCONTROL_PRESSED ) - state = IndicatorState_Pressed; - else - state = IndicatorState_Normal; + wxRect rectBitmap = rect; + rectBitmap.width = GetCheckBitmapSize().x; + DrawCheckItemBitmap(dc, bitmap, rectBitmap, flags); - status = flags & wxCONTROL_CHECKED ? IndicatorStatus_Checked - : flags & wxCONTROL_UNDETERMINED - ? IndicatorStatus_Undetermined - : IndicatorStatus_Unchecked; + wxRect rectLabel = rect; + wxCoord shift = rectBitmap.width + 2*GetCheckItemMargin(); + rectLabel.x += shift; + rectLabel.width -= shift; + DrawItem(dc, label, rectLabel, flags); } +// ---------------------------------------------------------------------------- +// check and radio bitmaps +// ---------------------------------------------------------------------------- + void wxStdRenderer::DrawCheckButton(wxDC& dc, const wxString& label, const wxBitmap& bitmap, @@ -560,9 +677,10 @@ void wxStdRenderer::DrawCheckButton(wxDC& dc, wxAlignment align, int indexAccel) { - wxBitmap bmp(bitmap.Ok() ? bitmap : GetCheckBitmap(flags)); - - DrawCheckOrRadioButton(dc, label, bmp, rect, flags, align, indexAccel); + if (bitmap.IsOk()) + DrawCheckOrRadioButton(dc, label, bitmap, rect, flags, align, indexAccel); + else + DrawCheckOrRadioButton(dc, label, GetCheckBitmap(flags), rect, flags, align, indexAccel); } void wxStdRenderer::DrawRadioButton(wxDC& dc, @@ -573,9 +691,11 @@ void wxStdRenderer::DrawRadioButton(wxDC& dc, wxAlignment align, int indexAccel) { - wxBitmap bmp(bitmap.Ok() ? bitmap : GetRadioBitmap(flags)); + if (bitmap.IsOk()) + DrawCheckOrRadioButton(dc, label, bitmap, rect, flags, align, indexAccel); + else + DrawCheckOrRadioButton(dc, label, GetRadioBitmap(flags), rect, flags, align, indexAccel); - DrawCheckOrRadioButton(dc, label, bmp, rect, flags, align, indexAccel); } void wxStdRenderer::DrawCheckOrRadioButton(wxDC& dc, @@ -681,269 +801,470 @@ void wxStdRenderer::DrawLineWrapMark(wxDC& WXUNUSED(dc), // nothing by default } +int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl * WXUNUSED(text)) const +{ + return 1; +} + +wxRect +wxStdRenderer::GetTextTotalArea(const wxTextCtrl *text, const wxRect& rect) const +{ + wxRect rectTotal = rect; + rectTotal.Inflate(GetTextBorderWidth(text)); + return rectTotal; +} + +wxRect wxStdRenderer::GetTextClientArea(const wxTextCtrl *text, + const wxRect& rect, + wxCoord *extraSpaceBeyond) const +{ + wxRect rectText = rect; + rectText.Deflate(GetTextBorderWidth(text)); + + if ( extraSpaceBeyond ) + *extraSpaceBeyond = 0; + + return rectText; +} + #endif // wxUSE_TEXTCTRL // ---------------------------------------------------------------------------- -// scrollbars geometry +// scrollbars drawing // ---------------------------------------------------------------------------- -#if wxUSE_SCROLLBAR +void wxStdRenderer::DrawScrollbarArrow(wxDC& dc, + wxDirection dir, + const wxRect& rect, + int flags) +{ + DrawArrow(dc, dir, rect, flags); +} -/* static */ -void wxStdRenderer::GetScrollBarThumbSize(wxCoord length, - int thumbPos, - int thumbSize, - int range, - wxCoord *thumbStart, - wxCoord *thumbEnd) +void wxStdRenderer::DrawScrollCorner(wxDC& dc, const wxRect& rect) +{ + DrawSolidRect(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect); +} + +// ---------------------------------------------------------------------------- +// status bar +// ---------------------------------------------------------------------------- + +#if wxUSE_STATUSBAR + +wxSize wxStdRenderer::GetStatusBarBorders() const +{ + // Rendered border may be different depending on field's style, we use + // the largest value so that any field certainly fits into the borders + // we return: + wxRect raised = GetBorderDimensions(wxBORDER_RAISED); + wxRect flat = GetBorderDimensions(wxBORDER_STATIC); + wxASSERT_MSG( raised.x == raised.width && raised.y == raised.height && + flat.x == flat.width && flat.y == flat.height, + wxT("this code expects uniform borders, you must override GetStatusBarBorders") ); + + // take the larger of flat/raised values: + wxSize border(wxMax(raised.x, flat.x), wxMax(raised.y, flat.y)); + + return border; +} + +wxCoord wxStdRenderer::GetStatusBarBorderBetweenFields() const { - // the thumb can't be made less than this number of pixels - static const wxCoord thumbMinWidth = 8; // FIXME: should be configurable + return 2; +} + +wxSize wxStdRenderer::GetStatusBarFieldMargins() const +{ + return wxSize(2, 2); +} - *thumbStart = (length*thumbPos) / range; - *thumbEnd = (length*(thumbPos + thumbSize)) / range; +void wxStdRenderer::DrawStatusField(wxDC& dc, + const wxRect& rect, + const wxString& label, + int flags, + int style) +{ + wxRect rectIn; - if ( *thumbEnd - *thumbStart < thumbMinWidth ) + if ( style == wxSB_RAISED ) + DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn); + else if ( style != wxSB_FLAT ) + DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn); + else + rectIn = rect; + + rectIn.Deflate(GetStatusBarFieldMargins()); + + wxDCClipper clipper(dc, rectIn); + DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL); +} + +#endif // wxUSE_STATUSBAR + +// ---------------------------------------------------------------------------- +// top level windows +// ---------------------------------------------------------------------------- + +int wxStdRenderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const +{ + wxRect client = GetFrameClientArea(rect, flags); + + if ( client.Contains(pt) ) + return wxHT_TOPLEVEL_CLIENT_AREA; + + if ( flags & wxTOPLEVEL_TITLEBAR ) { - // adjust the end if possible - if ( *thumbStart <= length - thumbMinWidth ) + wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + + if ( flags & wxTOPLEVEL_ICON ) { - // yes, just make it wider - *thumbEnd = *thumbStart + thumbMinWidth; + if ( wxRect(client.GetPosition(), GetFrameIconSize()).Contains(pt) ) + return wxHT_TOPLEVEL_ICON; } - else // it is at the bottom of the scrollbar + + wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH, + client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2, + FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT); + + if ( flags & wxTOPLEVEL_BUTTON_CLOSE ) { - // so move it a bit up - *thumbStart = length - thumbMinWidth; - *thumbEnd = length; + if ( btnRect.Contains(pt) ) + return wxHT_TOPLEVEL_BUTTON_CLOSE; + btnRect.x -= FRAME_BUTTON_WIDTH + 2; } + if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE ) + { + if ( btnRect.Contains(pt) ) + return wxHT_TOPLEVEL_BUTTON_MAXIMIZE; + btnRect.x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_RESTORE ) + { + if ( btnRect.Contains(pt) ) + return wxHT_TOPLEVEL_BUTTON_RESTORE; + btnRect.x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_ICONIZE ) + { + if ( btnRect.Contains(pt) ) + return wxHT_TOPLEVEL_BUTTON_ICONIZE; + btnRect.x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_HELP ) + { + if ( btnRect.Contains(pt) ) + return wxHT_TOPLEVEL_BUTTON_HELP; + btnRect.x -= FRAME_BUTTON_WIDTH; + } + + if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT ) + return wxHT_TOPLEVEL_TITLEBAR; } -} -wxRect wxStdRenderer::GetScrollbarRect(const wxScrollBar *scrollbar, - wxScrollBar::Element elem, - int thumbPos) const -{ - if ( thumbPos == -1 ) + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) { - thumbPos = scrollbar->GetThumbPosition(); + // we are certainly at one of borders, let's decide which one: + + int border = 0; + // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined! + if ( pt.x < client.x ) + border |= wxHT_TOPLEVEL_BORDER_W; + else if ( pt.x >= client.width + client.x ) + border |= wxHT_TOPLEVEL_BORDER_E; + if ( pt.y < client.y ) + border |= wxHT_TOPLEVEL_BORDER_N; + else if ( pt.y >= client.height + client.y ) + border |= wxHT_TOPLEVEL_BORDER_S; + return border; } - const wxSize sizeArrow = GetScrollbarArrowSize(); + return wxHT_NOWHERE; +} - wxSize sizeTotal = scrollbar->GetClientSize(); - wxCoord *start, *width; - wxCoord length, arrow; - wxRect rect; - if ( scrollbar->IsVertical() ) +void wxStdRenderer::DrawFrameTitleBar(wxDC& dc, + const wxRect& rect, + const wxString& title, + const wxIcon& icon, + int flags, + int specialButton, + int specialButtonFlags) +{ + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) { - rect.x = 0; - rect.width = sizeTotal.x; - length = sizeTotal.y; - start = &rect.y; - width = &rect.height; - arrow = sizeArrow.y; + DrawFrameBorder(dc, rect, flags); } - else // horizontal + if ( flags & wxTOPLEVEL_TITLEBAR ) { - rect.y = 0; - rect.height = sizeTotal.y; - length = sizeTotal.x; - start = &rect.x; - width = &rect.width; - arrow = sizeArrow.x; + DrawFrameBackground(dc, rect, flags); + if ( flags & wxTOPLEVEL_ICON ) + DrawFrameIcon(dc, rect, icon, flags); + DrawFrameTitle(dc, rect, title, flags); + + wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + wxCoord x,y; + x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH; + y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2; + + if ( flags & wxTOPLEVEL_BUTTON_CLOSE ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE, + (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH + 2; + } + if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE, + (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_RESTORE ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE, + (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_ICONIZE ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE, + (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ? + specialButtonFlags : 0); + x -= FRAME_BUTTON_WIDTH; + } + if ( flags & wxTOPLEVEL_BUTTON_HELP ) + { + DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP, + (specialButton == wxTOPLEVEL_BUTTON_HELP) ? + specialButtonFlags : 0); + } } +} - switch ( elem ) - { - case wxScrollBar::Element_Arrow_Line_1: - *start = 0; - *width = arrow; - break; +void wxStdRenderer::DrawFrameBorder(wxDC& dc, const wxRect& rect, int flags) +{ + if ( !(flags & wxTOPLEVEL_BORDER) ) + return; - case wxScrollBar::Element_Arrow_Line_2: - *start = length - arrow; - *width = arrow; - break; + wxRect r(rect); - case wxScrollBar::Element_Arrow_Page_1: - case wxScrollBar::Element_Arrow_Page_2: - // we don't have them at all - break; + DrawAntiSunkenBorder(dc, &r); + DrawExtraBorder(dc, &r); + if ( flags & wxTOPLEVEL_RESIZEABLE ) + DrawExtraBorder(dc, &r); +} - 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 - { - GetScrollBarThumbSize(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; +void wxStdRenderer::DrawFrameBackground(wxDC& dc, const wxRect& rect, int flags) +{ + if ( !(flags & wxTOPLEVEL_TITLEBAR) ) + return; - case wxScrollBar::Element_Max: - default: - wxFAIL_MSG( _T("unknown scrollbar element") ); - } + wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE + ? wxColourScheme::TITLEBAR_ACTIVE + : wxColourScheme::TITLEBAR); - return rect; + wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + r.height = FRAME_TITLEBAR_HEIGHT; + + DrawBackground(dc, col, r); } -wxCoord wxStdRenderer::GetScrollbarSize(const wxScrollBar *scrollbar) +void wxStdRenderer::DrawFrameTitle(wxDC& dc, + const wxRect& rect, + const wxString& title, + int flags) { - const wxSize sizeArrowSB = GetScrollbarArrowSize(); - - wxCoord sizeArrow, sizeTotal; - if ( scrollbar->GetWindowStyle() & wxVERTICAL ) + wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE + ? wxColourScheme::TITLEBAR_ACTIVE_TEXT + : wxColourScheme::TITLEBAR_TEXT); + dc.SetTextForeground(col); + + wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + r.height = FRAME_TITLEBAR_HEIGHT; + if ( flags & wxTOPLEVEL_ICON ) { - sizeArrow = sizeArrowSB.y; - sizeTotal = scrollbar->GetSize().y; + r.x += FRAME_TITLEBAR_HEIGHT; + r.width -= FRAME_TITLEBAR_HEIGHT + 2; } - else // horizontal + else { - sizeArrow = sizeArrowSB.x; - sizeTotal = scrollbar->GetSize().x; + r.x += 1; + r.width -= 3; } - return sizeTotal - 2*sizeArrow; -} - -wxHitTest -wxStdRenderer::HitTestScrollbar(const wxScrollBar *scrollbar, const wxPoint& pt) const -{ - // 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) - const wxSize sizeArrowSB = GetScrollbarArrowSize(); - - wxCoord coord, sizeArrow, sizeTotal; - wxSize size = scrollbar->GetSize(); - if ( scrollbar->GetWindowStyle() & wxVERTICAL ) + if ( flags & wxTOPLEVEL_BUTTON_CLOSE ) + r.width -= FRAME_BUTTON_WIDTH + 2; + if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE ) + r.width -= FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_RESTORE ) + r.width -= FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_ICONIZE ) + r.width -= FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_HELP ) + r.width -= FRAME_BUTTON_WIDTH; + + dc.SetFont(m_titlebarFont); + + wxString s; + wxCoord textW; + dc.GetTextExtent(title, &textW, NULL); + if ( textW > r.width ) { - if ( pt.x < 0 || pt.x > size.x ) - return wxHT_NOWHERE; + // text is too big, let's shorten it and add "..." after it: + size_t len = title.length(); + wxCoord WSoFar, letterW; + + dc.GetTextExtent(wxT("..."), &WSoFar, NULL); + if ( WSoFar > r.width ) + { + // not enough space to draw anything + return; + } - coord = pt.y; - sizeArrow = sizeArrowSB.y; - sizeTotal = size.y; + s.Alloc(len); + for (size_t i = 0; i < len; i++) + { + dc.GetTextExtent(title[i], &letterW, NULL); + if ( letterW + WSoFar > r.width ) + break; + WSoFar += letterW; + s << title[i]; + } + s << wxT("..."); } - else // horizontal + else // no need to truncate the title { - if ( pt.y < 0 || pt.y > size.y ) - return wxHT_NOWHERE; - - coord = pt.x; - sizeArrow = sizeArrowSB.x; - sizeTotal = size.x; + s = title; } - // test for the arrows first as it's faster - if ( coord < 0 || coord > sizeTotal ) + dc.DrawLabel(s, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL); +} + +void wxStdRenderer::DrawFrameIcon(wxDC& dc, + const wxRect& rect, + const wxIcon& icon, + int flags) +{ + if ( icon.IsOk() ) { - return wxHT_NOWHERE; + wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + dc.DrawIcon(icon, r.x, r.y); } - else if ( coord < sizeArrow ) +} + +void wxStdRenderer::DrawFrameButton(wxDC& dc, + wxCoord x, wxCoord y, + int button, + int flags) +{ + FrameButtonType idx; + switch (button) { - return wxHT_SCROLLBAR_ARROW_LINE_1; + case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break; + case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break; + case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break; + case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break; + case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break; + default: + wxFAIL_MSG(wxT("incorrect button specification")); + return; } - else if ( coord > sizeTotal - sizeArrow ) + + wxBitmap bmp = GetFrameButtonBitmap(idx); + if ( !bmp.IsOk() ) + return; + + wxRect rectBtn(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT); + if ( flags & wxCONTROL_PRESSED ) { - return wxHT_SCROLLBAR_ARROW_LINE_2; + DrawSunkenBorder(dc, &rectBtn); + + rectBtn.Offset(1, 1); } 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 - { - GetScrollBarThumbSize(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; + DrawRaisedBorder(dc, &rectBtn); } + + DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rectBtn); + + wxRect rectBmp(0, 0, bmp.GetWidth(), bmp.GetHeight()); + dc.DrawBitmap(bmp, rectBmp.CentreIn(rectBtn).GetPosition(), true); } +int wxStdRenderer::GetFrameBorderWidth(int flags) const +{ + return flags & wxTOPLEVEL_RESIZEABLE ? 4 : 3; +} -wxCoord -wxStdRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar, int thumbPos) + +wxRect wxStdRenderer::GetFrameClientArea(const wxRect& rect, int flags) const { - int range = scrollbar->GetRange(); - if ( !range ) + wxRect r(rect); + + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) { - // the only valid position anyhow - return 0; + r.Inflate(-GetFrameBorderWidth(flags)); } - if ( thumbPos == -1 ) + if ( flags & wxTOPLEVEL_TITLEBAR ) { - // by default use the current thumb position - thumbPos = scrollbar->GetThumbPosition(); + r.y += FRAME_TITLEBAR_HEIGHT; + r.height -= FRAME_TITLEBAR_HEIGHT; } - const wxSize sizeArrow = GetScrollbarArrowSize(); - return (thumbPos*GetScrollbarSize(scrollbar)) / range - + (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x); + return r; } -int wxStdRenderer::PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord) +wxSize +wxStdRenderer::GetFrameTotalSize(const wxSize& clientSize, int flags) const { - const wxSize sizeArrow = GetScrollbarArrowSize(); - return ((coord - (scrollbar->IsVertical() ? sizeArrow.y : sizeArrow.x)) * - scrollbar->GetRange() ) / GetScrollbarSize(scrollbar); + wxSize s(clientSize); + + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) + { + s.IncBy(2*GetFrameBorderWidth(flags)); + } + + if ( flags & wxTOPLEVEL_TITLEBAR ) + s.y += FRAME_TITLEBAR_HEIGHT; + + return s; } -#endif // wxUSE_SCROLLBAR +wxSize wxStdRenderer::GetFrameMinSize(int flags) const +{ + wxSize s; + + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) + { + s.IncBy(2*GetFrameBorderWidth(flags)); + } + if ( flags & wxTOPLEVEL_TITLEBAR ) + { + s.y += FRAME_TITLEBAR_HEIGHT; + + if ( flags & wxTOPLEVEL_ICON ) + s.x += FRAME_TITLEBAR_HEIGHT + 2; + if ( flags & wxTOPLEVEL_BUTTON_CLOSE ) + s.x += FRAME_BUTTON_WIDTH + 2; + if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE ) + s.x += FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_RESTORE ) + s.x += FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_ICONIZE ) + s.x += FRAME_BUTTON_WIDTH; + if ( flags & wxTOPLEVEL_BUTTON_HELP ) + s.x += FRAME_BUTTON_WIDTH; + } + + return s; +} + +wxSize wxStdRenderer::GetFrameIconSize() const +{ + return wxSize(16, 16); +}