]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/grid.cpp
no message
[wxWidgets.git] / src / generic / grid.cpp
index 7ae17f89a473e7654b6f9847b07e221972e08975..dd06aeda0b1d453f97319b3dbf3acc7b566479cd 100644 (file)
     #include "wx/log.h"
     #include "wx/textctrl.h"
     #include "wx/checkbox.h"
+    #include "wx/combobox.h"
+    #include "wx/valtext.h"
 #endif
 
-// this include needs to be outside precomp for BCC
 #include "wx/textfile.h"
+#include "wx/spinctrl.h"
 
 #include "wx/grid.h"
 
@@ -468,18 +470,49 @@ void wxGridCellTextEditor::PaintBackground(const wxRect& WXUNUSED(rectCell),
     // flicker
 }
 
+void wxGridCellTextEditor::SetSize(const wxRect& rectOrig)
+{
+    wxRect rect(rectOrig);
+
+    // Make the edit control large enough to allow for internal
+    // margins
+    //
+    // TODO: remove this if the text ctrl sizing is improved esp. for
+    // unix
+    //
+#if defined(__WXGTK__)
+    rect.Inflate(rect.x ? 1 : 0, rect.y ? 1 : 0);
+#else // !GTK
+    int extra = row && col ? 2 : 1;
+#if defined(__WXMOTIF__)
+    extra *= 2;
+#endif
+    rect.SetLeft( wxMax(0, rect.x - extra) );
+    rect.SetTop( wxMax(0, rect.y - extra) );
+    rect.SetRight( rect.GetRight() + 2*extra );
+    rect.SetBottom( rect.GetBottom() + 2*extra );
+#endif // GTK/!GTK
+
+    wxGridCellEditor::SetSize(rect);
+}
+
 void wxGridCellTextEditor::BeginEdit(int row, int col, wxGrid* grid)
 {
     wxASSERT_MSG(m_control,
                  wxT("The wxGridCellEditor must be Created first!"));
 
     m_startValue = grid->GetTable()->GetValue(row, col);
-    Text()->SetValue(m_startValue);
+
+    DoBeginEdit(m_startValue);
+}
+
+void wxGridCellTextEditor::DoBeginEdit(const wxString& startValue)
+{
+    Text()->SetValue(startValue);
     Text()->SetInsertionPointEnd();
     Text()->SetFocus();
 }
 
-
 bool wxGridCellTextEditor::EndEdit(int row, int col, bool saveValue,
                                    wxGrid* grid)
 {
@@ -506,7 +539,12 @@ void wxGridCellTextEditor::Reset()
     wxASSERT_MSG(m_control,
                  wxT("The wxGridCellEditor must be Created first!"));
 
-    Text()->SetValue(m_startValue);
+    DoReset(m_startValue);
+}
+
+void wxGridCellTextEditor::DoReset(const wxString& startValue)
+{
+    Text()->SetValue(startValue);
     Text()->SetInsertionPointEnd();
 }
 
@@ -550,6 +588,187 @@ void wxGridCellTextEditor::HandleReturn(wxKeyEvent& event)
 #endif
 }
 
+// ----------------------------------------------------------------------------
+// wxGridCellNumberEditor
+// ----------------------------------------------------------------------------
+
+wxGridCellNumberEditor::wxGridCellNumberEditor(int min, int max)
+{
+    m_min = min;
+    m_max = max;
+}
+
+void wxGridCellNumberEditor::Create(wxWindow* parent,
+                                    wxWindowID id,
+                                    wxEvtHandler* evtHandler)
+{
+    if ( HasRange() )
+    {
+        // create a spin ctrl
+        m_control = new wxSpinCtrl(parent, -1, wxEmptyString,
+                                   wxDefaultPosition, wxDefaultSize,
+                                   wxSP_ARROW_KEYS,
+                                   m_min, m_max);
+
+        wxGridCellEditor::Create(parent, id, evtHandler);
+    }
+    else
+    {
+        // just a text control
+        wxGridCellTextEditor::Create(parent, id, evtHandler);
+
+#if wxUSE_VALIDATORS
+        Text()->SetValidator(new wxTextValidator(wxFILTER_NUMERIC));
+#endif // wxUSE_VALIDATORS
+    }
+}
+
+void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)
+{
+    // first get the value
+    wxGridTableBase *table = grid->GetTable();
+    if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
+    {
+        m_valueOld = table->GetValueAsLong(row, col);
+    }
+    else
+    {
+        wxFAIL_MSG( _T("this cell doesn't have numeric value") );
+
+        return;
+    }
+
+    if ( HasRange() )
+    {
+        Spin()->SetValue(m_valueOld);
+    }
+    else
+    {
+        DoBeginEdit(GetString());
+    }
+}
+
+bool wxGridCellNumberEditor::EndEdit(int row, int col, bool saveValue,
+                                     wxGrid* grid)
+{
+    bool changed;
+    long value;
+
+    if ( HasRange() )
+    {
+        value = Spin()->GetValue();
+        changed = value != m_valueOld;
+    }
+    else
+    {
+        changed = Text()->GetValue().ToLong(&value) && (value != m_valueOld);
+    }
+
+    if ( changed )
+    {
+        grid->GetTable()->SetValueAsLong(row, col, value);
+    }
+
+    return changed;
+}
+
+void wxGridCellNumberEditor::Reset()
+{
+    if ( HasRange() )
+    {
+        Spin()->SetValue(m_valueOld);
+    }
+    else
+    {
+        DoReset(GetString());
+    }
+}
+
+void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event)
+{
+    if ( !HasRange() )
+    {
+        long keycode = event.KeyCode();
+        if ( isdigit(keycode) || keycode == '+' || keycode == '-' )
+        {
+            wxGridCellTextEditor::StartingKey(event);
+
+            // skip Skip() below
+            return;
+        }
+    }
+
+    event.Skip();
+}
+// ----------------------------------------------------------------------------
+// wxGridCellFloatEditor
+// ----------------------------------------------------------------------------
+
+void wxGridCellFloatEditor::Create(wxWindow* parent,
+                                   wxWindowID id,
+                                   wxEvtHandler* evtHandler)
+{
+    wxGridCellTextEditor::Create(parent, id, evtHandler);
+
+#if wxUSE_VALIDATORS
+    Text()->SetValidator(new wxTextValidator(wxFILTER_NUMERIC));
+#endif // wxUSE_VALIDATORS
+}
+
+void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)
+{
+    // first get the value
+    wxGridTableBase *table = grid->GetTable();
+    if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
+    {
+        m_valueOld = table->GetValueAsDouble(row, col);
+    }
+    else
+    {
+        wxFAIL_MSG( _T("this cell doesn't have float value") );
+
+        return;
+    }
+
+    DoBeginEdit(GetString());
+}
+
+bool wxGridCellFloatEditor::EndEdit(int row, int col, bool saveValue,
+                                     wxGrid* grid)
+{
+    double value;
+    if ( Text()->GetValue().ToDouble(&value) && (value != m_valueOld) )
+    {
+        grid->GetTable()->SetValueAsDouble(row, col, value);
+
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+void wxGridCellFloatEditor::Reset()
+{
+    DoReset(GetString());
+}
+
+void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event)
+{
+    long keycode = event.KeyCode();
+    if ( isdigit(keycode) ||
+         keycode == '+' || keycode == '-' || keycode == '.' )
+    {
+        wxGridCellTextEditor::StartingKey(event);
+
+        // skip Skip() below
+        return;
+    }
+
+    event.Skip();
+}
+
 // ----------------------------------------------------------------------------
 // wxGridCellBoolEditor
 // ----------------------------------------------------------------------------
@@ -582,10 +801,10 @@ void wxGridCellBoolEditor::SetSize(const wxRect& r)
 
 void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)
 {
-    wxGridCellEditor::Show(show, attr);
+    m_control->Show(show);
+
     if ( show )
     {
-        // VZ: normally base class already does it, but it doesn't work (FIXME)
         wxColour colBg = attr ? attr->GetBackgroundColour() : *wxLIGHT_GREY;
         CBox()->SetBackgroundColour(colBg);
     }
@@ -640,6 +859,84 @@ void wxGridCellBoolEditor::StartingClick()
     CBox()->SetValue(!CBox()->GetValue());
 }
 
+// ----------------------------------------------------------------------------
+// wxGridCellChoiceEditor
+// ----------------------------------------------------------------------------
+
+wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count,
+                                               const wxChar* choices[],
+                                               bool allowOthers)
+                      : m_allowOthers(allowOthers)
+{
+    m_choices.Alloc(count);
+    for ( size_t n = 0; n < count; n++ )
+    {
+        m_choices.Add(choices[n]);
+    }
+}
+
+void wxGridCellChoiceEditor::Create(wxWindow* parent,
+                                    wxWindowID id,
+                                    wxEvtHandler* evtHandler)
+{
+    size_t count = m_choices.GetCount();
+    wxString *choices = new wxString[count];
+    for ( size_t n = 0; n < count; n++ )
+    {
+        choices[n] = m_choices[n];
+    }
+
+    m_control = new wxComboBox(parent, id, wxEmptyString,
+                               wxDefaultPosition, wxDefaultSize,
+                               count, choices,
+                               m_allowOthers ? 0 : wxCB_READONLY);
+
+    delete [] choices;
+
+    wxGridCellEditor::Create(parent, id, evtHandler);
+}
+
+void wxGridCellChoiceEditor::PaintBackground(const wxRect& WXUNUSED(rectCell),
+                                             wxGridCellAttr * WXUNUSED(attr))
+{
+    // as we fill the entire client area, don't do anything here to minimize
+    // flicker
+}
+
+void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
+{
+    wxASSERT_MSG(m_control,
+                 wxT("The wxGridCellEditor must be Created first!"));
+
+    m_startValue = grid->GetTable()->GetValue(row, col);
+
+    Combo()->SetValue(m_startValue);
+    Combo()->SetInsertionPointEnd();
+    Combo()->SetFocus();
+}
+
+bool wxGridCellChoiceEditor::EndEdit(int row, int col, 
+                                     bool saveValue,
+                                     wxGrid* grid)
+{
+    wxString value = Combo()->GetValue();
+    bool changed = value != m_startValue;
+
+    if ( changed )
+        grid->GetTable()->SetValue(row, col, value);
+
+    m_startValue = wxEmptyString;
+    Combo()->SetValue(m_startValue);
+
+    return changed;
+}
+
+void wxGridCellChoiceEditor::Reset()
+{
+    Combo()->SetValue(m_startValue);
+    Combo()->SetInsertionPointEnd();
+}
+
 // ----------------------------------------------------------------------------
 // wxGridCellEditorEvtHandler
 // ----------------------------------------------------------------------------
@@ -712,20 +1009,19 @@ void wxGridCellRenderer::Draw(wxGrid& grid,
     dc.DrawRectangle(rect);
 }
 
+wxGridCellRenderer::~wxGridCellRenderer()
+{
+}
+
 // ----------------------------------------------------------------------------
 // wxGridCellStringRenderer
 // ----------------------------------------------------------------------------
 
-void wxGridCellStringRenderer::Draw(wxGrid& grid,
-                                    wxGridCellAttr& attr,
-                                    wxDC& dc,
-                                    const wxRect& rectCell,
-                                    int row, int col,
-                                    bool isSelected)
+void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid,
+                                                     wxGridCellAttr& attr,
+                                                     wxDC& dc,
+                                                     bool isSelected)
 {
-    wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
-
-    // now we only have to draw the text
     dc.SetBackgroundMode( wxTRANSPARENT );
 
     // TODO some special colours for attr.IsReadOnly() case?
@@ -740,65 +1036,215 @@ void wxGridCellStringRenderer::Draw(wxGrid& grid,
         dc.SetTextBackground( attr.GetBackgroundColour() );
         dc.SetTextForeground( attr.GetTextColour() );
     }
+
     dc.SetFont( attr.GetFont() );
+}
+
+wxSize wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr& attr,
+                                               wxDC& dc,
+                                               const wxString& text)
+{
+    wxCoord x, y;
+    dc.SetFont(attr.GetFont());
+    dc.GetTextExtent(text, &x, &y);
+
+    return wxSize(x, y);
+}
+
+wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid,
+                                             wxGridCellAttr& attr,
+                                             wxDC& dc,
+                                             int row, int col)
+{
+    return DoGetBestSize(attr, dc, grid.GetCellValue(row, col));
+}
+
+void wxGridCellStringRenderer::Draw(wxGrid& grid,
+                                    wxGridCellAttr& attr,
+                                    wxDC& dc,
+                                    const wxRect& rectCell,
+                                    int row, int col,
+                                    bool isSelected)
+{
+    wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
+
+    // now we only have to draw the text
+    SetTextColoursAndFont(grid, attr, dc, isSelected);
 
     int hAlign, vAlign;
     attr.GetAlignment(&hAlign, &vAlign);
 
     wxRect rect = rectCell;
-    rect.x++;
-    rect.y++;
-    rect.width -= 2;
-    rect.height -= 2;
+    rect.Inflate(-1);
 
     grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
                            rect, hAlign, vAlign);
 }
 
 // ----------------------------------------------------------------------------
-// wxGridCellBoolRenderer
+// wxGridCellNumberRenderer
 // ----------------------------------------------------------------------------
 
-void wxGridCellBoolRenderer::Draw(wxGrid& grid,
-                                  wxGridCellAttr& attr,
-                                  wxDC& dc,
-                                  const wxRect& rect,
-                                  int row, int col,
-                                  bool isSelected)
+wxString wxGridCellNumberRenderer::GetString(wxGrid& grid, int row, int col)
 {
-    wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
+    wxGridTableBase *table = grid.GetTable();
+    wxString text;
+    if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
+    {
+        text.Printf(_T("%ld"), table->GetValueAsLong(row, col));
+    }
+    //else: leave the string empty or put 0 into it?
+
+    return text;
+}
+
+void wxGridCellNumberRenderer::Draw(wxGrid& grid,
+                                    wxGridCellAttr& attr,
+                                    wxDC& dc,
+                                    const wxRect& rectCell,
+                                    int row, int col,
+                                    bool isSelected)
+{
+    wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
+
+    SetTextColoursAndFont(grid, attr, dc, isSelected);
+
+    // draw the text right aligned by default
+    int hAlign, vAlign;
+    attr.GetAlignment(&hAlign, &vAlign);
+    hAlign = wxRIGHT;
+
+    wxRect rect = rectCell;
+    rect.Inflate(-1);
+
+    grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
+}
+
+wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
+                                             wxGridCellAttr& attr,
+                                             wxDC& dc,
+                                             int row, int col)
+{
+    return DoGetBestSize(attr, dc, GetString(grid, row, col));
+}
+
+// ----------------------------------------------------------------------------
+// wxGridCellFloatRenderer
+// ----------------------------------------------------------------------------
+
+wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision)
+{
+    SetWidth(width);
+    SetPrecision(precision);
+}
+
+wxString wxGridCellFloatRenderer::GetString(wxGrid& grid, int row, int col)
+{
+    wxGridTableBase *table = grid.GetTable();
+    wxString text;
+    if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
+    {
+        if ( !m_format )
+        {
+            m_format.Printf(_T("%%%d.%d%%f"), m_width, m_precision);
+        }
+
+        text.Printf(m_format, table->GetValueAsDouble(row, col));
+    }
+    //else: leave the string empty or put 0 into it?
+
+    return text;
+}
+
+void wxGridCellFloatRenderer::Draw(wxGrid& grid,
+                                   wxGridCellAttr& attr,
+                                   wxDC& dc,
+                                   const wxRect& rectCell,
+                                   int row, int col,
+                                   bool isSelected)
+{
+    wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
+
+    SetTextColoursAndFont(grid, attr, dc, isSelected);
+
+    // draw the text right aligned by default
+    int hAlign, vAlign;
+    attr.GetAlignment(&hAlign, &vAlign);
+    hAlign = wxRIGHT;
+
+    wxRect rect = rectCell;
+    rect.Inflate(-1);
+
+    grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
+}
+
+wxSize wxGridCellFloatRenderer::GetBestSize(wxGrid& grid,
+                                            wxGridCellAttr& attr,
+                                            wxDC& dc,
+                                            int row, int col)
+{
+    return DoGetBestSize(attr, dc, GetString(grid, row, col));
+}
+
+// ----------------------------------------------------------------------------
+// wxGridCellBoolRenderer
+// ----------------------------------------------------------------------------
 
-    // between checkmark and box
-    static const wxCoord margin = 4;
+wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
 
-    // get checkbox size
-    static wxCoord s_checkSize = 0;
-    if ( s_checkSize == 0 )
+// between checkmark and box
+static const wxCoord wxGRID_CHECKMARK_MARGIN = 4;
+
+wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
+                                           wxGridCellAttr& WXUNUSED(attr),
+                                           wxDC& WXUNUSED(dc),
+                                           int WXUNUSED(row),
+                                           int WXUNUSED(col))
+{
+    // compute it only once (no locks for MT safeness in GUI thread...)
+    if ( !ms_sizeCheckMark.x )
     {
-        // compute it only once (no locks for MT safeness in GUI thread...)
+        // get checkbox size
+        wxCoord checkSize = 0;
         wxCheckBox *checkbox = new wxCheckBox(&grid, -1, wxEmptyString);
         wxSize size = checkbox->GetBestSize();
-        s_checkSize = size.y + margin;
+        checkSize = size.y + wxGRID_CHECKMARK_MARGIN;
 
-        // FIXME wxGTK::wxCheckBox::GetBestSize() is really weird...
+        // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result
 #ifdef __WXGTK__
-        s_checkSize -= size.y / 2;
+        checkSize -= size.y / 2;
 #endif
 
         delete checkbox;
+
+        ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize;
     }
 
+    return ms_sizeCheckMark;
+}
+
+void wxGridCellBoolRenderer::Draw(wxGrid& grid,
+                                  wxGridCellAttr& attr,
+                                  wxDC& dc,
+                                  const wxRect& rect,
+                                  int row, int col,
+                                  bool isSelected)
+{
+    wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
+
     // draw a check mark in the centre (ignoring alignment - TODO)
+    wxSize size = GetBestSize(grid, attr, dc, row, col);
     wxRect rectMark;
-    rectMark.x = rect.x + rect.width/2 - s_checkSize/2;
-    rectMark.y = rect.y + rect.height/2 - s_checkSize/2;
-    rectMark.width = rectMark.height = s_checkSize;
+    rectMark.x = rect.x + rect.width/2 - size.x/2;
+    rectMark.y = rect.y + rect.height/2 - size.y/2;
+    rectMark.width = size.x;
+    rectMark.height = size.y;
 
     dc.SetBrush(*wxTRANSPARENT_BRUSH);
     dc.SetPen(wxPen(attr.GetTextColour(), 1, wxSOLID));
     dc.DrawRectangle(rectMark);
 
-    rectMark.Inflate(-margin);
+    rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN);
 
     bool value;
     if (grid.GetTable()->CanGetValueAs(row, col, wxT("bool")))
@@ -1449,13 +1895,13 @@ wxString wxGridTableBase::GetColLabelValue( int col )
 
 wxString wxGridTableBase::GetTypeName( int WXUNUSED(row), int WXUNUSED(col) )
 {
-    return wxT("string");
+    return wxGRID_VALUE_STRING;
 }
 
 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row), int WXUNUSED(col),
                                      const wxString& typeName )
 {
-    return typeName == wxT("string");
+    return typeName == wxGRID_VALUE_STRING;
 }
 
 bool wxGridTableBase::CanSetValueAs( int row, int col, const wxString& typeName )
@@ -2262,13 +2708,18 @@ void wxGrid::Create()
     m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
     m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
 
-    // data type registration
+    // data type registration: register all standard data types
+    // TODO: may be allow the app to selectively disable some of them?
     m_typeRegistry = new wxGridTypeRegistry;
-    RegisterDataType(wxT("string"), new wxGridCellStringRenderer,
-                                    new wxGridCellTextEditor);
-    RegisterDataType(wxT("bool"), new wxGridCellBoolRenderer,
-                                  new wxGridCellBoolEditor);
-
+    RegisterDataType(wxGRID_VALUE_STRING,
+                     new wxGridCellStringRenderer,
+                     new wxGridCellTextEditor);
+    RegisterDataType(wxGRID_VALUE_BOOL,
+                     new wxGridCellBoolRenderer,
+                     new wxGridCellBoolEditor);
+    RegisterDataType(wxGRID_VALUE_NUMBER,
+                     new wxGridCellNumberRenderer,
+                     new wxGridCellNumberEditor);
 
     // subwindow components that make up the wxGrid
     m_cornerLabelWin = new wxGridCornerLabelWindow( this,
@@ -4470,6 +4921,12 @@ void wxGrid::DrawCellBorder( wxDC& dc, const wxGridCellCoords& coords )
 
 void wxGrid::DrawHighlight(wxDC& dc)
 {
+    if ( IsCellEditControlEnabled() )
+    {
+        // don't show highlight when the edit control is shown
+        return;
+    }
+
     // if the active cell was repainted, repaint its highlight too because it
     // might have been damaged by the grid lines
     size_t count = m_cellsExposed.GetCount();
@@ -4856,11 +5313,6 @@ bool wxGrid::IsCellEditControlEnabled() const
     return m_cellEditCtrlEnabled ? !IsCurrentCellReadOnly() : FALSE;
 }
 
-wxWindow *wxGrid::GetGridWindow() const
-{
-    return m_gridWin;
-}
-
 void wxGrid::ShowCellEditControl()
 {
     if ( IsCellEditControlEnabled() )
@@ -4877,58 +5329,22 @@ void wxGrid::ShowCellEditControl()
 
             // convert to scrolled coords
             //
-            int left, top, right, bottom;
-            CalcScrolledPosition( rect.GetLeft(), rect.GetTop(), &left, &top );
-            CalcScrolledPosition( rect.GetRight(), rect.GetBottom(), &right, &bottom );
-
-            // cell is shifted by one pixel
-            left--;
-            top--;
-            right--;
-            bottom--;
+            CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
 
-            // Make the edit control large enough to allow for internal
-            // margins
-            //
-            // TODO: remove this if the text ctrl sizing is improved esp. for
-            // unix
-            //
-            int extra;
-#if defined(__WXMOTIF__)
-            if ( row == 0  || col == 0 )
-            {
-                extra = 2;
-            }
-            else
-            {
-                extra = 4;
-            }
-#else
-            if ( row == 0  || col == 0 )
-            {
-                extra = 1;
-            }
-            else
-            {
-                extra = 2;
-            }
-#endif
+            // done in PaintBackground()
+#if 0
+            // erase the highlight and the cell contents because the editor
+            // might not cover the entire cell
+            wxClientDC dc( m_gridWin );
+            PrepareDC( dc );
+            dc.SetBrush(*wxLIGHT_GREY_BRUSH); //wxBrush(attr->GetBackgroundColour(), wxSOLID));
+            dc.SetPen(*wxTRANSPARENT_PEN);
+            dc.DrawRectangle(rect);
+#endif // 0
 
-#if defined(__WXGTK__)
-            int top_diff = 0;
-            int left_diff = 0;
-            if (left != 0) left_diff++;
-            if (top != 0) top_diff++;
-            rect.SetLeft( left + left_diff );
-            rect.SetTop( top + top_diff );
-            rect.SetRight( rect.GetRight() - left_diff );
-            rect.SetBottom( rect.GetBottom() - top_diff );
-#else
-            rect.SetLeft( wxMax(0, left - extra) );
-            rect.SetTop( wxMax(0, top - extra) );
-            rect.SetRight( rect.GetRight() + 2*extra );
-            rect.SetBottom( rect.GetBottom() + 2*extra );
-#endif
+            // cell is shifted by one pixel
+            rect.x--;
+            rect.y--;
 
             wxGridCellAttr* attr = GetCellAttr(row, col);
             wxGridCellEditor* editor = attr->GetEditor(GetDefaultEditorForCell(row, col));
@@ -4939,6 +5355,7 @@ void wxGrid::ShowCellEditControl()
             }
 
             editor->SetSize( rect );
+
             editor->Show( TRUE, attr );
             editor->BeginEdit(row, col, this);
             attr->DecRef();
@@ -5025,7 +5442,7 @@ int wxGrid::YToRow( int y )
             return i;
     }
 
-    return m_numRows; //-1;
+    return -1;
 }
 
 
@@ -5039,7 +5456,7 @@ int wxGrid::XToCol( int x )
             return i;
     }
 
-    return m_numCols; //-1;
+    return -1;
 }
 
 
@@ -6190,19 +6607,20 @@ void wxGrid::RegisterDataType(const wxString& typeName,
 }
 
 
-wxGridCellEditor* wxGrid::GetDefaultEditorForCell(int row, int col)
+wxGridCellEditor* wxGrid::GetDefaultEditorForCell(int row, int col) const
 {
     wxString typeName = m_table->GetTypeName(row, col);
     return GetDefaultEditorForType(typeName);
 }
 
-wxGridCellRenderer* wxGrid::GetDefaultRendererForCell(int row, int col)
+wxGridCellRenderer* wxGrid::GetDefaultRendererForCell(int row, int col) const
 {
     wxString typeName = m_table->GetTypeName(row, col);
     return GetDefaultRendererForType(typeName);
 }
 
-wxGridCellEditor* wxGrid::GetDefaultEditorForType(const wxString& typeName)
+wxGridCellEditor*
+wxGrid::GetDefaultEditorForType(const wxString& typeName) const
 {
     int index = m_typeRegistry->FindDataType(typeName);
     if (index == -1) {
@@ -6213,7 +6631,8 @@ wxGridCellEditor* wxGrid::GetDefaultEditorForType(const wxString& typeName)
     return m_typeRegistry->GetEditor(index);
 }
 
-wxGridCellRenderer* wxGrid::GetDefaultRendererForType(const wxString& typeName)
+wxGridCellRenderer*
+wxGrid::GetDefaultRendererForType(const wxString& typeName) const
 {
     int index = m_typeRegistry->FindDataType(typeName);
     if (index == -1) {
@@ -6323,6 +6742,62 @@ int wxGrid::GetColMinimalWidth(int col) const
     return obj ? (int)obj : WXGRID_MIN_COL_WIDTH;
 }
 
+void wxGrid::AutoSizeColumn( int col, bool setAsMin )
+{
+    wxClientDC dc(m_gridWin);
+
+    wxCoord width, widthMax = 0;
+    for ( int row = 0; row < m_numRows; row++ )
+    {
+        wxGridCellAttr* attr = GetCellAttr(row, col);
+        wxGridCellRenderer* renderer = attr->GetRenderer(GetDefaultRendererForCell(row,col));
+        if ( renderer )
+        {
+            width = renderer->GetBestSize(*this, *attr, dc, row, col).x;
+            if ( width > widthMax )
+            {
+                widthMax = width;
+            }
+        }
+
+        attr->DecRef();
+    }
+
+    // now also compare with the column label width
+    dc.SetFont( GetLabelFont() );
+    dc.GetTextExtent( GetColLabelValue(col), &width, NULL );
+    if ( width > widthMax )
+    {
+        widthMax = width;
+    }
+
+    if ( !widthMax )
+    {
+        // empty column - give default width (notice that if widthMax is less
+        // than default width but != 0, it's ok)
+        widthMax = m_defaultColWidth;
+    }
+    else
+    {
+        // leave some space around text
+        widthMax += 10;
+    }
+
+    SetColSize(col, widthMax);
+    if ( setAsMin )
+    {
+        SetColMinimalWidth(col, widthMax);
+    }
+}
+
+void wxGrid::AutoSizeColumns( bool setAsMin )
+{
+    for ( int col = 0; col < m_numCols; col++ )
+    {
+        AutoSizeColumn(col, setAsMin);
+    }
+}
+
 //
 // ------ cell value accessor functions
 //