// data structures used for the data type registry
// ----------------------------------------------------------------------------
-struct wxGridDataTypeInfo {
+struct wxGridDataTypeInfo
+{
wxGridDataTypeInfo(const wxString& typeName,
wxGridCellRenderer* renderer,
wxGridCellEditor* editor)
WX_DEFINE_ARRAY(wxGridDataTypeInfo*, wxGridDataTypeInfoArray);
-class WXDLLEXPORT wxGridTypeRegistry {
+class WXDLLEXPORT wxGridTypeRegistry
+{
public:
~wxGridTypeRegistry();
+
void RegisterDataType(const wxString& typeName,
wxGridCellRenderer* renderer,
wxGridCellEditor* editor);
wxGridDataTypeInfoArray m_typeinfo;
};
-
-
-
// ----------------------------------------------------------------------------
// conditional compilation
// ----------------------------------------------------------------------------
{
if (m_control)
{
+ m_control->PopEventHandler(TRUE /* delete it*/);
+
m_control->Destroy();
m_control = NULL;
}
// unix
//
#if defined(__WXGTK__)
- rect.Inflate(rect.x ? 1 : 0, rect.y ? 1 : 0);
+ if (rect.x != 0)
+ {
+ rect.x += 1;
+ rect.y += 1;
+ rect.width -= 1;
+ rect.height -= 1;
+ }
#else // !GTK
int extra_x = ( rect.x > 2 )? 2 : 1;
int extra_y = ( rect.y > 2 )? 2 : 1;
}
else
{
- wxFAIL_MSG( _T("this cell doesn't have numeric value") );
-
- return;
+ wxString sValue = table->GetValue(row, col);
+ if (! sValue.ToLong(&m_valueOld))
+ {
+ wxFAIL_MSG( _T("this cell doesn't have numeric value") );
+ return;
+ }
}
if ( HasRange() )
if ( changed )
{
- grid->GetTable()->SetValueAsLong(row, col, value);
+ if (grid->GetTable()->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER))
+ grid->GetTable()->SetValueAsLong(row, col, value);
+ else
+ grid->GetTable()->SetValue(row, col, wxString::Format("%ld", value));
}
return changed;
}
else
{
- wxFAIL_MSG( _T("this cell doesn't have float value") );
-
- return;
+ wxString sValue = table->GetValue(row, col);
+ if (! sValue.ToDouble(&m_valueOld))
+ {
+ wxFAIL_MSG( _T("this cell doesn't have float value") );
+ return;
+ }
}
DoBeginEdit(GetString());
double value;
if ( Text()->GetValue().ToDouble(&value) && (value != m_valueOld) )
{
- grid->GetTable()->SetValueAsDouble(row, col, value);
+ if (grid->GetTable()->CanSetValueAs(row, col, wxGRID_VALUE_FLOAT))
+ grid->GetTable()->SetValueAsDouble(row, col, value);
+ else
+ grid->GetTable()->SetValue(row, col, wxString::Format("%f", value));
return TRUE;
}
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?)
- int w, h;
- m_control->GetSize(&w, &h);
+#if defined(__WXGTK__) || defined (__WXMOTIF__)
// the checkbox without label still has some space to the right in wxGTK,
// so shift it to the right
-#if defined(__WXGTK__) || defined (__WXMOTIF__)
- w -= 8;
-#endif // GTK && Motif
+ size.x -= 8;
+#elif defined(__WXMSW__)
+ // here too...
+ size.x -= 6;
+ size.y -= 2;
+#endif
- m_control->Move(r.x + r.width/2 - w/2, r.y + r.height/2 - h/2);
+ m_control->Move(r.x + r.width/2 - size.x/2, r.y + r.height/2 - size.y/2);
}
void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)
wxGridCellEditor::Create(parent, id, evtHandler);
}
-void wxGridCellChoiceEditor::PaintBackground(const wxRect& WXUNUSED(rectCell),
- wxGridCellAttr * WXUNUSED(attr))
+void wxGridCellChoiceEditor::PaintBackground(const wxRect& rectCell,
+ wxGridCellAttr * attr)
{
// as we fill the entire client area, don't do anything here to minimize
// flicker
+
+ // TODO: It doesn't actually fill the client area since the height of a
+ // combo always defaults to the standard... Until someone has time to
+ // figure out the right rectangle to paint, just do it the normal way...
+ wxGridCellEditor::PaintBackground(rectCell, attr);
}
void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
+// FIXME these checkbox size calculations are really ugly...
+
// between checkmark and box
-static const wxCoord wxGRID_CHECKMARK_MARGIN = 4;
+#ifdef __WXGTK__
+ static const wxCoord wxGRID_CHECKMARK_MARGIN = 4;
+#else
+ static const wxCoord wxGRID_CHECKMARK_MARGIN = 2;
+#endif
wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
wxGridCellAttr& WXUNUSED(attr),
// 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 - 2;
+ }
+
+ // draw a border around checkmark
wxRect rectMark;
rectMark.x = rect.x + rect.width/2 - size.x/2;
rectMark.y = rect.y + rect.height/2 - size.y/2;
rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN);
+#ifdef __WXMSW__
+ // looks nicer under MSW
+ rectMark.x++;
+#endif // MSW
+
bool value;
- if (grid.GetTable()->CanGetValueAs(row, col, wxT("bool")))
+ if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
value = grid.GetTable()->GetValueAsBool(row, col);
else
value = !!grid.GetTable()->GetValue(row, col);
wxGridTypeRegistry::~wxGridTypeRegistry()
{
- for (size_t i=0; i<m_typeinfo.Count(); i++)
+ size_t count = m_typeinfo.Count();
+ for ( size_t i = 0; i < count; i++ )
delete m_typeinfo[i];
}
wxRegion reg = GetUpdateRegion();
m_owner->CalcCellsExposed( reg );
m_owner->DrawGridCellArea( dc );
- m_owner->DrawGridSpace( dc );
#if WXGRID_DRAW_LINES
m_owner->DrawAllGridLines( dc, reg );
#endif
+ m_owner->DrawGridSpace( dc );
m_owner->DrawHighlight( dc );
}
m_inOnKeyDown = FALSE;
m_batchCount = 0;
+
+ m_extraWidth =
+ m_extraHeight = 50;
+
+ CalcDimensions();
}
// ----------------------------------------------------------------------------
if ( m_numRows > 0 && m_numCols > 0 )
{
- int right = GetColRight( m_numCols-1 ) + 50;
- int bottom = GetRowBottom( m_numRows-1 ) + 50;
+ int right = GetColRight( m_numCols-1 ) + m_extraWidth;
+ int bottom = GetRowBottom( m_numRows-1 ) + m_extraHeight;
// TODO: restore the scroll position that we had before sizing
//
// Hide the edit control, so it
// won't interfer with drag-shrinking.
if ( IsCellEditControlEnabled() )
+ {
HideCellEditControl();
+ SaveEditControlValue();
+ }
// Have we captured the mouse yet?
if (! m_winCapture)
m_isDragging = FALSE;
m_startDragPos = wxDefaultPosition;
-// if ( coords == wxGridNoCellCoords && m_cursorMode != WXGRID_CURSOR_SELECT_CELL )
-// {
-// ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
-// }
-
-// if ( coords != wxGridNoCellCoords )
-// {
- // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL
- // immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under
- // wxGTK
+ // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL
+ // immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under
+ // wxGTK
#if 0
- if ( event.Entering() || event.Leaving() )
- {
- ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
- m_gridWin->SetCursor( *wxSTANDARD_CURSOR );
- }
- else
+ if ( event.Entering() || event.Leaving() )
+ {
+ ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+ m_gridWin->SetCursor( *wxSTANDARD_CURSOR );
+ }
+ else
#endif // 0
- // ------------ Left button pressed
- //
- if ( event.LeftDown() && coords != wxGridNoCellCoords )
+ // ------------ Left button pressed
+ //
+ if ( event.LeftDown() && coords != wxGridNoCellCoords )
+ {
+ if ( event.ShiftDown() )
{
- DisableCellEditControl();
- if ( event.ShiftDown() )
- {
- SelectBlock( m_currentCellCoords, coords );
- }
- else if ( XToEdgeOfCol(x) < 0 &&
- YToEdgeOfRow(y) < 0 )
+ SelectBlock( m_currentCellCoords, coords );
+ }
+ else if ( XToEdgeOfCol(x) < 0 &&
+ YToEdgeOfRow(y) < 0 )
+ {
+ if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK,
+ coords.GetRow(),
+ coords.GetCol(),
+ event ) )
{
- if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK,
- coords.GetRow(),
- coords.GetCol(),
- event ) )
+ DisableCellEditControl();
+ MakeCellVisible( coords );
+
+ // if this is the second click on this cell then start
+ // the edit control
+ if ( m_waitForSlowClick &&
+ (coords == m_currentCellCoords) &&
+ CanEnableCellControl())
{
- MakeCellVisible( coords );
-
- // if this is the second click on this cell then start
- // the edit control
- if ( m_waitForSlowClick &&
- (coords == m_currentCellCoords) &&
- CanEnableCellControl())
- {
- EnableCellEditControl();
+ EnableCellEditControl();
- wxGridCellAttr* attr = GetCellAttr(m_currentCellCoords);
- attr->GetEditor(this, coords.GetRow(), coords.GetCol())->StartingClick();
- attr->DecRef();
+ wxGridCellAttr* attr = GetCellAttr(m_currentCellCoords);
+ attr->GetEditor(this, coords.GetRow(), coords.GetCol())->StartingClick();
+ attr->DecRef();
- m_waitForSlowClick = FALSE;
- }
- else
- {
- SetCurrentCell( coords );
- m_waitForSlowClick = TRUE;
- }
+ m_waitForSlowClick = FALSE;
+ }
+ else
+ {
+ SetCurrentCell( coords );
+ m_waitForSlowClick = TRUE;
}
}
}
+ }
- // ------------ Left double click
- //
- else if ( event.LeftDClick() && coords != wxGridNoCellCoords )
+ // ------------ Left double click
+ //
+ else if ( event.LeftDClick() && coords != wxGridNoCellCoords )
+ {
+ DisableCellEditControl();
+
+ if ( XToEdgeOfCol(x) < 0 && YToEdgeOfRow(y) < 0 )
{
- DisableCellEditControl();
- if ( XToEdgeOfCol(x) < 0 && YToEdgeOfRow(y) < 0 )
- {
- SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK,
- coords.GetRow(),
- coords.GetCol(),
- event );
- }
+ SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK,
+ coords.GetRow(),
+ coords.GetCol(),
+ event );
}
+ }
- // ------------ Left button released
- //
- else if ( event.LeftUp() )
+ // ------------ Left button released
+ //
+ else if ( event.LeftUp() )
+ {
+ if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{
- if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
+ if ( IsSelection() )
{
- if ( IsSelection() )
+ if (m_winCapture)
{
- if (m_winCapture)
- {
- m_winCapture->ReleaseMouse();
- m_winCapture = NULL;
- }
- SendEvent( wxEVT_GRID_RANGE_SELECT, -1, -1, event );
+ m_winCapture->ReleaseMouse();
+ m_winCapture = NULL;
}
-
- // Show the edit control, if it has been hidden for
- // drag-shrinking.
- ShowCellEditControl();
+ SendEvent( wxEVT_GRID_RANGE_SELECT, -1, -1, event );
}
- else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
- {
- ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
- DoEndDragResizeRow();
- // Note: we are ending the event *after* doing
- // default processing in this case
- //
- SendEvent( wxEVT_GRID_ROW_SIZE, m_dragRowOrCol, -1, event );
- }
- else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
- {
- ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
- DoEndDragResizeCol();
+ // Show the edit control, if it has been hidden for
+ // drag-shrinking.
+ ShowCellEditControl();
+ }
+ else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
+ {
+ ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+ DoEndDragResizeRow();
- // Note: we are ending the event *after* doing
- // default processing in this case
- //
- SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol, event );
- }
+ // Note: we are ending the event *after* doing
+ // default processing in this case
+ //
+ SendEvent( wxEVT_GRID_ROW_SIZE, m_dragRowOrCol, -1, event );
+ }
+ else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
+ {
+ ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+ DoEndDragResizeCol();
- m_dragLastPos = -1;
+ // Note: we are ending the event *after* doing
+ // default processing in this case
+ //
+ SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol, event );
}
+ m_dragLastPos = -1;
+ }
- // ------------ Right button down
- //
- else if ( event.RightDown() && coords != wxGridNoCellCoords )
+
+ // ------------ Right button down
+ //
+ else if ( event.RightDown() && coords != wxGridNoCellCoords )
+ {
+ DisableCellEditControl();
+ if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK,
+ coords.GetRow(),
+ coords.GetCol(),
+ event ) )
{
- DisableCellEditControl();
- if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK,
- coords.GetRow(),
- coords.GetCol(),
- event ) )
- {
- // no default action at the moment
- }
+ // no default action at the moment
}
+ }
- // ------------ Right double click
- //
- else if ( event.RightDClick() && coords != wxGridNoCellCoords )
+ // ------------ Right double click
+ //
+ else if ( event.RightDClick() && coords != wxGridNoCellCoords )
+ {
+ DisableCellEditControl();
+ if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK,
+ coords.GetRow(),
+ coords.GetCol(),
+ event ) )
{
- DisableCellEditControl();
- if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK,
- coords.GetRow(),
- coords.GetCol(),
- event ) )
- {
- // no default action at the moment
- }
+ // no default action at the moment
}
+ }
- // ------------ Moving and no button action
+ // ------------ Moving and no button action
+ //
+ else if ( event.Moving() && !event.IsButton() )
+ {
+ int dragRow = YToEdgeOfRow( y );
+ int dragCol = XToEdgeOfCol( x );
+
+ // Dragging on the corner of a cell to resize in both
+ // directions is not implemented yet...
//
- else if ( event.Moving() && !event.IsButton() )
+ if ( dragRow >= 0 && dragCol >= 0 )
{
- int dragRow = YToEdgeOfRow( y );
- int dragCol = XToEdgeOfCol( x );
+ ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+ return;
+ }
- // Dragging on the corner of a cell to resize in both
- // directions is not implemented yet...
- //
- if ( dragRow >= 0 && dragCol >= 0 )
- {
- ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
- return;
- }
+ if ( dragRow >= 0 )
+ {
+ m_dragRowOrCol = dragRow;
- if ( dragRow >= 0 )
+ if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{
- m_dragRowOrCol = dragRow;
-
- if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
- {
- if ( CanDragRowSize() && CanDragGridSize() )
- ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW);
- }
-
- return;
+ if ( CanDragRowSize() && CanDragGridSize() )
+ ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW);
}
if ( dragCol >= 0 )
{
m_dragRowOrCol = dragCol;
+ }
- if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
- {
- if ( CanDragColSize() && CanDragGridSize() )
- ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL);
- }
+ return;
+ }
- return;
- }
+ if ( dragCol >= 0 )
+ {
+ m_dragRowOrCol = dragCol;
- // Neither on a row or col edge
- //
- if ( m_cursorMode != WXGRID_CURSOR_SELECT_CELL )
+ if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{
- ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+ if ( CanDragColSize() && CanDragGridSize() )
+ ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL);
}
+
+ return;
}
+
+ // Neither on a row or col edge
+ //
+ if ( m_cursorMode != WXGRID_CURSOR_SELECT_CELL )
+ {
+ ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+ }
+ }
}
dc.SetLogicalFunction( wxINVERT );
dc.DrawLine( left, m_dragLastPos, left+cw, m_dragLastPos );
HideCellEditControl();
+ SaveEditControlValue();
int rowTop = GetRowTop(m_dragRowOrCol);
SetRowSize( m_dragRowOrCol,
dc.SetLogicalFunction( wxINVERT );
dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top+ch );
HideCellEditControl();
+ SaveEditControlValue();
int colLeft = GetColLeft(m_dragRowOrCol);
SetColSize( m_dragRowOrCol,
MovePageDown();
break;
- // We don't want these keys to trigger the edit control, any others?
- case WXK_SHIFT:
- case WXK_ALT:
- case WXK_CONTROL:
- case WXK_CAPITAL:
- event.Skip();
- break;
-
case WXK_SPACE:
if ( !IsEditable() )
{
// Otherwise fall through to default
default:
- // now try the cell edit control
- //
- if ( !IsCellEditControlEnabled() && CanEnableCellControl() )
+ // alphanumeric keys or F2 (special key just for this) enable
+ // the cell edit control
+ if ( !(event.AltDown() ||
+ event.MetaDown() ||
+ event.ControlDown()) &&
+ (isalnum(event.KeyCode()) || event.KeyCode() == WXK_F2) &&
+ !IsCellEditControlEnabled() &&
+ CanEnableCellControl() )
{
EnableCellEditControl();
int row = m_currentCellCoords.GetRow();
}
else
{
- // let others process char events for readonly cells
+ // let others process char events with modifiers or all
+ // char events for readonly cells
event.Skip();
}
break;
dc.SetPen( *wxTRANSPARENT_PEN );
if ( right > GetColRight(m_numCols-1) )
- dc.DrawRectangle( GetColRight(m_numCols-1)+1, top,
+ dc.DrawRectangle( GetColRight(m_numCols-1), top,
right - GetColRight(m_numCols-1), ch );
if ( bottom > GetRowBottom(m_numRows-1) )
- dc.DrawRectangle( left, GetRowBottom(m_numRows-1)+1,
+ dc.DrawRectangle( left, GetRowBottom(m_numRows-1),
cw, bottom - GetRowBottom(m_numRows-1) );
}
}
new wxGridCellEditorEvtHandler(this, editor));
}
+ editor->Show( TRUE, attr );
+
editor->SetSize( rect );
- editor->Show( TRUE, attr );
editor->BeginEdit(row, col, this);
attr->DecRef();
}
return obj ? (int)obj : WXGRID_MIN_COL_WIDTH;
}
+// ----------------------------------------------------------------------------
+// auto sizing
+// ----------------------------------------------------------------------------
+
void wxGrid::AutoSizeColumn( int col, bool setAsMin )
{
wxClientDC dc(m_gridWin);
}
}
-void wxGrid::AutoSizeColumns( bool setAsMin )
+int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
{
+ int width = m_rowLabelWidth;
+
for ( int col = 0; col < m_numCols; col++ )
{
- AutoSizeColumn(col, setAsMin);
+ if ( !calcOnly )
+ {
+ AutoSizeColumn(col, setAsMin);
+ }
+
+ width += GetColWidth(col);
}
+
+ return width;
}
-//
-// ------ cell value accessor functions
-//
+int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
+{
+ int height = m_colLabelHeight;
+
+ for ( int row = 0; row < m_numRows; row++ )
+ {
+ // if ( !calcOnly ) AutoSizeRow(row, setAsMin) -- TODO
+
+ height += GetRowHeight(row);
+ }
+
+ return height;
+}
+
+void wxGrid::AutoSize()
+{
+ // set the size too
+ SetSize(SetOrCalcColumnSizes(FALSE), SetOrCalcRowSizes(FALSE));
+}
+
+wxSize wxGrid::DoGetBestSize() const
+{
+ // don't set sizes, only calculate them
+ wxGrid *self = (wxGrid *)this; // const_cast
+
+ return wxSize(self->SetOrCalcColumnSizes(TRUE),
+ self->SetOrCalcRowSizes(TRUE));
+}
+
+void wxGrid::Fit()
+{
+ AutoSize();
+}
+
+// ----------------------------------------------------------------------------
+// cell value accessor functions
+// ----------------------------------------------------------------------------
void wxGrid::SetCellValue( int row, int col, const wxString& s )
{