diff --git a/include/wx/univ/button.h b/include/wx/univ/button.h index eaacff1179..564a58a73a 100644 --- a/include/wx/univ/button.h +++ b/include/wx/univ/button.h @@ -111,6 +111,9 @@ protected: virtual wxSize DoGetBestClientSize() const; virtual void DoDraw(wxControlRenderer *renderer); + virtual wxString GetInputHandlerType() const; + virtual bool CanBeHighlighted() const { return TRUE; } + // common part of all ctors void Init(); diff --git a/include/wx/univ/checkbox.h b/include/wx/univ/checkbox.h index 7afd0341fc..4dcf55f5b0 100644 --- a/include/wx/univ/checkbox.h +++ b/include/wx/univ/checkbox.h @@ -24,6 +24,8 @@ #define wxACTION_CHECKBOX_CLEAR _T("clear") // SetValue(FALSE) #define wxACTION_CHECKBOX_TOGGLE _T("toggle") // toggle the check state +// additionally it accepts wxACTION_BUTTON_PRESS and RELEASE + // ---------------------------------------------------------------------------- // wxCheckBox // ---------------------------------------------------------------------------- @@ -79,14 +81,32 @@ public: virtual void SetValue(bool value); virtual bool GetValue() const; - // set/get the margin between the checkbox bitmap and the label - void SetMargin(wxCoord margin) { m_checkMargin = margin; } - wxCoord GetMargin() const { return m_checkMargin; } + // set/get the margins between the checkbox bitmap and the border and + // between the bitmap and the label and above it + void SetMargins(wxCoord marginLeft, wxCoord marginRight, wxCoord marginTop) + { + m_checkMarginLeft = marginLeft; + m_checkMarginRight = marginRight; + m_checkMarginTop = marginTop; + } + wxCoord GetLeftMargin() const { return m_checkMarginLeft; } + wxCoord GetRightMargin() const { return m_checkMarginRight; } + wxCoord GetTopMargin() const { return m_checkMarginTop; } // set/get the bitmaps to use for the checkbox indicator void SetBitmap(const wxBitmap& bmp, State state, Status status); wxBitmap GetBitmap(State state, Status status) const; + // wxCheckBox actions + void Toggle(); + virtual void Press(); + virtual void Release(); + virtual void Click(); + virtual void ChangeValue(bool value); + + // overridden base class virtuals + virtual bool IsPressed() const { return m_isPressed; } + protected: virtual bool PerformAction(const wxControlAction& action, long numArg = -1, @@ -94,9 +114,15 @@ protected: virtual void DoDraw(wxControlRenderer *renderer); virtual wxSize DoGetBestClientSize() const; + virtual wxString GetInputHandlerType() const; + virtual bool CanBeHighlighted() const { return TRUE; } + // common part of all ctors void Init(); + // set the margins to the default values if they were not set yet + void SetMargins(); + private: // the current check status Status m_status; @@ -104,8 +130,13 @@ private: // the bitmaps to use for the different states wxBitmap m_bitmaps[State_Max][Status_Max]; - // the distance between the checkbox and the label (-1 means default) - wxCoord m_checkMargin; + // the distance between the checkbox and the label/border (-1 means default) + wxCoord m_checkMarginLeft, + m_checkMarginRight, + m_checkMarginTop; + + // is the checkbox currently pressed? + bool m_isPressed; DECLARE_DYNAMIC_CLASS(wxCheckBox) }; diff --git a/include/wx/univ/control.h b/include/wx/univ/control.h index fc8e2298db..992758dba5 100644 --- a/include/wx/univ/control.h +++ b/include/wx/univ/control.h @@ -90,9 +90,8 @@ public: const wxString& strArg = wxEmptyString); protected: - // create the event translator object for this control: the base class - // action creates the default one which doesn't do anything - virtual wxInputHandler *CreateInputHandler() const; + // get the type of event translator object for this control + virtual wxString GetInputHandlerType() const; // event handlers void OnMouse(wxMouseEvent& event); diff --git a/include/wx/univ/inphand.h b/include/wx/univ/inphand.h index 75c0577c80..fb5f8c1b7f 100644 --- a/include/wx/univ/inphand.h +++ b/include/wx/univ/inphand.h @@ -25,6 +25,18 @@ class WXDLLEXPORT wxListBox; class WXDLLEXPORT wxRenderer; class WXDLLEXPORT wxScrollBar; +// ---------------------------------------------------------------------------- +// types of the standard input handlers which can be passed to +// wxTheme::GetInputHandler() +// ---------------------------------------------------------------------------- + +#define wxINP_HANDLER_DEFAULT _T("") +#define wxINP_HANDLER_BUTTON _T("button") +#define wxINP_HANDLER_CHECKBOX _T("checkbox") +#define wxINP_HANDLER_RADIOBTN _T("radiobtn") +#define wxINP_HANDLER_SCROLLBAR _T("scrollbar") +#define wxINP_HANDLER_LISTBOX _T("listbox") + // ---------------------------------------------------------------------------- // wxInputHandler: maps the events to the actions // ---------------------------------------------------------------------------- @@ -232,4 +244,21 @@ protected: bool m_toggleOnPressAlways; }; +// ---------------------------------------------------------------------------- +// wxStdCheckboxInputHandler: handles the mouse events for the check and radio +// boxes (handling the keyboard input is simple, but its handling differs a +// lot between GTK and MSW, so a new class should be derived for this) +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxStdCheckboxInputHandler : public wxStdButtonInputHandler +{ +public: + wxStdCheckboxInputHandler(wxInputHandler *inphand); + + virtual bool HandleMouse(wxControl *control, + const wxMouseEvent& event); + virtual bool HandleMouseMove(wxControl *control, + const wxMouseEvent& event); +}; + #endif // _WX_UNIV_INPHAND_H_ diff --git a/include/wx/univ/listbox.h b/include/wx/univ/listbox.h index c428f0a5e6..87c86aaaba 100644 --- a/include/wx/univ/listbox.h +++ b/include/wx/univ/listbox.h @@ -168,6 +168,8 @@ protected: virtual void DoDraw(wxControlRenderer *renderer); virtual wxBorder GetDefaultBorder() const; + virtual wxString GetInputHandlerType() const; + // common part of all ctors void Init(); diff --git a/include/wx/univ/renderer.h b/include/wx/univ/renderer.h index aa9e332cfa..40a7718ede 100644 --- a/include/wx/univ/renderer.h +++ b/include/wx/univ/renderer.h @@ -104,6 +104,9 @@ public: int flags = 0, wxRect *rectIn = (wxRect *)NULL) = 0; + // draw a check/radio focus border + virtual void DrawCheckBoxFocusBorder(wxDC& dc, wxRect *rect) = 0; + // draw push button border and return the rectangle left for the label virtual void DrawButtonBorder(wxDC& dc, const wxRect& rect, @@ -194,6 +197,16 @@ public: // get the height of a listbox item from the base font height virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) = 0; + // get the standard size of the checkbox bitmap and the margins around it + virtual wxSize GetCheckBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const = 0; + + // get the standard size of the radio btn bitmap and the margins around it + virtual wxSize GetRadioBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const = 0; + // virtual dtor for any base class virtual ~wxRenderer(); @@ -279,6 +292,8 @@ public: virtual void DrawVerticalLine(wxDC& dc, wxCoord x, wxCoord y1, wxCoord y2) { m_renderer->DrawVerticalLine(dc, x, y1, y2); } + virtual void DrawCheckBoxFocusBorder(wxDC& dc, wxRect *rect) + { m_renderer->DrawCheckBoxFocusBorder(dc, rect); } virtual void DrawButtonBorder(wxDC& dc, const wxRect& rect, int flags = 0, @@ -332,6 +347,18 @@ public: { return m_renderer->PixelToScrollbar(scrollbar, coord); } virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) { return m_renderer->GetListboxItemHeight(fontHeight); } + virtual wxSize GetCheckBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const + { return m_renderer->GetCheckBitmapSize(marginLeft, + marginRight, + marginTop); } + virtual wxSize GetRadioBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const + { return m_renderer->GetRadioBitmapSize(marginLeft, + marginRight, + marginTop); } protected: wxRenderer *m_renderer; @@ -365,7 +392,10 @@ public: wxStretch stretch = wxSTRETCH_NOT); void DrawBackgroundBitmap(); void DrawScrollbar(const wxScrollBar *scrollbar, int thumbPosOld); - void DrawLabelBox(const wxBitmap& bitmap, wxCoord margin); + void DrawLabelBox(const wxBitmap& bitmap, + wxCoord marginLeft, + wxCoord marginRight, + wxCoord marginTop); // accessors wxWindow *GetWindow() const { return m_window; } diff --git a/include/wx/univ/scrolbar.h b/include/wx/univ/scrolbar.h index a94119d293..e0669606fd 100644 --- a/include/wx/univ/scrolbar.h +++ b/include/wx/univ/scrolbar.h @@ -110,7 +110,9 @@ protected: virtual void DoDraw(wxControlRenderer *renderer); virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; } - // event handler + virtual wxString GetInputHandlerType() const; + + // event handlers void OnIdle(wxIdleEvent& event); // SetThumbPosition() helper diff --git a/include/wx/univ/theme.h b/include/wx/univ/theme.h index db65d9b5bb..94ba4fcfab 100644 --- a/include/wx/univ/theme.h +++ b/include/wx/univ/theme.h @@ -23,8 +23,8 @@ // ---------------------------------------------------------------------------- class WXDLLEXPORT wxRenderer; -class WXDLLEXPORT wxInputHandler; class WXDLLEXPORT wxColourScheme; +class WXDLLEXPORT wxInputHandler; struct WXDLLEXPORT wxThemeInfo; class WXDLLEXPORT wxTheme @@ -52,8 +52,8 @@ public: // this theme virtual wxRenderer *GetRenderer() = 0; - // get the input handler for the control with this name - virtual wxInputHandler *GetInputHandler(const wxString& control) = 0; + // get the input handler of the given type + virtual wxInputHandler *GetInputHandler(const wxString& handlerType) = 0; // get the colour scheme for the control with this name virtual wxColourScheme *GetColourScheme() = 0; diff --git a/samples/univ/univ.cpp b/samples/univ/univ.cpp index f63cb9917c..4a1d02446c 100644 --- a/samples/univ/univ.cpp +++ b/samples/univ/univ.cpp @@ -108,6 +108,7 @@ public: protected: // event handlers void OnButton(wxCommandEvent& event); + void OnCheckBox(wxCommandEvent& event); void OnListBox(wxCommandEvent& event); void OnLeftUp(wxMouseEvent& event); @@ -148,6 +149,7 @@ WX_USE_THEME(gtk); BEGIN_EVENT_TABLE(MyUnivFrame, wxFrame) EVT_BUTTON(-1, MyUnivFrame::OnButton) + EVT_CHECKBOX(-1, MyUnivFrame::OnCheckBox) EVT_LISTBOX(-1, MyUnivFrame::OnListBox) EVT_LEFT_UP(MyUnivFrame::OnLeftUp) @@ -353,6 +355,12 @@ void MyUnivFrame::OnButton(wxCommandEvent& event) } } +void MyUnivFrame::OnCheckBox(wxCommandEvent& event) +{ + wxLogDebug(_T("Checkbox became %schecked."), + event.IsChecked() ? _T("") : _T("un")); +} + void MyUnivFrame::OnListBox(wxCommandEvent& event) { wxLogDebug(_T("Listbox item %d selected."), event.GetInt()); diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index c1bdf28185..fc2f7fb884 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -348,6 +348,8 @@ static wxWindowGTK *FindFocusedChild(wxWindowGTK *win) static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) { + // wxUniversal widgets draw the borders and scrollbars themselves +#ifndef __WXUNIVERSAL__ if (!win->m_hasVMT) return; @@ -385,8 +387,6 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) } } - // wxUniversal widgets draw the borders themselves -#ifndef __WXUNIVERSAL__ int dx = 0; int dy = 0; if (GTK_WIDGET_NO_WINDOW (widget)) @@ -1452,6 +1452,7 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, wxMouseEvent event(g_captureWindowHasMouse ? wxEVT_ENTER_WINDOW : wxEVT_LEAVE_WINDOW); InitMouseEvent(event, gdk_event); + event.SetEventObject(win); win->GetEventHandler()->ProcessEvent(event); } } diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index c1bdf28185..fc2f7fb884 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -348,6 +348,8 @@ static wxWindowGTK *FindFocusedChild(wxWindowGTK *win) static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) { + // wxUniversal widgets draw the borders and scrollbars themselves +#ifndef __WXUNIVERSAL__ if (!win->m_hasVMT) return; @@ -385,8 +387,6 @@ static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) } } - // wxUniversal widgets draw the borders themselves -#ifndef __WXUNIVERSAL__ int dx = 0; int dy = 0; if (GTK_WIDGET_NO_WINDOW (widget)) @@ -1452,6 +1452,7 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, wxMouseEvent event(g_captureWindowHasMouse ? wxEVT_ENTER_WINDOW : wxEVT_LEAVE_WINDOW); InitMouseEvent(event, gdk_event); + event.SetEventObject(win); win->GetEventHandler()->ProcessEvent(event); } } diff --git a/src/univ/button.cpp b/src/univ/button.cpp index 960aee4641..c46c934a17 100644 --- a/src/univ/button.cpp +++ b/src/univ/button.cpp @@ -130,6 +130,11 @@ void wxButton::DoDraw(wxControlRenderer *renderer) // input processing // ---------------------------------------------------------------------------- +wxString wxButton::GetInputHandlerType() const +{ + return wxINP_HANDLER_BUTTON; +} + void wxButton::Press() { if ( !m_isPressed ) @@ -296,6 +301,7 @@ bool wxStdButtonInputHandler::HandleMouseMove(wxControl *control, m_winHasMouse = FALSE; // we do have a pressed button, so release it + control->SetCurrent(FALSE); control->PerformAction(wxACTION_BUTTON_RELEASE); return TRUE; @@ -309,6 +315,7 @@ bool wxStdButtonInputHandler::HandleMouseMove(wxControl *control, // we did have a pressed button which we released when leaving the // window, press it again + control->SetCurrent(TRUE); control->PerformAction(wxACTION_BUTTON_PRESS); return TRUE; diff --git a/src/univ/checkbox.cpp b/src/univ/checkbox.cpp index 4ecd5eeca6..aeadab4c53 100644 --- a/src/univ/checkbox.cpp +++ b/src/univ/checkbox.cpp @@ -33,10 +33,13 @@ #include "wx/dcclient.h" #include "wx/checkbox.h" #include "wx/validate.h" + + #include "wx/button.h" // for wxACTION_BUTTON_XXX #endif #include "wx/univ/theme.h" #include "wx/univ/renderer.h" +#include "wx/univ/inphand.h" #include "wx/univ/colschem.h" // ============================================================================ @@ -51,7 +54,10 @@ IMPLEMENT_DYNAMIC_CLASS(wxCheckBox, wxControl) void wxCheckBox::Init() { - m_checkMargin = -1; + m_checkMarginLeft = + m_checkMarginRight = + m_checkMarginTop = -1; + m_isPressed = FALSE; m_status = Status_Unchecked; } @@ -125,16 +131,36 @@ void wxCheckBox::DoDraw(wxControlRenderer *renderer) else state = State_Normal; - renderer->DrawLabelBox(GetBitmap(state, m_status), m_checkMargin); + SetMargins(); + + renderer->DrawLabelBox(GetBitmap(state, m_status), + m_checkMarginLeft, + m_checkMarginRight, + m_checkMarginTop); } // ---------------------------------------------------------------------------- // geometry calculations // ---------------------------------------------------------------------------- +void wxCheckBox::SetMargins() +{ + wxCoord *left = m_checkMarginLeft == -1 ? &m_checkMarginLeft : NULL, + *right = m_checkMarginRight == -1 ? &m_checkMarginRight : NULL, + *top = m_checkMarginTop == -1 ? &m_checkMarginTop : NULL; + if ( left || right || top ) + { + GetRenderer()->GetCheckBitmapSize(left, right, top); + } +} + wxSize wxCheckBox::DoGetBestClientSize() const { - wxClientDC dc(wxConstCast(this, wxCheckBox)); + wxCheckBox *self = wxConstCast(this, wxCheckBox); + + self->SetMargins(); + + wxClientDC dc(self); wxCoord width, height; dc.GetMultiLineTextExtent(GetLabel(), &width, &height); @@ -143,25 +169,82 @@ wxSize wxCheckBox::DoGetBestClientSize() const height = bmp.GetHeight(); height += GetCharHeight(); - width += bmp.GetWidth() + 2*GetCharWidth(); + width += bmp.GetWidth() + + m_checkMarginLeft + m_checkMarginRight + + GetCharWidth(); return wxSize(width, height); } +// ---------------------------------------------------------------------------- +// checkbox actions +// ---------------------------------------------------------------------------- + +void wxCheckBox::Press() +{ + if ( !m_isPressed ) + { + m_isPressed = TRUE; + + Refresh(); + } +} + +void wxCheckBox::Release() +{ + if ( m_isPressed ) + { + m_isPressed = FALSE; + + Refresh(); + } +} + +void wxCheckBox::Toggle() +{ + ChangeValue(!GetValue()); + + m_isPressed = FALSE; +} + +void wxCheckBox::ChangeValue(bool value) +{ + SetValue(value); + + Click(); +} + +void wxCheckBox::Click() +{ + wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, GetId()); + InitCommandEvent(event); + event.SetInt(IsChecked()); + Command(event); +} + // ---------------------------------------------------------------------------- // input handling // ---------------------------------------------------------------------------- +wxString wxCheckBox::GetInputHandlerType() const +{ + return wxINP_HANDLER_CHECKBOX; +} + bool wxCheckBox::PerformAction(const wxControlAction& action, long numArg, const wxString& strArg) { + if ( action == wxACTION_BUTTON_PRESS ) + Press(); + else if ( action == wxACTION_BUTTON_RELEASE ) + Release(); if ( action == wxACTION_CHECKBOX_CHECK ) - SetValue(TRUE); + ChangeValue(TRUE); else if ( action == wxACTION_CHECKBOX_CLEAR ) - SetValue(FALSE); + ChangeValue(FALSE); else if ( action == wxACTION_CHECKBOX_TOGGLE ) - SetValue(!GetValue()); + Toggle(); else return wxControl::PerformAction(action, numArg, strArg); @@ -170,3 +253,27 @@ bool wxCheckBox::PerformAction(const wxControlAction& action, #endif // wxUSE_CHECKBOX +#if wxUSE_CHECKBOX || wxUSE_RADIOBTN + +// ---------------------------------------------------------------------------- +// wxStdCheckboxInputHandler +// ---------------------------------------------------------------------------- + +wxStdCheckboxInputHandler::wxStdCheckboxInputHandler(wxInputHandler *inphand) + : wxStdButtonInputHandler(inphand) +{ +} + +bool wxStdCheckboxInputHandler::HandleMouse(wxControl *control, + const wxMouseEvent& event) +{ + return wxStdButtonInputHandler::HandleMouse(control, event); +} + +bool wxStdCheckboxInputHandler::HandleMouseMove(wxControl *control, + const wxMouseEvent& event) +{ + return wxStdButtonInputHandler::HandleMouseMove(control, event); +} + +#endif // wxUSE_RADIOBTN || wxUSE_CHECKBOX diff --git a/src/univ/control.cpp b/src/univ/control.cpp index 039cbefa3c..feae6b5f35 100644 --- a/src/univ/control.cpp +++ b/src/univ/control.cpp @@ -77,7 +77,7 @@ bool wxControl::Create(wxWindow *parent, if ( !wxControlBase::Create(parent, id, pos, size, style, validator, name) ) return FALSE; - m_handler = CreateInputHandler(); + m_handler = wxTheme::Get()->GetInputHandler(GetInputHandlerType()); return TRUE; } @@ -143,9 +143,9 @@ void wxControl::OnFocus(wxFocusEvent& event) // input processing // ---------------------------------------------------------------------------- -wxInputHandler *wxControl::CreateInputHandler() const +wxString wxControl::GetInputHandlerType() const { - return wxTheme::Get()->GetInputHandler(GetClassInfo()->GetClassName()); + return wxINP_HANDLER_DEFAULT; } void wxControl::OnKeyDown(wxKeyEvent& event) diff --git a/src/univ/listbox.cpp b/src/univ/listbox.cpp index 000669344e..19b40949b3 100644 --- a/src/univ/listbox.cpp +++ b/src/univ/listbox.cpp @@ -870,6 +870,15 @@ void wxListBox::Activate(int item) } } +// ---------------------------------------------------------------------------- +// input handling +// ---------------------------------------------------------------------------- + +wxString wxListBox::GetInputHandlerType() const +{ + return wxINP_HANDLER_LISTBOX; +} + bool wxListBox::PerformAction(const wxControlAction& action, long numArg, const wxString& strArg) diff --git a/src/univ/renderer.cpp b/src/univ/renderer.cpp index 22e998287b..98bc14e8eb 100644 --- a/src/univ/renderer.cpp +++ b/src/univ/renderer.cpp @@ -458,7 +458,7 @@ void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap, } else if ( alignment & wxALIGN_CENTRE ) { - x = (rect.GetLeft() + rect.GetRight() - width) / 2; + x = (rect.GetLeft() + rect.GetRight() - width + 1) / 2; } else // alignment & wxALIGN_LEFT { @@ -471,7 +471,7 @@ void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap, } else if ( alignment & wxALIGN_CENTRE_VERTICAL ) { - y = (rect.GetTop() + rect.GetBottom() - height) / 2; + y = (rect.GetTop() + rect.GetBottom() - height + 1) / 2; } else // alignment & wxALIGN_TOP { @@ -635,19 +635,26 @@ void wxControlRenderer::DrawItems(const wxListBox *lbox, } } -void wxControlRenderer::DrawLabelBox(const wxBitmap& bitmap, wxCoord margin) +void wxControlRenderer::DrawLabelBox(const wxBitmap& bitmap, + wxCoord marginLeft, + wxCoord marginRight, + wxCoord marginTop) { m_dc.SetFont(m_window->GetFont()); m_dc.SetTextForeground(m_window->GetForegroundColour()); - if ( margin == -1 ) - margin = 4; + // draw the focus border around everything + int flags = m_window->GetStateFlags(); + if ( flags & wxCONTROL_FOCUSED ) + { + m_renderer->DrawCheckBoxFocusBorder(m_dc, &m_rect); + } // calculate the position of the bitmap and of the label - wxRect rectBmp; - rectBmp.width = bitmap.GetWidth(); - rectBmp.height = bitmap.GetHeight(); - rectBmp.y = m_rect.y + (m_rect.height - rectBmp.height + 1) / 2; + wxCoord xBmp, + yBmp = m_rect.y + + (m_rect.height - bitmap.GetHeight() + 1) / 2 + + marginTop; wxRect rectLabel; wxString label = m_window->GetLabel(); @@ -656,25 +663,25 @@ void wxControlRenderer::DrawLabelBox(const wxBitmap& bitmap, wxCoord margin) if ( m_window->GetWindowStyle() & wxALIGN_RIGHT ) { - rectBmp.x = m_rect.GetRight() - rectBmp.width; + xBmp = m_rect.GetRight() - bitmap.GetWidth() - marginLeft; rectLabel.SetLeft(m_rect.GetLeft()); - rectLabel.SetRight(rectBmp.GetLeft() - margin); + rectLabel.SetRight(xBmp - marginRight); } else // normal (checkbox to the left of the text) case { - rectBmp.x = m_rect.GetLeft(); - rectLabel.SetLeft(rectBmp.GetRight() + margin); + xBmp = m_rect.GetLeft() + marginLeft; + rectLabel.SetLeft(xBmp + bitmap.GetWidth() + marginRight); rectLabel.SetRight(m_rect.GetRight()); } - DrawBitmap(bitmap, rectBmp); + m_dc.DrawBitmap(bitmap, xBmp, yBmp, TRUE /* use mask */); wxControl *ctrl = wxStaticCast(m_window, wxControl); m_renderer->DrawLabel(m_dc, label, rectLabel, - m_window->GetStateFlags(), + flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, ctrl->GetAccelIndex()); } diff --git a/src/univ/scrolbar.cpp b/src/univ/scrolbar.cpp index 7760bffc1b..7a03df5a22 100644 --- a/src/univ/scrolbar.cpp +++ b/src/univ/scrolbar.cpp @@ -309,6 +309,11 @@ void wxScrollBar::SetState(Element which, int flags) // input processing // ---------------------------------------------------------------------------- +wxString wxScrollBar::GetInputHandlerType() const +{ + return wxINP_HANDLER_SCROLLBAR; +} + bool wxScrollBar::PerformAction(const wxControlAction& action, long numArg, const wxString& strArg) diff --git a/src/univ/themes/gtk.cpp b/src/univ/themes/gtk.cpp index e2a085f73c..a890676c64 100644 --- a/src/univ/themes/gtk.cpp +++ b/src/univ/themes/gtk.cpp @@ -31,6 +31,7 @@ #include "wx/window.h" #include "wx/button.h" + #include "wx/checkbox.h" #include "wx/scrolbar.h" #endif // WX_PRECOMP @@ -86,6 +87,7 @@ public: int flags = 0, int alignment = wxALIGN_LEFT, int indexAccel = -1); + virtual void DrawCheckBoxFocusBorder(wxDC& dc, wxRect *rect); virtual void DrawButtonBorder(wxDC& dc, const wxRect& rect, int flags = 0, @@ -126,9 +128,16 @@ public: virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) { return fontHeight + 2; } + virtual wxSize GetCheckBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const; + virtual wxSize GetRadioBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const; + // helpers for "wxBitmap wxColourScheme::Get()" void DrawCheckBitmap(wxDC& dc, const wxRect& rect); - void DrawUncheckBitmap(wxDC& dc, const wxRect& rect); + void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed); protected: // DrawBackground() helpers @@ -276,6 +285,17 @@ protected: } }; +class wxGTKCheckboxInputHandler : public wxStdCheckboxInputHandler +{ +public: + wxGTKCheckboxInputHandler(wxInputHandler *handler) + : wxStdCheckboxInputHandler(handler) { } + + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed); +}; + // ---------------------------------------------------------------------------- // wxGTKColourScheme: uses the standard GTK colours // ---------------------------------------------------------------------------- @@ -290,9 +310,10 @@ public: #endif // wxUSE_CHECKBOX private: - // the checkbox bitmaps - wxBitmap m_bmpCheck, - m_bmpUncheck; + // 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]; }; // ---------------------------------------------------------------------------- @@ -312,6 +333,9 @@ public: virtual wxColourScheme *GetColourScheme() { return m_scheme; } private: + // get the default input handler + wxInputHandler *GetDefaultInputHandler(); + wxGTKRenderer *m_renderer; // the names of the already created handlers and the handlers themselves @@ -319,6 +343,8 @@ private: wxSortedArrayString m_handlerNames; wxArrayHandlers m_handlers; + wxGTKInputHandler *m_handlerDefault; + wxGTKColourScheme *m_scheme; WX_DECLARE_THEME(gtk) @@ -338,6 +364,7 @@ wxGTKTheme::wxGTKTheme() { m_scheme = new wxGTKColourScheme; m_renderer = new wxGTKRenderer(m_scheme); + m_handlerDefault = NULL; } wxGTKTheme::~wxGTKTheme() @@ -345,6 +372,16 @@ wxGTKTheme::~wxGTKTheme() WX_CLEAR_ARRAY(m_handlers); } +wxInputHandler *wxGTKTheme::GetDefaultInputHandler() +{ + if ( !m_handlerDefault ) + { + m_handlerDefault = new wxGTKInputHandler(m_renderer); + } + + return m_handlerDefault; +} + wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control) { wxInputHandler *handler; @@ -352,15 +389,17 @@ wxInputHandler *wxGTKTheme::GetInputHandler(const wxString& control) if ( n == wxNOT_FOUND ) { // create a new handler - if ( control.Matches(_T("wx*Button")) ) - handler = new wxStdButtonInputHandler(GetInputHandler(_T("wxControl"))); - else if ( control == _T("wxScrollBar") ) + if ( control == wxINP_HANDLER_BUTTON ) + handler = new wxStdButtonInputHandler(GetDefaultInputHandler()); + else if ( control == wxINP_HANDLER_SCROLLBAR ) handler = new wxGTKScrollBarInputHandler(m_renderer, - GetInputHandler(_T("wxControl"))); - else if ( control == _T("wxListBox") ) - handler = new wxStdListboxInputHandler(GetInputHandler(_T("wxControl")), FALSE); + GetDefaultInputHandler()); + else if ( control == wxINP_HANDLER_CHECKBOX ) + handler = new wxGTKCheckboxInputHandler(GetDefaultInputHandler()); + else if ( control == wxINP_HANDLER_LISTBOX ) + handler = new wxStdListboxInputHandler(GetDefaultInputHandler()); else - handler = new wxGTKInputHandler(m_renderer); + handler = GetDefaultInputHandler(); n = m_handlerNames.Add(control); m_handlers.Insert(handler, n); @@ -455,26 +494,42 @@ wxColour wxGTKColourScheme::Get(wxGTKColourScheme::StdColour col) const wxBitmap wxGTKColourScheme::Get(wxCheckBox::State state, wxCheckBox::Status status) { - if ( !m_bmpCheck.Ok() ) + if ( !m_bitmapsCheckbox[0][0].Ok() ) { // init the bitmaps once only wxRect rect; rect.width = rect.height = 10; - m_bmpCheck.Create(rect.width, rect.height); - m_bmpUncheck.Create(rect.width, rect.height); + 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; - dc.SelectObject(m_bmpCheck); + + // normal checked + dc.SelectObject(m_bitmapsCheckbox[0][0]); renderer->DrawCheckBitmap(dc, rect); - dc.SelectObject(m_bmpUncheck); - renderer->DrawUncheckBitmap(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); } - return status == wxCheckBox::Status_Checked ? m_bmpCheck : m_bmpUncheck; + int row = state == wxCheckBox::State_Pressed ? 1 : 0; + int col = status == wxCheckBox::Status_Checked ? 0 : 1; + + return m_bitmapsCheckbox[row][col]; } #endif // wxUSE_CHECKBOX @@ -700,9 +755,14 @@ bool wxGTKRenderer::AreScrollbarsInsideBorder() const } // ---------------------------------------------------------------------------- -// button border +// borders // ---------------------------------------------------------------------------- +void wxGTKRenderer::DrawCheckBoxFocusBorder(wxDC& dc, wxRect *rect) +{ + DrawRect(dc, rect, m_penBlack); +} + void wxGTKRenderer::DrawButtonBorder(wxDC& dc, const wxRect& rectTotal, int flags, @@ -1288,6 +1348,38 @@ int wxGTKRenderer::PixelToScrollbar(const wxScrollBar *scrollbar, GetScrollbarArrowSize(scrollbar)); } +// ---------------------------------------------------------------------------- +// check/radio bitmaps geometry +// ---------------------------------------------------------------------------- + +wxSize wxGTKRenderer::GetCheckBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const +{ + if ( marginLeft ) + *marginLeft = 2; + if ( marginRight ) + *marginRight = 5; + if ( marginTop ) + *marginTop = 1; + + return wxSize(10, 10); +} + +wxSize wxGTKRenderer::GetRadioBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const +{ + if ( marginLeft ) + *marginLeft = 1; + if ( marginRight ) + *marginRight = 4; + if ( marginTop ) + *marginTop = 1; + + return wxSize(11, 11); +} + // ---------------------------------------------------------------------------- // size adjustments // ---------------------------------------------------------------------------- @@ -1327,7 +1419,9 @@ void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window) // checkbox buttons // ---------------------------------------------------------------------------- -void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc, const wxRect& rectTotal) +void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc, + const wxRect& rectTotal, + bool isPressed) { wxRect rect = rectTotal; DrawShadedRect(dc, &rect, m_penHighlight, m_penBlack); @@ -1335,7 +1429,11 @@ void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc, const wxRect& rectTotal) wxColour col = wxSCHEME_COLOUR(m_scheme, SHADOW_IN); dc.SetPen(wxPen(col, 0, wxSOLID)); - dc.DrawPoint(rect.GetRight(), rect.GetBottom()); + 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)); @@ -1412,3 +1510,24 @@ bool wxGTKInputHandler::HandleMouseMove(wxControl *control, return TRUE; } +// ---------------------------------------------------------------------------- +// wxGTKCheckboxInputHandler +// ---------------------------------------------------------------------------- + +bool wxGTKCheckboxInputHandler::HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) +{ + if ( pressed ) + { + int keycode = event.GetKeyCode(); + if ( keycode == WXK_SPACE || keycode == WXK_RETURN ) + { + control->PerformAction(wxACTION_CHECKBOX_TOGGLE); + + return TRUE; + } + } + + return FALSE; +} diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index 66d33b2d58..471d2e009c 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -104,6 +104,7 @@ public: int flags = 0, int alignment = wxALIGN_LEFT, int indexAccel = -1); + virtual void DrawCheckBoxFocusBorder(wxDC& dc, wxRect *rect); virtual void DrawButtonBorder(wxDC& dc, const wxRect& rect, int flags = 0, @@ -143,6 +144,13 @@ public: virtual wxCoord GetListboxItemHeight(wxCoord fontHeight) { return fontHeight; } + virtual wxSize GetCheckBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const; + virtual wxSize GetRadioBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const; + protected: // common part of DrawLabel() and DrawItem() void DrawFocusRect(wxDC& dc, const wxRect& rect); @@ -258,6 +266,17 @@ protected: int m_interval; }; +class wxWin32CheckboxInputHandler : public wxStdCheckboxInputHandler +{ +public: + wxWin32CheckboxInputHandler(wxInputHandler *handler) + : wxStdCheckboxInputHandler(handler) { } + + virtual bool HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed); +}; + // ---------------------------------------------------------------------------- // wxWin32ColourScheme: uses (default) Win32 colours // ---------------------------------------------------------------------------- @@ -289,6 +308,9 @@ public: virtual wxColourScheme *GetColourScheme(); private: + // get the default input handler + wxInputHandler *GetDefaultInputHandler(); + wxWin32Renderer *m_renderer; // the names of the already created handlers and the handlers themselves @@ -296,6 +318,8 @@ private: wxSortedArrayString m_handlerNames; wxArrayHandlers m_handlers; + wxWin32InputHandler *m_handlerDefault; + wxWin32ColourScheme *m_scheme; WX_DECLARE_THEME(win32) @@ -315,6 +339,7 @@ wxWin32Theme::wxWin32Theme() { m_scheme = new wxWin32ColourScheme; m_renderer = new wxWin32Renderer(m_scheme); + m_handlerDefault = NULL; } wxWin32Theme::~wxWin32Theme() @@ -325,6 +350,16 @@ wxWin32Theme::~wxWin32Theme() delete m_scheme; } +wxInputHandler *wxWin32Theme::GetDefaultInputHandler() +{ + if ( !m_handlerDefault ) + { + m_handlerDefault = new wxWin32InputHandler(m_renderer); + } + + return m_handlerDefault; +} + wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) { wxInputHandler *handler; @@ -332,15 +367,17 @@ wxInputHandler *wxWin32Theme::GetInputHandler(const wxString& control) if ( n == wxNOT_FOUND ) { // create a new handler - if ( control.Matches(_T("wx*Button")) ) - handler = new wxStdButtonInputHandler(GetInputHandler(_T("wxControl"))); - else if ( control == _T("wxScrollBar") ) + if ( control == wxINP_HANDLER_BUTTON ) + handler = new wxStdButtonInputHandler(GetDefaultInputHandler()); + else if ( control == wxINP_HANDLER_SCROLLBAR ) handler = new wxWin32ScrollBarInputHandler(m_renderer, - GetInputHandler(_T("wxControl"))); - else if ( control == _T("wxListBox") ) - handler = new wxStdListboxInputHandler(GetInputHandler(_T("wxControl"))); + GetDefaultInputHandler()); + else if ( control == wxINP_HANDLER_CHECKBOX ) + handler = new wxWin32CheckboxInputHandler(GetDefaultInputHandler()); + else if ( control == wxINP_HANDLER_LISTBOX ) + handler = new wxStdListboxInputHandler(GetDefaultInputHandler()); else - handler = new wxWin32InputHandler(m_renderer); + handler = GetDefaultInputHandler(); n = m_handlerNames.Add(control); m_handlers.Insert(handler, n); @@ -843,9 +880,14 @@ bool wxWin32Renderer::AreScrollbarsInsideBorder() const } // ---------------------------------------------------------------------------- -// button border +// borders // ---------------------------------------------------------------------------- +void wxWin32Renderer::DrawCheckBoxFocusBorder(wxDC& dc, wxRect *rect) +{ + // we don't have it +} + void wxWin32Renderer::DrawButtonBorder(wxDC& dc, const wxRect& rectTotal, int flags, @@ -1268,6 +1310,34 @@ int wxWin32Renderer::PixelToScrollbar(const wxScrollBar *scrollbar, return StandardPixelToScrollbar(scrollbar, coord, m_sizeScrollbarArrow); } +// ---------------------------------------------------------------------------- +// check/radio bitmaps geometry +// ---------------------------------------------------------------------------- + +wxSize wxWin32Renderer::GetCheckBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const +{ + if ( marginLeft ) + *marginLeft = 2; + if ( marginRight ) + *marginRight = 5; + + return wxSize(10, 10); +} + +wxSize wxWin32Renderer::GetRadioBitmapSize(wxCoord *marginLeft, + wxCoord *marginRight, + wxCoord *marginTop) const +{ + if ( marginLeft ) + *marginLeft = 1; + if ( marginRight ) + *marginRight = 4; + + return wxSize(11, 11); +} + // ---------------------------------------------------------------------------- // size adjustments // ---------------------------------------------------------------------------- @@ -1492,3 +1562,42 @@ bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl *control, return wxStdScrollBarInputHandler::HandleMouseMove(control, event); } + +// ---------------------------------------------------------------------------- +// wxWin32CheckboxInputHandler +// ---------------------------------------------------------------------------- + +bool wxWin32CheckboxInputHandler::HandleKey(wxControl *control, + const wxKeyEvent& event, + bool pressed) +{ + if ( pressed ) + { + wxControlAction action; + int keycode = event.GetKeyCode(); + switch ( keycode ) + { + case WXK_SPACE: + action = wxACTION_CHECKBOX_TOGGLE; + break; + + case '-': + action = wxACTION_CHECKBOX_CHECK; + break; + + case '+': + case '=': + action = wxACTION_CHECKBOX_CLEAR; + break; + } + + if ( !!action ) + { + control->PerformAction(wxACTION_CHECKBOX_TOGGLE); + + return TRUE; + } + } + + return FALSE; +}