wxWidgets/include/wx/generic/private/grid.h
Vadim Zeitlin 4a07d70634 Send right and double click events in wxGrid when using native header.
Previously only simple left click event was sent in this case, now also
generate right and double click ones.

Closes #12156.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64937 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2010-07-13 12:38:00 +00:00

866 lines
28 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: wx/generic/private/grid.h
// Purpose: Private wxGrid structures
// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
// Modified by: Santiago Palacios
// Created: 1/08/1999
// RCS-ID: $Id$
// Copyright: (c) Michael Bedward
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_GENERIC_GRID_PRIVATE_H_
#define _WX_GENERIC_GRID_PRIVATE_H_
#include "wx/defs.h"
#if wxUSE_GRID
// ----------------------------------------------------------------------------
// array classes
// ----------------------------------------------------------------------------
WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridCellAttr *, wxArrayAttrs,
class WXDLLIMPEXP_ADV);
struct wxGridCellWithAttr
{
wxGridCellWithAttr(int row, int col, wxGridCellAttr *attr_)
: coords(row, col), attr(attr_)
{
wxASSERT( attr );
}
wxGridCellWithAttr(const wxGridCellWithAttr& other)
: coords(other.coords),
attr(other.attr)
{
attr->IncRef();
}
wxGridCellWithAttr& operator=(const wxGridCellWithAttr& other)
{
coords = other.coords;
if (attr != other.attr)
{
attr->DecRef();
attr = other.attr;
attr->IncRef();
}
return *this;
}
void ChangeAttr(wxGridCellAttr* new_attr)
{
if (attr != new_attr)
{
// "Delete" (i.e. DecRef) the old attribute.
attr->DecRef();
attr = new_attr;
// Take ownership of the new attribute, i.e. no IncRef.
}
}
~wxGridCellWithAttr()
{
attr->DecRef();
}
wxGridCellCoords coords;
wxGridCellAttr *attr;
};
WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr, wxGridCellWithAttrArray,
class WXDLLIMPEXP_ADV);
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// header column providing access to the column information stored in wxGrid
// via wxHeaderColumn interface
class wxGridHeaderColumn : public wxHeaderColumn
{
public:
wxGridHeaderColumn(wxGrid *grid, int col)
: m_grid(grid),
m_col(col)
{
}
virtual wxString GetTitle() const { return m_grid->GetColLabelValue(m_col); }
virtual wxBitmap GetBitmap() const { return wxNullBitmap; }
virtual int GetWidth() const { return m_grid->GetColSize(m_col); }
virtual int GetMinWidth() const { return 0; }
virtual wxAlignment GetAlignment() const
{
int horz,
vert;
m_grid->GetColLabelAlignment(&horz, &vert);
return static_cast<wxAlignment>(horz);
}
virtual int GetFlags() const
{
// 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(m_col) )
flags |= wxCOL_RESIZABLE;
if ( m_grid->CanDragColMove() )
flags |= wxCOL_REORDERABLE;
if ( GetWidth() == 0 )
flags |= wxCOL_HIDDEN;
return flags;
}
virtual bool IsSortKey() const
{
return m_grid->IsSortingBy(m_col);
}
virtual bool IsSortOrderAscending() const
{
return m_grid->IsSortOrderAscending();
}
private:
// these really should be const but are not because the column needs to be
// assignable to be used in a wxVector (in STL build, in non-STL build we
// avoid the need for this)
wxGrid *m_grid;
int m_col;
};
// header control retreiving column information from the grid
class wxGridHeaderCtrl : public wxHeaderCtrl
{
public:
wxGridHeaderCtrl(wxGrid *owner)
: wxHeaderCtrl(owner,
wxID_ANY,
wxDefaultPosition,
wxDefaultSize,
wxHD_ALLOW_HIDE |
(owner->CanDragColMove() ? wxHD_ALLOW_REORDER : 0))
{
}
protected:
virtual const wxHeaderColumn& GetColumn(unsigned int idx) const
{
return m_columns[idx];
}
private:
wxGrid *GetOwner() const { return static_cast<wxGrid *>(GetParent()); }
static wxMouseEvent GetDummyMouseEvent()
{
// make up a dummy event for the grid event to use -- unfortunately we
// can't do anything else here
wxMouseEvent e;
e.SetState(wxGetMouseState());
return e;
}
// override the base class method to update our m_columns array
virtual void OnColumnCountChanging(unsigned int count)
{
const unsigned countOld = m_columns.size();
if ( count < countOld )
{
// just discard the columns which don't exist any more (notice that
// we can't use resize() here as it would require the vector
// value_type, i.e. wxGridHeaderColumn to be default constructible,
// which it is not)
m_columns.erase(m_columns.begin() + count, m_columns.end());
}
else // new columns added
{
// add columns for the new elements
for ( unsigned n = countOld; n < count; n++ )
m_columns.push_back(wxGridHeaderColumn(GetOwner(), n));
}
}
// override to implement column auto sizing
virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
{
// TODO: currently grid doesn't support computing the column best width
// from its contents so we just use the best label width as is
GetOwner()->SetColSize(idx, widthTitle);
return true;
}
// overridden to react to the actions using the columns popup menu
virtual void UpdateColumnVisibility(unsigned int idx, bool show)
{
GetOwner()->SetColSize(idx, show ? wxGRID_AUTOSIZE : 0);
// as this is done by the user we should notify the main program about
// it
GetOwner()->SendGridSizeEvent(wxEVT_GRID_COL_SIZE, -1, idx,
GetDummyMouseEvent());
}
// overridden to react to the columns order changes in the customization
// dialog
virtual void UpdateColumnsOrder(const wxArrayInt& order)
{
GetOwner()->SetColumnsOrder(order);
}
// event handlers forwarding wxHeaderCtrl events to wxGrid
void OnClick(wxHeaderCtrlEvent& event)
{
GetOwner()->SendEvent(wxEVT_GRID_LABEL_LEFT_CLICK,
-1, event.GetColumn(),
GetDummyMouseEvent());
GetOwner()->DoColHeaderClick(event.GetColumn());
}
void OnDoubleClick(wxHeaderCtrlEvent& event)
{
if ( !GetOwner()->SendEvent(wxEVT_GRID_LABEL_LEFT_DCLICK,
-1, event.GetColumn(),
GetDummyMouseEvent()) )
{
event.Skip();
}
}
void OnRightClick(wxHeaderCtrlEvent& event)
{
if ( !GetOwner()->SendEvent(wxEVT_GRID_LABEL_RIGHT_CLICK,
-1, event.GetColumn(),
GetDummyMouseEvent()) )
{
event.Skip();
}
}
void OnBeginResize(wxHeaderCtrlEvent& event)
{
GetOwner()->DoStartResizeCol(event.GetColumn());
event.Skip();
}
void OnResizing(wxHeaderCtrlEvent& event)
{
GetOwner()->DoUpdateResizeColWidth(event.GetWidth());
}
void OnEndResize(wxHeaderCtrlEvent& event)
{
// we again need to pass a mouse event to be used for the grid event
// generation but we don't have it here so use a dummy one as in
// UpdateColumnVisibility()
wxMouseEvent e;
e.SetState(wxGetMouseState());
GetOwner()->DoEndDragResizeCol(e);
event.Skip();
}
void OnBeginReorder(wxHeaderCtrlEvent& event)
{
GetOwner()->DoStartMoveCol(event.GetColumn());
}
void OnEndReorder(wxHeaderCtrlEvent& event)
{
GetOwner()->DoEndMoveCol(event.GetNewOrder());
}
wxVector<wxGridHeaderColumn> m_columns;
DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(wxGridHeaderCtrl);
};
// common base class for various grid subwindows
class WXDLLIMPEXP_ADV wxGridSubwindow : public wxWindow
{
public:
wxGridSubwindow(wxGrid *owner,
int additionalStyle = 0,
const wxString& name = wxPanelNameStr)
: wxWindow(owner, wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxBORDER_NONE | additionalStyle,
name)
{
m_owner = owner;
}
virtual bool AcceptsFocus() const { return false; }
wxGrid *GetOwner() { return m_owner; }
protected:
void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
wxGrid *m_owner;
DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(wxGridSubwindow);
};
class WXDLLIMPEXP_ADV wxGridRowLabelWindow : public wxGridSubwindow
{
public:
wxGridRowLabelWindow(wxGrid *parent)
: wxGridSubwindow(parent)
{
}
private:
void OnPaint( wxPaintEvent& event );
void OnMouseEvent( wxMouseEvent& event );
void OnMouseWheel( wxMouseEvent& event );
DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(wxGridRowLabelWindow);
};
class WXDLLIMPEXP_ADV wxGridColLabelWindow : public wxGridSubwindow
{
public:
wxGridColLabelWindow(wxGrid *parent)
: wxGridSubwindow(parent)
{
}
private:
void OnPaint( wxPaintEvent& event );
void OnMouseEvent( wxMouseEvent& event );
void OnMouseWheel( wxMouseEvent& event );
DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(wxGridColLabelWindow);
};
class WXDLLIMPEXP_ADV wxGridCornerLabelWindow : public wxGridSubwindow
{
public:
wxGridCornerLabelWindow(wxGrid *parent)
: wxGridSubwindow(parent)
{
}
private:
void OnMouseEvent( wxMouseEvent& event );
void OnMouseWheel( wxMouseEvent& event );
void OnPaint( wxPaintEvent& event );
DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow);
};
class WXDLLIMPEXP_ADV wxGridWindow : public wxGridSubwindow
{
public:
wxGridWindow(wxGrid *parent)
: wxGridSubwindow(parent,
wxWANTS_CHARS | wxCLIP_CHILDREN,
"GridWindow")
{
}
virtual void ScrollWindow( int dx, int dy, const wxRect *rect );
virtual bool AcceptsFocus() const { return true; }
private:
void OnPaint( wxPaintEvent &event );
void OnMouseWheel( wxMouseEvent& event );
void OnMouseEvent( wxMouseEvent& event );
void OnKeyDown( wxKeyEvent& );
void OnKeyUp( wxKeyEvent& );
void OnChar( wxKeyEvent& );
void OnEraseBackground( wxEraseEvent& );
void OnFocus( wxFocusEvent& );
DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(wxGridWindow);
};
// ----------------------------------------------------------------------------
// the internal data representation used by wxGridCellAttrProvider
// ----------------------------------------------------------------------------
// this class stores attributes set for cells
class WXDLLIMPEXP_ADV wxGridCellAttrData
{
public:
void SetAttr(wxGridCellAttr *attr, int row, int col);
wxGridCellAttr *GetAttr(int row, int col) const;
void UpdateAttrRows( size_t pos, int numRows );
void UpdateAttrCols( size_t pos, int numCols );
private:
// searches for the attr for given cell, returns wxNOT_FOUND if not found
int FindIndex(int row, int col) const;
wxGridCellWithAttrArray m_attrs;
};
// this class stores attributes set for rows or columns
class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
{
public:
// empty ctor to suppress warnings
wxGridRowOrColAttrData() {}
~wxGridRowOrColAttrData();
void SetAttr(wxGridCellAttr *attr, int rowOrCol);
wxGridCellAttr *GetAttr(int rowOrCol) const;
void UpdateAttrRowsOrCols( size_t pos, int numRowsOrCols );
private:
wxArrayInt m_rowsOrCols;
wxArrayAttrs m_attrs;
};
// NB: this is just a wrapper around 3 objects: one which stores cell
// attributes, and 2 others for row/col ones
class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
{
public:
wxGridCellAttrData m_cellAttrs;
wxGridRowOrColAttrData m_rowAttrs,
m_colAttrs;
};
// ----------------------------------------------------------------------------
// operations classes abstracting the difference between operating on rows and
// columns
// ----------------------------------------------------------------------------
// This class allows to write a function only once because by using its methods
// it will apply to both columns and rows.
//
// This is an abstract interface definition, the two concrete implementations
// below should be used when working with rows and columns respectively.
class wxGridOperations
{
public:
// Returns the operations in the other direction, i.e. wxGridRowOperations
// if this object is a wxGridColumnOperations and vice versa.
virtual wxGridOperations& Dual() const = 0;
// Return the number of rows or columns.
virtual int GetNumberOfLines(const wxGrid *grid) const = 0;
// Return the selection mode which allows selecting rows or columns.
virtual wxGrid::wxGridSelectionModes GetSelectionMode() const = 0;
// Make a wxGridCellCoords from the given components: thisDir is row or
// column and otherDir is column or row
virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const = 0;
// Calculate the scrolled position of the given abscissa or ordinate.
virtual int CalcScrolledPosition(wxGrid *grid, int pos) const = 0;
// Selects the horizontal or vertical component from the given object.
virtual int Select(const wxGridCellCoords& coords) const = 0;
virtual int Select(const wxPoint& pt) const = 0;
virtual int Select(const wxSize& sz) const = 0;
virtual int Select(const wxRect& r) const = 0;
virtual int& Select(wxRect& r) const = 0;
// Returns width or height of the rectangle
virtual int& SelectSize(wxRect& r) const = 0;
// Make a wxSize such that Select() applied to it returns first component
virtual wxSize MakeSize(int first, int second) const = 0;
// Sets the row or column component of the given cell coordinates
virtual void Set(wxGridCellCoords& coords, int line) const = 0;
// Draws a line parallel to the row or column, i.e. horizontal or vertical:
// pos is the horizontal or vertical position of the line and start and end
// are the coordinates of the line extremities in the other direction
virtual void
DrawParallelLine(wxDC& dc, int start, int end, int pos) const = 0;
// Draw a horizontal or vertical line across the given rectangle
// (this is implemented in terms of above and uses Select() to extract
// start and end from the given rectangle)
void DrawParallelLineInRect(wxDC& dc, const wxRect& rect, int pos) const
{
const int posStart = Select(rect.GetPosition());
DrawParallelLine(dc, posStart, posStart + Select(rect.GetSize()), pos);
}
// Return the index of the row or column at the given pixel coordinate.
virtual int
PosToLine(const wxGrid *grid, int pos, bool clip = false) const = 0;
// Get the top/left position, in pixels, of the given row or column
virtual int GetLineStartPos(const wxGrid *grid, int line) const = 0;
// Get the bottom/right position, in pixels, of the given row or column
virtual int GetLineEndPos(const wxGrid *grid, int line) const = 0;
// Get the height/width of the given row/column
virtual int GetLineSize(const wxGrid *grid, int line) const = 0;
// Get wxGrid::m_rowBottoms/m_colRights array
virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const = 0;
// Get default height row height or column width
virtual int GetDefaultLineSize(const wxGrid *grid) const = 0;
// Return the minimal acceptable row height or column width
virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const = 0;
// Return the minimal row height or column width
virtual int GetMinimalLineSize(const wxGrid *grid, int line) const = 0;
// Set the row height or column width
virtual void SetLineSize(wxGrid *grid, int line, int size) const = 0;
// Set the row default height or column default width
virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const = 0;
// Return the index of the line at the given position
//
// NB: currently this is always identity for the rows as reordering is only
// implemented for the lines
virtual int GetLineAt(const wxGrid *grid, int line) const = 0;
// Get the row or column label window
virtual wxWindow *GetHeaderWindow(wxGrid *grid) const = 0;
// Get the width or height of the row or column label window
virtual int GetHeaderWindowSize(wxGrid *grid) const = 0;
// This class is never used polymorphically but give it a virtual dtor
// anyhow to suppress g++ complaints about it
virtual ~wxGridOperations() { }
};
class wxGridRowOperations : public wxGridOperations
{
public:
virtual wxGridOperations& Dual() const;
virtual int GetNumberOfLines(const wxGrid *grid) const
{ return grid->GetNumberRows(); }
virtual wxGrid::wxGridSelectionModes GetSelectionMode() const
{ return wxGrid::wxGridSelectRows; }
virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const
{ return wxGridCellCoords(thisDir, otherDir); }
virtual int CalcScrolledPosition(wxGrid *grid, int pos) const
{ return grid->CalcScrolledPosition(wxPoint(pos, 0)).x; }
virtual int Select(const wxGridCellCoords& c) const { return c.GetRow(); }
virtual int Select(const wxPoint& pt) const { return pt.x; }
virtual int Select(const wxSize& sz) const { return sz.x; }
virtual int Select(const wxRect& r) const { return r.x; }
virtual int& Select(wxRect& r) const { return r.x; }
virtual int& SelectSize(wxRect& r) const { return r.width; }
virtual wxSize MakeSize(int first, int second) const
{ return wxSize(first, second); }
virtual void Set(wxGridCellCoords& coords, int line) const
{ coords.SetRow(line); }
virtual void DrawParallelLine(wxDC& dc, int start, int end, int pos) const
{ dc.DrawLine(start, pos, end, pos); }
virtual int PosToLine(const wxGrid *grid, int pos, bool clip = false) const
{ return grid->YToRow(pos, clip); }
virtual int GetLineStartPos(const wxGrid *grid, int line) const
{ return grid->GetRowTop(line); }
virtual int GetLineEndPos(const wxGrid *grid, int line) const
{ return grid->GetRowBottom(line); }
virtual int GetLineSize(const wxGrid *grid, int line) const
{ return grid->GetRowHeight(line); }
virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const
{ return grid->m_rowBottoms; }
virtual int GetDefaultLineSize(const wxGrid *grid) const
{ return grid->GetDefaultRowSize(); }
virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const
{ return grid->GetRowMinimalAcceptableHeight(); }
virtual int GetMinimalLineSize(const wxGrid *grid, int line) const
{ return grid->GetRowMinimalHeight(line); }
virtual void SetLineSize(wxGrid *grid, int line, int size) const
{ grid->SetRowSize(line, size); }
virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const
{ grid->SetDefaultRowSize(size, resizeExisting); }
virtual int GetLineAt(const wxGrid * WXUNUSED(grid), int line) const
{ return line; } // TODO: implement row reordering
virtual wxWindow *GetHeaderWindow(wxGrid *grid) const
{ return grid->GetGridRowLabelWindow(); }
virtual int GetHeaderWindowSize(wxGrid *grid) const
{ return grid->GetRowLabelSize(); }
};
class wxGridColumnOperations : public wxGridOperations
{
public:
virtual wxGridOperations& Dual() const;
virtual int GetNumberOfLines(const wxGrid *grid) const
{ return grid->GetNumberCols(); }
virtual wxGrid::wxGridSelectionModes GetSelectionMode() const
{ return wxGrid::wxGridSelectColumns; }
virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const
{ return wxGridCellCoords(otherDir, thisDir); }
virtual int CalcScrolledPosition(wxGrid *grid, int pos) const
{ return grid->CalcScrolledPosition(wxPoint(0, pos)).y; }
virtual int Select(const wxGridCellCoords& c) const { return c.GetCol(); }
virtual int Select(const wxPoint& pt) const { return pt.y; }
virtual int Select(const wxSize& sz) const { return sz.y; }
virtual int Select(const wxRect& r) const { return r.y; }
virtual int& Select(wxRect& r) const { return r.y; }
virtual int& SelectSize(wxRect& r) const { return r.height; }
virtual wxSize MakeSize(int first, int second) const
{ return wxSize(second, first); }
virtual void Set(wxGridCellCoords& coords, int line) const
{ coords.SetCol(line); }
virtual void DrawParallelLine(wxDC& dc, int start, int end, int pos) const
{ dc.DrawLine(pos, start, pos, end); }
virtual int PosToLine(const wxGrid *grid, int pos, bool clip = false) const
{ return grid->XToCol(pos, clip); }
virtual int GetLineStartPos(const wxGrid *grid, int line) const
{ return grid->GetColLeft(line); }
virtual int GetLineEndPos(const wxGrid *grid, int line) const
{ return grid->GetColRight(line); }
virtual int GetLineSize(const wxGrid *grid, int line) const
{ return grid->GetColWidth(line); }
virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const
{ return grid->m_colRights; }
virtual int GetDefaultLineSize(const wxGrid *grid) const
{ return grid->GetDefaultColSize(); }
virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const
{ return grid->GetColMinimalAcceptableWidth(); }
virtual int GetMinimalLineSize(const wxGrid *grid, int line) const
{ return grid->GetColMinimalWidth(line); }
virtual void SetLineSize(wxGrid *grid, int line, int size) const
{ grid->SetColSize(line, size); }
virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const
{ grid->SetDefaultColSize(size, resizeExisting); }
virtual int GetLineAt(const wxGrid *grid, int line) const
{ return grid->GetColAt(line); }
virtual wxWindow *GetHeaderWindow(wxGrid *grid) const
{ return grid->GetGridColLabelWindow(); }
virtual int GetHeaderWindowSize(wxGrid *grid) const
{ return grid->GetColLabelSize(); }
};
// This class abstracts the difference between operations going forward
// (down/right) and backward (up/left) and allows to use the same code for
// functions which differ only in the direction of grid traversal
//
// Like wxGridOperations it's an ABC with two concrete subclasses below. Unlike
// it, this is a normal object and not just a function dispatch table and has a
// non-default ctor.
//
// Note: the explanation of this discrepancy is the existence of (very useful)
// Dual() method in wxGridOperations which forces us to make wxGridOperations a
// function dispatcher only.
class wxGridDirectionOperations
{
public:
// The oper parameter to ctor selects whether we work with rows or columns
wxGridDirectionOperations(wxGrid *grid, const wxGridOperations& oper)
: m_grid(grid),
m_oper(oper)
{
}
// Check if the component of this point in our direction is at the
// boundary, i.e. is the first/last row/column
virtual bool IsAtBoundary(const wxGridCellCoords& coords) const = 0;
// Increment the component of this point in our direction
virtual void Advance(wxGridCellCoords& coords) const = 0;
// Find the line at the given distance, in pixels, away from this one
// (this uses clipping, i.e. anything after the last line is counted as the
// last one and anything before the first one as 0)
virtual int MoveByPixelDistance(int line, int distance) const = 0;
// This class is never used polymorphically but give it a virtual dtor
// anyhow to suppress g++ complaints about it
virtual ~wxGridDirectionOperations() { }
protected:
wxGrid * const m_grid;
const wxGridOperations& m_oper;
};
class wxGridBackwardOperations : public wxGridDirectionOperations
{
public:
wxGridBackwardOperations(wxGrid *grid, const wxGridOperations& oper)
: wxGridDirectionOperations(grid, oper)
{
}
virtual bool IsAtBoundary(const wxGridCellCoords& coords) const
{
wxASSERT_MSG( m_oper.Select(coords) >= 0, "invalid row/column" );
return m_oper.Select(coords) == 0;
}
virtual void Advance(wxGridCellCoords& coords) const
{
wxASSERT( !IsAtBoundary(coords) );
m_oper.Set(coords, m_oper.Select(coords) - 1);
}
virtual int MoveByPixelDistance(int line, int distance) const
{
int pos = m_oper.GetLineStartPos(m_grid, line);
return m_oper.PosToLine(m_grid, pos - distance + 1, true);
}
};
class wxGridForwardOperations : public wxGridDirectionOperations
{
public:
wxGridForwardOperations(wxGrid *grid, const wxGridOperations& oper)
: wxGridDirectionOperations(grid, oper),
m_numLines(oper.GetNumberOfLines(grid))
{
}
virtual bool IsAtBoundary(const wxGridCellCoords& coords) const
{
wxASSERT_MSG( m_oper.Select(coords) < m_numLines, "invalid row/column" );
return m_oper.Select(coords) == m_numLines - 1;
}
virtual void Advance(wxGridCellCoords& coords) const
{
wxASSERT( !IsAtBoundary(coords) );
m_oper.Set(coords, m_oper.Select(coords) + 1);
}
virtual int MoveByPixelDistance(int line, int distance) const
{
int pos = m_oper.GetLineStartPos(m_grid, line);
return m_oper.PosToLine(m_grid, pos + distance, true);
}
private:
const int m_numLines;
};
// ----------------------------------------------------------------------------
// private helpers
// ----------------------------------------------------------------------------
namespace
{
// ensure that first is less or equal to second, swapping the values if
// necessary
void EnsureFirstLessThanSecond(int& first, int& second)
{
if ( first > second )
wxSwap(first, second);
}
} // anonymous namespace
// ----------------------------------------------------------------------------
// data structures used for the data type registry
// ----------------------------------------------------------------------------
struct wxGridDataTypeInfo
{
wxGridDataTypeInfo(const wxString& typeName,
wxGridCellRenderer* renderer,
wxGridCellEditor* editor)
: m_typeName(typeName), m_renderer(renderer), m_editor(editor)
{}
~wxGridDataTypeInfo()
{
wxSafeDecRef(m_renderer);
wxSafeDecRef(m_editor);
}
wxString m_typeName;
wxGridCellRenderer* m_renderer;
wxGridCellEditor* m_editor;
wxDECLARE_NO_COPY_CLASS(wxGridDataTypeInfo);
};
WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo*, wxGridDataTypeInfoArray,
class WXDLLIMPEXP_ADV);
class WXDLLIMPEXP_ADV wxGridTypeRegistry
{
public:
wxGridTypeRegistry() {}
~wxGridTypeRegistry();
void RegisterDataType(const wxString& typeName,
wxGridCellRenderer* renderer,
wxGridCellEditor* editor);
// find one of already registered data types
int FindRegisteredDataType(const wxString& typeName);
// try to FindRegisteredDataType(), if this fails and typeName is one of
// standard typenames, register it and return its index
int FindDataType(const wxString& typeName);
// try to FindDataType(), if it fails see if it is not one of already
// registered data types with some params in which case clone the
// registered data type and set params for it
int FindOrCloneDataType(const wxString& typeName);
wxGridCellRenderer* GetRenderer(int index);
wxGridCellEditor* GetEditor(int index);
private:
wxGridDataTypeInfoArray m_typeinfo;
};
#endif // wxUSE_GRID
#endif // _WX_GENERIC_GRID_PRIVATE_H_