]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/grid.cpp
document that SetValue() accepts values in 0..GetRange interval, inclusive
[wxWidgets.git] / src / generic / grid.cpp
index e3436a823398ee3f85f040d84547b0fee945dd2c..945a7914bc43a2076602ac37ce35b51a8fff18cb 100644 (file)
@@ -120,16 +120,43 @@ DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED)
 // private classes
 // ----------------------------------------------------------------------------
 
-class WXDLLIMPEXP_ADV wxGridRowLabelWindow : public wxWindow
+// common base class for various grid subwindows
+class WXDLLIMPEXP_ADV wxGridSubwindow : public wxWindow
 {
 public:
-    wxGridRowLabelWindow() { m_owner = (wxGrid *)NULL; }
+    wxGridSubwindow() { m_owner = NULL; }
+    wxGridSubwindow(wxGrid *owner,
+                    wxWindowID id,
+                    const wxPoint& pos,
+                    const wxSize& size,
+                    int additionalStyle = 0,
+                    const wxString& name = wxPanelNameStr)
+        : wxWindow(owner, id, pos, size,
+                   wxWANTS_CHARS | wxBORDER_NONE | additionalStyle,
+                   name)
+    {
+        m_owner = owner;
+    }
+
+    wxGrid *GetOwner() { return m_owner; }
+
+protected:
+    void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
+
+    wxGrid *m_owner;
+
+    DECLARE_EVENT_TABLE()
+    DECLARE_NO_COPY_CLASS(wxGridSubwindow)
+};
+
+class WXDLLIMPEXP_ADV wxGridRowLabelWindow : public wxGridSubwindow
+{
+public:
+    wxGridRowLabelWindow() { }
     wxGridRowLabelWindow( wxGrid *parent, wxWindowID id,
                           const wxPoint &pos, const wxSize &size );
 
 private:
-    wxGrid   *m_owner;
-
     void OnPaint( wxPaintEvent& event );
     void OnMouseEvent( wxMouseEvent& event );
     void OnMouseWheel( wxMouseEvent& event );
@@ -143,16 +170,14 @@ private:
 };
 
 
-class WXDLLIMPEXP_ADV wxGridColLabelWindow : public wxWindow
+class WXDLLIMPEXP_ADV wxGridColLabelWindow : public wxGridSubwindow
 {
 public:
-    wxGridColLabelWindow() { m_owner = (wxGrid *)NULL; }
+    wxGridColLabelWindow() { }
     wxGridColLabelWindow( wxGrid *parent, wxWindowID id,
                           const wxPoint &pos, const wxSize &size );
 
 private:
-    wxGrid   *m_owner;
-
     void OnPaint( wxPaintEvent& event );
     void OnMouseEvent( wxMouseEvent& event );
     void OnMouseWheel( wxMouseEvent& event );
@@ -166,16 +191,14 @@ private:
 };
 
 
-class WXDLLIMPEXP_ADV wxGridCornerLabelWindow : public wxWindow
+class WXDLLIMPEXP_ADV wxGridCornerLabelWindow : public wxGridSubwindow
 {
 public:
-    wxGridCornerLabelWindow() { m_owner = (wxGrid *)NULL; }
+    wxGridCornerLabelWindow() { }
     wxGridCornerLabelWindow( wxGrid *parent, wxWindowID id,
                              const wxPoint &pos, const wxSize &size );
 
 private:
-    wxGrid *m_owner;
-
     void OnMouseEvent( wxMouseEvent& event );
     void OnMouseWheel( wxMouseEvent& event );
     void OnKeyDown( wxKeyEvent& event );
@@ -188,12 +211,11 @@ private:
     DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow)
 };
 
-class WXDLLIMPEXP_ADV wxGridWindow : public wxWindow
+class WXDLLIMPEXP_ADV wxGridWindow : public wxGridSubwindow
 {
 public:
     wxGridWindow()
     {
-        m_owner = NULL;
         m_rowLabelWin = NULL;
         m_colLabelWin = NULL;
     }
@@ -202,14 +224,10 @@ public:
                   wxGridRowLabelWindow *rowLblWin,
                   wxGridColLabelWindow *colLblWin,
                   wxWindowID id, const wxPoint &pos, const wxSize &size );
-    virtual ~wxGridWindow() {}
 
     void ScrollWindow( int dx, int dy, const wxRect *rect );
 
-    wxGrid* GetOwner() { return m_owner; }
-
 private:
-    wxGrid                   *m_owner;
     wxGridRowLabelWindow     *m_rowLabelWin;
     wxGridColLabelWindow     *m_colLabelWin;
 
@@ -624,21 +642,29 @@ void wxGridCellTextEditor::Create(wxWindow* parent,
                                   wxWindowID id,
                                   wxEvtHandler* evtHandler)
 {
-    m_control = new wxTextCtrl(parent, id, wxEmptyString,
-                               wxDefaultPosition, wxDefaultSize
+    DoCreate(parent, id, evtHandler);
+}
+
+void wxGridCellTextEditor::DoCreate(wxWindow* parent,
+                                    wxWindowID id,
+                                    wxEvtHandler* evtHandler,
+                                    long style)
+{
 #if defined(__WXMSW__)
-                               ,
-                               wxTE_PROCESS_ENTER |
-                               wxTE_PROCESS_TAB |
-                               wxTE_AUTO_SCROLL |
-                               wxNO_BORDER
+    style |= wxTE_PROCESS_ENTER |
+             wxTE_PROCESS_TAB |
+             wxTE_AUTO_SCROLL |
+             wxNO_BORDER;
 #endif
-                              );
+
+    m_control = new wxTextCtrl(parent, id, wxEmptyString,
+                               wxDefaultPosition, wxDefaultSize,
+                               style);
 
     // set max length allowed in the textctrl, if the parameter was set
-    if (m_maxChars != 0)
+    if ( m_maxChars != 0 )
     {
-        ((wxTextCtrl*)m_control)->SetMaxLength(m_maxChars);
+        Text()->SetMaxLength(m_maxChars);
     }
 
     wxGridCellEditor::Create(parent, id, evtHandler);
@@ -2699,7 +2725,7 @@ int wxGridCellAttrData::FindIndex(int row, int col) const
 
 wxGridRowOrColAttrData::~wxGridRowOrColAttrData()
 {
-    size_t count = m_attrs.Count();
+    size_t count = m_attrs.GetCount();
     for ( size_t n = 0; n < count; n++ )
     {
         m_attrs[n]->DecRef();
@@ -2940,7 +2966,7 @@ void wxGridCellAttrProvider::UpdateAttrCols( size_t pos, int numCols )
 
 wxGridTypeRegistry::~wxGridTypeRegistry()
 {
-    size_t count = m_typeinfo.Count();
+    size_t count = m_typeinfo.GetCount();
     for ( size_t i = 0; i < count; i++ )
         delete m_typeinfo[i];
 }
@@ -3648,7 +3674,12 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
 
     if ( !m_colLabels.IsEmpty() )
     {
-        m_colLabels.RemoveAt( colID, numCols );
+        // m_colLabels stores just as many elements as it needs, e.g. if only
+        // the label of the first column had been set it would have only one
+        // element and not numCols, so account for it
+        int nToRm = m_colLabels.size() - colID;
+        if ( nToRm > 0 )
+            m_colLabels.RemoveAt( colID, nToRm );
     }
 
     for ( row = 0; row < curNumRows; row++ )
@@ -3740,9 +3771,18 @@ void wxGridStringTable::SetColLabelValue( int col, const wxString& value )
 //////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////
 
+BEGIN_EVENT_TABLE(wxGridSubwindow, wxWindow)
+    EVT_MOUSE_CAPTURE_LOST(wxGridSubwindow::OnMouseCaptureLost)
+END_EVENT_TABLE()
+
+void wxGridSubwindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
+{
+    m_owner->CancelMouseCapture();
+}
+
 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow, wxWindow )
 
-BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxWindow )
+BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxGridSubwindow )
     EVT_PAINT( wxGridRowLabelWindow::OnPaint )
     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel )
     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent )
@@ -3754,7 +3794,7 @@ END_EVENT_TABLE()
 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid *parent,
                                             wxWindowID id,
                                             const wxPoint &pos, const wxSize &size )
-  : wxWindow( parent, id, pos, size, wxWANTS_CHARS | wxBORDER_NONE | wxFULL_REPAINT_ON_RESIZE )
+  : wxGridSubwindow(parent, id, pos, size)
 {
     m_owner = parent;
 }
@@ -3813,7 +3853,7 @@ void wxGridRowLabelWindow::OnChar( wxKeyEvent& event )
 
 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow, wxWindow )
 
-BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxWindow )
+BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxGridSubwindow )
     EVT_PAINT( wxGridColLabelWindow::OnPaint )
     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel )
     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent )
@@ -3825,7 +3865,7 @@ END_EVENT_TABLE()
 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid *parent,
                                             wxWindowID id,
                                             const wxPoint &pos, const wxSize &size )
-  : wxWindow( parent, id, pos, size, wxWANTS_CHARS | wxBORDER_NONE | wxFULL_REPAINT_ON_RESIZE )
+  : wxGridSubwindow(parent, id, pos, size)
 {
     m_owner = parent;
 }
@@ -3887,7 +3927,7 @@ void wxGridColLabelWindow::OnChar( wxKeyEvent& event )
 
 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow, wxWindow )
 
-BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxWindow )
+BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxGridSubwindow )
     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel )
     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent )
     EVT_PAINT( wxGridCornerLabelWindow::OnPaint )
@@ -3899,7 +3939,7 @@ END_EVENT_TABLE()
 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent,
                                                   wxWindowID id,
                                                   const wxPoint &pos, const wxSize &size )
-  : wxWindow( parent, id, pos, size, wxWANTS_CHARS | wxBORDER_NONE | wxFULL_REPAINT_ON_RESIZE )
+  : wxGridSubwindow(parent, id, pos, size)
 {
     m_owner = parent;
 }
@@ -3970,7 +4010,7 @@ void wxGridCornerLabelWindow::OnChar( wxKeyEvent& event )
 
 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxWindow )
 
-BEGIN_EVENT_TABLE( wxGridWindow, wxWindow )
+BEGIN_EVENT_TABLE( wxGridWindow, wxGridSubwindow )
     EVT_PAINT( wxGridWindow::OnPaint )
     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel )
     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent )
@@ -3988,10 +4028,8 @@ wxGridWindow::wxGridWindow( wxGrid *parent,
                             wxWindowID id,
                             const wxPoint &pos,
                             const wxSize &size )
-            : wxWindow(
-                parent, id, pos, size,
-                wxWANTS_CHARS | wxBORDER_NONE | wxCLIP_CHILDREN | wxFULL_REPAINT_ON_RESIZE,
-                wxT("grid window") )
+            : wxGridSubwindow(parent, id, pos, size,
+                              wxCLIP_CHILDREN, wxT("grid window") )
 {
     m_owner = parent;
     m_rowLabelWin = rowLblWin;
@@ -4363,7 +4401,7 @@ bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership,
         // stop all processing
         m_created = false;
 
-        if (m_table) 
+        if (m_table)
         {
             m_table->SetView(0);
             if( m_ownTable )
@@ -4401,7 +4439,7 @@ bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership,
             // original one current cell and selection regions
             // might be invalid,
             m_selectingKeyboard = wxGridNoCellCoords;
-            m_currentCellCoords = 
+            m_currentCellCoords =
               wxGridCellCoords(wxMin(m_numRows, m_currentCellCoords.GetRow()),
                                wxMin(m_numCols, m_currentCellCoords.GetCol()));
             if (m_selectingTopLeft.GetRow() >= m_numRows ||
@@ -5802,6 +5840,21 @@ void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent& event )
     }
 }
 
+void wxGrid::CancelMouseCapture()
+{
+    // cancel operation currently in progress, whatever it is
+    if ( m_winCapture )
+    {
+        m_isDragging = false;
+        m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
+        m_winCapture->SetCursor( *wxSTANDARD_CURSOR );
+        m_winCapture = NULL;
+
+        // remove traces of whatever we drew on screen
+        Refresh();
+    }
+}
+
 void wxGrid::ChangeCursorMode(CursorMode mode,
                               wxWindow *win,
                               bool captureMouse)
@@ -5969,7 +6022,7 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
                 m_winCapture->CaptureMouse();
             }
 
-            
+
         }
         else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
         {
@@ -6732,7 +6785,7 @@ int wxGrid::SendEvent( const wxEventType type,
            pos.y += GetColLabelSize();
        if ( mouseEv.GetEventObject() == GetGridColLabelWindow() )
            pos.x += GetRowLabelSize();
-       
+
        wxGridEvent gridEvt( GetId(),
                type,
                this,
@@ -6898,14 +6951,10 @@ void wxGrid::Refresh(bool eraseb, const wxRect* rect)
     }
 }
 
-void wxGrid::OnSize( wxSizeEvent& event )
+void wxGrid::OnSize(wxSizeEvent& WXUNUSED(event))
 {
-    // position the child windows
-    CalcWindowSizes();
-
-    // don't call CalcDimensions() from here, the base class handles the size
-    // changes itself
-    event.Skip();
+    // update our children window positions and scrollbars
+    CalcDimensions();
 }
 
 void wxGrid::OnKeyDown( wxKeyEvent& event )
@@ -6933,7 +6982,7 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
             else if (event.GetKeyCode() == WXK_LEFT)
                 event.m_keyCode = WXK_RIGHT;
         }
-    
+
         // try local handlers
         switch ( event.GetKeyCode() )
         {
@@ -8079,7 +8128,7 @@ void wxGrid::DrawTextRectangle(wxDC& dc,
             continue;
         }
 
-        long lineWidth = 0,
+        wxCoord lineWidth = 0,
              lineHeight = 0;
         dc.GetTextExtent(line, &lineWidth, &lineHeight);
 
@@ -8160,9 +8209,9 @@ void wxGrid::GetTextBoxSize( const wxDC& dc,
                              const wxArrayString& lines,
                              long *width, long *height ) const
 {
-    long w = 0;
-    long h = 0;
-    long lineW = 0, lineH = 0;
+    wxCoord w = 0;
+    wxCoord h = 0;
+    wxCoord lineW = 0, lineH = 0;
 
     size_t i;
     for ( i = 0; i < lines.GetCount(); i++ )
@@ -9368,7 +9417,13 @@ wxString wxGrid::GetColLabelValue( int col ) const
 
 void wxGrid::SetRowLabelSize( int width )
 {
-    width = wxMax( width, 0 );
+    wxASSERT( width >= 0 || width == wxGRID_AUTOSIZE );
+
+    if ( width == wxGRID_AUTOSIZE )
+    {
+        width = CalcColOrRowLabelAreaMinSize(wxGRID_ROW);
+    }
+
     if ( width != m_rowLabelWidth )
     {
         if ( width == 0 )
@@ -9391,7 +9446,13 @@ void wxGrid::SetRowLabelSize( int width )
 
 void wxGrid::SetColLabelSize( int height )
 {
-    height = wxMax( height, 0 );
+    wxASSERT( height >=0 || height == wxGRID_AUTOSIZE );
+
+    if ( height == wxGRID_AUTOSIZE )
+    {
+        height = CalcColOrRowLabelAreaMinSize(wxGRID_COLUMN);
+    }
+
     if ( height != m_colLabelHeight )
     {
         if ( height == 0 )
@@ -9609,7 +9670,7 @@ void wxGrid::SetCellHighlightPenWidth(int width)
         // make any visible change if the the thickness is getting smaller.
         int row = m_currentCellCoords.GetRow();
         int col = m_currentCellCoords.GetCol();
-        if ( GetColWidth(col) <= 0 || GetRowHeight(row) <= 0 )
+        if ( row == -1 || col == -1 || GetColWidth(col) <= 0 || GetRowHeight(row) <= 0 )
             return;
 
         wxRect rect = CellToRect(row, col);
@@ -10215,10 +10276,7 @@ wxGridCellEditor * wxGrid::GetDefaultEditorForType(const wxString& typeName) con
     int index = m_typeRegistry->FindOrCloneDataType(typeName);
     if ( index == wxNOT_FOUND )
     {
-        wxString errStr;
-
-        errStr.Printf(wxT("Unknown data type name [%s]"), typeName.c_str());
-        wxFAIL_MSG(errStr.c_str());
+        wxFAIL_MSG(wxString::Format(wxT("Unknown data type name [%s]"), typeName.c_str()));
 
         return NULL;
     }
@@ -10231,10 +10289,7 @@ wxGridCellRenderer * wxGrid::GetDefaultRendererForType(const wxString& typeName)
     int index = m_typeRegistry->FindOrCloneDataType(typeName);
     if ( index == wxNOT_FOUND )
     {
-        wxString errStr;
-
-        errStr.Printf(wxT("Unknown data type name [%s]"), typeName.c_str());
-        wxFAIL_MSG(errStr.c_str());
+        wxFAIL_MSG(wxString::Format(wxT("Unknown data type name [%s]"), typeName.c_str()));
 
         return NULL;
     }
@@ -10438,8 +10493,11 @@ int  wxGrid::GetRowMinimalAcceptableHeight() const
 // auto sizing
 // ----------------------------------------------------------------------------
 
-void wxGrid::AutoSizeColOrRow( int colOrRow, bool setAsMin, bool column )
+void
+wxGrid::AutoSizeColOrRow(int colOrRow, bool setAsMin, wxGridDirection direction)
 {
+    const bool column = direction == wxGRID_COLUMN;
+
     wxClientDC dc(m_gridWin);
 
     // cancel editing of cell
@@ -10550,12 +10608,66 @@ void wxGrid::AutoSizeColOrRow( int colOrRow, bool setAsMin, bool column )
     }
 }
 
+wxCoord wxGrid::CalcColOrRowLabelAreaMinSize(wxGridDirection direction)
+{
+    // calculate size for the rows or columns?
+    const bool calcRows = direction == wxGRID_ROW;
+
+    wxClientDC dc(calcRows ? GetGridRowLabelWindow()
+                           : GetGridColLabelWindow());
+    dc.SetFont(GetLabelFont());
+
+    // which dimension should we take into account for calculations?
+    //
+    // for columns, the text can be only horizontal so it's easy but for rows
+    // we also have to take into account the text orientation
+    const bool
+        useWidth = calcRows || (GetColLabelTextOrientation() == wxVERTICAL);
+
+    wxArrayString lines;
+    wxCoord extentMax = 0;
+
+    const int numRowsOrCols = calcRows ? m_numRows : m_numCols;
+    for ( int rowOrCol = 0; rowOrCol < numRowsOrCols; rowOrCol++ )
+    {
+        lines.Clear();
+
+        wxString label = calcRows ? GetRowLabelValue(rowOrCol)
+                                  : GetColLabelValue(rowOrCol);
+        StringToLines(label, lines);
+
+        long w, h;
+        GetTextBoxSize(dc, lines, &w, &h);
+
+        const wxCoord extent = useWidth ? w : h;
+        if ( extent > extentMax )
+            extentMax = extent;
+    }
+
+    if ( !extentMax )
+    {
+        // empty column - give default extent (notice that if extentMax is less
+        // than default extent but != 0, it's OK)
+        extentMax = calcRows ? GetDefaultRowLabelSize()
+                             : GetDefaultColLabelSize();
+    }
+
+    // leave some space around text (taken from AutoSizeColOrRow)
+    if ( calcRows )
+        extentMax += 10;
+    else
+        extentMax += 6;
+
+    return extentMax;
+}
+
 int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
 {
     int width = m_rowLabelWidth;
 
-    if ( !calcOnly )
-        BeginBatch();
+    wxGridUpdateLocker locker;
+    if(!calcOnly)
+        locker.Create(this);
 
     for ( int col = 0; col < m_numCols; col++ )
     {
@@ -10565,9 +10677,6 @@ int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
         width += GetColWidth(col);
     }
 
-    if ( !calcOnly )
-        EndBatch();
-
     return width;
 }
 
@@ -10575,8 +10684,9 @@ int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
 {
     int height = m_colLabelHeight;
 
-    if ( !calcOnly )
-        BeginBatch();
+    wxGridUpdateLocker locker;
+    if(!calcOnly)
+        locker.Create(this);
 
     for ( int row = 0; row < m_numRows; row++ )
     {
@@ -10586,15 +10696,12 @@ int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
         height += GetRowHeight(row);
     }
 
-    if ( !calcOnly )
-        EndBatch();
-
     return height;
 }
 
 void wxGrid::AutoSize()
 {
-    BeginBatch();
+    wxGridUpdateLocker locker(this);
 
     // we need to round up the size of the scrollable area to a multiple of
     // scroll step to ensure that we don't get the scrollbars when we're sized
@@ -10660,8 +10767,6 @@ void wxGrid::AutoSize()
     // client size but also leave space for (not needed any more) scrollbars
     SetScrollbars(0, 0, 0, 0, 0, 0, true);
     SetClientSize(sizeFit.x + m_rowLabelWidth, sizeFit.y + m_colLabelHeight);
-
-    EndBatch();
 }
 
 void wxGrid::AutoSizeRowLabelSize( int row )