Merge branch 'grid-editors-placement'

Fix positions of the checkboxes drawn by wxGridCellBoolRenderer and
shown by wxGridCellBoolEditor so that there is no jump when starting or
stopping to edit grid cells with boolean values.

See https://github.com/wxWidgets/wxWidgets/pull/1662
This commit is contained in:
Vadim Zeitlin
2019-11-29 16:24:07 +01:00
14 changed files with 364 additions and 275 deletions

View File

@@ -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
{

View File

@@ -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_

View File

@@ -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;

View File

@@ -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); }

View File

@@ -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.

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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 )
#if defined(__WXMSW__)
rect.x += 2;
else
rect.x += 3;
if ( rect.y == 0 )
rect.y += 2;
else
rect.y += 3;
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);
}
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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
{
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", &w, "min-height", &h, NULL);
"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);
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__
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

View File

@@ -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)

View File

@@ -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