X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d10f4bf950c4ad064b982fe8fe07d5ca5e3af7ba..1b0b798d77b7b93b81d62162b290441bc9175e3e:/src/generic/grid.cpp?ds=sidebyside diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 83b2116205..22bd89555c 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -2,7 +2,7 @@ // Name: generic/grid.cpp // Purpose: wxGrid and related classes // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) -// Modified by: +// Modified by: Robin Dunn, Vadim Zeitlin // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) Michael Bedward (mbedward@ozemail.com.au) @@ -30,9 +30,11 @@ #pragma hdrstop #endif +#if wxUSE_GRID + #if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID) -#include "gridg.cpp" -#else + #include "gridg.cpp" +#else // wxUSE_NEW_GRID #ifndef WX_PRECOMP #include "wx/utils.h" @@ -115,6 +117,7 @@ DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE) DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL) DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN) DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN) +DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED) // ---------------------------------------------------------------------------- // private classes @@ -182,7 +185,7 @@ private: DECLARE_EVENT_TABLE() }; -class WXDLLEXPORT wxGridWindow : public wxPanel +class WXDLLEXPORT wxGridWindow : public wxWindow { public: wxGridWindow() @@ -385,13 +388,31 @@ wxRect wxGridNoCellRect( -1, -1, -1, -1 ); // The scroll bars may be a little flakey once in a while, but that is // surely much less horrible than having scroll lines of only 1!!! // -- Robin -static const size_t GRID_SCROLL_LINE = 15; // 1; - +// +// Well, it's still seriously broken so it might be better but needs +// fixing anyhow +// -- Vadim +static const size_t GRID_SCROLL_LINE_X = 15; // 1; +static const size_t GRID_SCROLL_LINE_Y = GRID_SCROLL_LINE_X; // the size of hash tables used a bit everywhere (the max number of elements // in these hash tables is the number of rows/columns) static const int GRID_HASH_SIZE = 100; +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +static inline int GetScrollX(int x) +{ + return (x + GRID_SCROLL_LINE_X - 1) / GRID_SCROLL_LINE_X; +} + +static inline int GetScrollY(int y) +{ + return (y + GRID_SCROLL_LINE_Y - 1) / GRID_SCROLL_LINE_Y; +} + // ============================================================================ // implementation // ============================================================================ @@ -517,6 +538,8 @@ void wxGridCellEditor::StartingClick() { } +#if wxUSE_TEXTCTRL + // ---------------------------------------------------------------------------- // wxGridCellTextEditor // ---------------------------------------------------------------------------- @@ -1143,6 +1166,10 @@ bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event) return FALSE; } +#endif // wxUSE_TEXTCTRL + +#if wxUSE_CHECKBOX + // ---------------------------------------------------------------------------- // wxGridCellBoolEditor // ---------------------------------------------------------------------------- @@ -1287,6 +1314,10 @@ bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event) return FALSE; } +#endif // wxUSE_CHECKBOX + +#if wxUSE_COMBOBOX + // ---------------------------------------------------------------------------- // wxGridCellChoiceEditor // ---------------------------------------------------------------------------- @@ -1407,6 +1438,8 @@ void wxGridCellChoiceEditor::SetParameters(const wxString& params) } } +#endif // wxUSE_COMBOBOX + // ---------------------------------------------------------------------------- // wxGridCellEditorEvtHandler // ---------------------------------------------------------------------------- @@ -1865,9 +1898,24 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid, // wxGridCellAttr // ---------------------------------------------------------------------------- +void wxGridCellAttr::Init(wxGridCellAttr *attrDefault) +{ + m_nRef = 1; + + m_isReadOnly = Unset; + + m_renderer = NULL; + m_editor = NULL; + + m_attrkind = wxGridCellAttr::Cell; + + SetDefAttr(attrDefault); +} + wxGridCellAttr *wxGridCellAttr::Clone() const { - wxGridCellAttr *attr = new wxGridCellAttr; + wxGridCellAttr *attr = new wxGridCellAttr(m_defGridAttr); + if ( HasTextColour() ) attr->SetTextColour(GetTextColour()); if ( HasBackgroundColour() ) @@ -1893,8 +1941,6 @@ wxGridCellAttr *wxGridCellAttr::Clone() const attr->SetKind( m_attrkind ); - attr->SetDefAttr(m_defGridAttr); - return attr; } @@ -1917,7 +1963,7 @@ void wxGridCellAttr::MergeWith(wxGridCellAttr *mergefrom) // // Maybe add support for merge of Render and Editor? if (!HasRenderer() && mergefrom->HasRenderer() ) - { + { m_renderer = mergefrom->m_renderer; m_renderer->IncRef(); } @@ -1938,7 +1984,7 @@ const wxColour& wxGridCellAttr::GetTextColour() const { return m_colText; } - else if (m_defGridAttr != this) + else if (m_defGridAttr && m_defGridAttr != this) { return m_defGridAttr->GetTextColour(); } @@ -1954,7 +2000,7 @@ const wxColour& wxGridCellAttr::GetBackgroundColour() const { if (HasBackgroundColour()) return m_colBack; - else if (m_defGridAttr != this) + else if (m_defGridAttr && m_defGridAttr != this) return m_defGridAttr->GetBackgroundColour(); else { @@ -1968,7 +2014,7 @@ const wxFont& wxGridCellAttr::GetFont() const { if (HasFont()) return m_font; - else if (m_defGridAttr != this) + else if (m_defGridAttr && m_defGridAttr != this) return m_defGridAttr->GetFont(); else { @@ -1985,7 +2031,7 @@ void wxGridCellAttr::GetAlignment(int *hAlign, int *vAlign) const if ( hAlign ) *hAlign = m_hAlign; if ( vAlign ) *vAlign = m_vAlign; } - else if (m_defGridAttr != this) + else if (m_defGridAttr && m_defGridAttr != this) m_defGridAttr->GetAlignment(hAlign, vAlign); else { @@ -2003,59 +2049,96 @@ void wxGridCellAttr::GetAlignment(int *hAlign, int *vAlign) const wxGridCellRenderer* wxGridCellAttr::GetRenderer(wxGrid* grid, int row, int col) const { - wxGridCellRenderer* renderer = NULL; + wxGridCellRenderer *renderer; - if ( m_defGridAttr != this || grid == NULL ) + if ( m_renderer && this != m_defGridAttr ) { - renderer = m_renderer; // use local attribute - if ( renderer ) - renderer->IncRef(); + // use the cells renderer if it has one + renderer = m_renderer; + renderer->IncRef(); } - - if ( !renderer && grid ) // get renderer for the data type + else // no non default cell renderer { - // GetDefaultRendererForCell() will do IncRef() for us - renderer = grid->GetDefaultRendererForCell(row, col); - } + // get default renderer for the data type + if ( grid ) + { + // GetDefaultRendererForCell() will do IncRef() for us + renderer = grid->GetDefaultRendererForCell(row, col); + } + else + { + renderer = NULL; + } - if ( !renderer ) - { - // if we still don't have one then use the grid default - // (no need for IncRef() here neither) - renderer = m_defGridAttr->GetRenderer(NULL,0,0); + if ( !renderer ) + { + if (m_defGridAttr && this != m_defGridAttr ) + { + // if we still don't have one then use the grid default + // (no need for IncRef() here neither) + renderer = m_defGridAttr->GetRenderer(NULL, 0, 0); + } + else // default grid attr + { + // use m_renderer which we had decided not to use initially + renderer = m_renderer; + if ( renderer ) + renderer->IncRef(); + } + } } - if ( !renderer) - { - wxFAIL_MSG(wxT("Missing default cell attribute")); - } + // we're supposed to always find something + wxASSERT_MSG(renderer, wxT("Missing default cell renderer")); return renderer; } +// same as above, except for s/renderer/editor/g wxGridCellEditor* wxGridCellAttr::GetEditor(wxGrid* grid, int row, int col) const { - wxGridCellEditor* editor = NULL; + wxGridCellEditor *editor; - if ( m_defGridAttr != this || grid == NULL ) + if ( m_editor && this != m_defGridAttr ) { - editor = m_editor; // use local attribute - if ( editor ) - editor->IncRef(); + // use the cells editor if it has one + editor = m_editor; + editor->IncRef(); } - - if ( !editor && grid ) // get renderer for the data type - editor = grid->GetDefaultEditorForCell(row, col); - - if ( !editor ) - // if we still don't have one then use the grid default - editor = m_defGridAttr->GetEditor(NULL,0,0); - - if ( !editor ) + else // no non default cell editor { - wxFAIL_MSG(wxT("Missing default cell attribute")); + // get default editor for the data type + if ( grid ) + { + // GetDefaultEditorForCell() will do IncRef() for us + editor = grid->GetDefaultEditorForCell(row, col); + } + else + { + editor = NULL; + } + + if ( !editor ) + { + if ( m_defGridAttr && this != m_defGridAttr ) + { + // if we still don't have one then use the grid default + // (no need for IncRef() here neither) + editor = m_defGridAttr->GetEditor(NULL, 0, 0); + } + else // default grid attr + { + // use m_editor which we had decided not to use initially + editor = m_editor; + if ( editor ) + editor->IncRef(); + } + } } + // we're supposed to always find something + wxASSERT_MSG(editor, wxT("Missing default cell editor")); + return editor; } @@ -2073,6 +2156,9 @@ void wxGridCellAttrData::SetAttr(wxGridCellAttr *attr, int row, int col) } else { + // free the old attribute + m_attrs[(size_t)n].attr->DecRef(); + if ( attr ) { // change the attribute @@ -2302,18 +2388,18 @@ wxGridCellAttr *wxGridCellAttrProvider::GetAttr(int row, int col, //Also check merge cache, so we don't have to re-merge every time.. wxGridCellAttr *attrcell = (wxGridCellAttr *)NULL, *attrrow = (wxGridCellAttr *)NULL, - *attrcol = (wxGridCellAttr *)NULL; - + *attrcol = (wxGridCellAttr *)NULL; + attrcell = m_data->m_cellAttrs.GetAttr(row, col); attrcol = m_data->m_colAttrs.GetAttr(col); attrrow = m_data->m_rowAttrs.GetAttr(row); - if((attrcell != attrrow) && (attrrow !=attrcol) && (attrcell != attrcol)){ + if((attrcell != attrrow) && (attrrow !=attrcol) && (attrcell != attrcol)){ // Two or move are non NULL attr = new wxGridCellAttr; attr->SetKind(wxGridCellAttr::Merged); - //Order important.. + //Order important.. if(attrcell){ attr->MergeWith(attrcell); attrcell->DecRef(); @@ -2335,7 +2421,7 @@ wxGridCellAttr *wxGridCellAttrProvider::GetAttr(int row, int col, // one or none is non null return it or null. if(attrrow) attr = attrrow; if(attrcol) attr = attrcol; - if(attrcell) attr = attrcell; + if(attrcell) attr = attrcell; } } break; @@ -2455,19 +2541,24 @@ int wxGridTypeRegistry::FindDataType(const wxString& typeName) { // check whether this is one of the standard ones, in which case // register it "on the fly" +#if wxUSE_TEXTCTRL if ( typeName == wxGRID_VALUE_STRING ) { RegisterDataType(wxGRID_VALUE_STRING, new wxGridCellStringRenderer, new wxGridCellTextEditor); - } - else if ( typeName == wxGRID_VALUE_BOOL ) + } else +#endif // wxUSE_TEXTCTRL +#if wxUSE_CHECKBOX + if ( typeName == wxGRID_VALUE_BOOL ) { RegisterDataType(wxGRID_VALUE_BOOL, new wxGridCellBoolRenderer, new wxGridCellBoolEditor); - } - else if ( typeName == wxGRID_VALUE_NUMBER ) + } else +#endif // wxUSE_CHECKBOX +#if wxUSE_TEXTCTRL + if ( typeName == wxGRID_VALUE_NUMBER ) { RegisterDataType(wxGRID_VALUE_NUMBER, new wxGridCellNumberRenderer, @@ -2478,14 +2569,16 @@ int wxGridTypeRegistry::FindDataType(const wxString& typeName) RegisterDataType(wxGRID_VALUE_FLOAT, new wxGridCellFloatRenderer, new wxGridCellFloatEditor); - } - else if ( typeName == wxGRID_VALUE_CHOICE ) + } else +#endif // wxUSE_TEXTCTRL +#if wxUSE_COMBOBOX + if ( typeName == wxGRID_VALUE_CHOICE ) { RegisterDataType(wxGRID_VALUE_CHOICE, new wxGridCellStringRenderer, new wxGridCellChoiceEditor); - } - else + } else +#endif // wxUSE_COMBOBOX { return wxNOT_FOUND; } @@ -3002,7 +3095,7 @@ bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows ) { for ( n = 0; n < numRows; n++ ) { - m_data.Remove( pos ); + m_data.RemoveAt( pos ); } } if ( GetView() ) @@ -3118,7 +3211,7 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols ) { for ( n = 0; n < numCols; n++ ) { - m_data[row].Remove( pos ); + m_data[row].RemoveAt( pos ); } } } @@ -3393,9 +3486,9 @@ void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent& event ) ////////////////////////////////////////////////////////////////////// -IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxPanel ) +IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxWindow ) -BEGIN_EVENT_TABLE( wxGridWindow, wxPanel ) +BEGIN_EVENT_TABLE( wxGridWindow, wxWindow ) EVT_PAINT( wxGridWindow::OnPaint ) EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel) EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent ) @@ -3408,12 +3501,12 @@ wxGridWindow::wxGridWindow( wxGrid *parent, wxGridRowLabelWindow *rowLblWin, wxGridColLabelWindow *colLblWin, wxWindowID id, const wxPoint &pos, const wxSize &size ) - : wxPanel( parent, id, pos, size, wxWANTS_CHARS, "grid window" ) + : wxWindow( parent, id, pos, size, wxWANTS_CHARS, "grid window" ) { m_owner = parent; m_rowLabelWin = rowLblWin; m_colLabelWin = colLblWin; - SetBackgroundColour( "WHITE" ); + SetBackgroundColour(_T("WHITE")); } @@ -3439,7 +3532,7 @@ void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect ) { - wxPanel::ScrollWindow( dx, dy, rect ); + wxWindow::ScrollWindow( dx, dy, rect ); m_rowLabelWin->ScrollWindow( 0, dy, rect ); m_colLabelWin->ScrollWindow( dx, 0, rect ); } @@ -3502,6 +3595,8 @@ wxGrid::wxGrid( wxWindow *parent, wxGrid::~wxGrid() { + // Must do this or ~wxScrollHelper will pop the wrong event handler + SetTargetWindow(this); ClearAttrCache(); wxSafeDecRef(m_defaultCellAttr); @@ -3534,17 +3629,16 @@ void wxGrid::Create() m_cellEditCtrlEnabled = FALSE; - m_defaultCellAttr = new wxGridCellAttr; - m_defaultCellAttr->SetDefAttr(m_defaultCellAttr); + m_defaultCellAttr = new wxGridCellAttr(m_defaultCellAttr); // Set default cell attributes m_defaultCellAttr->SetKind(wxGridCellAttr::Default); m_defaultCellAttr->SetFont(GetFont()); m_defaultCellAttr->SetAlignment(wxALIGN_LEFT, wxALIGN_TOP); m_defaultCellAttr->SetTextColour( - wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT)); + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); m_defaultCellAttr->SetBackgroundColour( - wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); m_defaultCellAttr->SetRenderer(new wxGridCellStringRenderer); m_defaultCellAttr->SetEditor(new wxGridCellTextEditor); @@ -3583,6 +3677,8 @@ void wxGrid::Create() wxDefaultSize ); SetTargetWindow( m_gridWin ); + + Init(); } @@ -3600,7 +3696,9 @@ bool wxGrid::CreateGrid( int numRows, int numCols, m_table->SetView( this ); m_ownTable = TRUE; m_selection = new wxGridSelection( this, selmode ); - Init(); + + CalcDimensions(); + m_created = TRUE; return m_created; @@ -3608,12 +3706,10 @@ bool wxGrid::CreateGrid( int numRows, int numCols, void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode) { - if ( !m_created ) - { - wxFAIL_MSG( wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); - } - else - m_selection->SetSelectionMode( selmode ); + wxCHECK_RET( m_created, + wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); + + m_selection->SetSelectionMode( selmode ); } bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership, @@ -3640,7 +3736,9 @@ bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership, if (takeOwnership) m_ownTable = TRUE; m_selection = new wxGridSelection( this, selmode ); - Init(); + + CalcDimensions(); + m_created = TRUE; } @@ -3690,7 +3788,7 @@ void wxGrid::Init() m_gridLineColour = wxColour( 128, 128, 255 ); m_gridLinesEnabled = TRUE; m_cellHighlightColour = m_gridLineColour; - m_cellHighlightPenWidth = 3; + m_cellHighlightPenWidth = 2; m_cellHighlightROPenWidth = 1; m_cursorMode = WXGRID_CURSOR_SELECT_CELL; @@ -3712,8 +3810,8 @@ void wxGrid::Init() m_selectingTopLeft = wxGridNoCellCoords; m_selectingBottomRight = wxGridNoCellCoords; - m_selectionBackground = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT); - m_selectionForeground = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT); + m_selectionBackground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); + m_selectionForeground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); m_editable = TRUE; // default for whole grid @@ -3721,9 +3819,7 @@ void wxGrid::Init() m_batchCount = 0; m_extraWidth = - m_extraHeight = 50; - - CalcDimensions(); + m_extraHeight = 0; } // ---------------------------------------------------------------------------- @@ -3808,9 +3904,9 @@ void wxGrid::CalcDimensions() int cw, ch; GetClientSize( &cw, &ch ); - if ( m_colLabelWin->IsShown() ) - cw -= m_rowLabelWidth; if ( m_rowLabelWin->IsShown() ) + cw -= m_rowLabelWidth; + if ( m_colLabelWin->IsShown() ) ch -= m_colLabelHeight; // grid total size @@ -3820,32 +3916,34 @@ void wxGrid::CalcDimensions() // preserve (more or less) the previous position int x, y; GetViewStart( &x, &y ); - // maybe we don't need scrollbars at all? and if we do, transform w and h - // from pixels into logical units + + // maybe we don't need scrollbars at all? + // + // also adjust the position to be valid for the new scroll rangs if ( w <= cw ) { - w = 0; x= 0; + w = x = 0; } else { - w = (w + GRID_SCROLL_LINE - 1)/GRID_SCROLL_LINE; - if ( x >= w ) - x = w - 1; + if ( x >= w ) + x = w - 1; } + if ( h <= ch ) { - h = 0; y = 0; + h = y = 0; } else { - h = (h + GRID_SCROLL_LINE - 1)/GRID_SCROLL_LINE; - if ( y >= h ) - y = h - 1; + if ( y >= h ) + y = h - 1; } // do set scrollbar parameters - SetScrollbars( GRID_SCROLL_LINE, GRID_SCROLL_LINE, - w, h, x, y, (GetBatchCount() != 0)); + SetScrollbars( GRID_SCROLL_LINE_X, GRID_SCROLL_LINE_Y, + GetScrollX(w), GetScrollY(h), x, y, + GetBatchCount() != 0); } @@ -3986,8 +4084,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg ) { for ( i = 0; i < numRows; i++ ) { - m_rowHeights.Remove( pos ); - m_rowBottoms.Remove( pos ); + m_rowHeights.RemoveAt( pos ); + m_rowBottoms.RemoveAt( pos ); } int h = 0; @@ -4122,8 +4220,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg ) { for ( i = 0; i < numCols; i++ ) { - m_colWidths.Remove( pos ); - m_colRights.Remove( pos ); + m_colWidths.RemoveAt( pos ); + m_colRights.RemoveAt( pos ); } int w = 0; @@ -4178,8 +4276,8 @@ wxArrayInt wxGrid::CalcRowLabelsExposed( const wxRegion& reg ) wxRegionIterator iter( reg ); wxRect r; - wxArrayInt rowlabels; - + wxArrayInt rowlabels; + int top, bottom; while ( iter ) { @@ -5425,66 +5523,80 @@ bool wxGrid::DeleteCols( int pos, int numCols, bool WXUNUSED(updateLabels) ) // Generate a grid event based on a mouse event and // return the result of ProcessEvent() // -bool wxGrid::SendEvent( const wxEventType type, +int wxGrid::SendEvent( const wxEventType type, int row, int col, wxMouseEvent& mouseEv ) { - if ( type == wxEVT_GRID_ROW_SIZE || type == wxEVT_GRID_COL_SIZE ) - { - int rowOrCol = (row == -1 ? col : row); - - wxGridSizeEvent gridEvt( GetId(), - type, - this, - rowOrCol, - mouseEv.GetX() + GetRowLabelSize(), - mouseEv.GetY() + GetColLabelSize(), - mouseEv.ControlDown(), - mouseEv.ShiftDown(), - mouseEv.AltDown(), - mouseEv.MetaDown() ); - return GetEventHandler()->ProcessEvent(gridEvt); - } - else if ( type == wxEVT_GRID_RANGE_SELECT ) - { - // Right now, it should _never_ end up here! - wxGridRangeSelectEvent gridEvt( GetId(), - type, - this, - m_selectingTopLeft, - m_selectingBottomRight, - TRUE, - mouseEv.ControlDown(), - mouseEv.ShiftDown(), - mouseEv.AltDown(), - mouseEv.MetaDown() ); - - return GetEventHandler()->ProcessEvent(gridEvt); - } - else - { - wxGridEvent gridEvt( GetId(), - type, - this, - row, col, - mouseEv.GetX() + GetRowLabelSize(), - mouseEv.GetY() + GetColLabelSize(), - FALSE, - mouseEv.ControlDown(), - mouseEv.ShiftDown(), - mouseEv.AltDown(), - mouseEv.MetaDown() ); - return GetEventHandler()->ProcessEvent(gridEvt); - } + bool claimed; + bool vetoed= FALSE; + + if ( type == wxEVT_GRID_ROW_SIZE || type == wxEVT_GRID_COL_SIZE ) + { + int rowOrCol = (row == -1 ? col : row); + + wxGridSizeEvent gridEvt( GetId(), + type, + this, + rowOrCol, + mouseEv.GetX() + GetRowLabelSize(), + mouseEv.GetY() + GetColLabelSize(), + mouseEv.ControlDown(), + mouseEv.ShiftDown(), + mouseEv.AltDown(), + mouseEv.MetaDown() ); + + claimed = GetEventHandler()->ProcessEvent(gridEvt); + vetoed = !gridEvt.IsAllowed(); + } + else if ( type == wxEVT_GRID_RANGE_SELECT ) + { + // Right now, it should _never_ end up here! + wxGridRangeSelectEvent gridEvt( GetId(), + type, + this, + m_selectingTopLeft, + m_selectingBottomRight, + TRUE, + mouseEv.ControlDown(), + mouseEv.ShiftDown(), + mouseEv.AltDown(), + mouseEv.MetaDown() ); + + claimed = GetEventHandler()->ProcessEvent(gridEvt); + vetoed = !gridEvt.IsAllowed(); + } + else + { + wxGridEvent gridEvt( GetId(), + type, + this, + row, col, + mouseEv.GetX() + GetRowLabelSize(), + mouseEv.GetY() + GetColLabelSize(), + FALSE, + mouseEv.ControlDown(), + mouseEv.ShiftDown(), + mouseEv.AltDown(), + mouseEv.MetaDown() ); + claimed = GetEventHandler()->ProcessEvent(gridEvt); + vetoed = !gridEvt.IsAllowed(); + } + + // A Veto'd event may not be `claimed' so test this first + if (vetoed) return -1; + return claimed ? 1 : 0; } // Generate a grid event of specified type and return the result // of ProcessEvent(). // -bool wxGrid::SendEvent( const wxEventType type, +int wxGrid::SendEvent( const wxEventType type, int row, int col ) { + bool claimed; + bool vetoed= FALSE; + if ( type == wxEVT_GRID_ROW_SIZE || type == wxEVT_GRID_COL_SIZE ) { int rowOrCol = (row == -1 ? col : row); @@ -5494,7 +5606,8 @@ bool wxGrid::SendEvent( const wxEventType type, this, rowOrCol ); - return GetEventHandler()->ProcessEvent(gridEvt); + claimed = GetEventHandler()->ProcessEvent(gridEvt); + vetoed = !gridEvt.IsAllowed(); } else { @@ -5503,8 +5616,13 @@ bool wxGrid::SendEvent( const wxEventType type, this, row, col ); - return GetEventHandler()->ProcessEvent(gridEvt); - } + claimed = GetEventHandler()->ProcessEvent(gridEvt); + vetoed = !gridEvt.IsAllowed(); + } + + // A Veto'd event may not be `claimed' so test this first + if (vetoed) return -1; + return claimed ? 1 : 0; } @@ -5514,14 +5632,14 @@ void wxGrid::OnPaint( wxPaintEvent& WXUNUSED(event) ) } -// This is just here to make sure that CalcDimensions gets called when -// the grid view is resized... then the size event is skipped to allow -// the box sizers to handle everything -// -void wxGrid::OnSize( wxSizeEvent& WXUNUSED(event) ) +void wxGrid::OnSize( wxSizeEvent& event ) { + // position the child windows CalcWindowSizes(); - CalcDimensions(); + + // don't call CalcDimensions() from here, the base class handles the size + // changes itself + event.Skip(); } @@ -5794,7 +5912,7 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) // Otherwise refresh redraws the highlight! m_currentCellCoords = coords; - + DrawGridCellArea(dc,cells); DrawAllGridLines( dc, r ); } @@ -6554,11 +6672,11 @@ void wxGrid::EnableCellEditControl( bool enable ) if ( enable != m_cellEditCtrlEnabled ) { - // TODO allow the app to Veto() this event? - SendEvent(enable ? wxEVT_GRID_EDITOR_SHOWN : wxEVT_GRID_EDITOR_HIDDEN); - if ( enable ) { + if (SendEvent( wxEVT_GRID_EDITOR_SHOWN) <0) + return; + // this should be checked by the caller! wxASSERT_MSG( CanEnableCellControl(), _T("can't enable editing for this cell!") ); @@ -6570,6 +6688,9 @@ void wxGrid::EnableCellEditControl( bool enable ) } else { + //FIXME:add veto support + SendEvent( wxEVT_GRID_EDITOR_HIDDEN); + HideCellEditControl(); SaveEditControlValue(); @@ -6667,6 +6788,14 @@ void wxGrid::ShowCellEditControl() { editor->Create(m_gridWin, -1, new wxGridCellEditorEvtHandler(this, editor)); + + wxGridEditorCreatedEvent evt(GetId(), + wxEVT_GRID_EDITOR_CREATED, + this, + row, + col, + editor->GetControl()); + GetEventHandler()->ProcessEvent(evt); } editor->Show( TRUE, attr ); @@ -6708,6 +6837,8 @@ void wxGrid::SaveEditControlValue() int row = m_currentCellCoords.GetRow(); int col = m_currentCellCoords.GetCol(); + wxString oldval = GetCellValue(row,col); + wxGridCellAttr* attr = GetCellAttr(row, col); wxGridCellEditor* editor = attr->GetEditor(this, row, col); bool changed = editor->EndEdit(row, col, this); @@ -6717,9 +6848,13 @@ void wxGrid::SaveEditControlValue() if (changed) { - SendEvent( wxEVT_GRID_CELL_CHANGE, + if ( SendEvent( wxEVT_GRID_CELL_CHANGE, m_currentCellCoords.GetRow(), - m_currentCellCoords.GetCol() ); + m_currentCellCoords.GetCol() ) < 0 ) { + + // Event has been vetoed, set the data back. + SetCellValue(row,col,oldval); + } } } } @@ -6879,6 +7014,7 @@ bool wxGrid::IsVisible( int row, int col, bool wholeCellVisible ) // void wxGrid::MakeCellVisible( int row, int col ) { + int i; int xpos = -1, ypos = -1; @@ -6919,7 +7055,10 @@ void wxGrid::MakeCellVisible( int row, int col ) // we divide it later by GRID_SCROLL_LINE, make sure that we don't // have rounding errors (this is important, because if we do, we // might not scroll at all and some cells won't be redrawn) - ypos += GRID_SCROLL_LINE / 2; + // + // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full + // scroll unit... + ypos += GRID_SCROLL_LINE_Y; } if ( left < 0 ) @@ -6941,13 +7080,15 @@ void wxGrid::MakeCellVisible( int row, int col ) } // see comment for ypos above - xpos += GRID_SCROLL_LINE / 2; + xpos += GRID_SCROLL_LINE_X; } if ( xpos != -1 || ypos != -1 ) { - if ( xpos != -1 ) xpos /= GRID_SCROLL_LINE; - if ( ypos != -1 ) ypos /= GRID_SCROLL_LINE; + if ( xpos != -1 ) + xpos /= GRID_SCROLL_LINE_X; + if ( ypos != -1 ) + ypos /= GRID_SCROLL_LINE_Y; Scroll( xpos, ypos ); AdjustScrollbars(); } @@ -7972,19 +8113,20 @@ wxGridCellAttr *wxGrid::GetCellAttr(int row, int col) const wxGridCellAttr *wxGrid::GetOrCreateCellAttr(int row, int col) const { wxGridCellAttr *attr = (wxGridCellAttr *)NULL; - wxASSERT_MSG( m_table, - _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") ); - attr = m_table->GetAttr(row, col, wxGridCellAttr::Cell ); - if ( !attr ) - { - attr = new wxGridCellAttr; + wxCHECK_MSG( m_table, attr, + _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") ); + + attr = m_table->GetAttr(row, col, wxGridCellAttr::Cell); + if ( !attr ) + { + attr = new wxGridCellAttr(m_defaultCellAttr); + + // artificially inc the ref count to match DecRef() in caller + attr->IncRef(); + m_table->SetAttr(attr, row, col); + } - // artificially inc the ref count to match DecRef() in caller - attr->IncRef(); - m_table->SetAttr(attr, row, col); - } - attr->SetDefAttr(m_defaultCellAttr); return attr; } @@ -8208,8 +8350,8 @@ void wxGrid::SetDefaultRowSize( int height, bool resizeExistingRows ) if ( resizeExistingRows ) { InitRowHeights(); - if ( !GetBatchCount() ) - CalcDimensions(); + if ( !GetBatchCount() ) + CalcDimensions(); } } @@ -8243,8 +8385,8 @@ void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols ) if ( resizeExistingCols ) { InitColWidths(); - if ( !GetBatchCount() ) - CalcDimensions(); + if ( !GetBatchCount() ) + CalcDimensions(); } } @@ -8372,33 +8514,35 @@ void wxGrid::AutoSizeColOrRow( int colOrRow, bool setAsMin, bool column ) } } - if ( column ){ + if ( column ) + { SetColSize(col, extentMax); if ( !GetBatchCount() ) { - int cw, ch, dummy; - m_gridWin->GetClientSize( &cw, &ch ); - wxRect rect ( CellToRect( 0, col ) ); - rect.y = 0; - CalcScrolledPosition(rect.x, 0, &rect.x, &dummy); - rect.width = cw - rect.x; - rect.height = m_colLabelHeight; - m_colLabelWin->Refresh( TRUE, &rect ); - } - } - else{ + int cw, ch, dummy; + m_gridWin->GetClientSize( &cw, &ch ); + wxRect rect ( CellToRect( 0, col ) ); + rect.y = 0; + CalcScrolledPosition(rect.x, 0, &rect.x, &dummy); + rect.width = cw - rect.x; + rect.height = m_colLabelHeight; + m_colLabelWin->Refresh( TRUE, &rect ); + } + } + else + { SetRowSize(row, extentMax); if ( !GetBatchCount() ) { - int cw, ch, dummy; - m_gridWin->GetClientSize( &cw, &ch ); - wxRect rect ( CellToRect( row, 0 ) ); - rect.x = 0; - CalcScrolledPosition(0, rect.y, &dummy, &rect.y); - rect.width = m_rowLabelWidth; + int cw, ch, dummy; + m_gridWin->GetClientSize( &cw, &ch ); + wxRect rect ( CellToRect( row, 0 ) ); + rect.x = 0; + CalcScrolledPosition(0, rect.y, &dummy, &rect.y); + rect.width = m_rowLabelWidth; rect.height = ch - rect.y; - m_rowLabelWin->Refresh( TRUE, &rect ); - } + m_rowLabelWin->Refresh( TRUE, &rect ); + } } if ( setAsMin ) { @@ -8415,6 +8559,7 @@ int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin) if ( !calcOnly ) BeginBatch(); + for ( int col = 0; col < m_numCols; col++ ) { if ( !calcOnly ) @@ -8424,8 +8569,10 @@ int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin) width += GetColWidth(col); } + if ( !calcOnly ) EndBatch(); + return width; } @@ -8435,6 +8582,7 @@ int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin) if ( !calcOnly ) BeginBatch(); + for ( int row = 0; row < m_numRows; row++ ) { if ( !calcOnly ) @@ -8444,15 +8592,78 @@ int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin) height += GetRowHeight(row); } + if ( !calcOnly ) EndBatch(); + return height; } void wxGrid::AutoSize() { - // set the size too - SetClientSize(SetOrCalcColumnSizes(FALSE), SetOrCalcRowSizes(FALSE)); + BeginBatch(); + + wxSize size(SetOrCalcColumnSizes(FALSE), SetOrCalcRowSizes(FALSE)); + + // round up the size to a multiple of scroll step - this ensures that we + // won't get the scrollbars if we're sized exactly to this width + wxSize sizeFit(GetScrollX(size.x) * GRID_SCROLL_LINE_X, + GetScrollY(size.y) * GRID_SCROLL_LINE_Y); + + // distribute the extra space between teh columns/rows to avoid having + // extra white space + wxCoord diff = sizeFit.x - size.x; + if ( diff ) + { + // try to resize the columns uniformly + wxCoord diffPerCol = diff / m_numCols; + if ( diffPerCol ) + { + for ( int col = 0; col < m_numCols; col++ ) + { + SetColSize(col, GetColWidth(col) + diffPerCol); + } + } + + // add remaining amount to the last columns + diff -= diffPerCol * m_numCols; + if ( diff ) + { + for ( int col = m_numCols - 1; col >= m_numCols - diff; col-- ) + { + SetColSize(col, GetColWidth(col) + 1); + } + } + } + + // same for rows + diff = sizeFit.y - size.y; + if ( diff ) + { + // try to resize the columns uniformly + wxCoord diffPerRow = diff / m_numRows; + if ( diffPerRow ) + { + for ( int row = 0; row < m_numRows; row++ ) + { + SetRowSize(row, GetRowHeight(row) + diffPerRow); + } + } + + // add remaining amount to the last rows + diff -= diffPerRow * m_numRows; + if ( diff ) + { + for ( int row = m_numRows - 1; row >= m_numRows - diff; row-- ) + { + SetRowSize(row, GetRowHeight(row) + 1); + } + } + } + + EndBatch(); + + SetClientSize(sizeFit); } wxSize wxGrid::DoGetBestSize() const @@ -8669,7 +8880,7 @@ wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft, // ------ Grid event classes // -IMPLEMENT_DYNAMIC_CLASS( wxGridEvent, wxEvent ) +IMPLEMENT_DYNAMIC_CLASS( wxGridEvent, wxNotifyEvent ) wxGridEvent::wxGridEvent( int id, wxEventType type, wxObject* obj, int row, int col, int x, int y, bool sel, @@ -8690,7 +8901,7 @@ wxGridEvent::wxGridEvent( int id, wxEventType type, wxObject* obj, } -IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent, wxEvent ) +IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent, wxNotifyEvent ) wxGridSizeEvent::wxGridSizeEvent( int id, wxEventType type, wxObject* obj, int rowOrCol, int x, int y, @@ -8709,7 +8920,7 @@ wxGridSizeEvent::wxGridSizeEvent( int id, wxEventType type, wxObject* obj, } -IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent, wxEvent ) +IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent, wxNotifyEvent ) wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id, wxEventType type, wxObject* obj, const wxGridCellCoords& topLeft, @@ -8730,4 +8941,21 @@ wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id, wxEventType type, wxObjec } -#endif // ifndef wxUSE_NEW_GRID +IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent, wxCommandEvent) + +wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id, wxEventType type, + wxObject* obj, int row, + int col, wxControl* ctrl) + : wxCommandEvent(type, id) +{ + SetEventObject(obj); + m_row = row; + m_col = col; + m_ctrl = ctrl; +} + + +#endif // !wxUSE_NEW_GRID/wxUSE_NEW_GRID + +#endif // wxUSE_GRID +