]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/grid.cpp
no message
[wxWidgets.git] / src / generic / grid.cpp
index d728ad8407396cebbe7d156d44a6b42c39772d7f..dd06aeda0b1d453f97319b3dbf3acc7b566479cd 100644 (file)
@@ -41,6 +41,7 @@
     #include "wx/log.h"
     #include "wx/textctrl.h"
     #include "wx/checkbox.h"
+    #include "wx/combobox.h"
     #include "wx/valtext.h"
 #endif
 
@@ -858,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
 // ----------------------------------------------------------------------------
@@ -961,6 +1040,25 @@ void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid,
     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,
@@ -983,6 +1081,23 @@ void wxGridCellStringRenderer::Draw(wxGrid& grid,
                            rect, hAlign, vAlign);
 }
 
+// ----------------------------------------------------------------------------
+// wxGridCellNumberRenderer
+// ----------------------------------------------------------------------------
+
+wxString wxGridCellNumberRenderer::GetString(wxGrid& grid, int row, int col)
+{
+    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,
@@ -1002,15 +1117,15 @@ void wxGridCellNumberRenderer::Draw(wxGrid& grid,
     wxRect rect = rectCell;
     rect.Inflate(-1);
 
-    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?
+    grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
+}
 
-    grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign);
+wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
+                                             wxGridCellAttr& attr,
+                                             wxDC& dc,
+                                             int row, int col)
+{
+    return DoGetBestSize(attr, dc, GetString(grid, row, col));
 }
 
 // ----------------------------------------------------------------------------
@@ -1023,6 +1138,24 @@ wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision)
     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,
@@ -1042,66 +1175,76 @@ void wxGridCellFloatRenderer::Draw(wxGrid& grid,
     wxRect rect = rectCell;
     rect.Inflate(-1);
 
-    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?
+    grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
+}
 
-    grid.DrawTextRectangle(dc, text, 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
 // ----------------------------------------------------------------------------
 
-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);
+wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
 
-    // between checkmark and box
-    static const wxCoord margin = 4;
+// between checkmark and box
+static const wxCoord wxGRID_CHECKMARK_MARGIN = 4;
 
-    // get checkbox size
-    static wxCoord s_checkSize = 0;
-    if ( s_checkSize == 0 )
+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")))
@@ -5299,7 +5442,7 @@ int wxGrid::YToRow( int y )
             return i;
     }
 
-    return m_numRows; //-1;
+    return -1;
 }
 
 
@@ -5313,7 +5456,7 @@ int wxGrid::XToCol( int x )
             return i;
     }
 
-    return m_numCols; //-1;
+    return -1;
 }
 
 
@@ -6599,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
 //