]> git.saurik.com Git - wxWidgets.git/commitdiff
add a possibility to disable individual grid rows/columns resizing
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 26 Apr 2009 17:02:53 +0000 (17:02 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 26 Apr 2009 17:02:53 +0000 (17:02 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60408 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
docs/doxygen/overviews/grid.h
include/wx/generic/grid.h
include/wx/generic/private/grid.h
interface/wx/grid.h
samples/grid/griddemo.cpp
src/generic/grid.cpp

index ad4c3ef8e9ba9755a17b53b6e4251bf65cb83ad4..7d0825aa3bb925d0e29e441b15bc37433589d7fe 100644 (file)
@@ -329,6 +329,7 @@ All:
 
 All (GUI):
 
+- wxGrid: add possibility to prevent resizing of individual rows/columns.
 - wxHTML: add support for table borders width (Laurent Humbertclaude).
 
 i18n:
index d5ea310988c00318cab3de4992b7ca08682a45cd..91de20825a0181a539d859b85a55d3263fbbc24c 100644 (file)
@@ -143,12 +143,15 @@ to fit its contents with wxGrid::AutoSizeRow() or do it for all rows at once
 with wxGrid::AutoSizeRows().
 
 Additionally, by default the user can also drag the row separator lines to
-resize the rows interactively. This can be forbidden by calling
-wxGrid::DisableDragRowSize(). If you do allow the user to resize the grid rows,
-it may be a good idea to save their heights and restore it when the grid is
-recreated the next time (possibly during a next program execution): the
-functions wxGrid::GetRowSizes() and wxGrid::SetRowSizes() can help with this,
-you will just need to serialize wxGridSizesInfo structure returned by the
-former in some way and deserialize it back before calling the latter.
+resize the rows interactively. This can be forbidden completely by calling
+wxGrid::DisableDragRowSize() or just for the individual rows using
+wxGrid::DisableRowResize().
+
+If you do allow the user to resize the grid rows, it may be a good idea to save
+their heights and restore it when the grid is recreated the next time (possibly
+during a next program execution): the functions wxGrid::GetRowSizes() and
+wxGrid::SetRowSizes() can help with this, you will just need to serialize
+wxGridSizesInfo structure returned by the former in some way and deserialize it
+back before calling the latter.
 
 */
index 9c16160f286e7589a1377593447ab8e0dd41dfa6..0e8c1b9ff33b89f764a91682bf3bb50987683ff6 100644 (file)
@@ -16,6 +16,8 @@
 
 #if wxUSE_GRID
 
+#include "wx/hashmap.h"
+
 #include "wx/scrolwin.h"
 
 // ----------------------------------------------------------------------------
@@ -85,6 +87,8 @@ class WXDLLIMPEXP_FWD_CORE wxTextCtrl;
 class WXDLLIMPEXP_FWD_CORE wxSpinCtrl;
 #endif
 
+class wxGridFixedIndicesSet;
+
 class wxGridOperations;
 class wxGridRowOperations;
 class wxGridColumnOperations;
@@ -771,7 +775,7 @@ private:
 // their non default size for those which don't have the default size.
 // ----------------------------------------------------------------------------
 
-// Hashmap to store postions as the keys and sizes as the values
+// hash map to store positions as the keys and sizes as the values
 WX_DECLARE_HASH_MAP_WITH_DECL( unsigned, int, wxIntegerHash, wxIntegerEqual,
                                wxUnsignedToIntHashMap, class WXDLLIMPEXP_ADV );
 
@@ -1101,19 +1105,42 @@ public:
     void     SetCellHighlightPenWidth(int width);
     void     SetCellHighlightROPenWidth(int width);
 
+
+    // interactive grid mouse operations control
+    // -----------------------------------------
+
+    // functions globally enabling row/column interactive resizing (enabled by
+    // default)
     void     EnableDragRowSize( bool enable = true );
     void     DisableDragRowSize() { EnableDragRowSize( false ); }
-    bool     CanDragRowSize() const { return m_canDragRowSize; }
+
     void     EnableDragColSize( bool enable = true );
     void     DisableDragColSize() { EnableDragColSize( false ); }
-    bool     CanDragColSize() const { return m_canDragColSize; }
+
+        // if interactive resizing is enabled, some rows/columns can still have
+        // fixed size
+    void DisableRowResize(int row) { DoDisableLineResize(row, m_setFixedRows); }
+    void DisableColResize(int col) { DoDisableLineResize(col, m_setFixedCols); }
+
+        // these functions return whether the given row/column can be
+        // effectively resized: for this interactive resizing must be enabled
+        // and this index must not have been passed to DisableRow/ColResize()
+    bool CanDragRowSize(int row) const
+        { return m_canDragRowSize && DoCanResizeLine(row, m_setFixedRows); }
+    bool CanDragColSize(int col) const
+        { return m_canDragColSize && DoCanResizeLine(col, m_setFixedCols); }
+
+    // interactive column reordering (disabled by default)
     void     EnableDragColMove( bool enable = true );
     void     DisableDragColMove() { EnableDragColMove( false ); }
     bool     CanDragColMove() const { return m_canDragColMove; }
+
+    // interactive resizing of grid cells (enabled by default)
     void     EnableDragGridSize(bool enable = true);
     void     DisableDragGridSize() { EnableDragGridSize(false); }
     bool     CanDragGridSize() const { return m_canDragGridSize; }
 
+    // interactive dragging of cells (disabled by default)
     void     EnableDragCell( bool enable = true );
     void     DisableDragCell() { EnableDragCell( false ); }
     bool     CanDragCell() const { return m_canDragCell; }
@@ -1659,6 +1686,9 @@ public:
            wxGRID_CHECKBOX,
            wxGRID_CHOICE,
            wxGRID_COMBOBOX };
+
+    wxDEPRECATED_INLINE(bool CanDragRowSize() const, return m_canDragRowSize; )
+    wxDEPRECATED_INLINE(bool CanDragColSize() const, return m_canDragColSize; )
 #endif // WXWIN_COMPATIBILITY_2_8
 
 
@@ -2083,10 +2113,22 @@ private:
     bool DoAppendLines(bool (wxGridTableBase::*funcAppend)(size_t),
                        int num, bool updateLabels);
 
-    // Common part of Set{Col,Row}Sizes
+    // common part of Set{Col,Row}Sizes
     void DoSetSizes(const wxGridSizesInfo& sizeInfo,
                     const wxGridOperations& oper);
 
+    // common part of Disable{Row,Col}Resize and CanDrag{Row,Col}Size
+    void DoDisableLineResize(int line, wxGridFixedIndicesSet *& setFixed);
+    bool DoCanResizeLine(int line, const wxGridFixedIndicesSet *setFixed) const;
+
+
+
+    // these sets contain the indices of fixed, i.e. non-resizable
+    // interactively, grid rows or columns and are NULL if there are no fixed
+    // elements (which is the default)
+    wxGridFixedIndicesSet *m_setFixedRows,
+                          *m_setFixedCols;
+
     DECLARE_DYNAMIC_CLASS( wxGrid )
     DECLARE_EVENT_TABLE()
     wxDECLARE_NO_COPY_CLASS(wxGrid);
index 0b29eca1ff00ce6720a9b0b772e997c064d6dc6b..e8fc6ec0370982d302bb57c55eee391a0f5e4efb 100644 (file)
@@ -107,7 +107,7 @@ public:
         // we can't know in advance whether we can sort by this column or not
         // with wxGrid API so suppose we can by default
         int flags = wxCOL_SORTABLE;
-        if ( m_grid->CanDragColSize() )
+        if ( m_grid->CanDragColSize(m_col) )
             flags |= wxCOL_RESIZABLE;
         if ( m_grid->CanDragColMove() )
             flags |= wxCOL_REORDERABLE;
@@ -500,9 +500,6 @@ public:
     // Set the row default height or column default width
     virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const = 0;
 
-    // True if rows/columns can be resized by user
-    virtual bool CanResizeLines(const wxGrid *grid) const = 0;
-
 
     // Return the index of the line at the given position
     //
@@ -572,10 +569,8 @@ public:
         { return grid->GetRowMinimalHeight(line); }
     virtual void SetLineSize(wxGrid *grid, int line, int size) const
         { grid->SetRowSize(line, size); }
-    virtual bool CanResizeLines(const wxGrid *grid) const
-        { return grid->CanDragRowSize(); }
     virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const
-        {  grid->SetDefaultRowSize(size, resizeExisting); } 
+        {  grid->SetDefaultRowSize(size, resizeExisting); }
 
     virtual int GetLineAt(const wxGrid * WXUNUSED(grid), int line) const
         { return line; } // TODO: implement row reordering
@@ -635,10 +630,8 @@ public:
         { return grid->GetColMinimalWidth(line); }
     virtual void SetLineSize(wxGrid *grid, int line, int size) const
         { grid->SetColSize(line, size); }
-    virtual bool CanResizeLines(const wxGrid *grid) const
-        { return grid->CanDragColSize(); }
     virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const
-        {  grid->SetDefaultColSize(size, resizeExisting); } 
+        {  grid->SetDefaultColSize(size, resizeExisting); }
 
     virtual int GetLineAt(const wxGrid *grid, int line) const
         { return grid->GetColAt(line); }
index 22f1ff4f59a4f80dfaa2e3788b5aaa4cad410ab6..d65e97a00a7cdeb899c7c2faed5a1d52ccac9e76 100644 (file)
@@ -2037,6 +2037,8 @@ public:
 
     /**
         @name Column and Row Sizes
+
+        @see overview_grid_resizing
      */
     //@{
 
@@ -2322,6 +2324,17 @@ public:
 
     /**
         @name User-Resizing and Dragging
+
+        Functions controlling various interactive mouse operations.
+
+        By default, columns and rows can be resized by dragging the edges of
+        their labels (this can be disabled using DisableDragColSize() and
+        DisableDragRowSize() methods). And if grid line dragging is enabled with
+        EnableDragGridSize() they can also be resized by dragging the right or
+        bottom edge of the grid cells.
+
+        Columns can also be moved to interactively change their order but this
+        needs to be explicitly enabled with EnableDragColMove().
      */
     //@{
 
@@ -2338,13 +2351,15 @@ public:
     bool CanDragColMove() const;
 
     /**
-        Returns @true if columns can be resized by dragging with the mouse.
+        Returns @true if the given column can be resized by dragging with the
+        mouse.
 
-        Columns can be resized by dragging the edges of their labels. If grid
-        line dragging is enabled they can also be resized by dragging the right
-        edge of the column in the grid cell area (see EnableDragGridSize()).
+        This function returns @true if resizing the columns interactively is
+        globally enabled, i.e. if DisableDragColSize() hadn't been called, and
+        if this column wasn't explicitly marked as non-resizable with
+        DisableColResize().
     */
-    bool CanDragColSize() const;
+    bool CanDragColSize(int col) const;
 
     /**
         Return @true if the dragging of grid lines to resize rows and columns
@@ -2353,13 +2368,42 @@ public:
     bool CanDragGridSize() const;
 
     /**
-        Returns @true if rows can be resized by dragging with the mouse.
+        Returns @true if the given row can be resized by dragging with the
+        mouse.
 
-        Rows can be resized by dragging the edges of their labels. If grid line
-        dragging is enabled they can also be resized by dragging the lower edge
-        of the row in the grid cell area (see EnableDragGridSize()).
+        This is the same as CanDragColSize() but for rows.
     */
-    bool CanDragRowSize() const;
+    bool CanDragRowSize(int row) const;
+
+    /**
+        Disable interactive resizing of the specified column.
+
+        This method allows to disable resizing of an individual column in a
+        grid where the columns are otherwise resizable (which is the case by
+        default).
+
+        Notice that currently there is no way to make some columns resizable in
+        a grid where columns can't be resized by default as there doesn't seem
+        to be any need for this in practice. There is also no way to make the
+        column marked as fixed using this method resizeable again because it is
+        supposed that fixed columns are used for static parts of the grid and
+        so should remain fixed during the entire grid lifetime.
+
+        Also notice that disabling interactive column resizing will not prevent
+        the program from changing the column size.
+
+        @see EnableDragColSize()
+     */
+    void DisableColResize(int col);
+
+    /**
+        Disable interactive resizing of the specified row.
+
+        This is the same as DisableColResize() but for rows.
+
+        @see EnableDragRowSize()
+     */
+    void DisableRowResize(int row);
 
     /**
         Disables column moving by dragging with the mouse.
@@ -2401,6 +2445,8 @@ public:
 
     /**
         Enables or disables column sizing by dragging with the mouse.
+
+        @see DisableColResize()
     */
     void EnableDragColSize(bool enable = true);
 
@@ -2412,6 +2458,8 @@ public:
 
     /**
         Enables or disables row sizing by dragging with the mouse.
+
+        @see DisableRowResize()
     */
     void EnableDragRowSize(bool enable = true);
 
index c485fdfe4d15e8706a50474d1d5b0319875552f9..dc42486acbd8be074445aee43660fa4247098b21 100644 (file)
@@ -377,6 +377,14 @@ GridFrame::GridFrame()
     grid->SetCellAlignment(7, 1, wxALIGN_CENTRE, wxALIGN_CENTRE);
     grid->SetCellValue(7, 1, _T("Big box!"));
 
+    // create a separator-like row: it's grey and it's non-resizeable
+    grid->DisableRowResize(10);
+    grid->SetRowSize(10, 30);
+    attr = new wxGridCellAttr;
+    attr->SetBackgroundColour(*wxLIGHT_GREY);
+    grid->SetRowAttr(10, attr);
+    grid->SetCellValue(10, 0, "You can't resize this row interactively -- try it");
+
     // this does exactly nothing except testing that SetAttr() handles NULL
     // attributes and does reference counting correctly
     grid->SetAttr(11, 11, NULL);
index 80c7a07be70c90f851a208c38c98bc19a35ce0d9..231630ea0223e243db7fc1ebdf732001a639bdbd 100644 (file)
@@ -48,6 +48,7 @@
 #include "wx/tokenzr.h"
 #include "wx/renderer.h"
 #include "wx/headerctrl.h"
+#include "wx/hashset.h"
 
 #include "wx/generic/gridsel.h"
 #include "wx/generic/gridctrl.h"
@@ -71,6 +72,9 @@ const char wxGridNameStr[] = "grid";
 // Required for wxIs... functions
 #include <ctype.h>
 
+WX_DECLARE_HASH_SET_WITH_DECL(int, wxIntegerHash, wxIntegerEqual,
+                              wxGridFixedIndicesSet, class WXDLLIMPEXP_ADV);
+
 
 // ----------------------------------------------------------------------------
 // globals
@@ -1822,6 +1826,9 @@ wxGrid::~wxGrid()
 
     delete m_typeRegistry;
     delete m_selection;
+
+    delete m_setFixedRows;
+    delete m_setFixedCols;
 }
 
 //
@@ -2047,6 +2054,9 @@ void wxGrid::Init()
     m_rowLabelWidth  = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
     m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
 
+    m_setFixedRows =
+    m_setFixedCols = NULL;
+
     // init attr cache
     m_attrCache.row = -1;
     m_attrCache.col = -1;
@@ -2916,11 +2926,12 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
     //
     else if ( event.LeftDown() )
     {
-        // don't send a label click event for a hit on the
-        // edge of the row label - this is probably the user
-        // wanting to resize the row
-        //
-        if ( YToEdgeOfRow(y) < 0 )
+        row = YToEdgeOfRow(y);
+        if ( row != wxNOT_FOUND && CanDragRowSize(row) )
+        {
+            ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, m_rowLabelWin);
+        }
+        else // not a request to start resizing
         {
             row = YToRow(y);
             if ( row >= 0 &&
@@ -2948,12 +2959,6 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW, m_rowLabelWin);
             }
         }
-        else
-        {
-            // starting to drag-resize a row
-            if ( CanDragRowSize() )
-                ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, m_rowLabelWin);
-        }
     }
 
     // ------------ Left double click
@@ -2961,7 +2966,15 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
     else if (event.LeftDClick() )
     {
         row = YToEdgeOfRow(y);
-        if ( row < 0 )
+        if ( row != wxNOT_FOUND && CanDragRowSize(row) )
+        {
+            // adjust row height depending on label text
+            AutoSizeRowLabelSize( row );
+
+            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
+            m_dragLastPos = -1;
+        }
+        else // not on row separator or it's not resizeable
         {
             row = YToRow(y);
             if ( row >=0 &&
@@ -2970,14 +2983,6 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
                 // no default action at the moment
             }
         }
-        else
-        {
-            // adjust row height depending on label text
-            AutoSizeRowLabelSize( row );
-
-            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
-            m_dragLastPos = -1;
-        }
     }
 
     // ------------ Left button released
@@ -3027,12 +3032,11 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
     else if ( event.Moving() )
     {
         m_dragRowOrCol = YToEdgeOfRow( y );
-        if ( m_dragRowOrCol >= 0 )
+        if ( m_dragRowOrCol != wxNOT_FOUND )
         {
             if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
             {
-                // don't capture the mouse yet
-                if ( CanDragRowSize() )
+                if ( CanDragRowSize(m_dragRowOrCol) )
                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, m_rowLabelWin, false);
             }
         }
@@ -3248,12 +3252,14 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     else if ( event.LeftDown() )
     {
-        // don't send a label click event for a hit on the
-        // edge of the col label - this is probably the user
-        // wanting to resize the col
-        //
-        if ( XToEdgeOfCol(x) < 0 )
+        int col = XToEdgeOfCol(x);
+        if ( col != wxNOT_FOUND && CanDragColSize(col) )
         {
+            ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, GetColLabelWindow());
+        }
+        else // not a request to start resizing
+        {
+            col = XToCol(x);
             if ( col >= 0 &&
                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK, -1, col, event ) )
             {
@@ -3294,13 +3300,6 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
                 }
             }
         }
-        else
-        {
-            // starting to drag-resize a col
-            //
-            if ( CanDragColSize() )
-                ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, GetColLabelWindow());
-        }
     }
 
     // ------------ Left double click
@@ -3394,8 +3393,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
         {
             if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
             {
-                // don't capture the cursor yet
-                if ( CanDragColSize() )
+                if ( CanDragColSize(m_dragRowOrCol) )
                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, GetColLabelWindow(), false);
             }
         }
@@ -3796,27 +3794,24 @@ wxGrid::DoGridMouseMoveEvent(wxMouseEvent& WXUNUSED(event),
         return;
     }
 
-    if ( dragRow >= 0 )
+    if ( dragRow >= 0 && CanDragGridSize() && CanDragRowSize(dragRow) )
     {
-        m_dragRowOrCol = dragRow;
-
         if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
         {
-            if ( CanDragRowSize() && CanDragGridSize() )
-                ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, NULL, false);
+            m_dragRowOrCol = dragRow;
+            ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, NULL, false);
         }
     }
     // When using the native header window we can only resize the columns by
     // dragging the dividers in it because we can't make it enter into the
     // column resizing mode programmatically
-    else if ( dragCol >= 0 && !m_useNativeHeader )
+    else if ( dragCol >= 0 && !m_useNativeHeader &&
+                CanDragGridSize() && CanDragColSize(dragCol) )
     {
-        m_dragRowOrCol = dragCol;
-
         if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
         {
-            if ( CanDragColSize() && CanDragGridSize() )
-                ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, NULL, false);
+            m_dragRowOrCol = dragCol;
+            ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, NULL, false);
         }
     }
     else // Neither on a row or col edge
@@ -6124,23 +6119,15 @@ int wxGrid::XToPos(int x) const
     return PosToLinePos(x, true /* clip */, wxGridColumnOperations());
 }
 
-// return the row number that that the y coord is near the edge of, or -1 if
+// return the row number such that the y coord is near the edge of, or -1 if
 // not near an edge.
 //
-// coords can only possibly be near an edge if
-//    (a) the row/column is large enough to still allow for an "inner" area
-//        that is _not_ near the edge (i.e., if the height/width is smaller
-//        than WXGRID_LABEL_EDGE_ZONE, coords are _never_ considered to be
-//        near the edge).
-//   and
-//    (b) resizing rows/columns (the thing for which edge detection is
-//        relevant at all) is enabled.
-//
+// notice that position can only possibly be near an edge if the row/column is
+// large enough to still allow for an "inner" area that is _not_ near the edge
+// (i.e., if the height/width is smaller than WXGRID_LABEL_EDGE_ZONE, pos will
+// _never_ be considered to be near the edge).
 int wxGrid::PosToEdgeOfLine(int pos, const wxGridOperations& oper) const
 {
-    if ( !oper.CanResizeLines(this) )
-        return -1;
-
     const int line = oper.PosToLine(this, pos, true);
 
     if ( oper.GetLineSize(this, line) > WXGRID_LABEL_EDGE_ZONE )
@@ -7481,6 +7468,22 @@ wxGridCellRenderer * wxGrid::GetDefaultRendererForType(const wxString& typeName)
 // row/col size
 // ----------------------------------------------------------------------------
 
+void wxGrid::DoDisableLineResize(int line, wxGridFixedIndicesSet *& setFixed)
+{
+    if ( !setFixed )
+    {
+        setFixed = new wxGridFixedIndicesSet;
+    }
+
+    setFixed->insert(line);
+}
+
+bool
+wxGrid::DoCanResizeLine(int line, const wxGridFixedIndicesSet *setFixed) const
+{
+    return !setFixed || !setFixed->count(line);
+}
+
 void wxGrid::EnableDragRowSize( bool enable )
 {
     m_canDragRowSize = enable;