]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/grid.cpp
fix typo in drawing slider ticks; added assert to check for it (slightly modified...
[wxWidgets.git] / src / generic / grid.cpp
index 1685c4030c8a0e09730d2d4266a16002bde7704c..f6f8156d78d60aca6761446eed6d9edb391b3284 100644 (file)
@@ -1353,15 +1353,15 @@ void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
 
     m_startValue = grid->GetTable()->GetValue(row, col);
 
-    Combo()->SetValue(m_startValue);
-    size_t count = m_choices.GetCount();
-    for (size_t i=0; i<count; i++)
+    if (m_allowOthers)
+        Combo()->SetValue(m_startValue);
+    else
     {
-        if (m_startValue == m_choices[i])
-        {
-            Combo()->SetSelection(i);
-            break;
-        }
+        // find the right position, or default to the first if not found
+        int pos = Combo()->FindString(m_startValue);
+        if (pos == -1)
+            pos = 0;
+        Combo()->SetSelection(pos);
     }
     Combo()->SetInsertionPointEnd();
     Combo()->SetFocus();
@@ -1377,7 +1377,10 @@ bool wxGridCellChoiceEditor::EndEdit(int row, int col,
         grid->GetTable()->SetValue(row, col, value);
 
     m_startValue = wxEmptyString;
-    Combo()->SetValue(m_startValue);
+    if (m_allowOthers)
+        Combo()->SetValue(m_startValue);
+    else
+        Combo()->SetSelection(0);
 
     return changed;
 }
@@ -1556,6 +1559,15 @@ void wxGridCellStringRenderer::Draw(wxGrid& grid,
                                     bool isSelected)
 {
     wxRect rect = rectCell;
+    rect.Inflate(-1);
+
+    // erase only this cells background, overflow cells should have been erased
+    wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
+
+    int hAlign, vAlign;
+    attr.GetAlignment(&hAlign, &vAlign);
+
+    int overflowCols = 0;
 
     if (attr.GetOverflow())
     {
@@ -1568,29 +1580,63 @@ void wxGridCellStringRenderer::Draw(wxGrid& grid,
             int i, c_cols, c_rows;
             for (i = col+cell_cols; i < cols; i++)
             {
-                // check w/ anchor cell for multicell block
-                grid.GetCellSize(row, i, &c_rows, &c_cols);
-                if (c_rows > 0) c_rows = 0;
-                if (grid.GetTable()->IsEmptyCell(row+c_rows, i))
+                bool is_empty = TRUE;
+                for (int j=row; j<row+cell_rows; j++)
                 {
+                    // check w/ anchor cell for multicell block
+                    grid.GetCellSize(j, i, &c_rows, &c_cols);
+                    if (c_rows > 0) c_rows = 0;
+                    if (!grid.GetTable()->IsEmptyCell(j+c_rows, i))
+                    {
+                        is_empty = FALSE;
+                        break;
+                    }
+                }
+                if (is_empty)
                     rect.width += grid.GetColSize(i);
-                    if (rect.width >= best_width) break;
+                else
+                {
+                    i--;
+                    break;
                 }
-                else break;
+                if (rect.width >= best_width) break;
             }
+            overflowCols = i - col - cell_cols + 1;
+            if (overflowCols >= cols) overflowCols = cols - 1;
         }
-    }
 
-    // erase only this cells background, overflow cells should have been erased
-    wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
+        if (overflowCols > 0) // redraw overflow cells w/ proper hilight
+        {
+            hAlign = wxALIGN_LEFT; // if oveflowed then it's left aligned
+            wxRect clip = rect;
+            clip.x += rectCell.width;
+            // draw each overflow cell individually
+            int col_end = col+cell_cols+overflowCols;
+            if (col_end >= grid.GetNumberCols())
+                col_end = grid.GetNumberCols() - 1;
+            for (int i = col+cell_cols; i <= col_end; i++)
+            {
+                clip.width = grid.GetColSize(i) - 1;
+                dc.DestroyClippingRegion();
+                dc.SetClippingRegion(clip);
 
-    // now we only have to draw the text
-    SetTextColoursAndFont(grid, attr, dc, isSelected);
+                SetTextColoursAndFont(grid, attr, dc,
+                        grid.IsInSelection(row,i));
 
-    int hAlign, vAlign;
-    attr.GetAlignment(&hAlign, &vAlign);
+                grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
+                        rect, hAlign, vAlign);
+                clip.x += grid.GetColSize(i) - 1;
+            }
 
-    rect.Inflate(-1);
+            rect = rectCell;
+            rect.Inflate(-1);
+            rect.width++;
+            dc.DestroyClippingRegion();
+        }
+    }
+
+    // now we only have to draw the text
+    SetTextColoursAndFont(grid, attr, dc, isSelected);
 
     grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
                            rect, hAlign, vAlign);
@@ -1692,9 +1738,9 @@ wxString wxGridCellFloatRenderer::GetString(wxGrid& grid, int row, int col)
             {
                 if ( m_precision == -1 )
                 {
-                // default width/precision
-                m_format = _T("%f");
-            }
+                    // default width/precision
+                    m_format = _T("%f");
+                }
                 else
                 {
                     m_format.Printf(_T("%%.%df"), m_precision);
@@ -3092,7 +3138,7 @@ bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows )
 
     if ( numRows >= curNumRows )
     {
-        m_data.Clear();  // don't release memory just yet
+        m_data.Clear();
     }
     else
     {
@@ -3789,6 +3835,8 @@ void wxGrid::Init()
 
     // init attr cache
     m_attrCache.row = -1;
+    m_attrCache.col = -1;
+    m_attrCache.attr = NULL;
 
     // TODO: something better than this ?
     //
@@ -3866,7 +3914,7 @@ void wxGrid::InitRowHeights()
     m_rowBottoms.Alloc( m_numRows );
 
     int rowBottom = 0;
-    
+
     m_rowHeights.Add( m_defaultRowHeight, m_numRows );
 
     for ( int i = 0;  i < m_numRows;  i++ )
@@ -5308,6 +5356,13 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
     //
     else if ( event.Moving() && !event.IsButton() )
     {
+        if( coords.GetRow() < 0 || coords.GetCol() < 0 )
+        {
+            // out of grid cell area
+            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+            return;
+        }
+
         int dragRow = YToEdgeOfRow( y );
         int dragCol = XToEdgeOfCol( x );
 
@@ -5320,7 +5375,7 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
             return;
         }
 
-        if ( dragRow >= 0 && dragRow < GetNumberRows())
+        if ( dragRow >= 0 )
         {
             m_dragRowOrCol = dragRow;
 
@@ -5338,7 +5393,7 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
             return;
         }
 
-        if ( dragCol >= 0 && dragCol < GetNumberCols())
+        if ( dragCol >= 0 )
         {
             m_dragRowOrCol = dragCol;
 
@@ -5848,7 +5903,7 @@ void wxGrid::Refresh(bool eraseb, const wxRect* rect)
         else
         {
             m_cornerLabelWin->Refresh(eraseb, NULL);
-            m_colLabelWin->Refresh(eraseb, NULL);     
+            m_colLabelWin->Refresh(eraseb, NULL);
             m_rowLabelWin->Refresh(eraseb, NULL);
             m_gridWin->Refresh(eraseb, NULL);
         }
@@ -6208,7 +6263,7 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
         wxRect rect;
         rect = BlockToDeviceRect( wxGridCellCoords ( topRow, leftCol ),
                                   wxGridCellCoords ( bottomRow, rightCol ) );
-        m_gridWin->Refresh( FALSE, &rect );     
+        m_gridWin->Refresh( FALSE, &rect );
     }
     // Now handle changing an existing selection area.
     else if ( m_selectingTopLeft != updateTopLeft ||
@@ -6371,7 +6426,7 @@ void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells )
 {
     if ( !m_numRows || !m_numCols ) return;
 
-    int i, j, k, l, numCells = cells.GetCount();
+    int i, numCells = cells.GetCount();
     int row, col, cell_rows, cell_cols;
     wxGridCellCoordsArray redrawCells;
 
@@ -6386,7 +6441,7 @@ void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells )
         {
             wxGridCellCoords cell(row+cell_rows, col+cell_cols);
             bool marked = FALSE;
-            for ( j = 0;  j < numCells;  j++ )
+            for ( int j = 0;  j < numCells;  j++ )
             {
                 if ( cell == cells[j] )
                 {
@@ -6397,7 +6452,7 @@ void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells )
             if (!marked)
             {
                 int count = redrawCells.GetCount();
-                for (j = 0; j < count; j++)
+                for (int j = 0; j < count; j++)
                 {
                     if ( cell == redrawCells[j] )
                     {
@@ -6413,9 +6468,18 @@ void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells )
         // If this cell is empty, find cell to left that might want to overflow
         if (m_table && m_table->IsEmptyCell(row, col))
         {
-            for ( l = 0; l < cell_rows; l++ )
+            for ( int l = 0; l < cell_rows; l++ )
             {
-                for (j = col-1; j >= 0; j--)
+                // find a cell in this row to left alreay marked for repaint
+                int left = col;
+                for (int k = 0; k < int(redrawCells.GetCount()); k++)
+                    if ((redrawCells[k].GetCol() < left) &&
+                        (redrawCells[k].GetRow() == row))
+                        left=redrawCells[k].GetCol();
+
+                if (left == col) left = 0; // oh well
+
+                for (int j = col-1; j >= left; j--)
                 {
                     if (!m_table->IsEmptyCell(row+l, j))
                     {
@@ -6424,7 +6488,7 @@ void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells )
                             wxGridCellCoords cell(row+l, j);
                             bool marked = FALSE;
 
-                            for (k = 0; k < numCells; k++)
+                            for (int k = 0; k < numCells; k++)
                             {
                                 if ( cell == cells[k] )
                                 {
@@ -6435,7 +6499,7 @@ void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells )
                             if (!marked)
                             {
                                 int count = redrawCells.GetCount();
-                                for (k = 0; k < count; k++)
+                                for (int k = 0; k < count; k++)
                                 {
                                     if ( cell == redrawCells[k] )
                                     {
@@ -7206,31 +7270,36 @@ void wxGrid::ShowCellEditControl()
             editor->Show( TRUE, attr );
 
             // resize editor to overflow into righthand cells if allowed
+            int maxWidth = rect.width;
             wxString value = GetCellValue(row, col);
             if ( (value != wxEmptyString) && (attr->GetOverflow()) )
             {
-                wxClientDC dc(m_gridWin);
-                wxCoord y = 0, best_width = 0;
-                dc.SetFont(attr->GetFont());
-                dc.GetTextExtent(value, &best_width, &y);
-
-                int cell_rows, cell_cols;
-                attr->GetSize( &cell_rows, &cell_cols );
+                int y;
+                GetTextExtent(value, &maxWidth, &y,
+                        NULL, NULL, &attr->GetFont());
+                if (maxWidth < rect.width) maxWidth = rect.width;
+            }
+            int client_right = m_gridWin->GetClientSize().GetWidth();
+            if (rect.x+maxWidth > client_right)
+                maxWidth = client_right - rect.x;
 
-                if ((best_width > rect.width) && (col < m_numCols) && m_table)
+            if ((maxWidth > rect.width) && (col < m_numCols) && m_table)
+            {
+                GetCellSize( row, col, &cell_rows, &cell_cols );
+                // may have changed earlier
+                for (int i = col+cell_cols; i < m_numCols; i++)
                 {
-                    int i;
-                    for (i = col+cell_cols; i < m_numCols; i++)
-                    {
-                        if (m_table->IsEmptyCell(row,i))
-                        {
-                            rect.width += GetColWidth(i);
-                            if (rect.width >= best_width) break;
-                        }
-                        else
-                            break;
-                    }
+                    int c_rows, c_cols;
+                    GetCellSize( row, i, &c_rows, &c_cols );
+                    // looks weird going over a multicell
+                    if (m_table->IsEmptyCell(row,i) &&
+                            (rect.width < maxWidth) && (c_rows == 1))
+                        rect.width += GetColWidth(i);
+                    else
+                        break;
                 }
+                if (rect.GetRight() > client_right)
+                    rect.SetRight(client_right-1);
             }
             editor->SetSize( rect );
 
@@ -7238,7 +7307,7 @@ void wxGrid::ShowCellEditControl()
 
             editor->DecRef();
             attr->DecRef();
-         }
+        }
     }
 }
 
@@ -7331,11 +7400,12 @@ static int CoordToRowOrCol(int coord, int defaultDist, int minDist,
         defaultDist = 1;
     size_t i_max = coord / defaultDist,
            i_min = 0;
+
     if (BorderArray.IsEmpty())
     {
-        if((int) i_max <= nMax)
+        if((int) i_max < nMax)
             return i_max;
-        return maxOnOverflow ? (int)i_max : -1;
+        return maxOnOverflow ? nMax - 1 : -1;
     }
 
     if ( i_max >= BorderArray.GetCount())
@@ -8570,13 +8640,16 @@ void wxGrid::ClearAttrCache()
 
 void wxGrid::CacheAttr(int row, int col, wxGridCellAttr *attr) const
 {
-    wxGrid *self = (wxGrid *)this;  // const_cast
+    if ( attr != NULL )
+    {
+        wxGrid *self = (wxGrid *)this;  // const_cast
 
-    self->ClearAttrCache();
-    self->m_attrCache.row = row;
-    self->m_attrCache.col = col;
-    self->m_attrCache.attr = attr;
-    wxSafeIncRef(attr);
+        self->ClearAttrCache();
+        self->m_attrCache.row = row;
+        self->m_attrCache.col = col;
+        self->m_attrCache.attr = attr;
+        wxSafeIncRef(attr);
+    }
 }
 
 bool wxGrid::LookupAttr(int row, int col, wxGridCellAttr **attr) const
@@ -9217,13 +9290,17 @@ void wxGrid::AutoSize()
 
     // round up the size to a multiple of scroll step - this ensures that we
     // won't get the scrollbars if we're sized exactly to this width
-    wxSize sizeFit(GetScrollX(size.x) * GRID_SCROLL_LINE_X,
-                   GetScrollY(size.y) * GRID_SCROLL_LINE_Y);
+    // CalcDimension adds m_extraWidth + 1 etc. to calculate the necessary
+    // scrollbar steps
+    wxSize sizeFit(GetScrollX(size.x + m_extraWidth + 1) * GRID_SCROLL_LINE_X,
+                   GetScrollY(size.y + m_extraHeight + 1) * GRID_SCROLL_LINE_Y);
 
-    // distribute the extra space between teh columns/rows to avoid having
+    // distribute the extra space between the columns/rows to avoid having
     // extra white space
-    wxCoord diff = sizeFit.x - size.x;
-    if ( diff )
+
+    // Remove the extra m_extraWidth + 1 added above
+    wxCoord diff = sizeFit.x - size.x + (m_extraWidth + 1);
+    if ( diff && m_numCols )
     {
         // try to resize the columns uniformly
         wxCoord diffPerCol = diff / m_numCols;
@@ -9247,8 +9324,8 @@ void wxGrid::AutoSize()
     }
 
     // same for rows
-    diff = sizeFit.y - size.y;
-    if ( diff )
+    diff = sizeFit.y - size.y - (m_extraHeight + 1);
+    if ( diff && m_numRows )
     {
         // try to resize the columns uniformly
         wxCoord diffPerRow = diff / m_numRows;