diff --git a/include/wx/gtk/radiobox.h b/include/wx/gtk/radiobox.h index d7805a70ca..c12ad7ba9e 100644 --- a/include/wx/gtk/radiobox.h +++ b/include/wx/gtk/radiobox.h @@ -15,27 +15,8 @@ #pragma interface #endif -#include "wx/defs.h" - -#if wxUSE_RADIOBOX - -#include "wx/object.h" -#include "wx/list.h" -#include "wx/control.h" #include "wx/bitmap.h" -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxRadioBox; - -//----------------------------------------------------------------------------- -// global data -//----------------------------------------------------------------------------- - -extern const char *wxRadioBoxNameStr; - //----------------------------------------------------------------------------- // wxRadioBox //----------------------------------------------------------------------------- @@ -131,6 +112,4 @@ private: DECLARE_DYNAMIC_CLASS(wxRadioBox) }; -#endif - #endif // __GTKRADIOBOXH__ diff --git a/include/wx/gtk/radiobut.h b/include/wx/gtk/radiobut.h index 9435869fee..5014526385 100644 --- a/include/wx/gtk/radiobut.h +++ b/include/wx/gtk/radiobut.h @@ -15,26 +15,6 @@ #pragma interface #endif -#include "wx/defs.h" - -#if wxUSE_RADIOBOX - -#include "wx/object.h" -#include "wx/list.h" -#include "wx/control.h" - -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxRadioButton; - -//----------------------------------------------------------------------------- -// data -//----------------------------------------------------------------------------- - -extern const char* wxRadioButtonNameStr; - //----------------------------------------------------------------------------- // wxRadioButton //----------------------------------------------------------------------------- @@ -77,6 +57,4 @@ private: DECLARE_DYNAMIC_CLASS(wxRadioButton) }; -#endif - #endif // __GTKRADIOBUTTONH__ diff --git a/include/wx/gtk1/radiobox.h b/include/wx/gtk1/radiobox.h index d7805a70ca..c12ad7ba9e 100644 --- a/include/wx/gtk1/radiobox.h +++ b/include/wx/gtk1/radiobox.h @@ -15,27 +15,8 @@ #pragma interface #endif -#include "wx/defs.h" - -#if wxUSE_RADIOBOX - -#include "wx/object.h" -#include "wx/list.h" -#include "wx/control.h" #include "wx/bitmap.h" -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxRadioBox; - -//----------------------------------------------------------------------------- -// global data -//----------------------------------------------------------------------------- - -extern const char *wxRadioBoxNameStr; - //----------------------------------------------------------------------------- // wxRadioBox //----------------------------------------------------------------------------- @@ -131,6 +112,4 @@ private: DECLARE_DYNAMIC_CLASS(wxRadioBox) }; -#endif - #endif // __GTKRADIOBOXH__ diff --git a/include/wx/gtk1/radiobut.h b/include/wx/gtk1/radiobut.h index 9435869fee..5014526385 100644 --- a/include/wx/gtk1/radiobut.h +++ b/include/wx/gtk1/radiobut.h @@ -15,26 +15,6 @@ #pragma interface #endif -#include "wx/defs.h" - -#if wxUSE_RADIOBOX - -#include "wx/object.h" -#include "wx/list.h" -#include "wx/control.h" - -//----------------------------------------------------------------------------- -// classes -//----------------------------------------------------------------------------- - -class wxRadioButton; - -//----------------------------------------------------------------------------- -// data -//----------------------------------------------------------------------------- - -extern const char* wxRadioButtonNameStr; - //----------------------------------------------------------------------------- // wxRadioButton //----------------------------------------------------------------------------- @@ -77,6 +57,4 @@ private: DECLARE_DYNAMIC_CLASS(wxRadioButton) }; -#endif - #endif // __GTKRADIOBUTTONH__ diff --git a/include/wx/msw/radiobox.h b/include/wx/msw/radiobox.h index 115be65e20..58d86f40bc 100644 --- a/include/wx/msw/radiobox.h +++ b/include/wx/msw/radiobox.h @@ -16,12 +16,6 @@ #pragma interface "radiobox.h" #endif -#if wxUSE_RADIOBOX - -#include "wx/control.h" - -WXDLLEXPORT_DATA(extern const wxChar*) wxRadioBoxNameStr; - class WXDLLEXPORT wxBitmap; class WXDLLEXPORT wxRadioBox : public wxControl @@ -126,7 +120,5 @@ protected: virtual wxSize DoGetBestSize() const; }; -#endif // wxUSE_RADIOBOX - #endif // _WX_RADIOBOX_H_ diff --git a/include/wx/msw/radiobut.h b/include/wx/msw/radiobut.h index b0d96d99f1..d9c6c8afd2 100644 --- a/include/wx/msw/radiobut.h +++ b/include/wx/msw/radiobut.h @@ -16,12 +16,6 @@ #pragma interface "radiobut.h" #endif -#if wxUSE_RADIOBTN - -#include "wx/control.h" - -WXDLLEXPORT_DATA(extern const wxChar*) wxRadioButtonNameStr; - class WXDLLEXPORT wxRadioButton: public wxControl { DECLARE_DYNAMIC_CLASS(wxRadioButton) @@ -56,7 +50,5 @@ class WXDLLEXPORT wxRadioButton: public wxControl void Command(wxCommandEvent& event); }; -#endif // wxUSE_RADIOBTN - #endif // _WX_RADIOBUT_H_ diff --git a/include/wx/radiobox.h b/include/wx/radiobox.h index dc4b1df2ab..7b293a44ca 100644 --- a/include/wx/radiobox.h +++ b/include/wx/radiobox.h @@ -1,21 +1,40 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/radiobox.h +// Purpose: wxRadioBox declaration +// Author: Vadim Zeitlin +// Modified by: +// Created: 10.09.00 +// RCS-ID: $Id$ +// Copyright: (c) wxWindows team +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + #ifndef _WX_RADIOBOX_H_BASE_ #define _WX_RADIOBOX_H_BASE_ +#if wxUSE_RADIOBOX + +#include "wx/control.h" + +WXDLLEXPORT_DATA(extern const wxChar*) wxRadioBoxNameStr; + #if defined(__WXMSW__) -#include "wx/msw/radiobox.h" + #include "wx/msw/radiobox.h" #elif defined(__WXMOTIF__) -#include "wx/motif/radiobox.h" + #include "wx/motif/radiobox.h" #elif defined(__WXGTK__) -#include "wx/gtk/radiobox.h" + #include "wx/gtk/radiobox.h" #elif defined(__WXQT__) -#include "wx/qt/radiobox.h" + #include "wx/qt/radiobox.h" #elif defined(__WXMAC__) -#include "wx/mac/radiobox.h" + #include "wx/mac/radiobox.h" #elif defined(__WXPM__) -#include "wx/os2/radiobox.h" + #include "wx/os2/radiobox.h" #elif defined(__WXSTUBS__) -#include "wx/stubs/radiobox.h" + #include "wx/stubs/radiobox.h" #endif +#endif // wxUSE_RADIOBOX + #endif // _WX_RADIOBOX_H_BASE_ diff --git a/include/wx/radiobut.h b/include/wx/radiobut.h index a5ea84812d..f2ed555db5 100644 --- a/include/wx/radiobut.h +++ b/include/wx/radiobut.h @@ -29,6 +29,10 @@ }; */ +#include "wx/control.h" + +WXDLLEXPORT_DATA(extern const wxChar*) wxRadioButtonNameStr; + #if defined(__WXUNIVERSAL__) #include "wx/univ/radiobut.h" #elif defined(__WXMSW__) diff --git a/include/wx/univ/checkbox.h b/include/wx/univ/checkbox.h index 53599acd78..4a6ab343a8 100644 --- a/include/wx/univ/checkbox.h +++ b/include/wx/univ/checkbox.h @@ -104,17 +104,27 @@ protected: virtual wxString GetInputHandlerType() const; virtual bool CanBeHighlighted() const { return TRUE; } + // get the size of the bitmap using either the current one or the default + // one (query renderer then) + virtual wxSize GetBitmapSize() const; + // common part of all ctors void Init(); // send command event notifying about the checkbox state change - void SendEvent(); + virtual void SendEvent(); + + // get the state corresponding to the flags (combination of wxCONTROL_XXX) + wxCheckBox::State GetState(int flags) const; // directly access the bitmaps array without trying to find a valid bitmap // to use as GetBitmap() does wxBitmap DoGetBitmap(State state, Status status) const { return m_bitmaps[state][status]; } + // get the current status + Status GetStatus() const { return m_status; } + private: // the current check status Status m_status; diff --git a/include/wx/univ/colschem.h b/include/wx/univ/colschem.h index 6cdb5629b1..bb134417be 100644 --- a/include/wx/univ/colschem.h +++ b/include/wx/univ/colschem.h @@ -64,16 +64,6 @@ public: // get a standard colour virtual wxColour Get(StdColour col) const = 0; - // get a standard bitmap -#if wxUSE_CHECKBOX - virtual wxBitmap GetCheckBitmap(wxCheckBox::State state, - wxCheckBox::Status status) = 0; -#endif // wxUSE_CHECKBOX -#if wxUSE_RADIOBTN - virtual wxBitmap GetRadioBitmap(wxCheckBox::State state, - wxCheckBox::Status status) = 0; -#endif // wxUSE_RADIOBTN - // get the background colour for the given window virtual wxColour GetBackground(wxWindow *win) const = 0; diff --git a/include/wx/univ/radiobut.h b/include/wx/univ/radiobut.h index d2186a3ff6..fd0c642108 100644 --- a/include/wx/univ/radiobut.h +++ b/include/wx/univ/radiobut.h @@ -16,6 +16,8 @@ #pragma interface "univradiobut.h" #endif +#include "wx/checkbox.h" + // ---------------------------------------------------------------------------- // wxRadioButton // ---------------------------------------------------------------------------- @@ -51,9 +53,14 @@ public: // override some base class methods virtual void ChangeValue(bool value); - virtual wxBitmap GetBitmap(State state, Status status) const; protected: + // implement our own drawing + virtual void DoDraw(wxControlRenderer *renderer); + + // we use the radio button bitmaps for size calculation + virtual wxSize GetBitmapSize() const; + // the radio button can only be cleared using this method, not // ChangeValue() above - and it is protected as it can only be called by // another radiobutton diff --git a/include/wx/univ/renderer.h b/include/wx/univ/renderer.h index e9292afb2c..4f78749419 100644 --- a/include/wx/univ/renderer.h +++ b/include/wx/univ/renderer.h @@ -154,7 +154,7 @@ public: const wxRect& rect, int flags = 0) = 0; - // draw a checkbutton + // draw a checkbutton (bitmap may be invalid to use default one) virtual void DrawCheckButton(wxDC& dc, const wxString& label, const wxBitmap& bitmap, @@ -163,6 +163,15 @@ public: wxAlignment align = wxALIGN_LEFT, int indexAccel = -1) = 0; + // draw a radio button + virtual void DrawRadioButton(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rect, + int flags = 0, + wxAlignment align = wxALIGN_LEFT, + int indexAccel = -1) = 0; + // geometry functions // ------------------ @@ -203,6 +212,10 @@ public: // get the height of a listbox item from the base font height virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) = 0; + // get the size of a checkbox/radio button bitmap + virtual wxSize GetCheckBitmapSize() const = 0; + virtual wxSize GetRadioBitmapSize() const = 0; + // virtual dtor for any base class virtual ~wxRenderer(); @@ -325,6 +338,15 @@ public: int indexAccel = -1) { m_renderer->DrawCheckButton(dc, label, bitmap, rect, flags, align, indexAccel); } + virtual void DrawRadioButton(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rect, + int flags = 0, + wxAlignment align = wxALIGN_LEFT, + int indexAccel = -1) + { m_renderer->DrawRadioButton(dc, label, bitmap, rect, + flags, align, indexAccel); } virtual void AdjustSize(wxSize *size, const wxWindow *window) { m_renderer->AdjustSize(size, window); } @@ -350,6 +372,10 @@ public: { return m_renderer->PixelToScrollbar(scrollbar, coord); } virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) { return m_renderer->GetListboxItemHeight(fontHeight); } + virtual wxSize GetCheckBitmapSize() const + { return m_renderer->GetCheckBitmapSize(); } + virtual wxSize GetRadioBitmapSize() const + { return m_renderer->GetRadioBitmapSize(); } protected: wxRenderer *m_renderer; diff --git a/samples/univ/univ.cpp b/samples/univ/univ.cpp index 4a1d02446c..fdd7e417ca 100644 --- a/samples/univ/univ.cpp +++ b/samples/univ/univ.cpp @@ -38,6 +38,7 @@ #include "wx/button.h" #include "wx/checkbox.h" #include "wx/listbox.h" + #include "wx/radiobut.h" #include "wx/scrolbar.h" #include "wx/scrolwin.h" #include "wx/statbox.h" @@ -109,6 +110,7 @@ protected: // event handlers void OnButton(wxCommandEvent& event); void OnCheckBox(wxCommandEvent& event); + void OnRadioBox(wxCommandEvent& event); void OnListBox(wxCommandEvent& event); void OnLeftUp(wxMouseEvent& event); @@ -150,6 +152,7 @@ WX_USE_THEME(gtk); BEGIN_EVENT_TABLE(MyUnivFrame, wxFrame) EVT_BUTTON(-1, MyUnivFrame::OnButton) EVT_CHECKBOX(-1, MyUnivFrame::OnCheckBox) + EVT_RADIOBUTTON(-1, MyUnivFrame::OnRadioBox) EVT_LISTBOX(-1, MyUnivFrame::OnListBox) EVT_LEFT_UP(MyUnivFrame::OnLeftUp) @@ -340,6 +343,8 @@ MyUnivFrame::MyUnivFrame(const wxString& title) new wxCheckBox(this, -1, _T("Don't check me"), wxPoint(150, 550), wxDefaultSize, wxALIGN_RIGHT); + new wxRadioButton(this, -1, _T("Toggle me"), wxPoint(10, 600)); + new wxRadioButton(this, -1, _T("And then me"), wxPoint(150, 600)); } void MyUnivFrame::OnButton(wxCommandEvent& event) @@ -361,6 +366,11 @@ void MyUnivFrame::OnCheckBox(wxCommandEvent& event) event.IsChecked() ? _T("") : _T("un")); } +void MyUnivFrame::OnRadioBox(wxCommandEvent& event) +{ + wxLogDebug(_T("Radio button selected.")); +} + void MyUnivFrame::OnListBox(wxCommandEvent& event) { wxLogDebug(_T("Listbox item %d selected."), event.GetInt()); diff --git a/src/univ/checkbox.cpp b/src/univ/checkbox.cpp index 737c197c7b..00383df386 100644 --- a/src/univ/checkbox.cpp +++ b/src/univ/checkbox.cpp @@ -105,8 +105,6 @@ wxBitmap wxCheckBox::GetBitmap(State state, Status status) const wxBitmap bmp = m_bitmaps[state][status]; if ( !bmp.Ok() ) bmp = m_bitmaps[State_Normal][status]; - if ( !bmp.Ok() ) - bmp = wxTheme::Get()->GetColourScheme()->GetCheckBitmap(state, status); return bmp; } @@ -120,27 +118,33 @@ void wxCheckBox::SetBitmap(const wxBitmap& bmp, State state, Status status) // drawing // ---------------------------------------------------------------------------- +wxCheckBox::State wxCheckBox::GetState(int flags) const +{ + if ( flags & wxCONTROL_DISABLED ) + return State_Disabled; + else if ( flags & wxCONTROL_PRESSED ) + return State_Pressed; + else if ( flags & wxCONTROL_CURRENT ) + return State_Current; + else + return State_Normal; +} + void wxCheckBox::DoDraw(wxControlRenderer *renderer) { - State state; int flags = GetStateFlags(); - if ( flags & wxCONTROL_DISABLED ) - state = State_Disabled; - else if ( flags & wxCONTROL_PRESSED ) - state = State_Pressed; - else if ( flags & wxCONTROL_CURRENT ) - state = State_Current; - else - state = State_Normal; wxDC& dc = renderer->GetDC(); dc.SetFont(GetFont()); dc.SetTextForeground(GetForegroundColour()); + if ( m_status == Status_Checked ) + flags |= wxCONTROL_CHECKED; + renderer->GetRenderer()-> DrawCheckButton(dc, GetLabel(), - GetBitmap(state, m_status), + GetBitmap(GetState(flags), m_status), renderer->GetRect(), flags, GetWindowStyle() & wxALIGN_RIGHT ? wxALIGN_RIGHT @@ -152,6 +156,13 @@ void wxCheckBox::DoDraw(wxControlRenderer *renderer) // geometry calculations // ---------------------------------------------------------------------------- +wxSize wxCheckBox::GetBitmapSize() const +{ + wxBitmap bmp = GetBitmap(State_Normal, Status_Checked); + return bmp.Ok() ? wxSize(bmp.GetWidth(), bmp.GetHeight()) + : GetRenderer()->GetCheckBitmapSize(); +} + wxSize wxCheckBox::DoGetBestClientSize() const { wxClientDC dc(wxConstCast(this, wxCheckBox)); @@ -159,12 +170,12 @@ wxSize wxCheckBox::DoGetBestClientSize() const wxCoord width, height; dc.GetMultiLineTextExtent(GetLabel(), &width, &height); - wxBitmap bmp = GetBitmap(State_Normal, Status_Checked); - if ( height < bmp.GetHeight() ) - height = bmp.GetHeight(); + wxSize sizeBmp = GetBitmapSize(); + if ( height < sizeBmp.y ) + height = sizeBmp.y; height += GetCharHeight()/2; - width += bmp.GetWidth() + 2*GetCharWidth(); + width += sizeBmp.x + 2*GetCharWidth(); return wxSize(width, height); } diff --git a/src/univ/files.lst b/src/univ/files.lst index 1ed3480722..0adcd161c0 100644 --- a/src/univ/files.lst +++ b/src/univ/files.lst @@ -6,6 +6,7 @@ UNIVOBJS = \ control.o \ inphand.o \ listbox.o \ + radiobut.o \ renderer.o \ scrolbar.o \ statbmp.o \ @@ -25,6 +26,7 @@ UNIVDEPS = \ control.d \ inphand.d \ listbox.d \ + radiobut.d \ renderer.d \ scrolbar.d \ statbmp.d \ diff --git a/src/univ/radiobut.cpp b/src/univ/radiobut.cpp index 800e86fb0a..2780fc2539 100644 --- a/src/univ/radiobut.cpp +++ b/src/univ/radiobut.cpp @@ -76,7 +76,44 @@ void wxRadioButton::ChangeValue(bool value) { if ( !IsChecked() && value ) { - // TODO clear all all others in our group! + // clear all others radio buttons in our group: for this we need to + // find the radio button which is the first in the group, i.e. the one + // with wxRB_GROUP style + const wxWindowList& siblings = GetParent()->GetChildren(); + wxWindowList::Node *nodeStart = siblings.Find(this); + while ( nodeStart ) + { + // stop if we found a radio button with wxRB_GROUP style or it we + // are at the first control + if ( !nodeStart->GetPrevious() || + (nodeStart->GetData()->GetWindowStyle() & wxRB_GROUP) ) + break; + + nodeStart = nodeStart->GetPrevious(); + } + + // now clear all radio buttons from the starting one until the next + // one with wxRB_GROUP style + while ( nodeStart ) + { + wxWindow *win = nodeStart->GetData(); + if ( win != this ) + { + wxRadioButton *btn = wxDynamicCast(win, wxRadioButton); + if ( btn ) + { + btn->ClearValue(); + } + } + + nodeStart = nodeStart->GetNext(); + if ( !nodeStart || + (nodeStart->GetData()->GetWindowStyle() & wxRB_GROUP) ) + { + // we reached the next group + break; + } + } SetValue(TRUE); @@ -103,22 +140,36 @@ void wxRadioButton::SendEvent() } // ---------------------------------------------------------------------------- -// indicator bitmaps +// overridden wxCheckBox methods // ---------------------------------------------------------------------------- -wxBitmap wxRadioButton::GetBitmap(State state, Status status) const +wxSize wxRadioButton::GetBitmapSize() const { - // radio buttons don't have "undetermined" status - wxASSERT_MSG( status == Status_Checked || status == Status_Unchecked, - _T("invalid status for a radio button") ); + wxBitmap bmp = GetBitmap(State_Normal, Status_Checked); + return bmp.Ok() ? wxSize(bmp.GetWidth(), bmp.GetHeight()) + : GetRenderer()->GetRadioBitmapSize(); +} - wxBitmap bmp = DoGetBitmap(state, status); - if ( !bmp.Ok() ) - bmp = DoGetBitmap(State_Normal, status); - if ( !bmp.Ok() ) - bmp = wxTheme::Get()->GetColourScheme()->GetRadioBitmap(state, status); +void wxRadioButton::DoDraw(wxControlRenderer *renderer) +{ + wxDC& dc = renderer->GetDC(); + dc.SetFont(GetFont()); + dc.SetTextForeground(GetForegroundColour()); - return bmp; + int flags = GetStateFlags(); + Status status = GetStatus(); + if ( status == Status_Checked ) + flags |= wxCONTROL_CHECKED; + + renderer->GetRenderer()-> + DrawRadioButton(dc, + GetLabel(), + GetBitmap(GetState(flags), status), + renderer->GetRect(), + flags, + GetWindowStyle() & wxALIGN_RIGHT ? wxALIGN_RIGHT + : wxALIGN_LEFT, + GetAccelIndex()); } #endif // wxUSE_RADIOBTN diff --git a/src/univ/themes/gtk.cpp b/src/univ/themes/gtk.cpp index a71eb790df..89d804f943 100644 --- a/src/univ/themes/gtk.cpp +++ b/src/univ/themes/gtk.cpp @@ -117,6 +117,14 @@ public: wxAlignment align = wxALIGN_LEFT, int indexAccel = -1); + virtual void DrawRadioButton(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rect, + int flags = 0, + wxAlignment align = wxALIGN_LEFT, + int indexAccel = -1); + virtual void AdjustSize(wxSize *size, const wxWindow *window); virtual wxRect GetBorderDimensions(wxBorder border) const; virtual bool AreScrollbarsInsideBorder() const; @@ -133,6 +141,10 @@ public: virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord); virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) { return fontHeight + 2; } + virtual wxSize GetCheckBitmapSize() const + { return wxSize(10, 10); } + virtual wxSize GetRadioBitmapSize() const + { return wxSize(11, 11); } // helpers for "wxBitmap wxColourScheme::Get()" void DrawCheckBitmap(wxDC& dc, const wxRect& rect); @@ -215,6 +227,32 @@ protected: return size; } + // DrawCheckBitmap and DrawRadioBitmap helpers + + // draw the check bitmaps once and cache them for later use + wxBitmap GetCheckBitmap(int flags); + + // draw a /\ or \/ line from (x1, y1) to (x2, y1) passing by the point + // ((x1 + x2)/2, y2) + void DrawUpZag(wxDC& dc, + wxCoord x1, wxCoord x2, + wxCoord y1, wxCoord y2); + void DrawDownZag(wxDC& dc, + wxCoord x1, wxCoord x2, + wxCoord y1, wxCoord y2); + + // draw the radio button bitmap for the given state + void DrawRadioBitmap(wxDC& dc, const wxRect& rect, int flags); + + // draw check/radio - the bitmap must be a valid one by now + void DoDrawCheckOrRadioBitmap(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rectTotal, + int flags, + wxAlignment align, + int indexAccel); + private: const wxColourScheme *m_scheme; @@ -227,6 +265,11 @@ private: m_penGrey, m_penLightGrey, m_penHighlight; + + // the checkbox bitmaps: first row is for the normal, second for the + // pressed state and the columns are for checked and unchecked status + // respectively + wxBitmap m_bitmapsCheckbox[2][2]; }; // ---------------------------------------------------------------------------- @@ -304,22 +347,6 @@ class wxGTKColourScheme : public wxColourScheme public: virtual wxColour Get(StdColour col) const; virtual wxColour GetBackground(wxWindow *win) const; - -#if wxUSE_CHECKBOX - virtual wxBitmap GetCheckBitmap(wxCheckBox::State state, - wxCheckBox::Status status); -#endif // wxUSE_CHECKBOX - -#if wxUSE_RADIOBTN - virtual wxBitmap GetRadioBitmap(wxCheckBox::State state, - wxCheckBox::Status status); -#endif // wxUSE_RADIOBTN - -private: - // the checkbox bitmaps: first row is for the normal, second for the - // pressed state and the columns are for checked and unchecked status - // respectively - wxBitmap m_bitmapsCheckbox[2][2]; }; // ---------------------------------------------------------------------------- @@ -495,61 +522,6 @@ wxColour wxGTKColourScheme::Get(wxGTKColourScheme::StdColour col) const } } -#if wxUSE_CHECKBOX - -wxBitmap wxGTKColourScheme::GetCheckBitmap(wxCheckBox::State state, - wxCheckBox::Status status) -{ - if ( !m_bitmapsCheckbox[0][0].Ok() ) - { - // init the bitmaps once only - wxRect rect; - rect.width = - rect.height = 10; - for ( int i = 0; i < 2; i++ ) - { - for ( int j = 0; j < 2; j++ ) - m_bitmapsCheckbox[i][j].Create(rect.width, rect.height); - } - - wxGTKRenderer *renderer = (wxGTKRenderer *)wxTheme::Get()->GetRenderer(); - - wxMemoryDC dc; - - // normal checked - dc.SelectObject(m_bitmapsCheckbox[0][0]); - renderer->DrawCheckBitmap(dc, rect); - - // normal unchecked - dc.SelectObject(m_bitmapsCheckbox[0][1]); - renderer->DrawUncheckBitmap(dc, rect, FALSE); - - // pressed checked - m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0]; - - // pressed unchecked - dc.SelectObject(m_bitmapsCheckbox[1][1]); - renderer->DrawUncheckBitmap(dc, rect, TRUE); - } - - int row = state == wxCheckBox::State_Pressed ? 1 : 0; - int col = status == wxCheckBox::Status_Checked ? 0 : 1; - - return m_bitmapsCheckbox[row][col]; -} - -#endif // wxUSE_CHECKBOX - -#if wxUSE_RADIOBTN - -wxBitmap wxGTKColourScheme::GetRadioBitmap(wxCheckBox::State state, - wxCheckBox::Status status) -{ - return GetCheckBitmap(state, status); -} - -#endif // wxUSE_RADIOBTN - // ============================================================================ // wxGTKRenderer // ============================================================================ @@ -973,13 +945,186 @@ void wxGTKRenderer::DrawItem(wxDC& dc, // check/radion buttons // ---------------------------------------------------------------------------- +void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc, + const wxRect& rectTotal, + bool isPressed) +{ + wxRect rect = rectTotal; + DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack); + DrawAntiShadedRect(dc, &rect, m_penLightGrey, m_penDarkGrey); + + wxColour col = wxSCHEME_COLOUR(m_scheme, SHADOW_IN); + dc.SetPen(wxPen(col, 0, wxSOLID)); + dc.DrawPoint(rect.GetRight() - 1, rect.GetBottom() - 1); + + if ( isPressed ) + col = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED); + //else: it is SHADOW_IN, leave as is + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(col, wxSOLID)); + dc.DrawRectangle(rect); +} + +void wxGTKRenderer::DrawCheckBitmap(wxDC& dc, const wxRect& rectTotal) +{ + wxRect rect = rectTotal; + DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey); + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), wxSOLID)); + dc.DrawRectangle(rect); +} + +void wxGTKRenderer::DrawRadioBitmap(wxDC& dc, + const wxRect& rect, + int flags) +{ + wxCoord x = rect.x, + y = rect.y, + xRight = rect.GetRight(), + yBottom = rect.GetBottom(); + + wxCoord yMid = (y + yBottom) / 2; + + + // first fill the middle: as FloodFill() is not implemented on all + // platforms, this is the only thing to do + wxColour colBg = flags & wxCONTROL_CURRENT + ? wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT) + : wxSCHEME_COLOUR(m_scheme, SHADOW_IN); + dc.SetBrush(wxBrush(colBg, wxSOLID)); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(rect); + + // then draw the upper half + dc.SetPen(flags & wxCONTROL_CHECKED ? m_penDarkGrey : m_penHighlight); + DrawUpZag(dc, x, xRight, yMid, y); + DrawUpZag(dc, x + 1, xRight - 1, yMid, y + 1); + + bool drawIt = TRUE; + if ( flags & wxCONTROL_CHECKED ) + dc.SetPen(m_penBlack); + else if ( flags & wxCONTROL_PRESSED ) + dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), 0, wxSOLID)); + else // unchecked and unpressed + drawIt = FALSE; + + if ( drawIt ) + DrawUpZag(dc, x + 2, xRight - 2, yMid, y + 2); + + // and then the lower one + dc.SetPen(flags & wxCONTROL_CHECKED ? m_penHighlight : m_penBlack); + DrawDownZag(dc, x, xRight, yMid, yBottom); + if ( !(flags & wxCONTROL_CHECKED) ) + dc.SetPen(m_penDarkGrey); + DrawDownZag(dc, x + 1, xRight - 1, yMid, yBottom - 1); + + if ( !(flags & wxCONTROL_CHECKED) ) + drawIt = TRUE; // with the same pen + else if ( flags & wxCONTROL_PRESSED ) + { + dc.SetPen(wxPen(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), 0, wxSOLID)); + drawIt = TRUE; + } + else // checked and unpressed + drawIt = FALSE; + + if ( drawIt ) + DrawDownZag(dc, x + 2, xRight - 2, yMid, yBottom - 2); +} + +void wxGTKRenderer::DrawUpZag(wxDC& dc, + wxCoord x1, + wxCoord x2, + wxCoord y1, + wxCoord y2) +{ + wxCoord xMid = (x1 + x2) / 2; + dc.DrawLine(x1, y1, xMid, y2); + dc.DrawLine(xMid, y2, x2 + 1, y1 + 1); +} + +void wxGTKRenderer::DrawDownZag(wxDC& dc, + wxCoord x1, + wxCoord x2, + wxCoord y1, + wxCoord y2) +{ + wxCoord xMid = (x1 + x2) / 2; + dc.DrawLine(x1 + 1, y1 + 1, xMid, y2); + dc.DrawLine(xMid, y2, x2, y1); +} + +wxBitmap wxGTKRenderer::GetCheckBitmap(int flags) +{ + if ( !m_bitmapsCheckbox[0][0].Ok() ) + { + // init the bitmaps once only + wxRect rect; + wxSize size = GetCheckBitmapSize(); + rect.width = size.x; + rect.height = size.y; + for ( int i = 0; i < 2; i++ ) + { + for ( int j = 0; j < 2; j++ ) + m_bitmapsCheckbox[i][j].Create(rect.width, rect.height); + } + + wxMemoryDC dc; + + // normal checked + dc.SelectObject(m_bitmapsCheckbox[0][0]); + DrawCheckBitmap(dc, rect); + + // normal unchecked + dc.SelectObject(m_bitmapsCheckbox[0][1]); + DrawUncheckBitmap(dc, rect, FALSE); + + // pressed checked + m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0]; + + // pressed unchecked + dc.SelectObject(m_bitmapsCheckbox[1][1]); + DrawUncheckBitmap(dc, rect, TRUE); + } + + int row = flags & wxCONTROL_PRESSED ? 1 : 0; + int col = flags & wxCONTROL_CHECKED ? 0 : 1; + + return m_bitmapsCheckbox[row][col]; +} + void wxGTKRenderer::DrawCheckButton(wxDC& dc, const wxString& label, - const wxBitmap& bitmap, + const wxBitmap& bitmapOrig, const wxRect& rectTotal, int flags, wxAlignment align, int indexAccel) +{ + wxBitmap bitmap; + if ( bitmapOrig.Ok() ) + { + bitmap = bitmapOrig; + } + else + { + bitmap = GetCheckBitmap(flags); + } + + DoDrawCheckOrRadioBitmap(dc, label, bitmap, rectTotal, + flags, align, indexAccel); +} + +void wxGTKRenderer::DoDrawCheckOrRadioBitmap(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rectTotal, + int flags, + wxAlignment align, + int indexAccel) { wxRect rect = rectTotal; @@ -988,6 +1133,11 @@ void wxGTKRenderer::DrawCheckButton(wxDC& dc, // draw the focus border around everything DrawRect(dc, &rect, m_penBlack); } + else + { + // the border does not offset the string under GTK + rect.Inflate(-1); + } // calculate the position of the bitmap and of the label wxCoord xBmp, @@ -1016,6 +1166,35 @@ void wxGTKRenderer::DrawCheckButton(wxDC& dc, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, indexAccel); } +void wxGTKRenderer::DrawRadioButton(wxDC& dc, + const wxString& label, + const wxBitmap& bitmapOrig, + const wxRect& rectTotal, + int flags, + wxAlignment align, + int indexAccel) +{ + wxBitmap bitmap; + if ( bitmapOrig.Ok() ) + { + bitmap = bitmapOrig; + } + else + { + wxRect rect; + wxSize size = GetRadioBitmapSize(); + rect.width = size.x; + rect.height = size.y; + bitmap.Create(rect.width, rect.height); + wxMemoryDC dc; + dc.SelectObject(bitmap); + DrawRadioBitmap(dc, rect, flags); + } + + DoDrawCheckOrRadioBitmap(dc, label, bitmap, rectTotal, + flags, align, indexAccel); +} + // ---------------------------------------------------------------------------- // background // ---------------------------------------------------------------------------- @@ -1441,42 +1620,6 @@ void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window) } } -// ---------------------------------------------------------------------------- -// checkbox buttons -// ---------------------------------------------------------------------------- - -void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc, - const wxRect& rectTotal, - bool isPressed) -{ - wxRect rect = rectTotal; - DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack); - DrawAntiShadedRect(dc, &rect, m_penLightGrey, m_penDarkGrey); - - wxColour col = wxSCHEME_COLOUR(m_scheme, SHADOW_IN); - dc.SetPen(wxPen(col, 0, wxSOLID)); - dc.DrawPoint(rect.GetRight() - 1, rect.GetBottom() - 1); - - if ( isPressed ) - col = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED); - //else: it is SHADOW_IN, leave as is - - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(wxBrush(col, wxSOLID)); - dc.DrawRectangle(rect); -} - -void wxGTKRenderer::DrawCheckBitmap(wxDC& dc, const wxRect& rectTotal) -{ - wxRect rect = rectTotal; - DrawAntiShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); - DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey); - - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(wxBrush(wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), wxSOLID)); - dc.DrawRectangle(rect); -} - // ============================================================================ // wxInputHandler // ============================================================================ diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index d38950e203..9e530f1c7b 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -133,6 +133,13 @@ public: int flags = 0, wxAlignment align = wxALIGN_LEFT, int indexAccel = -1); + virtual void DrawRadioButton(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rect, + int flags = 0, + wxAlignment align = wxALIGN_LEFT, + int indexAccel = -1); virtual void AdjustSize(wxSize *size, const wxWindow *window); virtual wxRect GetBorderDimensions(wxBorder border) const; @@ -149,6 +156,10 @@ public: virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord); virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) { return fontHeight; } + virtual wxSize GetCheckBitmapSize() const + { return wxSize(13, 13); } + virtual wxSize GetRadioBitmapSize() const + { return wxSize(13, 13); } protected: // common part of DrawLabel() and DrawItem() @@ -195,6 +206,9 @@ protected: wxArrowDirection arrowDir, wxArrowStyle arrowStyle); + // helper of DrawCheckButton + wxBitmap GetCheckBitmap(int flags); + private: const wxColourScheme *m_scheme; @@ -285,16 +299,6 @@ class wxWin32ColourScheme : public wxColourScheme public: virtual wxColour Get(StdColour col) const; virtual wxColour GetBackground(wxWindow *win) const; - -#if wxUSE_CHECKBOX - virtual wxBitmap GetCheckBitmap(wxCheckBox::State state, - wxCheckBox::Status status); -#endif // wxUSE_CHECKBOX - -#if wxUSE_RADIOBTN - virtual wxBitmap GetRadioBitmap(wxCheckBox::State state, - wxCheckBox::Status status); -#endif // wxUSE_RADIOBTN }; // ---------------------------------------------------------------------------- @@ -476,134 +480,6 @@ wxColour wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col) const } } -#if wxUSE_CHECKBOX - -static char *checked_xpm[] = { -/* columns rows colors chars-per-pixel */ -"13 13 5 1", -"w c white", -"b c black", -"d c #7f7f7f", -"g c #c0c0c0", -"h c #e0e0e0", -/* pixels */ -"ddddddddddddh", -"dbbbbbbbbbbgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwbwgh", -"dbwwwwwwbbwgh", -"dbwbwwwbbbwgh", -"dbwbbwbbbwwgh", -"dbwbbbbbwwwgh", -"dbwwbbbwwwwgh", -"dbwwwbwwwwwgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dgggggggggggh", -"hhhhhhhhhhhhh" -}; - -static char *pressed_checked_xpm[] = { -/* columns rows colors chars-per-pixel */ -"13 13 4 1", -"b c black", -"d c #7f7f7f", -"g c #c0c0c0", -"h c #e0e0e0", -/* pixels */ -"ddddddddddddh", -"dbbbbbbbbbbgh", -"dbggggggggggh", -"dbgggggggbggh", -"dbggggggbbggh", -"dbgbgggbbbggh", -"dbgbbgbbbgggh", -"dbgbbbbbggggh", -"dbggbbbgggggh", -"dbgggbggggggh", -"dbggggggggggh", -"dbggggggggggh", -"dgggggggggggh", -"hhhhhhhhhhhhh" -}; - -static char *unchecked_xpm[] = { -/* columns rows colors chars-per-pixel */ -"13 13 5 1", -"w c white", -"b c black", -"d c #7f7f7f", -"g c #c0c0c0", -"h c #e0e0e0", -/* pixels */ -"ddddddddddddh", -"dbbbbbbbbbbgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dbwwwwwwwwwgh", -"dgggggggggggh", -"hhhhhhhhhhhhh" -}; - -static char *pressed_unchecked_xpm[] = { -/* columns rows colors chars-per-pixel */ -"13 13 4 1", -"b c black", -"d c #7f7f7f", -"g c #c0c0c0", -"h c #e0e0e0", -/* pixels */ -"ddddddddddddh", -"dbbbbbbbbbbgh", -"dbggggggggggh", -"dbggggggggggh", -"dbggggggggggh", -"dbggggggggggh", -"dbggggggggggh", -"dbggggggggggh", -"dbggggggggggh", -"dbggggggggggh", -"dbggggggggggh", -"dbggggggggggh", -"hhhhhhhhhhhhh" -}; - -wxBitmap wxWin32ColourScheme::GetCheckBitmap(wxCheckBox::State state, - wxCheckBox::Status status) -{ - char **xpm; - if ( status == wxCheckBox::Status_Checked ) - { - xpm = state == wxCheckBox::State_Pressed ? pressed_checked_xpm - : checked_xpm; - } - else - { - xpm = state == wxCheckBox::State_Pressed ? pressed_unchecked_xpm - : unchecked_xpm; - } - - return wxBitmap(xpm); -} - -#endif // wxUSE_CHECKBOX - -#if wxUSE_RADIOBTN - -wxBitmap wxWin32ColourScheme::GetRadioBitmap(wxCheckBox::State state, - wxCheckBox::Status status) -{ - return GetCheckBitmap(state, status); -} - -#endif // wxUSE_RADIOBTN - // ============================================================================ // wxWin32Renderer // ============================================================================ @@ -1282,6 +1158,119 @@ void wxWin32Renderer::DrawItem(wxDC& dc, // check/radio buttons // ---------------------------------------------------------------------------- +static char *checked_xpm[] = { +/* columns rows colors chars-per-pixel */ +"13 13 5 1", +"w c white", +"b c black", +"d c #7f7f7f", +"g c #c0c0c0", +"h c #e0e0e0", +/* pixels */ +"ddddddddddddh", +"dbbbbbbbbbbgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwbwgh", +"dbwwwwwwbbwgh", +"dbwbwwwbbbwgh", +"dbwbbwbbbwwgh", +"dbwbbbbbwwwgh", +"dbwwbbbwwwwgh", +"dbwwwbwwwwwgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dgggggggggggh", +"hhhhhhhhhhhhh" +}; + +static char *pressed_checked_xpm[] = { +/* columns rows colors chars-per-pixel */ +"13 13 4 1", +"b c black", +"d c #7f7f7f", +"g c #c0c0c0", +"h c #e0e0e0", +/* pixels */ +"ddddddddddddh", +"dbbbbbbbbbbgh", +"dbggggggggggh", +"dbgggggggbggh", +"dbggggggbbggh", +"dbgbgggbbbggh", +"dbgbbgbbbgggh", +"dbgbbbbbggggh", +"dbggbbbgggggh", +"dbgggbggggggh", +"dbggggggggggh", +"dbggggggggggh", +"dgggggggggggh", +"hhhhhhhhhhhhh" +}; + +static char *unchecked_xpm[] = { +/* columns rows colors chars-per-pixel */ +"13 13 5 1", +"w c white", +"b c black", +"d c #7f7f7f", +"g c #c0c0c0", +"h c #e0e0e0", +/* pixels */ +"ddddddddddddh", +"dbbbbbbbbbbgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dbwwwwwwwwwgh", +"dgggggggggggh", +"hhhhhhhhhhhhh" +}; + +static char *pressed_unchecked_xpm[] = { +/* columns rows colors chars-per-pixel */ +"13 13 4 1", +"b c black", +"d c #7f7f7f", +"g c #c0c0c0", +"h c #e0e0e0", +/* pixels */ +"ddddddddddddh", +"dbbbbbbbbbbgh", +"dbggggggggggh", +"dbggggggggggh", +"dbggggggggggh", +"dbggggggggggh", +"dbggggggggggh", +"dbggggggggggh", +"dbggggggggggh", +"dbggggggggggh", +"dbggggggggggh", +"dbggggggggggh", +"hhhhhhhhhhhhh" +}; + +wxBitmap wxWin32Renderer::GetCheckBitmap(int flags) +{ + char **xpm; + if ( flags & wxCONTROL_CHECKED ) + { + xpm = flags & wxCONTROL_PRESSED ? pressed_checked_xpm + : checked_xpm; + } + else // unchecked + { + xpm = flags & wxCONTROL_PRESSED ? pressed_unchecked_xpm + : unchecked_xpm; + } + + return wxBitmap(xpm); +} + void wxWin32Renderer::DrawCheckButton(wxDC& dc, const wxString& label, const wxBitmap& bitmap, @@ -1317,6 +1306,18 @@ void wxWin32Renderer::DrawCheckButton(wxDC& dc, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, indexAccel); } +void wxWin32Renderer::DrawRadioButton(wxDC& dc, + const wxString& label, + const wxBitmap& bitmap, + const wxRect& rect, + int flags, + wxAlignment align, + int indexAccel) +{ + // FIXME TODO + DrawCheckButton(dc, label, bitmap, rect, flags, align, indexAccel); +} + // ---------------------------------------------------------------------------- // background // ----------------------------------------------------------------------------