X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1ef49ab576d21e0428eacf26c98a2f0fb62cb94d..172541f64be8fcddb08f1c121da256d08c24a70b:/src/generic/grid.cpp diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index ea0184e2d0..439b9bbb12 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -47,6 +47,7 @@ #include "wx/textfile.h" #include "wx/spinctrl.h" #include "wx/tokenzr.h" +#include "wx/renderer.h" #include "wx/grid.h" #include "wx/generic/gridsel.h" @@ -109,6 +110,7 @@ DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK) DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK) DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK) DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK) +DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_BEGIN_DRAG) DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK) DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK) DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK) @@ -141,6 +143,7 @@ private: void OnMouseWheel( wxMouseEvent& event ); void OnKeyDown( wxKeyEvent& event ); void OnKeyUp( wxKeyEvent& ); + void OnChar( wxKeyEvent& ); DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow) DECLARE_EVENT_TABLE() @@ -163,6 +166,7 @@ private: void OnMouseWheel( wxMouseEvent& event ); void OnKeyDown( wxKeyEvent& event ); void OnKeyUp( wxKeyEvent& ); + void OnChar( wxKeyEvent& ); DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow) DECLARE_EVENT_TABLE() @@ -184,6 +188,7 @@ private: void OnMouseWheel( wxMouseEvent& event ); void OnKeyDown( wxKeyEvent& event ); void OnKeyUp( wxKeyEvent& ); + void OnChar( wxKeyEvent& ); void OnPaint( wxPaintEvent& event ); DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow) @@ -205,7 +210,7 @@ public: wxGridRowLabelWindow *rowLblWin, wxGridColLabelWindow *colLblWin, wxWindowID id, const wxPoint &pos, const wxSize &size ); - ~wxGridWindow(); + ~wxGridWindow(){} void ScrollWindow( int dx, int dy, const wxRect *rect ); @@ -221,6 +226,7 @@ private: void OnMouseEvent( wxMouseEvent& event ); void OnKeyDown( wxKeyEvent& ); void OnKeyUp( wxKeyEvent& ); + void OnChar( wxKeyEvent& ); void OnEraseBackground( wxEraseEvent& ); void OnFocus( wxFocusEvent& ); @@ -412,6 +418,7 @@ static const size_t GRID_SCROLL_LINE_Y = GRID_SCROLL_LINE_X; // in these hash tables is the number of rows/columns) static const int GRID_HASH_SIZE = 100; +#if 0 // ---------------------------------------------------------------------------- // private functions // ---------------------------------------------------------------------------- @@ -425,6 +432,7 @@ static inline int GetScrollY(int y) { return (y + GRID_SCROLL_LINE_Y - 1) / GRID_SCROLL_LINE_Y; } +#endif // ============================================================================ // implementation @@ -499,9 +507,11 @@ void wxGridCellEditor::Show(bool show, wxGridCellAttr *attr) m_colBgOld = m_control->GetBackgroundColour(); m_control->SetBackgroundColour(attr->GetBackgroundColour()); +// Workaround for GTK+1 font setting problem on some platforms +#if !defined(__WXGTK__) || defined(__WXGTK20__) m_fontOld = m_control->GetFont(); m_control->SetFont(attr->GetFont()); - +#endif // can't do anything more in the base class version, the other // attributes may only be used by the derived classes } @@ -520,12 +530,14 @@ void wxGridCellEditor::Show(bool show, wxGridCellAttr *attr) m_control->SetBackgroundColour(m_colBgOld); m_colBgOld = wxNullColour; } - +// Workaround for GTK+1 font setting problem on some platforms +#if !defined(__WXGTK__) || defined(__WXGTK20__) if ( m_fontOld.Ok() ) { m_control->SetFont(m_fontOld); m_fontOld = wxNullFont; } +#endif } } @@ -543,8 +555,40 @@ void wxGridCellEditor::HandleReturn(wxKeyEvent& event) bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent& event) { - // accept the simple key presses, not anything with Ctrl/Alt/Meta - return !(event.ControlDown() || event.AltDown()); + bool ctrl = event.ControlDown(); + bool alt = event.AltDown(); +#ifdef __WXMAC__ + // On the Mac the Alt key is more like shift and is used for entry of + // valid characters, so check for Ctrl and Meta instead. + alt = event.MetaDown(); +#endif + + // Assume it's not a valid char if ctrl or alt is down, but if both are + // down then it may be because of an AltGr key combination, so let them + // through in that case. + if ((ctrl || alt) && !(ctrl && alt)) + return false; + +#if wxUSE_UNICODE + int key = event.GetUnicodeKey(); + bool keyOk = true; + + // if the unicode key code is not really a unicode character (it may + // be a function key or etc., the platforms appear to always give us a + // small value in this case) then fallback to the ascii key code but + // don't do anything for function keys or etc. + if (key <= 127) + { + key = event.GetKeyCode(); + keyOk = (key <= 127); + } + return keyOk; +#else // !wxUSE_UNICODE + int key = event.GetKeyCode(); + if (key <= 255) + return true; + return false; +#endif // wxUSE_UNICODE/!wxUSE_UNICODE } void wxGridCellEditor::StartingKey(wxKeyEvent& event) @@ -692,48 +736,46 @@ void wxGridCellTextEditor::DoReset(const wxString& startValue) bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent& event) { - if ( wxGridCellEditor::IsAcceptedKey(event) ) - { - int keycode = event.GetKeyCode(); - switch ( keycode ) - { - case WXK_NUMPAD0: - case WXK_NUMPAD1: - case WXK_NUMPAD2: - case WXK_NUMPAD3: - case WXK_NUMPAD4: - case WXK_NUMPAD5: - case WXK_NUMPAD6: - case WXK_NUMPAD7: - case WXK_NUMPAD8: - case WXK_NUMPAD9: - case WXK_MULTIPLY: - case WXK_NUMPAD_MULTIPLY: - case WXK_ADD: - case WXK_NUMPAD_ADD: - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: - case WXK_DECIMAL: - case WXK_NUMPAD_DECIMAL: - case WXK_DIVIDE: - case WXK_NUMPAD_DIVIDE: - return true; - - default: - // accept 8 bit chars too if isprint() agrees - if ( (keycode < 255) && (wxIsprint(keycode)) ) - return true; - } - } - - return false; + return wxGridCellEditor::IsAcceptedKey(event); } void wxGridCellTextEditor::StartingKey(wxKeyEvent& event) { - if ( !Text()->EmulateKeyPress(event) ) + // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no + // longer an appropriate way to get the character into the text control. + // Do it ourselves instead. We know that if we get this far that we have + // a valid character, so not a whole lot of testing needs to be done. + + wxTextCtrl* tc = Text(); + wxChar ch; + long pos; + +#if wxUSE_UNICODE + ch = event.GetUnicodeKey(); + if (ch <= 127) + ch = (wxChar)event.GetKeyCode(); +#else + ch = (wxChar)event.GetKeyCode(); +#endif + switch (ch) { - event.Skip(); + case WXK_DELETE: + // delete the character at the cursor + pos = tc->GetInsertionPoint(); + if (pos < tc->GetLastPosition()) + tc->Remove(pos, pos+1); + break; + + case WXK_BACK: + // delete the character before the cursor + pos = tc->GetInsertionPoint(); + if (pos > 0) + tc->Remove(pos-1, pos); + break; + + default: + tc->WriteText(ch); + break; } } @@ -795,6 +837,7 @@ void wxGridCellNumberEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler) { +#if wxUSE_SPINCTRL if ( HasRange() ) { // create a spin ctrl @@ -806,6 +849,7 @@ void wxGridCellNumberEditor::Create(wxWindow* parent, wxGridCellEditor::Create(parent, id, evtHandler); } else +#endif { // just a text control wxGridCellTextEditor::Create(parent, id, evtHandler); @@ -828,19 +872,21 @@ void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid) { m_valueOld = 0; wxString sValue = table->GetValue(row, col); - if (! sValue.ToLong(&m_valueOld) && ! sValue.IsEmpty()) + if (! sValue.ToLong(&m_valueOld) && ! sValue.empty()) { wxFAIL_MSG( _T("this cell doesn't have numeric value") ); return; } } +#if wxUSE_SPINCTRL if ( HasRange() ) { Spin()->SetValue((int)m_valueOld); Spin()->SetFocus(); } else +#endif { DoBeginEdit(GetString()); } @@ -853,6 +899,7 @@ bool wxGridCellNumberEditor::EndEdit(int row, int col, long value = 0; wxString text; +#if wxUSE_SPINCTRL if ( HasRange() ) { value = Spin()->GetValue(); @@ -861,9 +908,10 @@ bool wxGridCellNumberEditor::EndEdit(int row, int col, text = wxString::Format(wxT("%ld"), value); } else +#endif { text = Text()->GetValue(); - changed = (text.IsEmpty() || text.ToLong(&value)) && (value != m_valueOld); + changed = (text.empty() || text.ToLong(&value)) && (value != m_valueOld); } if ( changed ) @@ -879,11 +927,13 @@ bool wxGridCellNumberEditor::EndEdit(int row, int col, void wxGridCellNumberEditor::Reset() { +#if wxUSE_SPINCTRL if ( HasRange() ) { Spin()->SetValue((int)m_valueOld); } else +#endif { DoReset(GetString()); } @@ -894,29 +944,10 @@ bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent& event) if ( wxGridCellEditor::IsAcceptedKey(event) ) { int keycode = event.GetKeyCode(); - switch ( keycode ) + if ( (keycode < 128) && + (wxIsdigit(keycode) || keycode == '+' || keycode == '-')) { - case WXK_NUMPAD0: - case WXK_NUMPAD1: - case WXK_NUMPAD2: - case WXK_NUMPAD3: - case WXK_NUMPAD4: - case WXK_NUMPAD5: - case WXK_NUMPAD6: - case WXK_NUMPAD7: - case WXK_NUMPAD8: - case WXK_NUMPAD9: - case WXK_ADD: - case WXK_NUMPAD_ADD: - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: - case WXK_UP: - case WXK_DOWN: - return true; - - default: - if ( (keycode < 128) && wxIsdigit(keycode) ) - return true; + return true; } } @@ -928,21 +959,7 @@ void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event) if ( !HasRange() ) { int keycode = event.GetKeyCode(); - if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-' - || keycode == WXK_NUMPAD0 - || keycode == WXK_NUMPAD1 - || keycode == WXK_NUMPAD2 - || keycode == WXK_NUMPAD3 - || keycode == WXK_NUMPAD4 - || keycode == WXK_NUMPAD5 - || keycode == WXK_NUMPAD6 - || keycode == WXK_NUMPAD7 - || keycode == WXK_NUMPAD8 - || keycode == WXK_NUMPAD9 - || keycode == WXK_ADD - || keycode == WXK_NUMPAD_ADD - || keycode == WXK_SUBTRACT - || keycode == WXK_NUMPAD_SUBTRACT) + if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-') { wxGridCellTextEditor::StartingKey(event); @@ -985,18 +1002,21 @@ void wxGridCellNumberEditor::SetParameters(const wxString& params) // return the value in the spin control if it is there (the text control otherwise) wxString wxGridCellNumberEditor::GetValue() const { - wxString s; + wxString s; - if( HasRange() ) - { - long value = Spin()->GetValue(); - s.Printf(wxT("%ld"), value); - } - else - { - s = Text()->GetValue(); - } - return s; +#if wxUSE_SPINCTRL + if( HasRange() ) + { + long value = Spin()->GetValue(); + s.Printf(wxT("%ld"), value); + } + else +#endif + { + s = Text()->GetValue(); + } + + return s; } // ---------------------------------------------------------------------------- @@ -1032,7 +1052,7 @@ void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid) { m_valueOld = 0.0; wxString sValue = table->GetValue(row, col); - if (! sValue.ToDouble(&m_valueOld) && ! sValue.IsEmpty()) + if (! sValue.ToDouble(&m_valueOld) && ! sValue.empty()) { wxFAIL_MSG( _T("this cell doesn't have float value") ); return; @@ -1048,7 +1068,7 @@ bool wxGridCellFloatEditor::EndEdit(int row, int col, double value = 0.0; wxString text(Text()->GetValue()); - if ( (text.IsEmpty() || text.ToDouble(&value)) && (value != m_valueOld) ) + if ( (text.empty() || text.ToDouble(&value)) && (value != m_valueOld) ) { if (grid->GetTable()->CanSetValueAs(row, col, wxGRID_VALUE_FLOAT)) grid->GetTable()->SetValueAsDouble(row, col, value); @@ -1071,24 +1091,11 @@ void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event) char tmpbuf[2]; tmpbuf[0] = (char) keycode; tmpbuf[1] = '\0'; - bool is_decimal_point = ( wxString(tmpbuf, *wxConvCurrent) == - wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) ); - if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-' - || is_decimal_point - || keycode == WXK_NUMPAD0 - || keycode == WXK_NUMPAD1 - || keycode == WXK_NUMPAD2 - || keycode == WXK_NUMPAD3 - || keycode == WXK_NUMPAD4 - || keycode == WXK_NUMPAD5 - || keycode == WXK_NUMPAD6 - || keycode == WXK_NUMPAD7 - || keycode == WXK_NUMPAD8 - || keycode == WXK_NUMPAD9 - || keycode == WXK_ADD - || keycode == WXK_NUMPAD_ADD - || keycode == WXK_SUBTRACT - || keycode == WXK_NUMPAD_SUBTRACT) + wxString strbuf(tmpbuf, *wxConvCurrent); + bool is_decimal_point = ( strbuf == + wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) ); + if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-' + || is_decimal_point ) { wxGridCellTextEditor::StartingKey(event); @@ -1153,42 +1160,19 @@ bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event) if ( wxGridCellEditor::IsAcceptedKey(event) ) { int keycode = event.GetKeyCode(); - switch ( keycode ) - { - case WXK_NUMPAD0: - case WXK_NUMPAD1: - case WXK_NUMPAD2: - case WXK_NUMPAD3: - case WXK_NUMPAD4: - case WXK_NUMPAD5: - case WXK_NUMPAD6: - case WXK_NUMPAD7: - case WXK_NUMPAD8: - case WXK_NUMPAD9: - case WXK_ADD: - case WXK_NUMPAD_ADD: - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: - case WXK_DECIMAL: - case WXK_NUMPAD_DECIMAL: - return true; - - default: - { - // additionally accept 'e' as in '1e+6', also '-', '+', and '.' - char tmpbuf[2]; - tmpbuf[0] = (char) keycode; - tmpbuf[1] = '\0'; - bool is_decimal_point = - ( wxString(tmpbuf, *wxConvCurrent) == - wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, - wxLOCALE_CAT_NUMBER) ); - if ( (keycode < 128) && - (wxIsdigit(keycode) || tolower(keycode) == 'e' || - is_decimal_point || keycode == '+' || keycode == '-') ) - return true; - } - } + printf("%d\n", keycode); + // accept digits, 'e' as in '1e+6', also '-', '+', and '.' + char tmpbuf[2]; + tmpbuf[0] = (char) keycode; + tmpbuf[1] = '\0'; + wxString strbuf(tmpbuf, *wxConvCurrent); + bool is_decimal_point = + ( strbuf == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, + wxLOCALE_CAT_NUMBER) ); + if ( (keycode < 128) && + (wxIsdigit(keycode) || tolower(keycode) == 'e' || + is_decimal_point || keycode == '+' || keycode == '-') ) + return true; } return false; @@ -1351,12 +1335,6 @@ bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event) int keycode = event.GetKeyCode(); switch ( keycode ) { - case WXK_MULTIPLY: - case WXK_NUMPAD_MULTIPLY: - case WXK_ADD: - case WXK_NUMPAD_ADD: - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: case WXK_SPACE: case '+': case '-': @@ -1367,6 +1345,26 @@ bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event) return false; } +void wxGridCellBoolEditor::StartingKey(wxKeyEvent& event) +{ + int keycode = event.GetKeyCode(); + switch ( keycode ) + { + case WXK_SPACE: + CBox()->SetValue(!CBox()->GetValue()); + break; + + case '+': + CBox()->SetValue(true); + break; + + case '-': + CBox()->SetValue(false); + break; + } +} + + // return the value as "1" for true and the empty string for false wxString wxGridCellBoolEditor::GetValue() const { @@ -1460,18 +1458,12 @@ bool wxGridCellChoiceEditor::EndEdit(int row, int col, wxGrid* grid) { wxString value = Combo()->GetValue(); - bool changed = value != m_startValue; - - if ( changed ) - grid->GetTable()->SetValue(row, col, value); + if ( value == m_startValue ) + return false; - m_startValue = wxEmptyString; - if (m_allowOthers) - Combo()->SetValue(m_startValue); - else - Combo()->SetSelection(0); + grid->GetTable()->SetValue(row, col, value); - return changed; + return true; } void wxGridCellChoiceEditor::Reset() @@ -1528,7 +1520,6 @@ void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event) m_editor->HandleReturn(event); break; - default: event.Skip(); } @@ -1583,18 +1574,18 @@ void wxGridCellRenderer::Draw(wxGrid& grid, // grey out fields if the grid is disabled if( grid.IsEnabled() ) { - if ( isSelected ) - { - dc.SetBrush( wxBrush(grid.GetSelectionBackground(), wxSOLID) ); - } - else - { - dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxSOLID) ); - } + if ( isSelected ) + { + dc.SetBrush( wxBrush(grid.GetSelectionBackground(), wxSOLID) ); + } + else + { + dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxSOLID) ); + } } else { - dc.SetBrush(wxBrush(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE), wxSOLID)); + dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE), wxSOLID)); } dc.SetPen( *wxTRANSPARENT_PEN ); @@ -1630,8 +1621,8 @@ void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid, } else { - dc.SetTextBackground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE)); - dc.SetTextForeground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT)); + dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); + dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); } dc.SetFont( attr.GetFont() ); @@ -1918,7 +1909,7 @@ void wxGridCellFloatRenderer::SetParameters(const wxString& params) else { wxString tmp = params.BeforeFirst(_T(',')); - if ( !!tmp ) + if ( !tmp.empty() ) { long width; if ( tmp.ToLong(&width) ) @@ -1932,7 +1923,7 @@ void wxGridCellFloatRenderer::SetParameters(const wxString& params) } tmp = params.AfterFirst(_T(',')); - if ( !!tmp ) + if ( !tmp.empty() ) { long precision; if ( tmp.ToLong(&precision) ) @@ -2417,7 +2408,9 @@ void wxGridCellAttrData::UpdateAttrRows( size_t pos, int numRows ) else { // ...or remove the attribute - m_attrs.RemoveAt((size_t)n); + // No need to DecRef the attribute itself since this is + // done be wxGridCellWithAttr's destructor! + m_attrs.RemoveAt(n); n--; count--; } } @@ -2450,7 +2443,9 @@ void wxGridCellAttrData::UpdateAttrCols( size_t pos, int numCols ) else { // ...or remove the attribute - m_attrs.RemoveAt((size_t)n); + // No need to DecRef the attribute itself since this is + // done be wxGridCellWithAttr's destructor! + m_attrs.RemoveAt(n); n--; count--; } } @@ -2548,8 +2543,9 @@ void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos, int numRowsOrCols rowOrCol += numRowsOrCols; else { - m_rowsOrCols.RemoveAt((size_t)n); - m_attrs.RemoveAt((size_t)n); + m_rowsOrCols.RemoveAt(n); + m_attrs[n]->DecRef(); + m_attrs.RemoveAt(n); n--; count--; } } @@ -2596,8 +2592,8 @@ wxGridCellAttr *wxGridCellAttrProvider::GetAttr(int row, int col, wxGridCellAttr *attrrow = m_data->m_rowAttrs.GetAttr(row); wxGridCellAttr *attrcol = m_data->m_colAttrs.GetAttr(col); - if((attrcell != attrrow) && (attrrow !=attrcol) && (attrcell != attrcol)){ - // Two or move are non NULL + if((attrcell != attrrow) && (attrrow != attrcol) && (attrcell != attrcol)){ + // Two or more are non NULL attr = new wxGridCellAttr; attr->SetKind(wxGridCellAttr::Merged); @@ -2619,11 +2615,21 @@ wxGridCellAttr *wxGridCellAttrProvider::GetAttr(int row, int col, //m_data->m_mergeAttr.SetAttr(attr, row, col); } else - { + { // one or none is non null return it or null. if(attrrow) attr = attrrow; - if(attrcol) attr = attrcol; - if(attrcell) attr = attrcell; + if(attrcol) + { + if(attr) + attr->DecRef(); + attr = attrcol; + } + if(attrcell) + { + if(attr) + attr->DecRef(); + attr = attrcell; + } } } break; @@ -2631,10 +2637,10 @@ wxGridCellAttr *wxGridCellAttrProvider::GetAttr(int row, int col, attr = m_data->m_cellAttrs.GetAttr(row, col); break; case (wxGridCellAttr::Col): - attr = m_data->m_colAttrs.GetAttr(col); + attr = m_data->m_colAttrs.GetAttr(col); break; case (wxGridCellAttr::Row): - attr = m_data->m_rowAttrs.GetAttr(row); + attr = m_data->m_rowAttrs.GetAttr(row); break; default: // unused as yet... @@ -3474,6 +3480,7 @@ BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxWindow ) EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent ) EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown ) EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp ) + EVT_CHAR ( wxGridRowLabelWindow::OnChar ) END_EVENT_TABLE() wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid *parent, @@ -3528,6 +3535,11 @@ void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent& event ) if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip(); } +void wxGridRowLabelWindow::OnChar( wxKeyEvent& event ) +{ + if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip(); +} + ////////////////////////////////////////////////////////////////////// @@ -3540,6 +3552,7 @@ BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxWindow ) EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent ) EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown ) EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp ) + EVT_CHAR ( wxGridColLabelWindow::OnChar ) END_EVENT_TABLE() wxGridColLabelWindow::wxGridColLabelWindow( wxGrid *parent, @@ -3593,6 +3606,10 @@ void wxGridColLabelWindow::OnKeyUp( wxKeyEvent& event ) if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip(); } +void wxGridColLabelWindow::OnChar( wxKeyEvent& event ) +{ + if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip(); +} ////////////////////////////////////////////////////////////////////// @@ -3605,6 +3622,7 @@ BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxWindow ) EVT_PAINT( wxGridCornerLabelWindow::OnPaint) EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown ) EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp ) + EVT_CHAR ( wxGridCornerLabelWindow::OnChar ) END_EVENT_TABLE() wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent, @@ -3623,6 +3641,15 @@ void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) ) int client_width = 0; GetClientSize( &client_width, &client_height ); +#if __WXGTK__ + wxRect rect; + rect.SetX( 1 ); + rect.SetY( 1 ); + rect.SetWidth( client_width - 2 ); + rect.SetHeight( client_height - 2 ); + + wxRendererNative::Get().DrawHeaderButton( this, dc, rect, 0 ); +#else dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) ); dc.DrawLine( client_width-1, client_height-1, client_width-1, 0 ); dc.DrawLine( client_width-1, client_height-1, 0, client_height-1 ); @@ -3632,6 +3659,7 @@ void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) ) dc.SetPen( *wxWHITE_PEN ); dc.DrawLine( 1, 1, client_width-1, 1 ); dc.DrawLine( 1, 1, 1, client_height-1 ); +#endif } @@ -3659,6 +3687,10 @@ void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent& event ) if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip(); } +void wxGridCornerLabelWindow::OnChar( wxKeyEvent& event ) +{ + if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip(); +} ////////////////////////////////////////////////////////////////////// @@ -3671,6 +3703,7 @@ BEGIN_EVENT_TABLE( wxGridWindow, wxWindow ) EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent ) EVT_KEY_DOWN( wxGridWindow::OnKeyDown ) EVT_KEY_UP( wxGridWindow::OnKeyUp ) + EVT_CHAR ( wxGridWindow::OnChar ) EVT_SET_FOCUS( wxGridWindow::OnFocus ) EVT_KILL_FOCUS( wxGridWindow::OnFocus ) EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground ) @@ -3692,11 +3725,6 @@ wxGridWindow::wxGridWindow( wxGrid *parent, } -wxGridWindow::~wxGridWindow() -{ -} - - void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { wxPaintDC dc( this ); @@ -3743,6 +3771,11 @@ void wxGridWindow::OnKeyUp( wxKeyEvent& event ) if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip(); } +void wxGridWindow::OnChar( wxKeyEvent& event ) +{ + if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip(); +} + void wxGridWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(event) ) { } @@ -3820,7 +3853,7 @@ wxEND_HANDLERS_TABLE() wxCONSTRUCTOR_5( wxGrid , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle ) /* - TODO : Expose more information of a list's layout etc. via appropriate objects (à la NotebookPageInfo) + TODO : Expose more information of a list's layout etc. via appropriate objects (à la NotebookPageInfo) */ #else IMPLEMENT_DYNAMIC_CLASS( wxGrid, wxScrolledWindow ) @@ -3831,6 +3864,7 @@ BEGIN_EVENT_TABLE( wxGrid, wxScrolledWindow ) EVT_SIZE( wxGrid::OnSize ) EVT_KEY_DOWN( wxGrid::OnKeyDown ) EVT_KEY_UP( wxGrid::OnKeyUp ) + EVT_CHAR ( wxGrid::OnChar ) EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground ) END_EVENT_TABLE() @@ -3855,6 +3889,7 @@ wxGrid::wxGrid( wxWindow *parent, m_rowMinHeights(GRID_HASH_SIZE) { Create(); + SetBestFittingSize(size); } bool wxGrid::Create(wxWindow *parent, wxWindowID id, @@ -3869,7 +3904,7 @@ bool wxGrid::Create(wxWindow *parent, wxWindowID id, m_rowMinHeights = wxLongToLongHashMap(GRID_HASH_SIZE) ; Create() ; - + SetBestFittingSize(size); return true; } @@ -3990,15 +4025,15 @@ void wxGrid::Create() wxColour lfg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); wxColour lbg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ); #endif - m_cornerLabelWin->SetDefaultForegroundColour(lfg); - m_cornerLabelWin->SetDefaultBackgroundColour(lbg); - m_rowLabelWin->SetDefaultForegroundColour(lfg); - m_rowLabelWin->SetDefaultBackgroundColour(lbg); - m_colLabelWin->SetDefaultForegroundColour(lfg); - m_colLabelWin->SetDefaultBackgroundColour(lbg); + m_cornerLabelWin->SetOwnForegroundColour(lfg); + m_cornerLabelWin->SetOwnBackgroundColour(lbg); + m_rowLabelWin->SetOwnForegroundColour(lfg); + m_rowLabelWin->SetOwnBackgroundColour(lbg); + m_colLabelWin->SetOwnForegroundColour(lfg); + m_colLabelWin->SetOwnBackgroundColour(lbg); - m_gridWin->SetDefaultForegroundColour(gfg); - m_gridWin->SetDefaultBackgroundColour(gbg); + m_gridWin->SetOwnForegroundColour(gfg); + m_gridWin->SetOwnBackgroundColour(gbg); Init(); } @@ -4139,6 +4174,7 @@ void wxGrid::Init() m_canDragRowSize = true; m_canDragColSize = true; m_canDragGridSize = true; + m_canDragCell = false; m_dragLastPos = -1; m_dragRowOrCol = -1; m_isDragging = false; @@ -4163,6 +4199,9 @@ void wxGrid::Init() m_extraWidth = m_extraHeight = 0; + + m_scrollLineX = GRID_SCROLL_LINE_X; + m_scrollLineY = GRID_SCROLL_LINE_Y; } // ---------------------------------------------------------------------------- @@ -4312,16 +4351,16 @@ void wxGrid::CalcWindowSizes() int cw, ch; GetClientSize( &cw, &ch ); - if ( m_cornerLabelWin->IsShown() ) + if ( m_cornerLabelWin && m_cornerLabelWin->IsShown() ) m_cornerLabelWin->SetSize( 0, 0, m_rowLabelWidth, m_colLabelHeight ); - if ( m_colLabelWin->IsShown() ) + if ( m_colLabelWin && m_colLabelWin->IsShown() ) m_colLabelWin->SetSize( m_rowLabelWidth, 0, cw-m_rowLabelWidth, m_colLabelHeight); - if ( m_rowLabelWin->IsShown() ) + if ( m_rowLabelWin && m_rowLabelWin->IsShown() ) m_rowLabelWin->SetSize( 0, m_colLabelHeight, m_rowLabelWidth, ch-m_colLabelHeight); - if ( m_gridWin->IsShown() ) + if ( m_gridWin && m_gridWin->IsShown() ) m_gridWin->SetSize( m_rowLabelWidth, m_colLabelHeight, cw-m_rowLabelWidth, ch-m_colLabelHeight); } @@ -4674,7 +4713,7 @@ wxArrayInt wxGrid::CalcRowLabelsExposed( const wxRegion& reg ) rowlabels.Add( row ); } - iter++ ; + ++iter; } return rowlabels; @@ -4725,7 +4764,7 @@ wxArrayInt wxGrid::CalcColLabelsExposed( const wxRegion& reg ) colLabels.Add( col ); } - iter++ ; + ++iter; } return colLabels; } @@ -4785,7 +4824,7 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg ) } } - iter++; + ++iter; } return cellsExposed; @@ -5346,6 +5385,7 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) XYToCell( x, y, coords ); int cell_rows, cell_cols; + bool isFirstDrag = !m_isDragging; GetCellSize( coords.GetRow(), coords.GetCol(), &cell_rows, &cell_cols ); if ((cell_rows < 0) || (cell_cols < 0)) { @@ -5396,6 +5436,19 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) m_selectingKeyboard = coords; HighlightBlock ( m_selectingKeyboard, coords ); } + else if ( CanDragCell() ) + { + if ( isFirstDrag ) + { + if ( m_selectingKeyboard == wxGridNoCellCoords) + m_selectingKeyboard = coords; + + SendEvent( wxEVT_GRID_CELL_BEGIN_DRAG, + coords.GetRow(), + coords.GetCol(), + event ); + } + } else { if ( !IsSelection() ) @@ -6413,44 +6466,7 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) // Otherwise fall through to default default: - // is it possible to edit the current cell at all? - if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) - { - // yes, now check whether the cells editor accepts the key - int row = m_currentCellCoords.GetRow(); - int col = m_currentCellCoords.GetCol(); - wxGridCellAttr* attr = GetCellAttr(row, col); - wxGridCellEditor *editor = attr->GetEditor(this, row, col); - - // is special and will always start editing, for - // other keys - ask the editor itself - if ( (event.GetKeyCode() == WXK_F2 && !event.HasModifiers()) - || editor->IsAcceptedKey(event) ) - { - // ensure cell is visble - MakeCellVisible(row, col); - EnableCellEditControl(); - - // a problem can arise if the cell is not completely - // visible (even after calling MakeCellVisible the - // control is not created and calling StartingKey will - // crash the app - if( editor->IsCreated() && m_cellEditCtrlEnabled ) editor->StartingKey(event); - } - else - { - event.Skip(); - } - - editor->DecRef(); - attr->DecRef(); - } - else - { - // let others process char events with modifiers or all - // char events for readonly cells - event.Skip(); - } + event.Skip(); break; } } @@ -6486,6 +6502,48 @@ void wxGrid::OnKeyUp( wxKeyEvent& event ) } } +void wxGrid::OnChar( wxKeyEvent& event ) +{ + // is it possible to edit the current cell at all? + if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) + { + // yes, now check whether the cells editor accepts the key + int row = m_currentCellCoords.GetRow(); + int col = m_currentCellCoords.GetCol(); + wxGridCellAttr* attr = GetCellAttr(row, col); + wxGridCellEditor *editor = attr->GetEditor(this, row, col); + + // is special and will always start editing, for + // other keys - ask the editor itself + if ( (event.GetKeyCode() == WXK_F2 && !event.HasModifiers()) + || editor->IsAcceptedKey(event) ) + { + // ensure cell is visble + MakeCellVisible(row, col); + EnableCellEditControl(); + + // a problem can arise if the cell is not completely + // visible (even after calling MakeCellVisible the + // control is not created and calling StartingKey will + // crash the app + if ( editor->IsCreated() && m_cellEditCtrlEnabled ) + editor->StartingKey(event); + } + else + { + event.Skip(); + } + + editor->DecRef(); + attr->DecRef(); + } + else + { + event.Skip(); + } +} + + void wxGrid::OnEraseBackground(wxEraseEvent&) { } @@ -7166,6 +7224,19 @@ void wxGrid::DrawRowLabel( wxDC& dc, int row ) if ( GetRowHeight(row) <= 0 ) return; + wxRect rect; +#ifdef __WXGTK__ + rect.SetX( 1 ); + rect.SetY( GetRowTop(row) + 1 ); + rect.SetWidth( m_rowLabelWidth - 2 ); + rect.SetHeight( GetRowHeight(row) - 2 ); + + CalcScrolledPosition( 0, rect.y, NULL, &rect.y ); + + wxWindowDC *win_dc = (wxWindowDC*) &dc; + + wxRendererNative::Get().DrawHeaderButton( win_dc->m_owner, dc, rect, 0 ); +#else int rowTop = GetRowTop(row), rowBottom = GetRowBottom(row) - 1; @@ -7180,7 +7251,7 @@ void wxGrid::DrawRowLabel( wxDC& dc, int row ) dc.SetPen( *wxWHITE_PEN ); dc.DrawLine( 1, rowTop, 1, rowBottom ); dc.DrawLine( 1, rowTop, m_rowLabelWidth-1, rowTop ); - +#endif dc.SetBackgroundMode( wxTRANSPARENT ); dc.SetTextForeground( GetLabelTextColour() ); dc.SetFont( GetLabelFont() ); @@ -7188,7 +7259,6 @@ void wxGrid::DrawRowLabel( wxDC& dc, int row ) int hAlign, vAlign; GetRowLabelAlignment( &hAlign, &vAlign ); - wxRect rect; rect.SetX( 2 ); rect.SetY( GetRowTop(row) + 2 ); rect.SetWidth( m_rowLabelWidth - 4 ); @@ -7216,8 +7286,20 @@ void wxGrid::DrawColLabel( wxDC& dc, int col ) if ( GetColWidth(col) <= 0 ) return; - int colLeft = GetColLeft(col), - colRight = GetColRight(col) - 1; + int colLeft = GetColLeft(col); + + wxRect rect; +#ifdef __WXGTK__ + rect.SetX( colLeft + 1 ); + rect.SetY( 1 ); + rect.SetWidth( GetColWidth(col) - 2 ); + rect.SetHeight( m_colLabelHeight - 2 ); + + wxWindowDC *win_dc = (wxWindowDC*) &dc; + + wxRendererNative::Get().DrawHeaderButton( win_dc->m_owner, dc, rect, 0 ); +#else + int colRight = GetColRight(col) - 1; dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) ); dc.DrawLine( colRight, 0, @@ -7231,7 +7313,7 @@ void wxGrid::DrawColLabel( wxDC& dc, int col ) dc.SetPen( *wxWHITE_PEN ); dc.DrawLine( colLeft, 1, colLeft, m_colLabelHeight-1 ); dc.DrawLine( colLeft, 1, colRight, 1 ); - +#endif dc.SetBackgroundMode( wxTRANSPARENT ); dc.SetTextForeground( GetLabelTextColour() ); dc.SetFont( GetLabelFont() ); @@ -7240,7 +7322,6 @@ void wxGrid::DrawColLabel( wxDC& dc, int col ) GetColLabelAlignment( &hAlign, &vAlign ); orient = GetColLabelTextOrientation(); - wxRect rect; rect.SetX( colLeft + 2 ); rect.SetY( 2 ); rect.SetWidth( GetColWidth(col) - 4 ); @@ -7448,6 +7529,16 @@ void wxGrid::ForceRefresh() EndBatch(); } +bool wxGrid::Enable(bool enable) +{ + if ( !wxScrolledWindow::Enable(enable) ) + return false; + + // redraw in the new state + m_gridWin->Refresh(); + + return true; +} // // ------ Edit control functions @@ -8871,14 +8962,24 @@ void wxGrid::SetDefaultCellFont( const wxFont& font ) m_defaultCellAttr->SetFont(font); } + +// For editors and renderers the type registry takes precedence over the +// default attr, so we need to register the new editor/renderer for the string +// data type in order to make setting a default editor/renderer appear to +// work correctly. + void wxGrid::SetDefaultRenderer(wxGridCellRenderer *renderer) { - m_defaultCellAttr->SetRenderer(renderer); + RegisterDataType(wxGRID_VALUE_STRING, + renderer, + GetDefaultEditorForType(wxGRID_VALUE_STRING)); } void wxGrid::SetDefaultEditor(wxGridCellEditor *editor) { - m_defaultCellAttr->SetEditor(editor); + RegisterDataType(wxGRID_VALUE_STRING, + GetDefaultRendererForType(wxGRID_VALUE_STRING), + editor); } // ---------------------------------------------------------------------------- @@ -9086,9 +9187,10 @@ wxGridCellAttr *wxGrid::GetCellAttr(int row, int col) const wxGridCellAttr *wxGrid::GetOrCreateCellAttr(int row, int col) const { wxGridCellAttr *attr = (wxGridCellAttr *)NULL; + bool canHave = ((wxGrid*)this)->CanHaveAttributes(); - wxCHECK_MSG( m_table, attr, - _T("we may only be called if CanHaveAttributes() returned true and then m_table should be !NULL") ); + wxCHECK_MSG( canHave, attr, _T("Cell attributes not allowed")); + wxCHECK_MSG( m_table, attr, _T("must have a table") ); attr = m_table->GetAttr(row, col, wxGridCellAttr::Cell); if ( !attr ) @@ -9395,6 +9497,10 @@ void wxGrid::EnableDragGridSize( bool enable ) m_canDragGridSize = enable; } +void wxGrid::EnableDragCell( bool enable ) +{ + m_canDragCell = enable; +} void wxGrid::SetDefaultRowSize( int height, bool resizeExistingRows ) { @@ -9504,26 +9610,30 @@ void wxGrid::SetColSize( int col, int width ) void wxGrid::SetColMinimalWidth( int col, int width ) { if (width > GetColMinimalAcceptableWidth()) { - m_colMinWidths[col] = width; + wxLongToLongHashMap::key_type key = (wxLongToLongHashMap::key_type)col; + m_colMinWidths[key] = width; } } void wxGrid::SetRowMinimalHeight( int row, int width ) { if (width > GetRowMinimalAcceptableHeight()) { - m_rowMinHeights[row] = width; + wxLongToLongHashMap::key_type key = (wxLongToLongHashMap::key_type)row; + m_rowMinHeights[key] = width; } } int wxGrid::GetColMinimalWidth(int col) const { - wxLongToLongHashMap::const_iterator it = m_colMinWidths.find(col); + wxLongToLongHashMap::key_type key = (wxLongToLongHashMap::key_type)col; + wxLongToLongHashMap::const_iterator it = m_colMinWidths.find(key); return it != m_colMinWidths.end() ? (int)it->second : m_minAcceptableColWidth; } int wxGrid::GetRowMinimalHeight(int row) const { - wxLongToLongHashMap::const_iterator it = m_rowMinHeights.find(row); + wxLongToLongHashMap::key_type key = (wxLongToLongHashMap::key_type)row; + wxLongToLongHashMap::const_iterator it = m_rowMinHeights.find(key); return it != m_rowMinHeights.end() ? (int)it->second : m_minAcceptableRowHeight; } @@ -9853,13 +9963,33 @@ wxSize wxGrid::DoGetBestSize() const width = self->SetOrCalcColumnSizes(true); height = self->SetOrCalcRowSizes(true); + if (!width) width=100; + if (!height) height=80; + + // Round up to a multiple the scroll rate NOTE: this still doesn't get rid + // of the scrollbars, is there any magic incantaion for that? + int xpu, ypu; + GetScrollPixelsPerUnit(&xpu, &ypu); + if (xpu) + width += 1 + xpu - (width % xpu); + if (ypu) + height += 1 + ypu - (height % ypu); + + // limit to 1/4 of the screen size int maxwidth, maxheight; wxDisplaySize( & maxwidth, & maxheight ); - + maxwidth /= 2; + maxheight /= 2; if ( width > maxwidth ) width = maxwidth; if ( height > maxheight ) height = maxheight; - return wxSize( width, height ); + + wxSize best(width, height); + // NOTE: This size should be cached, but first we need to add calls to + // InvalidateBestSize everywhere that could change the results of this + // calculation. + // CacheBestSize(size); + return best; } void wxGrid::Fit() @@ -10071,7 +10201,7 @@ wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft, } else { - rect = wxRect( 0, 0, 0, 0 ); + rect = wxRect(0,0,0,0); } cellRect = CellToRect( bottomRight ); @@ -10146,7 +10276,7 @@ wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft, m_gridWin->GetClientSize( &cw, &ch ); if (right < 0 || bottom < 0 || left > cw || top > ch) - return wxRect( 0, 0, 0, 0); + return wxRect(0,0,0,0); rect.SetLeft( wxMax(0, left) ); rect.SetTop( wxMax(0, top) );