diff --git a/include/wx/checkbox.h b/include/wx/checkbox.h index 00e73dca9e..473ec494f4 100644 --- a/include/wx/checkbox.h +++ b/include/wx/checkbox.h @@ -99,6 +99,11 @@ public: virtual bool HasTransparentBackground() wxOVERRIDE { return true; } + // This semi-private function is currently used to allow wxMSW checkbox to + // blend in with its parent background colour without changing the + // background colour of the checkbox itself under the other platforms. + virtual void SetTransparentPartColour(const wxColour& WXUNUSED(col)) { } + // wxCheckBox-specific processing after processing the update event virtual void DoUpdateWindowUI(wxUpdateUIEvent& event) wxOVERRIDE { diff --git a/include/wx/generic/private/grid.h b/include/wx/generic/private/grid.h index cd92f64fe5..172738df55 100644 --- a/include/wx/generic/private/grid.h +++ b/include/wx/generic/private/grid.h @@ -15,6 +15,8 @@ #if wxUSE_GRID +#include "wx/headerctrl.h" + // Internally used (and hence intentionally not exported) event telling wxGrid // to hide the currently shown editor. wxDECLARE_EVENT( wxEVT_GRID_HIDE_EDITOR, wxCommandEvent ); @@ -1005,5 +1007,16 @@ private: wxGridDataTypeInfoArray m_typeinfo; }; +// Returns the rectangle for showing something of the given size in a cell with +// the given alignment. +// +// The function is used by wxGridCellBoolEditor and wxGridCellBoolRenderer to +// draw a check mark and position wxCheckBox respectively. +wxRect +wxGetContentRect(wxSize contentSize, + const wxRect& cellRect, + int hAlign, + int vAlign); + #endif // wxUSE_GRID #endif // _WX_GENERIC_GRID_PRIVATE_H_ diff --git a/include/wx/msw/checkbox.h b/include/wx/msw/checkbox.h index f8b12c1f3b..e8d042a1d6 100644 --- a/include/wx/msw/checkbox.h +++ b/include/wx/msw/checkbox.h @@ -45,6 +45,11 @@ public: // override some base class virtuals virtual void SetLabel(const wxString& label) wxOVERRIDE; + virtual void SetTransparentPartColour(const wxColour& col) wxOVERRIDE + { + SetBackgroundColour(col); + } + virtual bool MSWCommand(WXUINT param, WXWORD id) wxOVERRIDE; virtual void Command(wxCommandEvent& event) wxOVERRIDE; diff --git a/include/wx/renderer.h b/include/wx/renderer.h index 4a4b92375a..da22e391cb 100644 --- a/include/wx/renderer.h +++ b/include/wx/renderer.h @@ -259,7 +259,7 @@ public: int flags = 0) = 0; // Returns the default size of a check box. - virtual wxSize GetCheckBoxSize(wxWindow *win) = 0; + virtual wxSize GetCheckBoxSize(wxWindow *win, int flags = 0) = 0; // Returns the default size of a check mark. virtual wxSize GetCheckMarkSize(wxWindow *win) = 0; @@ -496,8 +496,8 @@ public: int flags = 0) wxOVERRIDE { m_rendererNative.DrawCheckMark( win, dc, rect, flags ); } - virtual wxSize GetCheckBoxSize(wxWindow *win) wxOVERRIDE - { return m_rendererNative.GetCheckBoxSize(win); } + virtual wxSize GetCheckBoxSize(wxWindow *win, int flags = 0) wxOVERRIDE + { return m_rendererNative.GetCheckBoxSize(win, flags); } virtual wxSize GetCheckMarkSize(wxWindow *win) wxOVERRIDE { return m_rendererNative.GetCheckMarkSize(win); } diff --git a/interface/wx/renderer.h b/interface/wx/renderer.h index 0cb0685fc7..c73779682a 100644 --- a/interface/wx/renderer.h +++ b/interface/wx/renderer.h @@ -237,7 +237,7 @@ public: virtual void DrawCheckMark(wxWindow *win, wxDC& dc, const wxRect& rect, int flags = 0 ); - virtual wxSize GetCheckBoxSize(wxWindow *win); + virtual wxSize GetCheckBoxSize(wxWindow *win, int flags = 0); virtual wxSize GetCheckMarkSize(wxWindow *win); @@ -573,8 +573,13 @@ public: @param win A valid, i.e. non-null, window pointer which is used to get the theme defining the checkbox size under some platforms. + + @param flags The only acceptable flag is @c wxCONTROL_CELL which means + that just the size of the checkbox itself is returned, without any + margins that are included by default. This parameter is only + available in wxWidgets 3.1.4 or later. */ - virtual wxSize GetCheckBoxSize(wxWindow* win) = 0; + virtual wxSize GetCheckBoxSize(wxWindow* win, int flags = 0) = 0; /** Returns the size of a check mark. diff --git a/samples/grid/griddemo.cpp b/samples/grid/griddemo.cpp index aa6f348e5e..bc68dae5dc 100644 --- a/samples/grid/griddemo.cpp +++ b/samples/grid/griddemo.cpp @@ -521,6 +521,10 @@ GridFrame::GridFrame() grid->SetCellEditor(3, 0, new wxGridCellBoolEditor); grid->SetCellBackgroundColour(3, 0, wxColour(255, 127, 127)); + grid->SetCellRenderer(3, 1, new wxGridCellBoolRenderer); + grid->SetCellEditor(3, 1, new wxGridCellBoolEditor); + grid->SetCellValue(3, 1, "1"); + wxGridCellAttr *attr; attr = new wxGridCellAttr; attr->SetTextColour(*wxBLUE); diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index f940fbbd40..d4983e04e0 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -111,6 +111,9 @@ const int GRID_HASH_SIZE = 100; // operation const int DRAG_SENSITIVITY = 3; +// the space between the cell edge and the checkbox mark +const int GRID_CELL_CHECKBOX_MARGIN = 2; + } // anonymous namespace #include "wx/arrimpl.cpp" @@ -6980,18 +6983,10 @@ void wxGrid::ShowCellEditControl() if (rect.x < 0) nXMove = rect.x; -#ifndef __WXQT__ - // cell is shifted by one pixel - // However, don't allow x or y to become negative - // since the SetSize() method interprets that as - // "don't change." - if (rect.x > 0) - rect.x--; - if (rect.y > 0) - rect.y--; -#else +#ifdef __WXQT__ // Substract 1 pixel in every dimension to fit in the cell area. // If not, Qt will draw the control outside the cell. + // TODO: Check offsets under Qt. rect.Deflate(1, 1); #endif @@ -10337,4 +10332,55 @@ wxGridCellEditor* wxGridTypeRegistry::GetEditor(int index) return editor; } +wxRect +wxGetContentRect(wxSize contentSize, + const wxRect& cellRect, + int hAlign, + int vAlign) +{ + // Keep square aspect ratio for the checkbox, but ensure that it fits into + // the available space, even if it's smaller than the standard size. + const wxCoord minSize = wxMin(cellRect.width, cellRect.height); + if ( contentSize.x >= minSize || contentSize.y >= minSize ) + { + // It must still have positive size, however. + const int fittingSize = wxMax(1, minSize - 2*GRID_CELL_CHECKBOX_MARGIN); + + contentSize.x = + contentSize.y = fittingSize; + } + + wxRect contentRect(contentSize); + + if ( hAlign & wxALIGN_CENTER_HORIZONTAL ) + { + contentRect = contentRect.CentreIn(cellRect, wxHORIZONTAL); + } + else if ( hAlign & wxALIGN_RIGHT ) + { + contentRect.SetX(cellRect.x + cellRect.width + - contentSize.x - GRID_CELL_CHECKBOX_MARGIN); + } + else // ( hAlign == wxALIGN_LEFT ) and invalid alignment value + { + contentRect.SetX(cellRect.x + GRID_CELL_CHECKBOX_MARGIN); + } + + if ( vAlign & wxALIGN_CENTER_VERTICAL ) + { + contentRect = contentRect.CentreIn(cellRect, wxVERTICAL); + } + else if ( vAlign & wxALIGN_BOTTOM ) + { + contentRect.SetY(cellRect.y + cellRect.height + - contentRect.y - GRID_CELL_CHECKBOX_MARGIN); + } + else // wxALIGN_TOP + { + contentRect.SetY(cellRect.y + GRID_CELL_CHECKBOX_MARGIN); + } + + return contentRect; +} + #endif // wxUSE_GRID diff --git a/src/generic/gridctrl.cpp b/src/generic/gridctrl.cpp index f6df548502..585a8e6341 100644 --- a/src/generic/gridctrl.cpp +++ b/src/generic/gridctrl.cpp @@ -31,6 +31,7 @@ #include "wx/tokenzr.h" #include "wx/renderer.h" +#include "wx/generic/private/grid.h" // ---------------------------------------------------------------------------- // wxGridCellRenderer @@ -936,7 +937,8 @@ wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid, // compute it only once (no locks for MT safeness in GUI thread...) if ( !ms_sizeCheckMark.x ) { - ms_sizeCheckMark = wxRendererNative::Get().GetCheckBoxSize(&grid); + ms_sizeCheckMark = + wxRendererNative::Get().GetCheckBoxSize(&grid, wxCONTROL_CELL); } return ms_sizeCheckMark; @@ -951,43 +953,13 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid, { wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); - // draw a check mark in the centre (ignoring alignment - TODO) - wxSize size = GetBestSize(grid, attr, dc, row, col); + int hAlign = wxALIGN_LEFT; + int vAlign = wxALIGN_CENTRE_VERTICAL; + attr.GetNonDefaultAlignment(&hAlign, &vAlign); - // don't draw outside the cell - wxCoord minSize = wxMin(rect.width, rect.height); - if ( size.x >= minSize || size.y >= minSize ) - { - // and even leave (at least) 1 pixel margin - size.x = size.y = minSize; - } - - // draw a border around checkmark - int vAlign, hAlign; - attr.GetAlignment(&hAlign, &vAlign); - - wxRect rectBorder; - if (hAlign == wxALIGN_CENTRE) - { - rectBorder.x = rect.x + rect.width / 2 - size.x / 2; - rectBorder.y = rect.y + rect.height / 2 - size.y / 2; - rectBorder.width = size.x; - rectBorder.height = size.y; - } - else if (hAlign == wxALIGN_LEFT) - { - rectBorder.x = rect.x + 2; - rectBorder.y = rect.y + rect.height / 2 - size.y / 2; - rectBorder.width = size.x; - rectBorder.height = size.y; - } - else if (hAlign == wxALIGN_RIGHT) - { - rectBorder.x = rect.x + rect.width - size.x - 2; - rectBorder.y = rect.y + rect.height / 2 - size.y / 2; - rectBorder.width = size.x; - rectBorder.height = size.y; - } + const wxRect checkBoxRect = + wxGetContentRect(GetBestSize(grid, attr, dc, row, col), + rect, hAlign, vAlign); bool value; if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) ) @@ -1000,11 +972,11 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid, value = wxGridCellBoolEditor::IsTrueValue(cellval); } - int flags = 0; + int flags = wxCONTROL_CELL; if (value) flags |= wxCONTROL_CHECKED; - wxRendererNative::Get().DrawCheckBox( &grid, dc, rectBorder, flags ); + wxRendererNative::Get().DrawCheckBox( &grid, dc, checkBoxRect, flags ); } #endif // wxUSE_GRID diff --git a/src/generic/grideditors.cpp b/src/generic/grideditors.cpp index f8799997e3..3fb11821ea 100644 --- a/src/generic/grideditors.cpp +++ b/src/generic/grideditors.cpp @@ -37,7 +37,6 @@ #include "wx/spinctrl.h" #include "wx/tokenzr.h" #include "wx/renderer.h" -#include "wx/headerctrl.h" #include "wx/datectrl.h" #include "wx/generic/gridsel.h" @@ -441,38 +440,17 @@ void wxGridCellTextEditor::SetSize(const wxRect& rectOrig) // Make the edit control large enough to allow for internal margins // - // TODO: remove this if the text ctrl sizing is improved esp. for unix + // TODO: remove this if the text ctrl sizing is improved // -#if defined(__WXGTK__) - if (rect.x != 0) - { - rect.x += 1; - rect.y += 1; - rect.width -= 1; - rect.height -= 1; - } -#elif defined(__WXMSW__) - if ( rect.x == 0 ) - rect.x += 2; - else - rect.x += 3; - - if ( rect.y == 0 ) - rect.y += 2; - else - rect.y += 3; +#if defined(__WXMSW__) + rect.x += 2; + rect.y += 2; rect.width -= 2; rect.height -= 2; -#elif defined(__WXOSX__) - rect.x += 1; - rect.y += 1; - - rect.width -= 1; - rect.height -= 1; -#else - int extra_x = ( rect.x > 2 ) ? 2 : 1; - int extra_y = ( rect.y > 2 ) ? 2 : 1; +#elif !defined(__WXGTK__) + int extra_x = 2; + int extra_y = 2; #if defined(__WXMOTIF__) extra_x *= 2; @@ -1240,83 +1218,50 @@ void wxGridCellBoolEditor::Create(wxWindow* parent, void wxGridCellBoolEditor::SetSize(const wxRect& r) { - bool resize = false; - wxSize size = m_control->GetSize(); - wxCoord minSize = wxMin(r.width, r.height); - - // check if the checkbox is not too big/small for this cell - wxSize sizeBest = m_control->GetBestSize(); - if ( !(size == sizeBest) ) - { - // reset to default size if it had been made smaller - size = sizeBest; - - resize = true; - } - - if ( size.x >= minSize || size.y >= minSize ) - { - // leave 1 pixel margin - size.x = size.y = minSize - 2; - - resize = true; - } - - if ( resize ) - { - m_control->SetSize(size); - } - - // position it in the centre of the rectangle (TODO: support alignment?) - -#if defined(__WXGTK__) || defined (__WXMOTIF__) - // the checkbox without label still has some space to the right in wxGTK, - // so shift it to the right - size.x -= 8; -#elif defined(__WXMSW__) - // here too, but in other way - size.x += 1; - size.y -= 2; -#endif - - int hAlign = wxALIGN_CENTRE; - int vAlign = wxALIGN_CENTRE; + int hAlign = wxALIGN_LEFT; + int vAlign = wxALIGN_CENTRE_VERTICAL; if (GetCellAttr()) - GetCellAttr()->GetAlignment(& hAlign, & vAlign); + GetCellAttr()->GetNonDefaultAlignment(&hAlign, &vAlign); - int x = 0, y = 0; - if (hAlign == wxALIGN_LEFT) - { - x = r.x + 2; + const wxRect checkBoxRect = + wxGetContentRect(m_control->GetSize(), r, hAlign, vAlign); -#ifdef __WXMSW__ - x += 2; -#endif - - y = r.y + r.height / 2 - size.y / 2; - } - else if (hAlign == wxALIGN_RIGHT) - { - x = r.x + r.width - size.x - 2; - y = r.y + r.height / 2 - size.y / 2; - } - else if (hAlign == wxALIGN_CENTRE) - { - x = r.x + r.width / 2 - size.x / 2; - y = r.y + r.height / 2 - size.y / 2; - } - - m_control->Move(x, y); + // Don't resize the checkbox, it should have its default (and fitting) + // size, but do move it to the right position. + m_control->Move(checkBoxRect.GetPosition()); } void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr) { m_control->Show(show); + // Under MSW we need to set the checkbox background colour to the same + // colour as is used by the cell in order for it to blend in, but using + // just SetBackgroundColour() would be wrong as this would actually change + // the background of the checkbox with e.g. GTK 3, making it unusable in + // any theme where the check mark colour is the same, or close to, our + // background colour -- which happens to be the case for the default GTK 3 + // theme, making this a rather serious problem. + // + // One possible workaround would be to set the foreground colour too, but + // wxRendererNative methods used in wxGridCellBoolRenderer don't currently + // take the colours into account, so this would mean that starting to edit + // a boolean field would change its colours, which would be jarring (and + // especially so as we currently set custom colours for all cells, not just + // those that really need them). + // + // A more portable solution could be to create a parent window using the + // background colour if it's different from the default and reparent the + // checkbox under it, so that the parent window colour showed through the + // transparent parts of the checkbox, but this would be more complicated + // for no real gain in practice. + // + // So, finally, just use the bespoke function that will change the + // background under MSW, but doesn't do anything elsewhere. if ( show ) { wxColour colBg = attr ? attr->GetBackgroundColour() : *wxLIGHT_GREY; - CBox()->SetBackgroundColour(colBg); + CBox()->SetTransparentPartColour(colBg); } } diff --git a/src/generic/renderg.cpp b/src/generic/renderg.cpp index 4a328ffaa8..b8fc63a3c0 100644 --- a/src/generic/renderg.cpp +++ b/src/generic/renderg.cpp @@ -111,7 +111,7 @@ public: const wxRect& rect, int flags = 0) wxOVERRIDE; - virtual wxSize GetCheckBoxSize(wxWindow *win) wxOVERRIDE; + virtual wxSize GetCheckBoxSize(wxWindow *win, int flags = 0) wxOVERRIDE; virtual wxSize GetCheckMarkSize(wxWindow *win) wxOVERRIDE; @@ -731,7 +731,7 @@ wxRendererGeneric::DrawCheckMark(wxWindow *WXUNUSED(win), dc.DrawCheckMark(rect); } -wxSize wxRendererGeneric::GetCheckBoxSize(wxWindow *win) +wxSize wxRendererGeneric::GetCheckBoxSize(wxWindow *win, int WXUNUSED(flags)) { wxCHECK_MSG( win, wxSize(0, 0), "Must have a valid window" ); @@ -740,7 +740,7 @@ wxSize wxRendererGeneric::GetCheckBoxSize(wxWindow *win) wxSize wxRendererGeneric::GetCheckMarkSize(wxWindow *win) { - return GetCheckBoxSize(win); + return GetCheckBoxSize(win, wxCONTROL_CELL); } wxSize wxRendererGeneric::GetExpanderSize(wxWindow *win) diff --git a/src/gtk/checkbox.cpp b/src/gtk/checkbox.cpp index d11c7ef205..0579417ebc 100644 --- a/src/gtk/checkbox.cpp +++ b/src/gtk/checkbox.cpp @@ -146,13 +146,32 @@ bool wxCheckBox::Create(wxWindow *parent, g_object_ref(m_widget); SetLabel( label ); + if ( style & wxNO_BORDER ) + { + gtk_container_set_border_width(GTK_CONTAINER(m_widgetCheckbox), 0); + } + g_signal_connect (m_widgetCheckbox, "toggled", G_CALLBACK (gtk_checkbox_toggled_callback), this); m_parent->DoAddChild( this ); +#ifdef __WXGTK3__ + // CSS added if the window has wxNO_BORDER inside base class PostCreation() + // makes checkbox look broken in the default GTK 3 theme, so avoid doing + // this by temporarily turning this flag off. + if ( style & wxNO_BORDER ) + ToggleWindowStyle(wxNO_BORDER); +#endif + PostCreation(size); +#ifdef __WXGTK3__ + // Turn it back on if necessary. + if ( style & wxNO_BORDER ) + ToggleWindowStyle(wxNO_BORDER); +#endif + return true; } diff --git a/src/gtk/renderer.cpp b/src/gtk/renderer.cpp index b35dfe381d..f4a3fb2819 100644 --- a/src/gtk/renderer.cpp +++ b/src/gtk/renderer.cpp @@ -133,7 +133,7 @@ public: virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0) wxOVERRIDE; - virtual wxSize GetCheckBoxSize(wxWindow *win) wxOVERRIDE; + virtual wxSize GetCheckBoxSize(wxWindow *win, int flags = 0) wxOVERRIDE; virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win) wxOVERRIDE; }; @@ -552,27 +552,131 @@ wxRendererGTK::DrawComboBoxDropButton(wxWindow *win, DrawDropArrow(win,dc,rect); } -#ifdef __WXGTK3__ -static void CheckBoxSize(wxGtkStyleContext& sc, int& w, int& h, GtkBorder* extra = NULL) +// Helper used by GetCheckBoxSize() and DrawCheckBox(). +namespace { - gtk_style_context_get(sc, GTK_STATE_FLAG_NORMAL, - "min-width", &w, "min-height", &h, NULL); - GtkBorder border, padding; - gtk_style_context_get_border(sc, GTK_STATE_FLAG_NORMAL, &border); - gtk_style_context_get_padding(sc, GTK_STATE_FLAG_NORMAL, &padding); - border.left += padding.left; - border.right += padding.right; - border.top += padding.top; - border.bottom += padding.bottom; - w += border.left + border.right; - h += border.top + border.bottom; - if (extra) - *extra = border; -} -#endif // __WXGTK3__ + +struct CheckBoxInfo +{ +#ifdef __WXGTK3__ + CheckBoxInfo(wxGtkStyleContext& sc, int flags) + { + wxUnusedVar(flags); + + sc.AddCheckButton(); + if (gtk_check_version(3,20,0) == NULL) + { + sc.Add("check"); + gtk_style_context_get(sc, GTK_STATE_FLAG_NORMAL, + "min-width", &indicator_width, + "min-height", &indicator_height, + NULL); + + GtkBorder border, padding; + gtk_style_context_get_border(sc, GTK_STATE_FLAG_NORMAL, &border); + gtk_style_context_get_padding(sc, GTK_STATE_FLAG_NORMAL, &padding); + + margin_left = border.left + padding.left; + margin_top = border.top + padding.top; + margin_right = border.right + padding.right; + margin_bottom = border.bottom + padding.bottom; + } + else + { + GValue value = G_VALUE_INIT; + g_value_init(&value, G_TYPE_INT); + + gtk_style_context_get_style_property(sc, "indicator-size", &value); + indicator_width = + indicator_height = g_value_get_int(&value); + + gtk_style_context_get_style_property(sc, "indicator-spacing", &value); + margin_left = + margin_top = + margin_right = + margin_bottom = g_value_get_int(&value); + + g_value_unset(&value); + } + } +#else // !__WXGTK3__ + CheckBoxInfo(GtkWidget* button, int flags) + { + gint indicator_size, indicator_margin; + gtk_widget_style_get(button, + "indicator_size", &indicator_size, + "indicator_spacing", &indicator_margin, + NULL); + + // If wxCONTROL_CELL is set then we want to get the size of wxCheckBox + // control to draw the check mark centered and at the same position as + // wxCheckBox does, so offset the check mark itself by the focus margin + // in the same way as gtk_real_check_button_draw_indicator() does it, see + // https://github.com/GNOME/gtk/blob/GTK_2_16_0/gtk/gtkcheckbutton.c#L374 + if ( flags & wxCONTROL_CELL ) + { + gint focus_width, focus_pad; + gtk_widget_style_get(button, + "focus-line-width", &focus_width, + "focus-padding", &focus_pad, + NULL); + + indicator_margin += focus_width + focus_pad; + } + + // In GTK 2 width and height are the same and so are left/right and + // top/bottom. + indicator_width = + indicator_height = indicator_size; + + margin_left = + margin_top = + margin_right = + margin_bottom = indicator_margin; + } +#endif // __WXGTK3__/!__WXGTK3__ + + // Make sure we fit into the provided rectangle, eliminating margins and + // even reducing the size if necessary. + void FitInto(const wxRect& rect) + { + if ( indicator_width > rect.width ) + { + indicator_width = rect.width; + margin_left = + margin_right = 0; + } + else if ( indicator_width + margin_left + margin_right > rect.width ) + { + margin_left = + margin_right = (rect.width - indicator_width) / 2; + } + + if ( indicator_height > rect.height ) + { + indicator_height = rect.height; + margin_top = + margin_bottom = 0; + } + else if ( indicator_height + margin_top + margin_bottom > rect.height ) + { + margin_top = + margin_bottom = (rect.height - indicator_height) / 2; + } + } + + gint indicator_width, + indicator_height; + gint margin_left, + margin_top, + margin_right, + margin_bottom; +}; + +} // anonymous namespace wxSize -wxRendererGTK::GetCheckBoxSize(wxWindow* win) +wxRendererGTK::GetCheckBoxSize(wxWindow* win, int flags) { wxSize size; // Even though we don't use the window in this implementation, still check @@ -582,32 +686,16 @@ wxRendererGTK::GetCheckBoxSize(wxWindow* win) #ifdef __WXGTK3__ wxGtkStyleContext sc(win->GetContentScaleFactor()); - sc.AddCheckButton(); - if (gtk_check_version(3,20,0) == NULL) - { - sc.Add("check"); - CheckBoxSize(sc, size.x, size.y); - } - else - { - GValue value = G_VALUE_INIT; - g_value_init(&value, G_TYPE_INT); - gtk_style_context_get_style_property(sc, "indicator-size", &value); - size.x = g_value_get_int(&value); - gtk_style_context_get_style_property(sc, "indicator-spacing", &value); - size.x += 2 * g_value_get_int(&value); - size.y = size.x; - g_value_unset(&value); - } -#else // !__WXGTK3__ - gint indicator_size, indicator_spacing; - gtk_widget_style_get(wxGTKPrivate::GetCheckButtonWidget(), - "indicator_size", &indicator_size, - "indicator_spacing", &indicator_spacing, - NULL); - size.x = size.y = indicator_size + indicator_spacing * 2; -#endif // !__WXGTK3__ + const CheckBoxInfo info(sc, flags); +#else // !__WXGTK3__ + GtkWidget* button = wxGTKPrivate::GetCheckButtonWidget(); + + const CheckBoxInfo info(button, flags); +#endif // __WXGTK3__/!__WXGTK3__ + + size.x = info.indicator_width + info.margin_left + info.margin_right; + size.y = info.indicator_height + info.margin_top + info.margin_bottom; return size; } @@ -618,14 +706,63 @@ wxRendererGTK::DrawCheckBox(wxWindow*, const wxRect& rect, int flags ) { -#ifndef __WXGTK3__ - GtkWidget *button = wxGTKPrivate::GetCheckButtonWidget(); +#ifdef __WXGTK3__ + cairo_t* cr = wxGetGTKDrawable(dc); + if (cr == NULL) + return; - gint indicator_size, indicator_spacing; - gtk_widget_style_get(button, - "indicator_size", &indicator_size, - "indicator_spacing", &indicator_spacing, - NULL); + int state = GTK_STATE_FLAG_NORMAL; + if (flags & wxCONTROL_CHECKED) + { + state = GTK_STATE_FLAG_ACTIVE; + if (gtk_check_version(3,14,0) == NULL) + state = GTK_STATE_FLAG_CHECKED; + } + if (flags & wxCONTROL_DISABLED) + state |= GTK_STATE_FLAG_INSENSITIVE; + if (flags & wxCONTROL_UNDETERMINED) + state |= GTK_STATE_FLAG_INCONSISTENT; + if (flags & wxCONTROL_CURRENT) + state |= GTK_STATE_FLAG_PRELIGHT; + + wxGtkStyleContext sc(dc.GetContentScaleFactor()); + + CheckBoxInfo info(sc, flags); + info.FitInto(rect); + + const int w = info.indicator_width + info.margin_left + info.margin_right; + const int h = info.indicator_height + info.margin_top + info.margin_bottom; + + const int x = rect.x + (rect.width - w) / 2; + const int y = rect.y + (rect.height - h) / 2; + + if (gtk_check_version(3,20,0) == NULL) + { + gtk_style_context_set_state(sc, GtkStateFlags(state)); + gtk_render_background(sc, cr, x, y, w, h); + gtk_render_frame(sc, cr, x, y, w, h); + + // check is rendered in content area + gtk_render_check(sc, cr, + x + info.margin_left, y + info.margin_top, + info.indicator_width, info.indicator_height); + } + else + { + // need save/restore for GTK+ 3.6 & 3.8 + gtk_style_context_save(sc); + gtk_style_context_set_state(sc, GtkStateFlags(state)); + gtk_render_background(sc, cr, x, y, w, h); + gtk_render_frame(sc, cr, x, y, w, h); + gtk_style_context_add_class(sc, "check"); + gtk_render_check(sc, cr, x, y, w, h); + gtk_style_context_restore(sc); + } +#else // !__WXGTK3__ + GtkWidget* button = wxGTKPrivate::GetCheckButtonWidget(); + + CheckBoxInfo info(button, flags); + info.FitInto(rect); GtkStateType state; @@ -646,69 +783,7 @@ wxRendererGTK::DrawCheckBox(wxWindow*, shadow_type = GTK_SHADOW_IN; else shadow_type = GTK_SHADOW_OUT; -#endif -#ifdef __WXGTK3__ - cairo_t* cr = wxGetGTKDrawable(dc); - if (cr == NULL) - return; - - int state = GTK_STATE_FLAG_NORMAL; - if (flags & wxCONTROL_CHECKED) - { - state = GTK_STATE_FLAG_ACTIVE; - if (gtk_check_version(3,14,0) == NULL) - state = GTK_STATE_FLAG_CHECKED; - } - if (flags & wxCONTROL_DISABLED) - state |= GTK_STATE_FLAG_INSENSITIVE; - if (flags & wxCONTROL_UNDETERMINED) - state |= GTK_STATE_FLAG_INCONSISTENT; - if (flags & wxCONTROL_CURRENT) - state |= GTK_STATE_FLAG_PRELIGHT; - - int w, h; - wxGtkStyleContext sc(dc.GetContentScaleFactor()); - sc.AddCheckButton(); - if (gtk_check_version(3,20,0) == NULL) - { - sc.Add("check"); - GtkBorder extra; - CheckBoxSize(sc, w, h, &extra); - - int x = rect.x + (rect.width - w) / 2; - int y = rect.y + (rect.height - h) / 2; - gtk_style_context_set_state(sc, GtkStateFlags(state)); - gtk_render_background(sc, cr, x, y, w, h); - gtk_render_frame(sc, cr, x, y, w, h); - - // check is rendered in content area - x += extra.left; - y += extra.top; - w -= extra.left + extra.right; - h -= extra.top + extra.bottom; - gtk_render_check(sc, cr, x, y, w, h); - } - else - { - GValue value = G_VALUE_INIT; - g_value_init(&value, G_TYPE_INT); - gtk_style_context_get_style_property(sc, "indicator-size", &value); - w = h = g_value_get_int(&value); - g_value_unset(&value); - - // need save/restore for GTK+ 3.6 & 3.8 - gtk_style_context_save(sc); - gtk_style_context_set_state(sc, GtkStateFlags(state)); - const int x = rect.x + (rect.width - w) / 2; - const int y = rect.y + (rect.height - h) / 2; - gtk_render_background(sc, cr, x, y, w, h); - gtk_render_frame(sc, cr, x, y, w, h); - gtk_style_context_add_class(sc, "check"); - gtk_render_check(sc, cr, x, y, w, h); - gtk_style_context_restore(sc); - } -#else GdkWindow* gdk_window = wxGetGTKDrawable(dc); if (gdk_window == NULL) return; @@ -722,11 +797,11 @@ wxRendererGTK::DrawCheckBox(wxWindow*, NULL, button, "cellcheck", - dc.LogicalToDeviceX(rect.x) + indicator_spacing, - dc.LogicalToDeviceY(rect.y) + indicator_spacing, - indicator_size, indicator_size + dc.LogicalToDeviceX(rect.x) + info.margin_left, + dc.LogicalToDeviceY(rect.y) + (rect.height - info.indicator_height) / 2, + info.indicator_width, info.indicator_height ); -#endif +#endif // __WXGTK3__/!__WXGTK3__ } void diff --git a/src/msw/renderer.cpp b/src/msw/renderer.cpp index 6645283603..71ca2a489b 100644 --- a/src/msw/renderer.cpp +++ b/src/msw/renderer.cpp @@ -162,7 +162,7 @@ public: wxTitleBarButton button, int flags = 0) wxOVERRIDE; - virtual wxSize GetCheckBoxSize(wxWindow *win) wxOVERRIDE; + virtual wxSize GetCheckBoxSize(wxWindow *win, int flags = 0) wxOVERRIDE; virtual int GetHeaderButtonHeight(wxWindow *win) wxOVERRIDE; @@ -288,7 +288,7 @@ public: wxTitleBarButton button, int flags = 0) wxOVERRIDE; - virtual wxSize GetCheckBoxSize(wxWindow *win) wxOVERRIDE; + virtual wxSize GetCheckBoxSize(wxWindow *win, int flags = 0) wxOVERRIDE; virtual wxSize GetCheckMarkSize(wxWindow* win) wxOVERRIDE; @@ -548,7 +548,7 @@ wxRendererMSW::DrawTitleBarBitmap(wxWindow *win, DoDrawFrameControl(DFC_CAPTION, kind, win, dc, rect, flags); } -wxSize wxRendererMSW::GetCheckBoxSize(wxWindow* win) +wxSize wxRendererMSW::GetCheckBoxSize(wxWindow* win, int WXUNUSED(flags)) { // We must have a valid window in order to return the size which is correct // for the display this window is on. @@ -893,7 +893,7 @@ wxRendererXP::DrawTitleBarBitmap(wxWindow *win, DoDrawButtonLike(hTheme, part, dc, rect, flags); } -wxSize wxRendererXP::GetCheckBoxSize(wxWindow* win) +wxSize wxRendererXP::GetCheckBoxSize(wxWindow* win, int flags) { wxCHECK_MSG( win, wxSize(0, 0), "Must have a valid window" ); @@ -907,7 +907,7 @@ wxSize wxRendererXP::GetCheckBoxSize(wxWindow* win) return wxSize(checkSize.cx, checkSize.cy); } } - return m_rendererNative.GetCheckBoxSize(win); + return m_rendererNative.GetCheckBoxSize(win, flags); } wxSize wxRendererXP::GetCheckMarkSize(wxWindow* win) diff --git a/src/osx/carbon/renderer.cpp b/src/osx/carbon/renderer.cpp index a7bc8dcc06..933ca65ebf 100644 --- a/src/osx/carbon/renderer.cpp +++ b/src/osx/carbon/renderer.cpp @@ -90,7 +90,7 @@ public: const wxRect& rect, int flags = 0) wxOVERRIDE; - virtual wxSize GetCheckBoxSize(wxWindow* win) wxOVERRIDE; + virtual wxSize GetCheckBoxSize(wxWindow* win, int flags = 0) wxOVERRIDE; virtual void DrawComboBoxDropButton(wxWindow *win, wxDC& dc, @@ -491,7 +491,7 @@ wxRendererMac::DrawCheckBox(wxWindow *win, kind, kThemeAdornmentNone); } -wxSize wxRendererMac::GetCheckBoxSize(wxWindow* win) +wxSize wxRendererMac::GetCheckBoxSize(wxWindow* win, int WXUNUSED(flags)) { // Even though we don't use the window in this implementation, still check // that it's valid to avoid surprises when running the same code under the