X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/dcfe4c3d715a669650457bade90e81cb2f9ce5c9..4e5b5abbfd20653c4d6f8c0751e3d045e33e234a:/src/generic/grid.cpp diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 0355d2f816..edc925b87e 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -44,7 +44,8 @@ // this include needs to be outside precomp for BCC #include "wx/textfile.h" -#include "wx/generic/grid.h" +#include "wx/grid.h" + // ---------------------------------------------------------------------------- // array classes @@ -207,6 +208,8 @@ class WXDLLEXPORT wxGridCellAttrData public: void SetAttr(wxGridCellAttr *attr, int row, int col); wxGridCellAttr *GetAttr(int row, int col) const; + void UpdateAttrRows( size_t pos, int numRows ); + void UpdateAttrCols( size_t pos, int numCols ); private: // searches for the attr for given cell, returns wxNOT_FOUND if not found @@ -223,6 +226,7 @@ public: void SetAttr(wxGridCellAttr *attr, int rowOrCol); wxGridCellAttr *GetAttr(int rowOrCol) const; + void UpdateAttrRowsOrCols( size_t pos, int numRowsOrCols ); private: wxArrayInt m_rowsOrCols; @@ -313,19 +317,24 @@ void wxGridCellEditor::HandleReturn(wxKeyEvent& event) } +void wxGridCellEditor::StartingKey(wxKeyEvent& event) +{ +} + + + wxGridCellTextEditor::wxGridCellTextEditor() { } void wxGridCellTextEditor::Create(wxWindow* parent, wxWindowID id, - const wxPoint& pos, - const wxSize& size, wxEvtHandler* evtHandler) { - m_control = new wxTextCtrl(parent, -1, "", pos, size + m_control = new wxTextCtrl(parent, -1, "", + wxDefaultPosition, wxDefaultSize #if defined(__WXMSW__) - , wxTE_MULTILINE | wxTE_NO_VSCROLL + , wxTE_MULTILINE | wxTE_NO_VSCROLL // necessary ??? #endif ); @@ -363,7 +372,9 @@ bool wxGridCellTextEditor::EndEdit(int row, int col, bool saveValue, if (changed) grid->GetTable()->SetValue(row, col, value); + m_startValue = ""; + ((wxTextCtrl*)m_control)->SetValue(m_startValue); return changed; } @@ -378,6 +389,22 @@ void wxGridCellTextEditor::Reset() ((wxTextCtrl*)m_control)->SetInsertionPointEnd(); } + +void wxGridCellTextEditor::StartingKey(wxKeyEvent& event) +{ + wxASSERT_MSG(m_control, + wxT("The wxGridCellEditor must be Created first!")); + + int code = event.KeyCode(); + if (code >= 32 && code < 255) { + wxString st((char)code); + if (! event.ShiftDown()) + st.LowerCase(); + ((wxTextCtrl*)m_control)->AppendText(st); + } +} + + void wxGridCellTextEditor::HandleReturn(wxKeyEvent& event) { #if defined(__WXMOTIF__) || defined(__WXGTK__) @@ -401,18 +428,10 @@ void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event) { case WXK_ESCAPE: m_editor->Reset(); + m_grid->EnableCellEditControl(FALSE); break; - case WXK_UP: - case WXK_DOWN: - case WXK_LEFT: - case WXK_RIGHT: - case WXK_PRIOR: - case WXK_NEXT: - case WXK_SPACE: - // send the event to the parent grid, skipping the - // event if nothing happens - // + case WXK_TAB: event.Skip( m_grid->ProcessEvent( event ) ); break; @@ -421,13 +440,6 @@ void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event) m_editor->HandleReturn(event); break; - case WXK_HOME: - case WXK_END: - // send the event to the parent grid, skipping the - // event if nothing happens - // - event.Skip( m_grid->ProcessEvent( event ) ); - break; default: event.Skip(); @@ -566,6 +578,18 @@ wxGridCellRenderer* wxGridCellAttr::GetRenderer() const } } +wxGridCellEditor* wxGridCellAttr::GetEditor() const +{ + if (HasEditor()) + return m_editor; + else if (m_defGridAttr != this) + return m_defGridAttr->GetEditor(); + else { + wxFAIL_MSG(wxT("Missing default cell attribute")); + return NULL; + } +} + // ---------------------------------------------------------------------------- // wxGridCellAttrData // ---------------------------------------------------------------------------- @@ -607,6 +631,72 @@ wxGridCellAttr *wxGridCellAttrData::GetAttr(int row, int col) const return attr; } +void wxGridCellAttrData::UpdateAttrRows( size_t pos, int numRows ) +{ + size_t count = m_attrs.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + wxGridCellCoords& coords = m_attrs[n].coords; + wxCoord row = coords.GetRow(); + if ((size_t)row >= pos) + { + if (numRows > 0) + { + // If rows inserted, include row counter where necessary + coords.SetRow(row + numRows); + } + else if (numRows < 0) + { + // If rows deleted ... + if ((size_t)row >= pos - numRows) + { + // ...either decrement row counter (if row still exists)... + coords.SetRow(row + numRows); + } + else + { + // ...or remove the attribute + m_attrs.RemoveAt((size_t)n); + n--; count--; + } + } + } + } +} + +void wxGridCellAttrData::UpdateAttrCols( size_t pos, int numCols ) +{ + size_t count = m_attrs.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + wxGridCellCoords& coords = m_attrs[n].coords; + wxCoord col = coords.GetCol(); + if ( (size_t)col >= pos ) + { + if ( numCols > 0 ) + { + // If rows inserted, include row counter where necessary + coords.SetCol(col + numCols); + } + else if (numCols < 0) + { + // If rows deleted ... + if ((size_t)col >= pos - numCols) + { + // ...either decrement row counter (if row still exists)... + coords.SetCol(col + numCols); + } + else + { + // ...or remove the attribute + m_attrs.RemoveAt((size_t)n); + n--; count--; + } + } + } + } +} + int wxGridCellAttrData::FindIndex(int row, int col) const { size_t count = m_attrs.GetCount(); @@ -675,6 +765,35 @@ void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr *attr, int rowOrCol) } } +void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos, int numRowsOrCols ) +{ + size_t count = m_attrs.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + int & rowOrCol = m_rowsOrCols[n]; + if ( (size_t)rowOrCol >= pos ) + { + if ( numRowsOrCols > 0 ) + { + // If rows inserted, include row counter where necessary + rowOrCol += numRowsOrCols; + } + else if ( numRowsOrCols < 0) + { + // If rows deleted, either decrement row counter (if row still exists) + if ((size_t)rowOrCol >= pos - numRowsOrCols) + rowOrCol += numRowsOrCols; + else + { + m_rowsOrCols.RemoveAt((size_t)n); + m_attrs.RemoveAt((size_t)n); + n--; count--; + } + } + } + } +} + // ---------------------------------------------------------------------------- // wxGridCellAttrProvider // ---------------------------------------------------------------------------- @@ -744,6 +863,26 @@ void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr *attr, int col) m_data->m_colAttrs.SetAttr(attr, col); } +void wxGridCellAttrProvider::UpdateAttrRows( size_t pos, int numRows ) +{ + if ( m_data ) + { + m_data->m_cellAttrs.UpdateAttrRows( pos, numRows ); + + m_data->m_rowAttrs.UpdateAttrRowsOrCols( pos, numRows ); + } +} + +void wxGridCellAttrProvider::UpdateAttrCols( size_t pos, int numCols ) +{ + if ( m_data ) + { + m_data->m_cellAttrs.UpdateAttrCols( pos, numCols ); + + m_data->m_colAttrs.UpdateAttrRowsOrCols( pos, numCols ); + } +} + // ---------------------------------------------------------------------------- // wxGridTableBase // ---------------------------------------------------------------------------- @@ -822,6 +961,22 @@ void wxGridTableBase::SetColAttr(wxGridCellAttr *attr, int col) } } +void wxGridTableBase::UpdateAttrRows( size_t pos, int numRows ) +{ + if ( m_attrProvider ) + { + m_attrProvider->UpdateAttrRows( pos, numRows ); + } +} + +void wxGridTableBase::UpdateAttrCols( size_t pos, int numCols ) +{ + if ( m_attrProvider ) + { + m_attrProvider->UpdateAttrCols( pos, numCols ); + } +} + bool wxGridTableBase::InsertRows( size_t pos, size_t numRows ) { wxFAIL_MSG( wxT("Called grid table class function InsertRows\n" @@ -1049,7 +1204,7 @@ bool wxGridStringTable::InsertRows( size_t pos, size_t numRows ) { m_data.Insert( sa, row ); } - + UpdateAttrRows( pos, numRows ); if ( GetView() ) { wxGridTableMessage msg( this, @@ -1129,7 +1284,7 @@ bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows ) m_data.Remove( pos ); } } - + UpdateAttrRows( pos, -((int)numRows) ); if ( GetView() ) { wxGridTableMessage msg( this, @@ -1162,7 +1317,7 @@ bool wxGridStringTable::InsertCols( size_t pos, size_t numCols ) m_data[row].Insert( wxEmptyString, col ); } } - + UpdateAttrCols( pos, numCols ); if ( GetView() ) { wxGridTableMessage msg( this, @@ -1246,7 +1401,7 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols ) } } } - + UpdateAttrCols( pos, -((int)numCols) ); if ( GetView() ) { wxGridTableMessage msg( this, @@ -1320,116 +1475,7 @@ void wxGridStringTable::SetColLabelValue( int col, const wxString& value ) - ////////////////////////////////////////////////////////////////////// - -IMPLEMENT_DYNAMIC_CLASS( wxGridTextCtrl, wxTextCtrl ) - -BEGIN_EVENT_TABLE( wxGridTextCtrl, wxTextCtrl ) - EVT_KEY_DOWN( wxGridTextCtrl::OnKeyDown ) -END_EVENT_TABLE() - - -wxGridTextCtrl::wxGridTextCtrl( wxWindow *par, - wxGrid *grid, - bool isCellControl, - wxWindowID id, - const wxString& value, - const wxPoint& pos, - const wxSize& size, - long style ) - : wxTextCtrl( par, id, value, pos, size, style ) -{ - m_grid = grid; - m_isCellControl = isCellControl; -} - - -void wxGridTextCtrl::OnKeyDown( wxKeyEvent& event ) -{ - switch ( event.KeyCode() ) - { - case WXK_ESCAPE: - m_grid->SetEditControlValue( startValue ); - SetInsertionPointEnd(); - break; - - case WXK_UP: - case WXK_DOWN: - case WXK_LEFT: - case WXK_RIGHT: - case WXK_PRIOR: - case WXK_NEXT: - case WXK_SPACE: - if ( m_isCellControl ) - { - // send the event to the parent grid, skipping the - // event if nothing happens - // - event.Skip( m_grid->ProcessEvent( event ) ); - } - else - { - // default text control response within the top edit - // control - // - event.Skip(); - } - break; - - case WXK_RETURN: - if ( m_isCellControl ) - { - if ( !m_grid->ProcessEvent( event ) ) - { -#if defined(__WXMOTIF__) || defined(__WXGTK__) - // wxMotif needs a little extra help... - // - int pos = GetInsertionPoint(); - wxString s( GetValue() ); - s = s.Left(pos) + "\n" + s.Mid(pos); - SetValue(s); - SetInsertionPoint( pos ); -#else - // the other ports can handle a Return key press - // - event.Skip(); -#endif - } - } - break; - - case WXK_HOME: - case WXK_END: - if ( m_isCellControl ) - { - // send the event to the parent grid, skipping the - // event if nothing happens - // - event.Skip( m_grid->ProcessEvent( event ) ); - } - else - { - // default text control response within the top edit - // control - // - event.Skip(); - } - break; - - default: - event.Skip(); - } -} - -void wxGridTextCtrl::SetStartValue( const wxString& s ) -{ - startValue = s; - wxTextCtrl::SetValue(s); -} - - - ////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow, wxWindow ) @@ -1657,8 +1703,10 @@ void wxGridWindow::OnEraseBackground(wxEraseEvent&) + ////////////////////////////////////////////////////////////////////// + IMPLEMENT_DYNAMIC_CLASS( wxGrid, wxScrolledWindow ) BEGIN_EVENT_TABLE( wxGrid, wxScrolledWindow ) @@ -1705,11 +1753,12 @@ wxGrid::~wxGrid() void wxGrid::Create() { m_created = FALSE; // set to TRUE by CreateGrid - m_displayed = FALSE; // set to TRUE by OnPaint + m_displayed = TRUE; // FALSE; // set to TRUE by OnPaint m_table = (wxGridTableBase *) NULL; m_ownTable = FALSE; - m_cellEditCtrl = (wxWindow *) NULL; + + m_cellEditCtrlEnabled = FALSE; m_defaultCellAttr = new wxGridCellAttr; m_defaultCellAttr->SetDefAttr(m_defaultCellAttr); @@ -1775,6 +1824,11 @@ bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership ) { if ( m_created ) { + // RD: Actually, this should probably be allowed. I think it would be + // nice to be able to switch multiple Tables in and out of a single + // View at runtime. Is there anything in the implmentation that would + // prevent this? + wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); return FALSE; } @@ -1862,9 +1916,11 @@ void wxGrid::Init() m_colRights.Add( colRight ); } + // Set default cell attributes m_defaultCellAttr->SetFont(GetFont()); m_defaultCellAttr->SetAlignment(wxLEFT, wxTOP); m_defaultCellAttr->SetRenderer(new wxGridCellStringRenderer); + m_defaultCellAttr->SetEditor(new wxGridCellTextEditor); m_defaultCellAttr->SetTextColour( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT)); m_defaultCellAttr->SetBackgroundColour( @@ -1879,6 +1935,9 @@ void wxGrid::Init() m_dragLastPos = -1; m_dragRowOrCol = -1; m_isDragging = FALSE; + m_startDragPos = wxDefaultPosition; + + m_waitForSlowClick = FALSE; m_rowResizeCursor = wxCursor( wxCURSOR_SIZENS ); m_colResizeCursor = wxCursor( wxCURSOR_SIZEWE ); @@ -1895,23 +1954,6 @@ void wxGrid::Init() m_inOnKeyDown = FALSE; m_batchCount = 0; - // TODO: extend this to other types of controls - // - m_cellEditCtrl = new wxGridTextCtrl( m_gridWin, - this, - FALSE, - wxGRID_CELLCTRL, - "", - wxPoint(1,1), - wxSize(1,1) -#if defined(__WXMSW__) - , wxTE_MULTILINE | wxTE_NO_VSCROLL -#endif - ); - - m_cellEditCtrl->Show( FALSE ); - m_cellEditCtrlEnabled = FALSE; - m_editCtrlType = wxGRID_TEXTCTRL; } @@ -2271,7 +2313,7 @@ void wxGrid::CalcCellsExposed( wxRegion& reg ) int colLeft, rowTop; for ( row = 0; row < m_numRows; row++ ) { - if ( m_rowBottoms[row] < top ) continue; + if ( m_rowBottoms[row] <= top ) continue; rowTop = m_rowBottoms[row] - m_rowHeights[row]; if ( rowTop > bottom ) break; @@ -2280,7 +2322,7 @@ void wxGrid::CalcCellsExposed( wxRegion& reg ) for ( col = 0; col < m_numCols; col++ ) { - if ( m_colRights[col] < left ) continue; + if ( m_colRights[col] <= left ) continue; colLeft = m_colRights[col] - m_colWidths[col]; if ( colLeft > right ) break; @@ -2317,6 +2359,10 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) wxClientDC dc( m_gridWin ); PrepareDC( dc ); + y = wxMax( y, + m_rowBottoms[m_dragRowOrCol] - + m_rowHeights[m_dragRowOrCol] + + WXGRID_MIN_ROW_HEIGHT ); dc.SetLogicalFunction(wxINVERT); if ( m_dragLastPos >= 0 ) { @@ -2479,6 +2525,10 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) wxClientDC dc( m_gridWin ); PrepareDC( dc ); + x = wxMax( x, + m_colRights[m_dragRowOrCol] - + m_colWidths[m_dragRowOrCol] + + WXGRID_MIN_COL_WIDTH ); dc.SetLogicalFunction(wxINVERT); if ( m_dragLastPos >= 0 ) { @@ -2729,6 +2779,19 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) if ( event.Dragging() ) { + //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); + + // Don't start doing anything until the mouse has been drug at + // least 3 pixels in any direction... + if (! m_isDragging) { + if (m_startDragPos == wxDefaultPosition) { + m_startDragPos = pos; + return; + } + if (abs(m_startDragPos.x - pos.x) < 4 && abs(m_startDragPos.y - pos.y) < 4) + return; + } + m_isDragging = TRUE; if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL ) { @@ -2736,6 +2799,13 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) // won't interfer with drag-shrinking. if ( IsCellEditControlEnabled() ) HideCellEditControl(); + + // Have we captured the mouse yet? + if (! m_winCapture) { + m_winCapture = m_gridWin; + m_winCapture->CaptureMouse(); + } + if ( coords != wxGridNoCellCoords ) { if ( !IsSelection() ) @@ -2746,6 +2816,12 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) { SelectBlock( m_currentCellCoords, coords ); } + + if (! IsVisible(coords)) { + MakeCellVisible(coords); + // TODO: need to introduce a delay or something here. The + // scrolling is way to fast, at least on MSW. + } } } else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW ) @@ -2756,6 +2832,10 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) wxClientDC dc( m_gridWin ); PrepareDC( dc ); + y = wxMax( y, + m_rowBottoms[m_dragRowOrCol] - + m_rowHeights[m_dragRowOrCol] + + WXGRID_MIN_ROW_HEIGHT ); dc.SetLogicalFunction(wxINVERT); if ( m_dragLastPos >= 0 ) { @@ -2772,6 +2852,9 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) wxClientDC dc( m_gridWin ); PrepareDC( dc ); + x = wxMax( x, + m_colRights[m_dragRowOrCol] - + m_colWidths[m_dragRowOrCol] + WXGRID_MIN_COL_WIDTH ); dc.SetLogicalFunction(wxINVERT); if ( m_dragLastPos >= 0 ) { @@ -2785,6 +2868,8 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) } m_isDragging = FALSE; + m_startDragPos = wxDefaultPosition; + if ( coords != wxGridNoCellCoords ) { @@ -2804,16 +2889,7 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) // if ( event.LeftDown() ) { - if ( event.AltDown() ) - { - MakeCellVisible( coords ); - SetCurrentCell( coords ); - EnableCellEditControl( TRUE ); - } - else - { - EnableCellEditControl( FALSE ); - } + EnableCellEditControl( FALSE ); if ( event.ShiftDown() ) { SelectBlock( m_currentCellCoords, coords ); @@ -2827,7 +2903,18 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) event ) ) { MakeCellVisible( coords ); - SetCurrentCell( coords ); + + // if this is the second click on this cell then start + // the edit control + if (m_waitForSlowClick && coords == m_currentCellCoords) { + EnableCellEditControl(TRUE); + ShowCellEditControl(); + m_waitForSlowClick = FALSE; + } + else { + SetCurrentCell( coords ); + m_waitForSlowClick = TRUE; + } } } } @@ -2856,6 +2943,10 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) { if ( IsSelection() ) { + if (m_winCapture) { + m_winCapture->ReleaseMouse(); + m_winCapture = NULL; + } SendEvent( EVT_GRID_RANGE_SELECT, -1, -1, event ); } @@ -3435,7 +3526,7 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) { // shouldn't be here - we are going round in circles... // - wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while alread active") ); + wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); } m_inOnKeyDown = TRUE; @@ -3448,6 +3539,12 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) if ( !parent->GetEventHandler()->ProcessEvent( keyEvt ) ) { + + // TODO: Should also support Shift-cursor keys for + // extending the selection. Maybe add a flag to + // MoveCursorXXX() and MoveCursorXXXBlock() and + // just send event.ShiftDown(). + // try local handlers // switch ( event.KeyCode() ) @@ -3496,17 +3593,6 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) } break; - case WXK_SPACE: - if ( !IsEditable() ) - { - MoveCursorRight(); - } - else - { - event.Skip(); - } - break; - case WXK_RETURN: if ( event.ControlDown() ) { @@ -3518,6 +3604,13 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) } break; + case WXK_TAB: + if (event.ShiftDown()) + MoveCursorLeft(); + else + MoveCursorRight(); + break; + case WXK_HOME: if ( event.ControlDown() ) { @@ -3550,26 +3643,46 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) 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() ) + { + MoveCursorRight(); + break; + } + // Otherwise fall through to default + default: // now try the cell edit control // if ( !IsCellEditControlEnabled() ) EnableCellEditControl( TRUE ); - if ( IsCellEditControlEnabled() ) - { - event.SetEventObject( m_cellEditCtrl ); - m_cellEditCtrl->GetEventHandler()->ProcessEvent( event ); - } - break; + if (IsCellEditControlEnabled()) { + wxGridCellAttr* attr = GetCellAttr(m_currentCellCoords); + attr->GetEditor()->StartingKey(event); + attr->DecRef(); + } + break; } } m_inOnKeyDown = FALSE; } + void wxGrid::OnEraseBackground(wxEraseEvent&) { } + + + void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) { if ( SendEvent( EVT_GRID_SELECT_CELL, coords.GetRow(), coords.GetCol() ) ) @@ -3583,15 +3696,23 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) { HideCellEditControl(); SaveEditControlValue(); + EnableCellEditControl(FALSE); + + // Clear the old current cell highlight + wxRect r = BlockToDeviceRect(m_currentCellCoords, m_currentCellCoords); + m_currentCellCoords = coords; // Otherwise refresh redraws the highlight! + m_gridWin->Refresh( FALSE, &r ); } m_currentCellCoords = coords; SetEditControlValue(); -#if 0 + if ( m_displayed ) { - ShowCellEditControl(); + wxClientDC dc(m_gridWin); + PrepareDC(dc); + DrawCellHighlight(dc); if ( IsSelection() ) { @@ -3600,9 +3721,6 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) if ( !GetBatchCount() ) m_gridWin->Refresh( FALSE, &r ); } } -#else - SelectBlock ( coords, coords ); -#endif } @@ -3683,12 +3801,36 @@ void wxGrid::DrawCell( wxDC& dc, const wxGridCellCoords& coords ) wxRect rect; rect.x = m_colRights[col] - m_colWidths[col]; rect.y = m_rowBottoms[row] - m_rowHeights[row]; - rect.width = m_colWidths[col] - 1; - rect.height = m_rowHeights[row] - 1; + rect.width = m_colWidths[col]-1; + rect.height = m_rowHeights[row]-1; wxGridCellAttr* attr = GetCellAttr(row, col); attr->GetRenderer()->Draw(*this, *attr, dc, rect, row, col, IsInSelection(coords)); attr->DecRef(); + + if (m_currentCellCoords == coords) + DrawCellHighlight(dc); +} + + +void wxGrid::DrawCellHighlight( wxDC& dc ) +{ + int row = m_currentCellCoords.GetRow(); + int col = m_currentCellCoords.GetCol(); + + if ( m_colWidths[col] <= 0 || m_rowHeights[row] <= 0 ) + return; + + wxRect rect; + rect.x = m_colRights[col] - m_colWidths[col]; + rect.y = m_rowBottoms[row] - m_rowHeights[row]; + rect.width = m_colWidths[col] - 1; + rect.height = m_rowHeights[row] - 1; + + dc.SetPen(wxPen(m_gridLineColour, 3, wxSOLID)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + + dc.DrawRectangle(rect); } void wxGrid::DrawCellBorder( wxDC& dc, const wxGridCellCoords& coords ) @@ -4006,35 +4148,30 @@ void wxGrid::EnableEditing( bool edit ) { m_editable = edit; - // TODO: extend this for other edit control types - // - if ( m_editCtrlType == wxGRID_TEXTCTRL ) - { - ((wxTextCtrl *)m_cellEditCtrl)->SetEditable( m_editable ); - } + EnableCellEditControl(m_editable); } } void wxGrid::EnableCellEditControl( bool enable ) { + if (! m_editable) + return; + if ( m_currentCellCoords == wxGridNoCellCoords ) SetCurrentCell( 0, 0 ); - if ( m_cellEditCtrl && - enable != m_cellEditCtrlEnabled ) - { + if ( enable != m_cellEditCtrlEnabled ) + { if ( enable ) { m_cellEditCtrlEnabled = enable; SetEditControlValue(); - // requires m_cellEditCtrlEnabled to be already true ShowCellEditControl(); } else { HideCellEditControl(); - // requires m_cellEditCtrlEnabled to be still true SaveEditControlValue(); m_cellEditCtrlEnabled = enable; } @@ -4044,8 +4181,6 @@ void wxGrid::EnableCellEditControl( bool enable ) void wxGrid::ShowCellEditControl() { - wxRect rect; - if ( IsCellEditControlEnabled() ) { if ( !IsVisible( m_currentCellCoords ) ) @@ -4054,14 +4189,16 @@ void wxGrid::ShowCellEditControl() } else { - rect = CellToRect( m_currentCellCoords ); + wxRect rect = CellToRect( m_currentCellCoords ); + int row = m_currentCellCoords.GetRow(); + int col = m_currentCellCoords.GetCol(); // convert to scrolled coords // int left, top, right, bottom; CalcScrolledPosition( rect.GetLeft(), rect.GetTop(), &left, &top ); CalcScrolledPosition( rect.GetRight(), rect.GetBottom(), &right, &bottom ); - + left--; top--; right--; bottom--; // cell is shifted by one pixel int cw, ch; m_gridWin->GetClientSize( &cw, &ch ); @@ -4070,8 +4207,7 @@ void wxGrid::ShowCellEditControl() // int extra; #if defined(__WXMOTIF__) - if ( m_currentCellCoords.GetRow() == 0 || - m_currentCellCoords.GetCol() == 0 ) + if ( row == 0 || col == 0 ) { extra = 2; } @@ -4080,8 +4216,7 @@ void wxGrid::ShowCellEditControl() extra = 4; } #else - if ( m_currentCellCoords.GetRow() == 0 || - m_currentCellCoords.GetCol() == 0 ) + if ( row == 0 || col == 0 ) { extra = 1; } @@ -4107,33 +4242,18 @@ void wxGrid::ShowCellEditControl() rect.SetBottom( rect.GetBottom() + 2*extra ); #endif - m_cellEditCtrl->SetSize( rect ); - m_cellEditCtrl->Show( TRUE ); - - switch ( m_editCtrlType ) - { - case wxGRID_TEXTCTRL: - ((wxTextCtrl *) m_cellEditCtrl)->SetInsertionPointEnd(); - break; - - case wxGRID_CHECKBOX: - // TODO: anything ??? - // - break; - - case wxGRID_CHOICE: - // TODO: anything ??? - // - break; - - case wxGRID_COMBOBOX: - // TODO: anything ??? - // - break; + wxGridCellAttr* attr = GetCellAttr(row, col); + wxGridCellEditor* editor = attr->GetEditor(); + if (! editor->IsCreated()) { + editor->Create(m_gridWin, -1, + new wxGridCellEditorEvtHandler(this, editor)); } - m_cellEditCtrl->SetFocus(); - } + editor->SetSize( rect ); + editor->Show( TRUE ); + editor->BeginEdit(row, col, this, attr); + attr->DecRef(); + } } } @@ -4142,94 +4262,36 @@ void wxGrid::HideCellEditControl() { if ( IsCellEditControlEnabled() ) { - m_cellEditCtrl->Show( FALSE ); - SetFocus(); + int row = m_currentCellCoords.GetRow(); + int col = m_currentCellCoords.GetCol(); + + wxGridCellAttr* attr = GetCellAttr(row, col); + attr->GetEditor()->Show( FALSE ); + attr->DecRef(); + m_gridWin->SetFocus(); } } void wxGrid::SetEditControlValue( const wxString& value ) { - if ( m_table ) - { - wxString s; - if ( !value ) - s = GetCellValue(m_currentCellCoords); - else - s = value; - - if ( IsCellEditControlEnabled() ) - { - switch ( m_editCtrlType ) - { - case wxGRID_TEXTCTRL: - ((wxGridTextCtrl *)m_cellEditCtrl)->SetStartValue(s); - break; - - case wxGRID_CHECKBOX: - // TODO: implement this - // - break; - - case wxGRID_CHOICE: - // TODO: implement this - // - break; - - case wxGRID_COMBOBOX: - // TODO: implement this - // - break; - } - } - } + // RD: The new Editors get the value from the table themselves now. This + // method can probably be removed... } void wxGrid::SaveEditControlValue() { - if ( m_table ) - { - wxWindow *ctrl = (wxWindow *)NULL; - - if ( IsCellEditControlEnabled() ) - { - ctrl = m_cellEditCtrl; - } - else - { - return; - } - - bool valueChanged = FALSE; - - switch ( m_editCtrlType ) - { - case wxGRID_TEXTCTRL: - valueChanged = (((wxGridTextCtrl *)ctrl)->GetValue() != - ((wxGridTextCtrl *)ctrl)->GetStartValue()); - SetCellValue( m_currentCellCoords, - ((wxTextCtrl *) ctrl)->GetValue() ); - break; - - case wxGRID_CHECKBOX: - // TODO: implement this - // - break; + if (IsCellEditControlEnabled()) { + int row = m_currentCellCoords.GetRow(); + int col = m_currentCellCoords.GetCol(); - case wxGRID_CHOICE: - // TODO: implement this - // - break; + wxGridCellAttr* attr = GetCellAttr(row, col); + bool changed = attr->GetEditor()->EndEdit(row, col, TRUE, this, attr); - case wxGRID_COMBOBOX: - // TODO: implement this - // - break; - } + attr->DecRef(); - if ( valueChanged ) - { + if (changed) { SendEvent( EVT_GRID_CELL_CHANGE, m_currentCellCoords.GetRow(), m_currentCellCoords.GetCol() ); @@ -4270,7 +4332,7 @@ int wxGrid::YToRow( int y ) if ( y < m_rowBottoms[i] ) return i; } - return -1; + return m_numRows; //-1; } @@ -4283,7 +4345,7 @@ int wxGrid::XToCol( int x ) if ( x < m_colRights[i] ) return i; } - return -1; + return m_numCols; //-1; } @@ -5118,6 +5180,11 @@ void wxGrid::SetDefaultRenderer(wxGridCellRenderer *renderer) m_defaultCellAttr->SetRenderer(renderer); } +void wxGrid::SetDefaultEditor(wxGridCellEditor *editor) +{ + m_defaultCellAttr->SetEditor(editor); +} + // ---------------------------------------------------------------------------- // access to the default attrbiutes // ---------------------------------------------------------------------------- @@ -5147,6 +5214,11 @@ wxGridCellRenderer *wxGrid::GetDefaultRenderer() const return m_defaultCellAttr->GetRenderer(); } +wxGridCellEditor *wxGrid::GetDefaultEditor() const +{ + return m_defaultCellAttr->GetEditor(); +} + // ---------------------------------------------------------------------------- // access to cell attributes // ---------------------------------------------------------------------------- @@ -5190,6 +5262,14 @@ wxGridCellRenderer* wxGrid::GetCellRenderer(int row, int col) return renderer; } +wxGridCellEditor* wxGrid::GetCellEditor(int row, int col) +{ + wxGridCellAttr* attr = GetCellAttr(row, col); + wxGridCellEditor* editor = attr->GetEditor(); + attr->DecRef(); + return editor; +} + // ---------------------------------------------------------------------------- // attribute support: cache, automatic provider creation, ... // ---------------------------------------------------------------------------- @@ -5380,6 +5460,16 @@ void wxGrid::SetCellRenderer(int row, int col, wxGridCellRenderer *renderer) } } +void wxGrid::SetCellEditor(int row, int col, wxGridCellEditor* editor) +{ + if ( CanHaveAttributes() ) + { + wxGridCellAttr *attr = GetOrCreateCellAttr(row, col); + attr->SetEditor(editor); + attr->DecRef(); + } +} + // ---------------------------------------------------------------------------- // row/col size // ----------------------------------------------------------------------------