added possibility to reorder columns by dragging them (patch 1409677)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39498 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2006-06-01 00:13:19 +00:00
parent ec376c8fd9
commit d417574519
6 changed files with 558 additions and 101 deletions

View File

@@ -91,6 +91,7 @@ All (GUI):
- Added wxDC::GradientFillLinear/Concentric()
- Added wxHyperlinkCtrl (Francesco Montorsi)
- Added clipboard events (wxEVT_COMMAND_TEXT_COPY/CUT/PASTE)
- Allow to reorder wxGrid columns by drag-and-drop (Santiago Palacios)
- Added wxRadioBox::SetItemToolTip()
- Added support for CMYK JPEG images loading (Robert Wruck)
- Added wxListCtrl::GetSubItemRect() and subitem hit testing (Agron Selimaj)

View File

@@ -2,7 +2,7 @@
%% Name: grid.tex
%% Purpose: wxGrid
%% Author:
%% Modified by:
%% Modified by: Santiago Palacios
%% Created:
%% RCS-ID: $Id$
%% Copyright: (c) wxWidgets
@@ -265,6 +265,15 @@ to the client size of the grid window.
\membersection{wxGrid::CanDragColMove}\label{wxgridcandragcolmove}
\func{bool}{CanDragColMove}{\void}
Returns true if columns can be moved by dragging with the mouse. Columns can be moved
by dragging on their labels.
\membersection{wxGrid::CanDragColSize}\label{wxgridcandragcolsize}
\func{bool}{CanDragColSize}{\void}
@@ -391,6 +400,15 @@ Equivalent to calling EnableCellEditControl(false).
\membersection{wxGrid::DisableDragColMove}\label{wxgriddisabledragcolmove}
\func{void}{DisableDragColMove}{\void}
Disables column moving by dragging with the mouse. Equivalent to passing false to
\helpref{wxGrid::EnableDragColMove}{wxgridenabledragcolmove}.
\membersection{wxGrid::DisableDragColSize}\label{wxgriddisabledragcolsize}
\func{void}{DisableDragColSize}{\void}
@@ -435,6 +453,14 @@ Enables or disables column sizing by dragging with the mouse.
\membersection{wxGrid::EnableDragColMove}\label{wxgridenabledragcolmove}
\func{void}{EnableDragColMove}{\param{bool }{enable = true}}
Enables or disables column moving by dragging with the mouse.
\membersection{wxGrid::EnableDragGridSize}\label{wxgridenabledraggridsize}
\func{void}{EnableDragGridSize}{\param{bool }{enable = true}}
@@ -596,6 +622,13 @@ and the \helpref{wxGrid overview}{gridoverview} for more information.
\membersection{wxGrid::GetColAt}\label{wxgridgetcolat}
\constfunc{int}{GetColAt}{\param{int }{colPos}}
Returns the column ID of the specified column position.
\membersection{wxGrid::GetColLeft}\label{wxgridgetcolleft}
\constfunc{int}{GetColLeft}{\param{int }{col}}
@@ -652,6 +685,14 @@ Get the minimal width of the given column/row.
\membersection{wxGrid::GetColPos}\label{wxgridgetcolpos}
\constfunc{int}{GetColPos}{\param{int }{colID}}
Returns the position of the specified column.
\membersection{wxGrid::GetColRight}\label{wxgridgetcolright}
\constfunc{int}{GetColRight}{\param{int }{col}}
@@ -1062,10 +1103,10 @@ used at present.
The sequence of actions begins with the grid object requesting the underlying grid
table to insert new columns. If this is successful the table notifies the grid and the
grid updates the display. For a default grid (one where you have called
grid updates the display. For a default grid (one where you have called
\helpref{wxGrid::CreateGrid}{wxgridcreategrid}) this process is automatic. If you are
using a custom grid table (specified with \helpref{wxGrid::SetTable}{wxgridsettable})
then you must override
then you must override
\helpref{wxGridTableBase::InsertCols}{wxgridtablebaseinsertcols} in your derived
table class.
@@ -1081,10 +1122,10 @@ present.
The sequence of actions begins with the grid object requesting the underlying grid
table to insert new rows. If this is successful the table notifies the grid and the
grid updates the display. For a default grid (one where you have called
grid updates the display. For a default grid (one where you have called
\helpref{wxGrid::CreateGrid}{wxgridcreategrid}) this process is automatic. If you are
using a custom grid table (specified with \helpref{wxGrid::SetTable}{wxgridsettable})
then you must override
then you must override
\helpref{wxGridTableBase::InsertRows}{wxgridtablebaseinsertrows} in your derived
table class.
@@ -1438,7 +1479,7 @@ function for those cells that contain string values.
The last form is for backward compatibility only.
See \helpref{wxGridTableBase::CanSetValueAs}{wxgridtablebasecangetvalueas}
See \helpref{wxGridTableBase::CanSetValueAs}{wxgridtablebasecangetvalueas}
and the \helpref{wxGrid overview}{gridoverview} for more information.
@@ -1449,8 +1490,8 @@ and the \helpref{wxGrid overview}{gridoverview} for more information.
Sets the cell attributes for all cells in the specified column.
For more information about controlling grid cell attributes see the
\helpref{wxGridCellAttr}{wxgridcellattr} cell attribute class and the
For more information about controlling grid cell attributes see the
\helpref{wxGridCellAttr}{wxgridcellattr} cell attribute class and the
\helpref{wxGrid classes overview}{gridoverview}.
@@ -1543,6 +1584,14 @@ with sizes smaller than the value specified here.
\membersection{wxGrid::SetColPos}\label{wxgridsetcolpos}
\func{void}{SetColPos}{\param{int }{colID}, \param{int }{newPos}}
Sets the position of the specified column.
\membersection{wxGrid::SetColSize}\label{wxgridsetcolsize}
\func{void}{SetColSize}{\param{int }{col}, \param{int }{width}}
@@ -1877,9 +1926,14 @@ Displays the in-place cell edit control for the current cell.
\membersection{wxGrid::XToCol}\label{wxgridxtocol}
\func{int}{XToCol}{\param{int }{x}}
\func{int}{XToCol}{\param{int }{x}, \param{bool }{clipToMinMax = false}}
Returns the grid column that corresponds to the logical x coordinate. Returns
\wxheading{Parameters}
\docparam{x}{The x position to evaluate.}
\docparam{clipToMinMax}{If true, rather than returning wxNOT\_FOUND, it returns either the first or last column depending on whether x is too far to the left or right respectively.}
\wxheading{Return value}
The grid column that corresponds to the logical x coordinate. Returns
{\tt wxNOT\_FOUND} if there is no column at the x position.
@@ -1906,6 +1960,6 @@ If no row edge is near to this position {\tt wxNOT\_FOUND} is returned.
\func{int}{YToRow}{\param{int }{y}}
Returns the grid row that corresponds to the logical y coordinate. Returns
Returns the grid row that corresponds to the logical y coordinate. Returns
{\tt wxNOT\_FOUND} if there is no row at the y position.

View File

@@ -2,7 +2,7 @@
// Name: wx/generic/grid.h
// Purpose: wxGrid and related classes
// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
// Modified by:
// Modified by: Santiago Palacios
// Created: 1/08/1999
// RCS-ID: $Id$
// Copyright: (c) Michael Bedward
@@ -1123,6 +1123,7 @@ public:
void DoEndDragResizeRow();
void DoEndDragResizeCol();
void DoEndDragMoveCol();
wxGridTableBase * GetTable() const { return m_table; }
bool SetTable( wxGridTableBase *table, bool takeOwnership = false,
@@ -1226,7 +1227,7 @@ public:
//
void XYToCell( int x, int y, wxGridCellCoords& );
int YToRow( int y );
int XToCol( int x );
int XToCol( int x, bool clipToMinMax = false );
int YToEdgeOfRow( int y );
int XToEdgeOfCol( int x );
@@ -1306,6 +1307,9 @@ public:
void EnableDragColSize( bool enable = true );
void DisableDragColSize() { EnableDragColSize( false ); }
bool CanDragColSize() { return m_canDragColSize; }
void EnableDragColMove( bool enable = true );
void DisableDragColMove() { EnableDragColMove( false ); }
bool CanDragColMove() { return m_canDragColMove; }
void EnableDragGridSize(bool enable = true);
void DisableDragGridSize() { EnableDragGridSize(false); }
bool CanDragGridSize() { return m_canDragGridSize; }
@@ -1361,6 +1365,33 @@ public:
void SetColSize( int col, int width );
//Column positions
int GetColAt( int colPos ) const
{
if ( m_colAt.IsEmpty() )
return colPos;
else
return m_colAt[colPos];
}
void SetColPos( int colID, int newPos );
int GetColPos( int colID ) const
{
if ( m_colAt.IsEmpty() )
return colID;
else
{
for ( int i = 0; i < m_numCols; i++ )
{
if ( m_colAt[i] == colID )
return i;
}
}
return -1;
}
// automatically size the column or row to fit to its contents, if
// setAsMin is true, this optimal width will also be set as minimal width
// for this column
@@ -1869,7 +1900,8 @@ protected:
WXGRID_CURSOR_RESIZE_ROW,
WXGRID_CURSOR_RESIZE_COL,
WXGRID_CURSOR_SELECT_ROW,
WXGRID_CURSOR_SELECT_COL
WXGRID_CURSOR_SELECT_COL,
WXGRID_CURSOR_MOVE_COL
};
// this method not only sets m_cursorMode but also sets the correct cursor
@@ -1885,8 +1917,13 @@ protected:
wxWindow *m_winCapture; // the window which captured the mouse
CursorMode m_cursorMode;
//Column positions
wxArrayInt m_colAt;
int m_moveToCol;
bool m_canDragRowSize;
bool m_canDragColSize;
bool m_canDragColMove;
bool m_canDragGridSize;
bool m_canDragCell;
int m_dragLastPos;
@@ -1980,7 +2017,7 @@ public:
bool MetaDown() { return m_meta; }
bool ShiftDown() { return m_shift; }
bool AltDown() { return m_alt; }
bool CmdDown()
bool CmdDown()
{
#if defined(__WXMAC__) || defined(__WXCOCOA__)
return MetaDown();
@@ -2022,7 +2059,7 @@ public:
bool MetaDown() { return m_meta; }
bool ShiftDown() { return m_shift; }
bool AltDown() { return m_alt; }
bool CmdDown()
bool CmdDown()
{
#if defined(__WXMAC__) || defined(__WXCOCOA__)
return MetaDown();
@@ -2077,7 +2114,7 @@ public:
bool MetaDown() { return m_meta; }
bool ShiftDown() { return m_shift; }
bool AltDown() { return m_alt; }
bool CmdDown()
bool CmdDown()
{
#if defined(__WXMAC__) || defined(__WXCOCOA__)
return MetaDown();

View File

@@ -2,7 +2,7 @@
// Name: griddemo.cpp
// Purpose: Grid control wxWidgets sample
// Author: Michael Bedward
// Modified by:
// Modified by: Santiago Palacios
// RCS-ID: $Id$
// Copyright: (c) Michael Bedward, Julian Smart, Vadim Zeitlin
// Licence: wxWindows license
@@ -68,6 +68,7 @@ BEGIN_EVENT_TABLE( GridFrame, wxFrame )
EVT_MENU( ID_TOGGLEEDIT, GridFrame::ToggleEditing )
EVT_MENU( ID_TOGGLEROWSIZING, GridFrame::ToggleRowSizing )
EVT_MENU( ID_TOGGLECOLSIZING, GridFrame::ToggleColSizing )
EVT_MENU( ID_TOGGLECOLMOVING, GridFrame::ToggleColMoving )
EVT_MENU( ID_TOGGLEGRIDSIZING, GridFrame::ToggleGridSizing )
EVT_MENU( ID_TOGGLEGRIDDRAGCELL, GridFrame::ToggleGridDragCell )
EVT_MENU( ID_TOGGLEGRIDLINES, GridFrame::ToggleGridLines )
@@ -146,6 +147,7 @@ GridFrame::GridFrame()
viewMenu->Append( ID_TOGGLEEDIT, _T("&Editable"), wxEmptyString, wxITEM_CHECK );
viewMenu->Append( ID_TOGGLEROWSIZING, _T("Ro&w drag-resize"), wxEmptyString, wxITEM_CHECK );
viewMenu->Append( ID_TOGGLECOLSIZING, _T("C&ol drag-resize"), wxEmptyString, wxITEM_CHECK );
viewMenu->Append( ID_TOGGLECOLMOVING, _T("Col drag-&move"), wxEmptyString, wxITEM_CHECK );
viewMenu->Append( ID_TOGGLEGRIDSIZING, _T("&Grid drag-resize"), wxEmptyString, wxITEM_CHECK );
viewMenu->Append( ID_TOGGLEGRIDDRAGCELL, _T("&Grid drag-cell"), wxEmptyString, wxITEM_CHECK );
viewMenu->Append( ID_TOGGLEGRIDLINES, _T("&Grid Lines"), wxEmptyString, wxITEM_CHECK );
@@ -376,6 +378,7 @@ void GridFrame::SetDefaults()
GetMenuBar()->Check( ID_TOGGLEEDIT, true );
GetMenuBar()->Check( ID_TOGGLEROWSIZING, true );
GetMenuBar()->Check( ID_TOGGLECOLSIZING, true );
GetMenuBar()->Check( ID_TOGGLECOLMOVING, false );
GetMenuBar()->Check( ID_TOGGLEGRIDSIZING, true );
GetMenuBar()->Check( ID_TOGGLEGRIDDRAGCELL, false );
GetMenuBar()->Check( ID_TOGGLEGRIDLINES, true );
@@ -429,6 +432,12 @@ void GridFrame::ToggleColSizing( wxCommandEvent& WXUNUSED(ev) )
GetMenuBar()->IsChecked( ID_TOGGLECOLSIZING ) );
}
void GridFrame::ToggleColMoving( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableDragColMove(
GetMenuBar()->IsChecked( ID_TOGGLECOLMOVING ) );
}
void GridFrame::ToggleGridSizing( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableDragGridSize(
@@ -927,6 +936,11 @@ void GridFrame::OnSelectCell( wxGridEvent& ev )
<< _T(", ShiftDown: ")<< (ev.ShiftDown() ? 'T':'F')
<< _T(", AltDown: ")<< (ev.AltDown() ? 'T':'F')
<< _T(", MetaDown: ")<< (ev.MetaDown() ? 'T':'F') << _T(" )");
//Indicate whether this column was moved
if ( ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() ) != ev.GetCol() )
logBuf << _T(" *** Column moved, current position: ") << ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() );
wxLogMessage( wxT("%s"), logBuf.c_str() );
// you must call Skip() if you want the default processing

View File

@@ -37,6 +37,7 @@ class GridFrame : public wxFrame
void ToggleEditing( wxCommandEvent& );
void ToggleRowSizing( wxCommandEvent& );
void ToggleColSizing( wxCommandEvent& );
void ToggleColMoving( wxCommandEvent& );
void ToggleGridSizing( wxCommandEvent& );
void ToggleGridDragCell ( wxCommandEvent& );
void ToggleGridLines( wxCommandEvent& );
@@ -107,6 +108,7 @@ public:
ID_TOGGLEEDIT,
ID_TOGGLEROWSIZING,
ID_TOGGLECOLSIZING,
ID_TOGGLECOLMOVING,
ID_TOGGLEGRIDSIZING,
ID_TOGGLEGRIDDRAGCELL,
ID_TOGGLEGRIDLINES,

View File

@@ -2,7 +2,7 @@
// Name: src/generic/grid.cpp
// Purpose: wxGrid and related classes
// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
// Modified by: Robin Dunn, Vadim Zeitlin
// Modified by: Robin Dunn, Vadim Zeitlin, Santiago Palacios
// Created: 1/08/1999
// RCS-ID: $Id$
// Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)
@@ -104,6 +104,7 @@ DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK)
DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK)
DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE)
DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE)
DEFINE_EVENT_TYPE(wxEVT_GRID_COL_MOVE)
DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT)
DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE)
DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL)
@@ -622,7 +623,7 @@ void wxGridCellTextEditor::Create(wxWindow* parent,
m_control = new wxTextCtrl(parent, id, wxEmptyString,
wxDefaultPosition, wxDefaultSize
#if defined(__WXMSW__)
, wxTE_PROCESS_TAB | wxTE_AUTO_SCROLL
, wxTE_PROCESS_TAB | wxTE_AUTO_SCROLL | wxNO_BORDER
#endif
);
@@ -658,27 +659,33 @@ void wxGridCellTextEditor::SetSize(const wxRect& rectOrig)
rect.width -= 1;
rect.height -= 1;
}
#else // !GTK
int extra_x = ( rect.x > 2 ) ? 2 : 1;
#elif defined(__WXMSW__)
if ( rect.x == 0 )
rect.x += 2;
else
rect.x += 3;
// MB: treat MSW separately here otherwise the caret doesn't show
// when the editor is in the first row.
#if defined(__WXMSW__)
int extra_y = 2;
if ( rect.y == 0 )
rect.y += 2;
else
rect.y += 3;
rect.width -= 2;
rect.height -= 2;
#else
int extra_x = ( rect.x > 2 ) ? 2 : 1;
int extra_y = ( rect.y > 2 ) ? 2 : 1;
#endif
#if defined(__WXMOTIF__)
extra_x *= 2;
extra_y *= 2;
#endif
#if defined(__WXMOTIF__)
extra_x *= 2;
extra_y *= 2;
#endif
rect.SetLeft( wxMax(0, rect.x - extra_x) );
rect.SetTop( wxMax(0, rect.y - extra_y) );
rect.SetRight( rect.GetRight() + 2 * extra_x );
rect.SetBottom( rect.GetBottom() + 2 * extra_y );
#endif // GTK/!GTK
#endif
wxGridCellEditor::SetSize(rect);
}
@@ -3506,6 +3513,15 @@ bool wxGridStringTable::InsertCols( size_t pos, size_t numCols )
return AppendCols( numCols );
}
if ( !m_colLabels.IsEmpty() )
{
m_colLabels.Insert( wxEmptyString, pos, numCols );
size_t i;
for ( i = pos; i < pos + numCols; i++ )
m_colLabels[i] = wxGridTableBase::GetColLabelValue( i );
}
for ( row = 0; row < curNumRows; row++ )
{
for ( col = pos; col < pos + numCols; col++ )
@@ -3580,9 +3596,20 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
return false;
}
if ( numCols > curNumCols - pos )
int colID;
if ( GetView() )
colID = GetView()->GetColAt( pos );
else
colID = pos;
if ( numCols > curNumCols - colID )
{
numCols = curNumCols - pos;
numCols = curNumCols - colID;
}
if ( !m_colLabels.IsEmpty() )
{
m_colLabels.RemoveAt( colID, numCols );
}
for ( row = 0; row < curNumRows; row++ )
@@ -3593,7 +3620,7 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
}
else
{
m_data[row].RemoveAt( pos, numCols );
m_data[row].RemoveAt( colID, numCols );
}
}
@@ -3851,7 +3878,7 @@ void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
wxRendererNative::Get().DrawHeaderButton( this, dc, rect, 0 );
#else // !__WXGTK__
dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW), 1, wxSOLID) );
dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID) );
dc.DrawLine( client_width - 1, client_height - 1, client_width - 1, 0 );
dc.DrawLine( client_width - 1, client_height - 1, 0, client_height - 1 );
dc.DrawLine( 0, 0, client_width, 0 );
@@ -4006,9 +4033,7 @@ static int CoordToRowOrCol(int coord, int defaultDist, int minDist,
const wxArrayInt& BorderArray, int nMax,
bool clipToMinMax);
#define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \
m_minAcceptableColWidth, \
m_colRights, m_numCols, true)
#define internalXToCol(x) XToCol(x, true)
#define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \
m_minAcceptableRowHeight, \
m_rowBottoms, m_numRows, true)
@@ -4376,6 +4401,8 @@ void wxGrid::Init()
m_cellHighlightPenWidth = 2;
m_cellHighlightROPenWidth = 1;
m_canDragColMove = false;
m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
m_winCapture = (wxWindow *)NULL;
m_canDragRowSize = true;
@@ -4453,7 +4480,7 @@ void wxGrid::InitColWidths()
for ( int i = 0; i < m_numCols; i++ )
{
colRight += m_defaultColWidth;
colRight = ( GetColPos( i ) + 1 ) * m_defaultColWidth;
m_colRights.Add( colRight );
}
}
@@ -4465,13 +4492,13 @@ int wxGrid::GetColWidth(int col) const
int wxGrid::GetColLeft(int col) const
{
return m_colRights.IsEmpty() ? col * m_defaultColWidth
return m_colRights.IsEmpty() ? GetColPos( col ) * m_defaultColWidth
: m_colRights[col] - m_colWidths[col];
}
int wxGrid::GetColRight(int col) const
{
return m_colRights.IsEmpty() ? (col + 1) * m_defaultColWidth
return m_colRights.IsEmpty() ? (GetColPos( col ) + 1) * m_defaultColWidth
: m_colRights[col];
}
@@ -4503,7 +4530,7 @@ void wxGrid::CalcDimensions()
ch -= m_colLabelHeight;
// grid total size
int w = m_numCols > 0 ? GetColRight(m_numCols - 1) + m_extraWidth + 1 : 0;
int w = m_numCols > 0 ? GetColRight(GetColAt( m_numCols - 1 )) + m_extraWidth + 1 : 0;
int h = m_numRows > 0 ? GetRowBottom(m_numRows - 1) + m_extraHeight + 1 : 0;
// take into account editor if shown
@@ -4755,6 +4782,25 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
int numCols = msg.GetCommandInt2();
m_numCols += numCols;
if ( !m_colAt.IsEmpty() )
{
//Shift the column IDs
int i;
for ( i = 0; i < m_numCols - numCols; i++ )
{
if ( m_colAt[i] >= (int)pos )
m_colAt[i] += numCols;
}
m_colAt.Insert( pos, pos, numCols );
//Set the new columns' positions
for ( i = pos + 1; i < (int)pos + numCols; i++ )
{
m_colAt[i] = i;
}
}
if ( !m_colWidths.IsEmpty() )
{
m_colWidths.Insert( m_defaultColWidth, pos, numCols );
@@ -4762,10 +4808,13 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
int right = 0;
if ( pos > 0 )
right = m_colRights[pos - 1];
right = m_colRights[GetColAt( pos - 1 )];
for ( i = pos; i < m_numCols; i++ )
int colPos;
for ( colPos = pos; colPos < m_numCols; colPos++ )
{
i = GetColAt( colPos );
right += m_colWidths[i];
m_colRights[i] = right;
}
@@ -4798,6 +4847,19 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
int numCols = msg.GetCommandInt();
int oldNumCols = m_numCols;
m_numCols += numCols;
if ( !m_colAt.IsEmpty() )
{
m_colAt.Add( 0, numCols );
//Set the new columns' positions
int i;
for ( i = oldNumCols; i < m_numCols; i++ )
{
m_colAt[i] = i;
}
}
if ( !m_colWidths.IsEmpty() )
{
m_colWidths.Add( m_defaultColWidth, numCols );
@@ -4805,10 +4867,13 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
int right = 0;
if ( oldNumCols > 0 )
right = m_colRights[oldNumCols - 1];
right = m_colRights[GetColAt( oldNumCols - 1 )];
for ( i = oldNumCols; i < m_numCols; i++ )
int colPos;
for ( colPos = oldNumCols; colPos < m_numCols; colPos++ )
{
i = GetColAt( colPos );
right += m_colWidths[i];
m_colRights[i] = right;
}
@@ -4836,14 +4901,32 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
int numCols = msg.GetCommandInt2();
m_numCols -= numCols;
if ( !m_colAt.IsEmpty() )
{
int colID = GetColAt( pos );
m_colAt.RemoveAt( pos, numCols );
//Shift the column IDs
int colPos;
for ( colPos = 0; colPos < m_numCols; colPos++ )
{
if ( m_colAt[colPos] > colID )
m_colAt[colPos] -= numCols;
}
}
if ( !m_colWidths.IsEmpty() )
{
m_colWidths.RemoveAt( pos, numCols );
m_colRights.RemoveAt( pos, numCols );
int w = 0;
for ( i = 0; i < m_numCols; i++ )
int colPos;
for ( colPos = 0; colPos < m_numCols; colPos++ )
{
i = GetColAt( colPos );
w += m_colWidths[i];
m_colRights[i] = w;
}
@@ -4979,8 +5062,11 @@ wxArrayInt wxGrid::CalcColLabelsExposed( const wxRegion& reg )
// find the cells within these bounds
//
int col;
for ( col = internalXToCol(left); col < m_numCols; col++ )
int colPos;
for ( colPos = GetColPos( internalXToCol(left) ); colPos < m_numCols; colPos++ )
{
col = GetColAt( colPos );
if ( GetColRight(col) < left )
continue;
@@ -5038,8 +5124,11 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg )
if ( GetRowTop(row) > bottom )
break;
for ( col = internalXToCol(left); col < m_numCols; col++ )
int colPos;
for ( colPos = GetColPos( internalXToCol(left) ); colPos < m_numCols; colPos++ )
{
col = GetColAt( colPos );
if ( GetColRight(col) <= left )
continue;
@@ -5287,6 +5376,9 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
{
m_isDragging = true;
m_colLabelWin->CaptureMouse();
if ( m_cursorMode == WXGRID_CURSOR_MOVE_COL )
m_dragRowOrCol = XToCol( x );
}
if ( event.LeftIsDown() )
@@ -5330,6 +5422,63 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
}
break;
case WXGRID_CURSOR_MOVE_COL:
{
if ( x < 0 )
m_moveToCol = GetColAt( 0 );
else
m_moveToCol = XToCol( x );
int markerX;
if ( m_moveToCol < 0 )
markerX = GetColRight( GetColAt( m_numCols - 1 ) );
else
markerX = GetColLeft( m_moveToCol );
if ( markerX != m_dragLastPos )
{
wxClientDC dc( m_colLabelWin );
int cw, ch;
m_colLabelWin->GetClientSize( &cw, &ch );
markerX++;
//Clean up the last indicator
if ( m_dragLastPos >= 0 )
{
wxPen pen( m_colLabelWin->GetBackgroundColour(), 2 );
dc.SetPen(pen);
dc.DrawLine( m_dragLastPos + 1, 0, m_dragLastPos + 1, ch );
dc.SetPen(wxNullPen);
if ( XToCol( m_dragLastPos ) != -1 )
DrawColLabel( dc, XToCol( m_dragLastPos ) );
}
//Moving to the same place? Don't draw a marker
if ( (m_moveToCol == m_dragRowOrCol)
|| (GetColPos( m_moveToCol ) == GetColPos( m_dragRowOrCol ) + 1)
|| (m_moveToCol < 0 && m_dragRowOrCol == GetColAt( m_numCols - 1 )))
{
m_dragLastPos = -1;
return;
}
//Draw the marker
wxPen pen( *wxBLUE, 2 );
dc.SetPen(pen);
dc.DrawLine( markerX, 0, markerX, ch );
dc.SetPen(wxNullPen);
m_dragLastPos = markerX - 1;
}
}
break;
// default label to suppress warnings about "enumeration value
// 'xxx' not handled in switch
default:
@@ -5370,31 +5519,46 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
if ( col >= 0 &&
!SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK, -1, col, event ) )
{
if ( !event.ShiftDown() && !event.CmdDown() )
ClearSelection();
if ( m_selection )
if ( m_canDragColMove )
{
if ( event.ShiftDown() )
{
m_selection->SelectBlock( 0,
m_currentCellCoords.GetCol(),
GetNumberRows() - 1, col,
event.ControlDown(),
event.ShiftDown(),
event.AltDown(),
event.MetaDown() );
}
else
{
m_selection->SelectCol( col,
event.ControlDown(),
event.ShiftDown(),
event.AltDown(),
event.MetaDown() );
}
}
//Show button as pressed
wxClientDC dc( m_colLabelWin );
int colLeft = GetColLeft( col );
int colRight = GetColRight( col ) - 1;
dc.SetPen( wxPen( m_colLabelWin->GetBackgroundColour(), 1 ) );
dc.DrawLine( colLeft, 1, colLeft, m_colLabelHeight-1 );
dc.DrawLine( colLeft, 1, colRight, 1 );
ChangeCursorMode(WXGRID_CURSOR_SELECT_COL, m_colLabelWin);
ChangeCursorMode(WXGRID_CURSOR_MOVE_COL, m_colLabelWin);
}
else
{
if ( !event.ShiftDown() && !event.CmdDown() )
ClearSelection();
if ( m_selection )
{
if ( event.ShiftDown() )
{
m_selection->SelectBlock( 0,
m_currentCellCoords.GetCol(),
GetNumberRows() - 1, col,
event.ControlDown(),
event.ShiftDown(),
event.AltDown(),
event.MetaDown() );
}
else
{
m_selection->SelectCol( col,
event.ControlDown(),
event.ShiftDown(),
event.AltDown(),
event.MetaDown() );
}
}
ChangeCursorMode(WXGRID_CURSOR_SELECT_COL, m_colLabelWin);
}
}
}
else
@@ -5434,14 +5598,26 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
//
else if ( event.LeftUp() )
{
if ( m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
switch ( m_cursorMode )
{
DoEndDragResizeCol();
case WXGRID_CURSOR_RESIZE_COL:
{
DoEndDragResizeCol();
// Note: we are ending the event *after* doing
// default processing in this case
//
SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol, event );
// Note: we are ending the event *after* doing
// default processing in this case
//
SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol, event );
}
break;
case WXGRID_CURSOR_MOVE_COL:
{
DoEndDragMoveCol();
SendEvent( wxEVT_GRID_COL_MOVE, -1, m_dragRowOrCol, event );
}
break;
}
ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, m_colLabelWin);
@@ -5536,7 +5712,8 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
_T("RESIZE_ROW"),
_T("RESIZE_COL"),
_T("SELECT_ROW"),
_T("SELECT_COL")
_T("SELECT_COL"),
_T("MOVE_COL"),
};
wxLogTrace(_T("grid"),
@@ -5577,6 +5754,10 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
win->SetCursor( m_colResizeCursor );
break;
case WXGRID_CURSOR_MOVE_COL:
win->SetCursor( wxCursor(wxCURSOR_HAND) );
break;
default:
win->SetCursor( *wxSTANDARD_CURSOR );
break;
@@ -6099,6 +6280,112 @@ void wxGrid::DoEndDragResizeCol()
}
}
void wxGrid::DoEndDragMoveCol()
{
//The user clicked on the column but didn't actually drag
if ( m_dragLastPos < 0 )
{
m_colLabelWin->Refresh(); //Do this to "unpress" the column
return;
}
int newPos;
if ( m_moveToCol == -1 )
newPos = m_numCols - 1;
else
{
newPos = GetColPos( m_moveToCol );
if ( newPos > GetColPos( m_dragRowOrCol ) )
newPos--;
}
SetColPos( m_dragRowOrCol, newPos );
}
void wxGrid::SetColPos( int colID, int newPos )
{
if ( m_colAt.IsEmpty() )
{
m_colAt.Alloc( m_numCols );
int i;
for ( i = 0; i < m_numCols; i++ )
{
m_colAt.Add( i );
}
}
int oldPos = GetColPos( colID );
//Reshuffle the m_colAt array
if ( newPos > oldPos )
{
int i;
for ( i = oldPos; i < newPos; i++ )
{
m_colAt[i] = m_colAt[i+1];
}
}
else
{
int i;
for ( i = oldPos; i > newPos; i-- )
{
m_colAt[i] = m_colAt[i-1];
}
}
m_colAt[newPos] = colID;
//Recalculate the column rights
if ( !m_colWidths.IsEmpty() )
{
int colRight = 0;
int colPos;
for ( colPos = 0; colPos < m_numCols; colPos++ )
{
int colID = GetColAt( colPos );
colRight += m_colWidths[colID];
m_colRights[colID] = colRight;
}
}
m_colLabelWin->Refresh();
m_gridWin->Refresh();
}
void wxGrid::EnableDragColMove( bool enable )
{
if ( m_canDragColMove == enable )
return;
m_canDragColMove = enable;
if ( !m_canDragColMove )
{
m_colAt.Clear();
//Recalculate the column rights
if ( !m_colWidths.IsEmpty() )
{
int colRight = 0;
int colPos;
for ( colPos = 0; colPos < m_numCols; colPos++ )
{
colRight += m_colWidths[colPos];
m_colRights[colPos] = colRight;
}
}
m_colLabelWin->Refresh();
m_gridWin->Refresh();
}
}
//
// ------ interaction with data model
//
@@ -7094,7 +7381,7 @@ void wxGrid::DrawGridSpace( wxDC& dc )
int right, bottom;
CalcUnscrolledPosition( cw, ch, &right, &bottom );
int rightCol = m_numCols > 0 ? GetColRight(m_numCols - 1) : 0;
int rightCol = m_numCols > 0 ? GetColRight(GetColAt( m_numCols - 1 )) : 0;
int bottomRow = m_numRows > 0 ? GetRowBottom(m_numRows - 1) : 0;
if ( right > rightCol || bottom > bottomRow )
@@ -7315,13 +7602,13 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
// avoid drawing grid lines past the last row and col
//
right = wxMin( right, GetColRight(m_numCols - 1) );
right = wxMin( right, GetColRight(GetColAt( m_numCols - 1 )) );
bottom = wxMin( bottom, GetRowBottom(m_numRows - 1) );
// no gridlines inside multicells, clip them out
int leftCol = internalXToCol(left);
int leftCol = GetColPos( internalXToCol(left) );
int topRow = internalYToRow(top);
int rightCol = internalXToCol(right);
int rightCol = GetColPos( internalXToCol(right) );
int bottomRow = internalYToRow(bottom);
#ifndef __WXMAC__
@@ -7333,8 +7620,11 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
for (j=topRow; j<bottomRow; j++)
{
for (i=leftCol; i<rightCol; i++)
int colPos;
for (colPos=leftCol; colPos<rightCol; colPos++)
{
i = GetColAt( colPos );
GetCellSize( j, i, &cell_rows, &cell_cols );
if ((cell_rows > 1) || (cell_cols > 1))
{
@@ -7399,8 +7689,11 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
// vertical grid lines
//
for ( i = internalXToCol(left); i < m_numCols; i++ )
int colPos;
for ( colPos = leftCol; colPos < m_numCols; colPos++ )
{
i = GetColAt( colPos );
int colRight = GetColRight(i) - 1;
if ( colRight > right )
{
@@ -7452,7 +7745,7 @@ void wxGrid::DrawRowLabel( wxDC& dc, int row )
int rowTop = GetRowTop(row),
rowBottom = GetRowBottom(row) - 1;
dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW), 1, wxSOLID) );
dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID) );
dc.DrawLine( m_rowLabelWidth - 1, rowTop, m_rowLabelWidth - 1, rowBottom );
dc.DrawLine( 0, rowTop, 0, rowBottom );
dc.DrawLine( 0, rowBottom, m_rowLabelWidth, rowBottom );
@@ -7511,7 +7804,7 @@ void wxGrid::DrawColLabel( wxDC& dc, int col )
#else
int colRight = GetColRight(col) - 1;
dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW), 1, wxSOLID) );
dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID) );
dc.DrawLine( colRight, 0, colRight, m_colLabelHeight - 1 );
dc.DrawLine( colLeft, 0, colRight, 0 );
dc.DrawLine( colLeft, m_colLabelHeight - 1,
@@ -7887,16 +8180,13 @@ void wxGrid::ShowCellEditControl()
if (rect.x < 0)
nXMove = rect.x;
// performed 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.SetBrush(wxBrush(GetCellAttr(row, col)->GetBackgroundColour(), wxSOLID));
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(rect);
#endif
// cell is shifted by one pixel
// However, don't allow x or y to become negative
@@ -8135,10 +8425,65 @@ int wxGrid::YToRow( int y )
m_minAcceptableRowHeight, m_rowBottoms, m_numRows, false);
}
int wxGrid::XToCol( int x )
int wxGrid::XToCol( int x, bool clipToMinMax )
{
return CoordToRowOrCol(x, m_defaultColWidth,
m_minAcceptableColWidth, m_colRights, m_numCols, false);
if (x < 0)
return clipToMinMax && (m_numCols > 0) ? GetColAt( 0 ) : -1;
if (!m_defaultColWidth)
m_defaultColWidth = 1;
int maxPos = x / m_defaultColWidth;
int minPos = 0;
if (m_colRights.IsEmpty())
{
if(maxPos < m_numCols)
return GetColAt( maxPos );
return clipToMinMax ? GetColAt( m_numCols - 1 ) : -1;
}
if ( maxPos >= m_numCols)
maxPos = m_numCols - 1;
else
{
if ( x >= m_colRights[GetColAt( maxPos )])
{
minPos = maxPos;
if (m_minAcceptableColWidth)
maxPos = x / m_minAcceptableColWidth;
else
maxPos = m_numCols - 1;
}
if ( maxPos >= m_numCols)
maxPos = m_numCols - 1;
}
//X is beyond the last column
if ( x >= m_colRights[GetColAt( maxPos )])
return clipToMinMax ? GetColAt( maxPos ) : -1;
//X is before the first column
if ( x < m_colRights[GetColAt( 0 )] )
return GetColAt( 0 );
//Perform a binary search
while ( maxPos - minPos > 0 )
{
wxCHECK_MSG(m_colRights[GetColAt( minPos )] <= x && x < m_colRights[GetColAt( maxPos )],
0, _T("wxGrid: internal error in XToCol"));
if (x >= m_colRights[GetColAt( maxPos - 1 )])
return GetColAt( maxPos );
else
maxPos--;
int median = minPos + (maxPos - minPos + 1) / 2;
if (x < m_colRights[GetColAt( median )])
maxPos = median;
else
minPos = median;
}
return GetColAt( maxPos );
}
// return the row number that that the y coord is near the edge of, or
@@ -8418,11 +8763,12 @@ bool wxGrid::MoveCursorLeft( bool expandSelection )
HighlightBlock( m_currentCellCoords, m_selectingKeyboard );
}
}
else if ( m_currentCellCoords.GetCol() > 0 )
else if ( GetColPos( m_currentCellCoords.GetCol() ) > 0 )
{
int row = m_currentCellCoords.GetRow();
int col = m_currentCellCoords.GetCol() - 1;
int col = GetColAt( GetColPos( m_currentCellCoords.GetCol() ) - 1 );
ClearSelection();
MakeCellVisible( row, col );
SetCurrentCell( row, col );
}
@@ -8452,11 +8798,12 @@ bool wxGrid::MoveCursorRight( bool expandSelection )
HighlightBlock( m_currentCellCoords, m_selectingKeyboard );
}
}
else if ( m_currentCellCoords.GetCol() < m_numCols - 1 )
else if ( GetColPos( m_currentCellCoords.GetCol() ) < m_numCols - 1 )
{
int row = m_currentCellCoords.GetRow();
int col = m_currentCellCoords.GetCol() + 1;
int col = GetColAt( GetColPos( m_currentCellCoords.GetCol() ) + 1 );
ClearSelection();
MakeCellVisible( row, col );
SetCurrentCell( row, col );
}
@@ -9812,7 +10159,7 @@ void wxGrid::SetColSize( int col, int width )
// should we check that it's bigger than GetColMinimalWidth(col) here?
// (VZ)
// No, because it is reasonable to assume the library user know's
// what he is doing. However whe should test against the weaker
// what he is doing. However we should test against the weaker
// constraint of minimalAcceptableWidth, as this breaks rendering
//
// This test then fixes sf.net bug #645734
@@ -9843,8 +10190,10 @@ void wxGrid::SetColSize( int col, int width )
m_colWidths[col] = w;
int i;
for ( i = col; i < m_numCols; i++ )
int colPos;
for ( colPos = GetColPos( col ); colPos < m_numCols; colPos++ )
{
i = GetColAt( colPos );
m_colRights[i] += diff;
}