X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0428ac8c47bc42aef38f2b4a01ea3e7ded41bf0f..9fd8f2dd3df305448a0c2d56508c04e26385a76d:/src/univ/stdrend.cpp?ds=inline diff --git a/src/univ/stdrend.cpp b/src/univ/stdrend.cpp index 14e2395353..5a78545902 100644 --- a/src/univ/stdrend.cpp +++ b/src/univ/stdrend.cpp @@ -24,11 +24,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 +60,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); } // ---------------------------------------------------------------------------- @@ -148,9 +167,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.Ok()) + { + colBg = col; + } + else if (window) + { + colBg = m_scheme->GetBackground(window); + } + else + { + colBg = wxSCHEME_COLOUR(m_scheme, CONTROL); + } DrawSolidRect(dc, colBg, rect); } @@ -168,7 +198,8 @@ void wxStdRenderer::DrawButtonSurface(wxDC& dc, // text // ---------------------------------------------------------------------------- -void wxStdRenderer::DrawFocusRect(wxDC& dc, const wxRect& rect) +void +wxStdRenderer::DrawFocusRect(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 @@ -353,12 +384,22 @@ void wxStdRenderer::DrawAntiSunkenBorder(wxDC& dc, wxRect *rect) DrawShadedRect(dc, rect, m_penHighlight, m_penDarkGrey); } -void wxStdRenderer::DrawFrameBorder(wxDC& dc, wxRect *rect) +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, @@ -375,11 +416,11 @@ void wxStdRenderer::DrawBorder(wxDC& dc, case wxBORDER_DOUBLE: DrawAntiSunkenBorder(dc, &rect); - DrawRect(dc, &rect, m_penLightGrey); + DrawExtraBorder(dc, &rect); break; case wxBORDER_STATIC: - DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + DrawStaticBorder(dc, &rect); break; case wxBORDER_RAISED: @@ -441,11 +482,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, @@ -548,7 +602,7 @@ void wxStdRenderer::DrawFrame(wxDC& dc, } else // no label { - DrawFrameBorder(dc, &rectFrame); + DrawBoxBorder(dc, &rectFrame); } } @@ -569,14 +623,14 @@ 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(dc, rect, flags); } } @@ -1047,3 +1101,423 @@ int wxStdRenderer::PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord) #endif // wxUSE_SCROLLBAR +// ---------------------------------------------------------------------------- +// 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, + _T("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 +{ + return 2; +} + +wxSize wxStdRenderer::GetStatusBarFieldMargins() const +{ + return wxSize(2, 2); +} + +void wxStdRenderer::DrawStatusField(wxDC& dc, + const wxRect& rect, + const wxString& label, + int flags, + int style) +{ + wxRect rectIn; + + if ( style == wxSB_RAISED ) + DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn); + else if ( style != wxSB_FLAT ) + DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn); + + 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 ) + { + wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + + if ( flags & wxTOPLEVEL_ICON ) + { + if ( wxRect(client.GetPosition(), GetFrameIconSize()).Contains(pt) ) + return wxHT_TOPLEVEL_ICON; + } + + 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 ) + { + 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; + } + + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) + { + // 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; + } + + return wxHT_NOWHERE; +} + +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) ) + { + DrawFrameBorder(dc, rect, flags); + } + if ( flags & wxTOPLEVEL_TITLEBAR ) + { + 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); + } + } +} + +void wxStdRenderer::DrawFrameBorder(wxDC& dc, const wxRect& rect, int flags) +{ + if ( !(flags & wxTOPLEVEL_BORDER) ) + return; + + wxRect r(rect); + + DrawAntiSunkenBorder(dc, &r); + DrawExtraBorder(dc, &r); + if ( flags & wxTOPLEVEL_RESIZEABLE ) + DrawExtraBorder(dc, &r); +} + +void wxStdRenderer::DrawFrameBackground(wxDC& dc, const wxRect& rect, int flags) +{ + if ( !(flags & wxTOPLEVEL_TITLEBAR) ) + return; + + wxColour col = m_scheme->Get(flags & wxTOPLEVEL_ACTIVE + ? wxColourScheme::TITLEBAR_ACTIVE + : wxColourScheme::TITLEBAR); + + wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + r.height = FRAME_TITLEBAR_HEIGHT; + + DrawBackground(dc, col, r); +} + +void wxStdRenderer::DrawFrameTitle(wxDC& dc, + const wxRect& rect, + const wxString& title, + int flags) +{ + 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 ) + { + r.x += FRAME_TITLEBAR_HEIGHT; + r.width -= FRAME_TITLEBAR_HEIGHT + 2; + } + else + { + r.x += 1; + r.width -= 3; + } + + 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 ) + { + // 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; + } + + 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 // no need to truncate the title + { + s = title; + } + + 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.Ok() ) + { + wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR); + dc.DrawIcon(icon, r.x, r.y); + } +} + +void wxStdRenderer::DrawFrameButton(wxDC& dc, + wxCoord x, wxCoord y, + int button, + int flags) +{ + FrameButtonType idx; + switch (button) + { + 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; + } + + wxBitmap bmp = GetFrameButtonBitmap(idx); + if ( !bmp.Ok() ) + return; + + wxRect rectBtn(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT); + if ( flags & wxCONTROL_PRESSED ) + { + DrawSunkenBorder(dc, &rectBtn); + + rectBtn.Offset(1, 1); + } + else + { + 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; +} + + +wxRect wxStdRenderer::GetFrameClientArea(const wxRect& rect, int flags) const +{ + wxRect r(rect); + + if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) ) + { + r.Inflate(-GetFrameBorderWidth(flags)); + } + + if ( flags & wxTOPLEVEL_TITLEBAR ) + { + r.y += FRAME_TITLEBAR_HEIGHT; + r.height -= FRAME_TITLEBAR_HEIGHT; + } + + return r; +} + +wxSize +wxStdRenderer::GetFrameTotalSize(const wxSize& clientSize, int flags) const +{ + 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; +} + +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); +}