Improve grid editors placing
Remove the code in wxGrid::ShowCellEditControl() which moves grid editors unnecessarily and also remove workarounds that were required because of it in the editors SetSize() functions. This helps to ensure that the editor is placed at the same position the renderer draws the cell value, so that it doesn't jump around annoyingly when editing starts (which was especially noticeable for boolean-valued cells).
This commit is contained in:
committed by
Vadim Zeitlin
parent
6a21d6f2e4
commit
3ca9491c5f
@@ -1007,5 +1007,12 @@ private:
|
|||||||
wxGridDataTypeInfoArray m_typeinfo;
|
wxGridDataTypeInfoArray m_typeinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns the rect of the check box in a cell with the given alignmens
|
||||||
|
// and the size.
|
||||||
|
// The function is used by wxGridCellBoolEditor and wxGridCellBoolRenderer.
|
||||||
|
wxRect wxGetGridCheckBoxRect(const wxSize& checkBoxSize,
|
||||||
|
const wxRect& cellRect,
|
||||||
|
int hAlign, int vAlign);
|
||||||
|
|
||||||
#endif // wxUSE_GRID
|
#endif // wxUSE_GRID
|
||||||
#endif // _WX_GENERIC_GRID_PRIVATE_H_
|
#endif // _WX_GENERIC_GRID_PRIVATE_H_
|
||||||
|
@@ -111,6 +111,9 @@ const int GRID_HASH_SIZE = 100;
|
|||||||
// operation
|
// operation
|
||||||
const int DRAG_SENSITIVITY = 3;
|
const int DRAG_SENSITIVITY = 3;
|
||||||
|
|
||||||
|
// the space between the cell edge and the checkbox mark
|
||||||
|
const int GRID_CELL_CHECKBOX_MARGIN_X = 2;
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
#include "wx/arrimpl.cpp"
|
#include "wx/arrimpl.cpp"
|
||||||
@@ -6980,18 +6983,10 @@ void wxGrid::ShowCellEditControl()
|
|||||||
if (rect.x < 0)
|
if (rect.x < 0)
|
||||||
nXMove = rect.x;
|
nXMove = rect.x;
|
||||||
|
|
||||||
#ifndef __WXQT__
|
#ifdef __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
|
|
||||||
// Substract 1 pixel in every dimension to fit in the cell area.
|
// Substract 1 pixel in every dimension to fit in the cell area.
|
||||||
// If not, Qt will draw the control outside the cell.
|
// If not, Qt will draw the control outside the cell.
|
||||||
|
// TODO: Check offsets under Qt.
|
||||||
rect.Deflate(1, 1);
|
rect.Deflate(1, 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -10337,4 +10332,44 @@ wxGridCellEditor* wxGridTypeRegistry::GetEditor(int index)
|
|||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxRect wxGetGridCheckBoxRect(const wxSize& checkBoxSize,
|
||||||
|
const wxRect& cellRect,
|
||||||
|
int hAlign, int WXUNUSED(vAlign))
|
||||||
|
{
|
||||||
|
// TODO: support vAlign
|
||||||
|
|
||||||
|
wxRect checkBoxRect;
|
||||||
|
checkBoxRect.SetY(cellRect.y + cellRect.height / 2 - checkBoxSize.y / 2);
|
||||||
|
|
||||||
|
wxCoord minSize = wxMin(cellRect.width, cellRect.height);
|
||||||
|
if ( checkBoxRect.GetWidth() >= minSize || checkBoxRect.GetHeight() >= minSize )
|
||||||
|
{
|
||||||
|
// let the checkbox mark be even smaller than the min size
|
||||||
|
// to leave some space between cell edges and the checkbox
|
||||||
|
const int newSize = wxMax(1, minSize - 2);
|
||||||
|
checkBoxRect.SetWidth(newSize);
|
||||||
|
checkBoxRect.SetHeight(newSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
checkBoxRect.SetSize(checkBoxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( hAlign & wxALIGN_CENTER_HORIZONTAL )
|
||||||
|
{
|
||||||
|
checkBoxRect.SetX(cellRect.x + cellRect.width / 2 - checkBoxSize.x / 2);
|
||||||
|
}
|
||||||
|
else if ( hAlign & wxALIGN_RIGHT )
|
||||||
|
{
|
||||||
|
checkBoxRect.SetX(cellRect.x + cellRect.width
|
||||||
|
- checkBoxSize.x - GRID_CELL_CHECKBOX_MARGIN_X);
|
||||||
|
}
|
||||||
|
else // ( hAlign == wxALIGN_LEFT ) and invalid alignment value
|
||||||
|
{
|
||||||
|
checkBoxRect.SetX(cellRect.x + GRID_CELL_CHECKBOX_MARGIN_X);
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkBoxRect;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_GRID
|
#endif // wxUSE_GRID
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include "wx/tokenzr.h"
|
#include "wx/tokenzr.h"
|
||||||
#include "wx/renderer.h"
|
#include "wx/renderer.h"
|
||||||
|
|
||||||
|
#include "wx/generic/private/grid.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxGridCellRenderer
|
// wxGridCellRenderer
|
||||||
@@ -936,7 +937,8 @@ wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
|
|||||||
// compute it only once (no locks for MT safeness in GUI thread...)
|
// compute it only once (no locks for MT safeness in GUI thread...)
|
||||||
if ( !ms_sizeCheckMark.x )
|
if ( !ms_sizeCheckMark.x )
|
||||||
{
|
{
|
||||||
ms_sizeCheckMark = wxRendererNative::Get().GetCheckBoxSize(&grid);
|
ms_sizeCheckMark =
|
||||||
|
wxRendererNative::Get().GetCheckBoxSize(&grid, wxCONTROL_CELL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ms_sizeCheckMark;
|
return ms_sizeCheckMark;
|
||||||
@@ -951,43 +953,16 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid,
|
|||||||
{
|
{
|
||||||
wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
|
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);
|
|
||||||
|
|
||||||
// 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;
|
int vAlign, hAlign;
|
||||||
attr.GetAlignment(&hAlign, &vAlign);
|
attr.GetAlignment(&hAlign, &vAlign);
|
||||||
|
|
||||||
wxRect rectBorder;
|
const wxRect
|
||||||
if (hAlign == wxALIGN_CENTRE)
|
checkBoxRect = wxGetGridCheckBoxRect
|
||||||
{
|
(
|
||||||
rectBorder.x = rect.x + rect.width / 2 - size.x / 2;
|
GetBestSize(grid, attr, dc, row, col),
|
||||||
rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
|
rect,
|
||||||
rectBorder.width = size.x;
|
hAlign, vAlign
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool value;
|
bool value;
|
||||||
if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
|
if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
|
||||||
@@ -1000,11 +975,11 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid,
|
|||||||
value = wxGridCellBoolEditor::IsTrueValue(cellval);
|
value = wxGridCellBoolEditor::IsTrueValue(cellval);
|
||||||
}
|
}
|
||||||
|
|
||||||
int flags = 0;
|
int flags = wxCONTROL_CELL;
|
||||||
if (value)
|
if (value)
|
||||||
flags |= wxCONTROL_CHECKED;
|
flags |= wxCONTROL_CHECKED;
|
||||||
|
|
||||||
wxRendererNative::Get().DrawCheckBox( &grid, dc, rectBorder, flags );
|
wxRendererNative::Get().DrawCheckBox( &grid, dc, checkBoxRect, flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // wxUSE_GRID
|
#endif // wxUSE_GRID
|
||||||
|
@@ -440,38 +440,17 @@ void wxGridCellTextEditor::SetSize(const wxRect& rectOrig)
|
|||||||
|
|
||||||
// Make the edit control large enough to allow for internal margins
|
// 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 defined(__WXMSW__)
|
||||||
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;
|
rect.x += 2;
|
||||||
else
|
|
||||||
rect.x += 3;
|
|
||||||
|
|
||||||
if ( rect.y == 0 )
|
|
||||||
rect.y += 2;
|
rect.y += 2;
|
||||||
else
|
|
||||||
rect.y += 3;
|
|
||||||
|
|
||||||
rect.width -= 2;
|
rect.width -= 2;
|
||||||
rect.height -= 2;
|
rect.height -= 2;
|
||||||
#elif defined(__WXOSX__)
|
#elif !defined(__WXGTK__)
|
||||||
rect.x += 1;
|
int extra_x = 2;
|
||||||
rect.y += 1;
|
int extra_y = 2;
|
||||||
|
|
||||||
rect.width -= 1;
|
|
||||||
rect.height -= 1;
|
|
||||||
#else
|
|
||||||
int extra_x = ( rect.x > 2 ) ? 2 : 1;
|
|
||||||
int extra_y = ( rect.y > 2 ) ? 2 : 1;
|
|
||||||
|
|
||||||
#if defined(__WXMOTIF__)
|
#if defined(__WXMOTIF__)
|
||||||
extra_x *= 2;
|
extra_x *= 2;
|
||||||
@@ -1239,73 +1218,28 @@ void wxGridCellBoolEditor::Create(wxWindow* parent,
|
|||||||
|
|
||||||
void wxGridCellBoolEditor::SetSize(const wxRect& r)
|
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 hAlign = wxALIGN_CENTRE;
|
||||||
int vAlign = wxALIGN_CENTRE;
|
int vAlign = wxALIGN_CENTRE;
|
||||||
if (GetCellAttr())
|
if (GetCellAttr())
|
||||||
GetCellAttr()->GetAlignment(& hAlign, & vAlign);
|
GetCellAttr()->GetAlignment(& hAlign, & vAlign);
|
||||||
|
|
||||||
int x = 0, y = 0;
|
const wxRect
|
||||||
if (hAlign == wxALIGN_LEFT)
|
checkBoxRect = wxGetGridCheckBoxRect
|
||||||
{
|
(
|
||||||
x = r.x + 2;
|
wxRendererNative::Get().
|
||||||
|
GetCheckBoxSize(GetWindow(), wxCONTROL_CELL),
|
||||||
|
r,
|
||||||
|
hAlign, vAlign
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
// resize the control if required
|
||||||
x += 2;
|
if ( m_control->GetSize() != checkBoxRect.GetSize() )
|
||||||
#endif
|
|
||||||
|
|
||||||
y = r.y + r.height / 2 - size.y / 2;
|
|
||||||
}
|
|
||||||
else if (hAlign == wxALIGN_RIGHT)
|
|
||||||
{
|
{
|
||||||
x = r.x + r.width - size.x - 2;
|
m_control->SetSize(checkBoxRect.GetSize());
|
||||||
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);
|
// and move it
|
||||||
|
m_control->Move(checkBoxRect.GetPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)
|
void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)
|
||||||
|
Reference in New Issue
Block a user