From 4dc12a1a28887acdab8e835e7c334ffc15b6e0a5 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 18 Aug 2000 19:05:02 +0000 Subject: [PATCH] added (half working) wxGTKRenderer git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8133 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/univ/button.h | 11 +- include/wx/univ/control.h | 22 +- include/wx/univ/renderer.h | 25 +- src/univ/button.cpp | 50 ++- src/univ/control.cpp | 26 +- src/univ/files.lst | 1 + src/univ/renderer.cpp | 24 +- src/univ/theme.cpp | 2 + src/univ/themes/gtk.cpp | 673 +++++++++++++++++++++++++++++++++++++ src/univ/themes/win32.cpp | 20 ++ 10 files changed, 818 insertions(+), 36 deletions(-) create mode 100644 src/univ/themes/gtk.cpp diff --git a/include/wx/univ/button.h b/include/wx/univ/button.h index 6712add26d..10605c5c8e 100644 --- a/include/wx/univ/button.h +++ b/include/wx/univ/button.h @@ -22,7 +22,10 @@ class WXDLLEXPORT wxInputHandler; // the actions supported by this control // ---------------------------------------------------------------------------- -#define wxACTION_BUTTON_TOGGLE _T("toggle") // press/release the button +#define wxACTION_BUTTON_TOGGLE _T("toggle") // press/release the button +#define wxACTION_BUTTON_PRESS _T("press") // press the button +#define wxACTION_BUTTON_RELEASE _T("release") // release the button +#define wxACTION_BUTTON_CLICK _T("click") // generate button click event // ---------------------------------------------------------------------------- // wxButton: a push button @@ -62,6 +65,12 @@ public: virtual bool IsPressed() const { return m_isPressed; } virtual bool IsDefault() const { return m_isDefault; } + // wxButton actions + void Press(); + void Release(); + void Toggle(); + void Click(); + protected: virtual wxInputHandler *CreateInputHandler() const; virtual bool PerformAction(const wxControlAction& action); diff --git a/include/wx/univ/control.h b/include/wx/univ/control.h index a106ebb716..d9cbd101e2 100644 --- a/include/wx/univ/control.h +++ b/include/wx/univ/control.h @@ -26,8 +26,12 @@ class WXDLLEXPORT wxInputHandler; typedef wxString wxControlAction; -// no action to perform (other actions are defined in the controls headers) -#define wxACTION_NONE _T("") +// the list of actions which apply to all controls (other actions are defined +// in the controls headers) + +#define wxACTION_NONE _T("") // no action to perform +#define wxACTION_HIGHLIGHT _T("focus") // highlight the control +#define wxACTION_UNHIGHLIGHT _T("unfocus") // remove highlight // ---------------------------------------------------------------------------- // wxControl: the base class for all GUI controls @@ -36,7 +40,7 @@ typedef wxString wxControlAction; class WXDLLEXPORT wxControl : public wxControlBase { public: - wxControl(); + wxControl() { Init(); } wxControl(wxWindow *parent, wxWindowID id, @@ -45,6 +49,8 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxControlNameStr) { + Init(); + Create(parent, id, pos, size, style, validator, name); } @@ -62,9 +68,13 @@ public: // get the state information virtual bool IsFocused() const; + virtual bool IsHighlighted() const; virtual bool IsPressed() const; virtual bool IsDefault() const; + // operations + void Highlight(bool doit = TRUE); + // implementation only from now on // return the index of the accel char in the label or -1 if none @@ -94,6 +104,9 @@ protected: void OnPaint(wxPaintEvent& event); private: + // common part of all ctors + void Init(); + // input processor wxInputHandler *m_handler; @@ -101,6 +114,9 @@ private: wxString m_label; int m_indexAccel; + // state + bool m_isHighlighted; + DECLARE_DYNAMIC_CLASS(wxControl) DECLARE_EVENT_TABLE() }; diff --git a/include/wx/univ/renderer.h b/include/wx/univ/renderer.h index cf5af17d6c..3f854377e1 100644 --- a/include/wx/univ/renderer.h +++ b/include/wx/univ/renderer.h @@ -36,12 +36,13 @@ class WXDLLEXPORT wxWindow; // control state flags used in wxRenderer enum { - wxRENDER_ENABLED = 0x00000001, - wxRENDER_FOCUSED = 0x00000002, - wxRENDER_PRESSED = 0x00000004, - wxRENDER_DEFAULT = 0x00000008, // button... + wxRENDER_ENABLED = 0x00000001, + wxRENDER_FOCUSED = 0x00000002, + wxRENDER_PRESSED = 0x00000004, + wxRENDER_DEFAULT = 0x00000008, // button... + wxRENDER_HIGHLIGHT = 0x00000010, - wxRENDER_FLAGS_MASK = 0x0000000f + wxRENDER_FLAGS_MASK = 0x0000001f }; // ---------------------------------------------------------------------------- @@ -51,6 +52,12 @@ enum class WXDLLEXPORT wxRenderer { public: + // draw the controls background + virtual void DrawBackground(wxDC& dc, + const wxColour& col, + const wxRect& rect, + int flags) = 0; + // draw the label inside the given rectangle with the specified alignment // and optionally emphasize the character with the given index virtual void DrawLabel(wxDC& dc, @@ -107,6 +114,11 @@ class WXDLLEXPORT wxDelegateRenderer : public wxRenderer public: wxDelegateRenderer(wxRenderer *renderer) : m_renderer(renderer) { } + virtual void DrawBackground(wxDC& dc, + const wxColour& col, + const wxRect& rect, + int flags) + { m_renderer->DrawBackground(dc, col, rect, flags); } virtual void DrawLabel(wxDC& dc, const wxString& label, const wxRect& rect, @@ -169,9 +181,6 @@ protected: // the current window state int GetStateFlags() const; - // paint the control background - void PaintBackground(); - private: wxControl *m_ctrl; wxRenderer *m_renderer; diff --git a/src/univ/button.cpp b/src/univ/button.cpp index 695ef2fd3d..ba1edc49ea 100644 --- a/src/univ/button.cpp +++ b/src/univ/button.cpp @@ -123,18 +123,50 @@ wxInputHandler *wxButton::CreateInputHandler() const return wxTheme::Get()->GetInputHandler(wxCONTROL_BUTTON); } +void wxButton::Press() +{ + m_isPressed = TRUE; +} + +void wxButton::Release() +{ + m_isPressed = FALSE; +} + +void wxButton::Toggle() +{ + m_isPressed = !m_isPressed; + + if ( !m_isPressed ) + { + // releasing button after it had been pressed generates a click event + Click(); + } +} + +void wxButton::Click() +{ + wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); + InitCommandEvent(event); + Command(event); +} + bool wxButton::PerformAction(const wxControlAction& action) { - if ( action == wxACTION_BUTTON_TOGGLE ) - { - m_isPressed = !m_isPressed; - } - else - { - return wxControl::PerformAction(action); - } + bool wasPressed = IsPressed(); - return TRUE; + if ( action == wxACTION_BUTTON_TOGGLE ) + Toggle(); + else if ( action == wxACTION_BUTTON_CLICK ) + Click(); + else if ( action == wxACTION_BUTTON_PRESS ) + Press(); + else if ( action == wxACTION_BUTTON_RELEASE ) + Release(); + else + return wxControl::PerformAction(action); + + return wasPressed != IsPressed(); } // ---------------------------------------------------------------------------- diff --git a/src/univ/control.cpp b/src/univ/control.cpp index 5e1e99881c..435a68a705 100644 --- a/src/univ/control.cpp +++ b/src/univ/control.cpp @@ -64,9 +64,10 @@ END_EVENT_TABLE() // creation // ---------------------------------------------------------------------------- -wxControl::wxControl() +void wxControl::Init() { m_indexAccel = -1; + m_isHighlighted = FALSE; } bool wxControl::Create(wxWindow *parent, @@ -107,6 +108,16 @@ bool wxControl::IsDefault() const return FALSE; } +bool wxControl::IsHighlighted() const +{ + return m_isHighlighted; +} + +void wxControl::Highlight(bool doit) +{ + m_isHighlighted = doit; +} + // ---------------------------------------------------------------------------- // mnemonics handling // ---------------------------------------------------------------------------- @@ -209,8 +220,17 @@ void wxControl::OnMouse(wxMouseEvent& event) bool wxControl::PerformAction(const wxControlAction& action) { - // nothing to do - return FALSE; + if ( (action == wxACTION_NONE) || !AcceptsFocus() ) + return FALSE; + + if ( action == wxACTION_HIGHLIGHT ) + Highlight(TRUE); + else if ( action == wxACTION_UNHIGHLIGHT ) + Highlight(FALSE); + else + return FALSE; + + return TRUE; } #endif // wxUSE_CONTROLS diff --git a/src/univ/files.lst b/src/univ/files.lst index 903b09d45a..6ee1692c1a 100644 --- a/src/univ/files.lst +++ b/src/univ/files.lst @@ -6,6 +6,7 @@ UNIVOBJS = \ statbox.o \ stattext.o \ theme.o \ + gtk.o \ win32.o # winuniv.o diff --git a/src/univ/renderer.cpp b/src/univ/renderer.cpp index 4adab5f4ff..27c03968fc 100644 --- a/src/univ/renderer.cpp +++ b/src/univ/renderer.cpp @@ -73,6 +73,8 @@ int wxControlRenderer::GetStateFlags() const // it is not, even our default/focused controls shouldn't appear as such if ( wxTheApp->IsActive() ) { + if ( m_ctrl->IsHighlighted() ) + flags |= wxRENDER_HIGHLIGHT; if ( m_ctrl->IsFocused() ) flags |= wxRENDER_FOCUSED; if ( m_ctrl->IsPressed() ) @@ -84,22 +86,17 @@ int wxControlRenderer::GetStateFlags() const return flags; } -void wxControlRenderer::PaintBackground() -{ - wxBrush brush(m_ctrl->GetBackgroundColour(), wxSOLID); - m_dc.SetBrush(brush); - m_dc.SetPen(*wxTRANSPARENT_PEN); - m_dc.DrawRectangle(m_rect); -} - void wxControlRenderer::DrawBorder() { + int flags = GetStateFlags(); + // draw outline m_renderer->DrawBorder(m_dc, m_ctrl->GetBorder(), - m_rect, GetStateFlags(), &m_rect); + m_rect, flags, &m_rect); // fill the inside - PaintBackground(); + m_renderer->DrawBackground(m_dc, + m_ctrl->GetBackgroundColour(), m_rect, flags); } void wxControlRenderer::DrawLabel() @@ -139,7 +136,10 @@ void wxControlRenderer::DrawFrame() void wxControlRenderer::DrawButtonBorder() { - m_renderer->DrawButtonBorder(m_dc, m_rect, GetStateFlags(), &m_rect); + int flags = GetStateFlags(); - PaintBackground(); + m_renderer->DrawButtonBorder(m_dc, m_rect, flags, &m_rect); + + m_renderer->DrawBackground(m_dc, m_ctrl->GetBackgroundColour(), + m_rect, flags); } diff --git a/src/univ/theme.cpp b/src/univ/theme.cpp index ef1869f48b..6d7be99f04 100644 --- a/src/univ/theme.cpp +++ b/src/univ/theme.cpp @@ -85,6 +85,8 @@ wxTheme::wxThemeInfo::wxThemeInfo(wxTheme::Constructor c, #if defined(__WXMSW__) ms_theme = Create(_T("win32")); +#elif defined(__WXGTK__) + ms_theme = Create(_T("gtk")); #endif // fallback to the first one in the list diff --git a/src/univ/themes/gtk.cpp b/src/univ/themes/gtk.cpp new file mode 100644 index 0000000000..c506a74538 --- /dev/null +++ b/src/univ/themes/gtk.cpp @@ -0,0 +1,673 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: univ/themes/gtk.cpp +// Purpose: wxUniversal theme implementing GTK-like LNF +// Author: Vadim Zeitlin +// Modified by: +// Created: 06.08.00 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +// =========================================================================== +// declarations +// =========================================================================== + +// --------------------------------------------------------------------------- +// headers +// --------------------------------------------------------------------------- + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/intl.h" + #include "wx/button.h" + #include "wx/dc.h" + #include "wx/window.h" +#endif // WX_PRECOMP + +#include "wx/univ/renderer.h" +#include "wx/univ/inphand.h" +#include "wx/univ/theme.h" + +// ---------------------------------------------------------------------------- +// wxGTKRenderer: draw the GUI elements in GTK style +// ---------------------------------------------------------------------------- + +class wxGTKRenderer : public wxRenderer +{ +public: + wxGTKRenderer(); + + // implement the base class pure virtuals + virtual void DrawBackground(wxDC& dc, + const wxColour& col, + const wxRect& rect, + int flags); + virtual void DrawLabel(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + int alignment = wxALIGN_LEFT | wxALIGN_TOP, + int indexAccel = -1); + virtual void DrawBorder(wxDC& dc, + wxBorder border, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + wxRect *rectIn = (wxRect *)NULL); + virtual void DrawFrame(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + int alignment = wxALIGN_LEFT, + int indexAccel = -1); + virtual void DrawButtonBorder(wxDC& dc, + const wxRect& rect, + int flags = wxRENDER_ENABLED, + wxRect *rectIn = (wxRect *)NULL); + + virtual void AdjustSize(wxSize *size, const wxWindow *window); + +protected: + // DrawBorder() helpers: all of them shift and clip the DC after drawing + // the border + + // just draw a rectangle with the given pen + void DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen); + + // draw the lower left part of rectangle + void DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen); + + // draw the rectange using the first brush for the left and top sides and + // the second one for the bottom and right ones + void DrawShadedRect(wxDC& dc, wxRect *rect, + const wxPen& pen1, const wxPen& pen2); + + // as DrawShadedRect() but the pixels in the bottom left and upper right + // border are drawn with the pen1, not pen2 + void DrawAntiShadedRect(wxDC& dc, wxRect *rect, + const wxPen& pen1, const wxPen& pen2); + + // draw the normal 3D border + void DrawRaisedBorder(wxDC& dc, wxRect *rect); + +private: + wxPen m_penBlack, + m_penDarkGrey, + m_penLightGrey, + m_penWhite, + m_penHighlight; +}; + +// ---------------------------------------------------------------------------- +// wxGTKInputHandler and derived classes: process the keyboard and mouse +// messages according to GTK standards +// ---------------------------------------------------------------------------- + +class wxGTKInputHandler : public wxInputHandler +{ +public: + virtual wxControlAction Map(const wxKeyEvent& event, bool pressed); + virtual wxControlAction Map(const wxMouseEvent& event); +}; + +class wxGTKButtonInputHandler : public wxGTKInputHandler +{ +public: + wxGTKButtonInputHandler(); + + virtual wxControlAction Map(const wxKeyEvent& event, bool pressed); + virtual wxControlAction Map(const wxMouseEvent& event); + +private: + wxWindow *m_winCapture; +}; + +// ---------------------------------------------------------------------------- +// wxGTKColourScheme +// ---------------------------------------------------------------------------- + +class wxGTKColourScheme : public wxColourScheme +{ +}; + +// ---------------------------------------------------------------------------- +// wxGTKTheme +// ---------------------------------------------------------------------------- + +WX_DEFINE_ARRAY(wxInputHandler *, wxArrayHandlers); + +class wxGTKTheme : public wxTheme +{ +public: + wxGTKTheme(); + virtual ~wxGTKTheme(); + + virtual wxRenderer *GetRenderer() { return m_renderer; } + virtual wxInputHandler *GetInputHandler(const wxString& control); + virtual wxColourScheme *GetColourScheme() { return m_scheme; } + +private: + wxGTKRenderer *m_renderer; + + // the names of the already created handlers and the handlers themselves + // (these arrays are synchronized) + wxSortedArrayString m_handlerNames; + wxArrayHandlers m_handlers; + + wxGTKColourScheme *m_scheme; + + WX_DECLARE_THEME(); +}; + +// ============================================================================ +// implementation +// ============================================================================ + +WX_IMPLEMENT_THEME(wxGTKTheme, gtk, wxTRANSLATE("GTK+ theme")); + +// ---------------------------------------------------------------------------- +// wxGTKTheme +// ---------------------------------------------------------------------------- + +wxGTKTheme::wxGTKTheme() +{ + m_renderer = new wxGTKRenderer; + m_scheme = NULL; +} + +wxGTKTheme::~wxGTKTheme() +{ + WX_CLEAR_ARRAY(m_handlers); +} + +wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control) +{ + wxInputHandler *handler; + int n = m_handlerNames.Index(control); + if ( n == wxNOT_FOUND ) + { + // create a new handler + n = m_handlerNames.Add(control); + + if ( control == wxCONTROL_BUTTON ) + handler = new wxGTKButtonInputHandler; + else + { + wxASSERT_MSG( control == wxCONTROL_DEFAULT, + _T("no input handler defined for this control") ); + + handler = new wxGTKInputHandler; + } + + m_handlers.Insert(handler, n); + } + else // we already have it + { + handler = m_handlers[n]; + } + + return handler; +} + +// ============================================================================ +// wxGTKRenderer +// ============================================================================ + +// ---------------------------------------------------------------------------- +// construction +// ---------------------------------------------------------------------------- + +wxGTKRenderer::wxGTKRenderer() + : m_penBlack(*wxBLACK_PEN), + m_penDarkGrey(wxColour(0x7f7f7f), 0, wxSOLID), + m_penLightGrey(wxColour(0xc0c0c0), 0, wxSOLID), + m_penWhite(*wxWHITE_PEN), + m_penHighlight(wxColour(0xe0e0e0), 0, wxSOLID) +{ +} + +// ---------------------------------------------------------------------------- +// border stuff +// ---------------------------------------------------------------------------- + +/* + The raised border in GTK looks like this: + + IIIIIIIIIIIIIIIIIIIIIIB + I GB + I GB I = white (HILIGHT) + I GB H = light grey (LIGHT) + I GB G = dark grey (SHADOI) + I GB B = black (DKSHADOI) + I GB I = hIghlight (COLOR_3DHILIGHT) + I GB + IGGGGGGGGGGGGGGGGGGGGGB + BBBBBBBBBBBBBBBBBBBBBBB + + The sunken border looks like this: + + GGGGGGGGGGGGGGGGGGGGGGI + GBBBBBBBBBBBBBBBBBBBBHI + GB HI + GB HI + GB HI + GB HI + GB HI + GB HI + GHHHHHHHHHHHHHHHHHHHHHI + IIIIIIIIIIIIIIIIIIIIIII + + The static border (used for the controls which don't get focus) is like + this: + + GGGGGGGGGGGGGGGGGGGGGGW + G W + G W + G W + G W + G W + G W + G W + WWWWWWWWWWWWWWWWWWWWWWW + + The most complicated is the double border: + + HHHHHHHHHHHHHHHHHHHHHHB + HWWWWWWWWWWWWWWWWWWWWGB + HWHHHHHHHHHHHHHHHHHHHGB + HWH HGB + HWH HGB + HWH HGB + HWH HGB + HWHHHHHHHHHHHHHHHHHHHGB + HGGGGGGGGGGGGGGGGGGGGGB + BBBBBBBBBBBBBBBBBBBBBBB + + And the simple border is, well, simple: + + BBBBBBBBBBBBBBBBBBBBBBB + B B + B B + B B + B B + B B + B B + B B + B B + BBBBBBBBBBBBBBBBBBBBBBB +*/ + +void wxGTKRenderer::DrawRect(wxDC& dc, wxRect *rect, const wxPen& pen) +{ + // draw + dc.SetPen(pen); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(*rect); + + // adjust the rect + rect->Inflate(-1); +} + +void wxGTKRenderer::DrawHalfRect(wxDC& dc, wxRect *rect, const wxPen& pen) +{ + // draw the bottom and right sides + dc.SetPen(pen); + dc.DrawLine(rect->GetLeft(), rect->GetBottom(), + rect->GetRight() + 1, rect->GetBottom()); + dc.DrawLine(rect->GetRight(), rect->GetTop(), + rect->GetRight(), rect->GetBottom()); + + // adjust the rect + rect->width--; + rect->height--; +} + +void wxGTKRenderer::DrawShadedRect(wxDC& dc, wxRect *rect, + const wxPen& pen1, const wxPen& pen2) +{ + // draw the rectangle + dc.SetPen(pen1); + dc.DrawLine(rect->GetLeft(), rect->GetTop(), + rect->GetLeft(), rect->GetBottom()); + dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(), + rect->GetRight(), rect->GetTop()); + dc.SetPen(pen2); + dc.DrawLine(rect->GetRight(), rect->GetTop(), + rect->GetRight(), rect->GetBottom()); + dc.DrawLine(rect->GetLeft(), rect->GetBottom(), + rect->GetRight() + 1, rect->GetBottom()); + + // adjust the rect + rect->Inflate(-1); +} + +void wxGTKRenderer::DrawAntiShadedRect(wxDC& dc, wxRect *rect, + const wxPen& pen1, const wxPen& pen2) +{ + // draw the rectangle + dc.SetPen(pen1); + dc.DrawLine(rect->GetLeft(), rect->GetTop(), + rect->GetLeft(), rect->GetBottom() + 1); + dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(), + rect->GetRight() + 1, rect->GetTop()); + dc.SetPen(pen2); + dc.DrawLine(rect->GetRight(), rect->GetTop() + 1, + rect->GetRight(), rect->GetBottom()); + dc.DrawLine(rect->GetLeft() + 1, rect->GetBottom(), + rect->GetRight() + 1, rect->GetBottom()); + + // adjust the rect + rect->Inflate(-1); +} + +void wxGTKRenderer::DrawRaisedBorder(wxDC& dc, wxRect *rect) +{ + DrawShadedRect(dc, rect, m_penHighlight, m_penBlack); + DrawShadedRect(dc, rect, m_penLightGrey, m_penDarkGrey); +} + +void wxGTKRenderer::DrawBorder(wxDC& dc, + wxBorder border, + const wxRect& rectTotal, + int WXUNUSED(flags), + wxRect *rectIn) +{ + wxRect rect = rectTotal; + + switch ( border ) + { + case wxBORDER_SUNKEN: + DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey); + break; + + case wxBORDER_STATIC: + DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + break; + + case wxBORDER_RAISED: + DrawRaisedBorder(dc, &rect); + break; + + case wxBORDER_DOUBLE: + DrawShadedRect(dc, &rect, m_penLightGrey, m_penBlack); + DrawShadedRect(dc, &rect, m_penHighlight, m_penDarkGrey); + DrawRect(dc, &rect, m_penLightGrey); + break; + + case wxBORDER_SIMPLE: + DrawRect(dc, &rect, m_penBlack); + break; + + default: + wxFAIL_MSG(_T("unknwon border type")); + // fall through + + case wxBORDER_DEFAULT: + case wxBORDER_NONE: + break; + } + + if ( rectIn ) + *rectIn = rect; +} + +// ---------------------------------------------------------------------------- +// button border +// ---------------------------------------------------------------------------- + +void wxGTKRenderer::DrawButtonBorder(wxDC& dc, + const wxRect& rectTotal, + int flags, + wxRect *rectIn) +{ + wxRect rect = rectTotal; + + if ( flags & wxRENDER_PRESSED ) + { + // button pressed: draw a black border around it and an inward shade + DrawRect(dc, &rect, m_penBlack); + DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + DrawAntiShadedRect(dc, &rect, m_penBlack, m_penDarkGrey); + } + else + { + // button not pressed + + if ( flags & wxRENDER_DEFAULT ) + { + // button is currently default: add an extra border around it + DrawRect(dc, &rect, m_penBlack); + } + + // now draw a normal button + DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack); + DrawAntiShadedRect(dc, &rect, + flags & wxRENDER_HIGHLIGHT ? m_penHighlight + : m_penLightGrey, + m_penDarkGrey); + } + + if ( rectIn ) + { + *rectIn = rect; + } +} + +// ---------------------------------------------------------------------------- +// frame +// ---------------------------------------------------------------------------- + +void wxGTKRenderer::DrawFrame(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags, + int alignment, + int indexAccel) +{ + wxCoord height = 0; // of the label + wxRect rectFrame = rect; + if ( !label.empty() ) + { + // the text should touch the top border of the rect, so the frame + // itself should be lower + dc.GetTextExtent(label, NULL, &height); + rectFrame.y += height / 2; + rectFrame.height -= height / 2; + } + + // draw the frame + DrawShadedRect(dc, &rectFrame, m_penDarkGrey, m_penHighlight); + DrawShadedRect(dc, &rectFrame, m_penHighlight, m_penDarkGrey); + + // and overwrite it with label (if any) + if ( !label.empty() ) + { + // TODO: the +5 and space insertion should be customizable + + wxRect rectText; + rectText.x = rectFrame.x + 5; + rectText.y = rect.y; + rectText.width = rectFrame.width - 7; // +2 border width + rectText.height = height; + + wxString label2; + label2 << _T(' ') << label << _T(' '); + if ( indexAccel != -1 ) + { + // adjust it as we prepended a space + indexAccel++; + } + + dc.SetBackgroundMode(wxSOLID); + DrawLabel(dc, label2, rectText, flags, alignment, indexAccel); + dc.SetBackgroundMode(wxTRANSPARENT); + } +} + +// ---------------------------------------------------------------------------- +// label +// ---------------------------------------------------------------------------- + +void wxGTKRenderer::DrawLabel(wxDC& dc, + const wxString& label, + const wxRect& rect, + int flags, + int alignment, + int indexAccel) +{ + if ( !(flags & wxRENDER_ENABLED) ) + { + // make the text grey and draw a shade for it + dc.SetTextForeground(0xe0e0e0); + wxRect rectShadow = rect; + rectShadow.x++; + rectShadow.y++; + dc.DrawLabel(label, rectShadow, alignment, indexAccel); + dc.SetTextForeground(0x7f7f7f); + } + + dc.DrawLabel(label, rect, alignment, indexAccel); +} + +// ---------------------------------------------------------------------------- +// background +// ---------------------------------------------------------------------------- + +void wxGTKRenderer::DrawBackground(wxDC& dc, + const wxColour& col, + const wxRect& rect, + int flags) +{ + // what colour should we use? + wxColour colBg; + if ( flags & wxRENDER_PRESSED ) + { + colBg = wxColour(0x7f7f7f); + } + else if ( flags & wxRENDER_HIGHLIGHT ) + { + colBg = wxColour(0xe0e0e0); + } + else + { + colBg = col; + } + + wxBrush brush(colBg, wxSOLID); + dc.SetBrush(brush); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(rect); +} + +// ---------------------------------------------------------------------------- +// size adjustments +// ---------------------------------------------------------------------------- + +void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window) +{ + if ( wxDynamicCast(window, wxButton) ) + { + // TODO + size->x += 3*window->GetCharWidth(); + size->y = (11*(window->GetCharHeight() + 8))/10; + } + else + { + // take into account the border width + wxBorder border = (wxBorder)(window->GetWindowStyle() & wxBORDER_MASK); + switch ( border ) + { + case wxBORDER_SUNKEN: + case wxBORDER_RAISED: + size->x += 4; + size->y += 4; + break; + + case wxBORDER_SIMPLE: + case wxBORDER_STATIC: + size->x += 2; + size->y += 2; + break; + + case wxBORDER_DOUBLE: + size->x += 6; + size->y += 6; + break; + + default: + wxFAIL_MSG(_T("unknwon border type")); + // fall through + + case wxBORDER_DEFAULT: + case wxBORDER_NONE: + break; + } + } +} + +// ============================================================================ +// wxInputHandler +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxGTKInputHandler +// ---------------------------------------------------------------------------- + +wxControlAction wxGTKInputHandler::Map(const wxKeyEvent& event, bool pressed) +{ + return wxACTION_NONE; +} + +wxControlAction wxGTKInputHandler::Map(const wxMouseEvent& event) +{ + if ( event.Entering() ) + return wxACTION_HIGHLIGHT; + else if ( event.Leaving() ) + return wxACTION_UNHIGHLIGHT; + + return wxACTION_NONE; +} + +// ---------------------------------------------------------------------------- +// wxGTKButtonInputHandler +// ---------------------------------------------------------------------------- + +wxGTKButtonInputHandler::wxGTKButtonInputHandler() +{ + m_winCapture = NULL; +} + +wxControlAction wxGTKButtonInputHandler::Map(const wxKeyEvent& event, + bool pressed) +{ + int keycode = event.GetKeyCode(); + if ( keycode == WXK_SPACE || keycode == WXK_RETURN ) + { + return wxACTION_BUTTON_TOGGLE; + } + + return wxGTKInputHandler::Map(event, pressed); +} + +wxControlAction wxGTKButtonInputHandler::Map(const wxMouseEvent& event) +{ + if ( event.IsButton() ) + { + return wxACTION_BUTTON_TOGGLE; + } +#if 0 // TODO + else if ( event.Leaving() ) + { + return wxACTION_BUTTON_RELEASE; + } +#endif // 0 + + return wxGTKInputHandler::Map(event); +} diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index a76f85620a..58866fe6dd 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -45,6 +45,10 @@ public: wxWin32Renderer(); // implement the base class pure virtuals + virtual void DrawBackground(wxDC& dc, + const wxColour& col, + const wxRect& rect, + int flags); virtual void DrawLabel(wxDC& dc, const wxString& label, const wxRect& rect, @@ -543,6 +547,22 @@ void wxWin32Renderer::DrawLabel(wxDC& dc, } } +// ---------------------------------------------------------------------------- +// background +// ---------------------------------------------------------------------------- + +void wxWin32Renderer::DrawBackground(wxDC& dc, + const wxColour& col, + const wxRect& rect, + int flags) +{ + // just fill it with the current colour + wxBrush brush(col, wxSOLID); + dc.SetBrush(brush); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(rect); +} + // ---------------------------------------------------------------------------- // size adjustments // ----------------------------------------------------------------------------