Add support for freezing columns and/or rows of wxGrid

Add wxGrid::FreezeTo() method which allows to freeze the given number of
columns and/or rows at the beginning of the grid, i.e. keep them pinned
in place while the rest of the grid is scrolled.

The main wxGridWindow (m_gridWin) now corresponds to the non-frozen part
of the grid, with up to 3 new similar windows for the frozen
rows/columns and the frozen corner cells (which only exist if both rows
and columns are frozen) being additionally used.

Doing this involved adding "wxGridWindow*" parameter to many functions
that previously only worked with m_gridWin itself and addressing
additional complications, such as mouse events that can now cross
different windows.

See https://github.com/wxWidgets/wxWidgets/pull/952 for the original
version of the changes.
This commit is contained in:
lucian-rotariu
2019-07-03 23:07:30 +03:00
committed by Vadim Zeitlin
parent f61b58bba3
commit 04f7f1fd32
6 changed files with 1477 additions and 409 deletions

View File

@@ -1021,14 +1021,19 @@ public:
int GetNumberRows() const { return m_numRows; }
int GetNumberCols() const { return m_numCols; }
int GetNumberFrozenRows() const { return m_numFrozenRows; }
int GetNumberFrozenCols() const { return m_numFrozenCols; }
// ------ display update functions
//
wxArrayInt CalcRowLabelsExposed( const wxRegion& reg ) const;
wxArrayInt CalcColLabelsExposed( const wxRegion& reg ) const;
wxGridCellCoordsArray CalcCellsExposed( const wxRegion& reg ) const;
wxArrayInt CalcRowLabelsExposed( const wxRegion& reg,
wxGridWindow *gridWindow = NULL) const;
wxArrayInt CalcColLabelsExposed( const wxRegion& reg,
wxGridWindow *gridWindow = NULL) const;
wxGridCellCoordsArray CalcCellsExposed( const wxRegion& reg,
wxGridWindow *gridWindow = NULL) const;
void PrepareDCFor(wxDC &dc, wxGridWindow *gridWindow);
void ClearGrid();
bool InsertRows(int pos = 0, int numRows = 1, bool updateLabels = true)
@@ -1062,12 +1067,24 @@ public:
pos, numCols, updateLabels);
}
bool FreezeTo(int row, int col);
bool FreezeTo(const wxGridCellCoords& coords)
{
return FreezeTo(coords.GetRow(), coords.GetCol());
}
bool IsFrozen() const;
void DrawGridCellArea( wxDC& dc , const wxGridCellCoordsArray& cells );
void DrawGridSpace( wxDC& dc );
void DrawGridSpace( wxDC& dc, wxGridWindow *gridWindow );
void DrawCellBorder( wxDC& dc, const wxGridCellCoords& );
void DrawAllGridLines( wxDC& dc, const wxRegion & reg );
void DrawAllGridLines();
void DrawAllGridWindowLines( wxDC& dc, const wxRegion & reg , wxGridWindow *gridWindow);
void DrawCell( wxDC& dc, const wxGridCellCoords& );
void DrawHighlight(wxDC& dc, const wxGridCellCoordsArray& cells);
void DrawFrozenBorder( wxDC& dc, wxGridWindow *gridWindow );
void DrawLabelFrozenBorder( wxDC& dc, wxWindow *window, bool isRow );
void ScrollWindow( int dx, int dy, const wxRect *rect ) wxOVERRIDE;
void UpdateGridWindows() const;
@@ -1165,11 +1182,15 @@ public:
// grid cells and labels so you will need to convert from device
// coordinates for mouse events etc.
//
wxGridCellCoords XYToCell(int x, int y) const;
void XYToCell(int x, int y, wxGridCellCoords& coords) const
{ coords = XYToCell(x, y); }
wxGridCellCoords XYToCell(const wxPoint& pos) const
{ return XYToCell(pos.x, pos.y); }
wxGridCellCoords XYToCell(int x, int y, wxGridWindow *gridWindow = NULL) const;
void XYToCell(int x, int y,
wxGridCellCoords& coords,
wxGridWindow *gridWindow = NULL) const
{ coords = XYToCell(x, y, gridWindow); }
wxGridCellCoords XYToCell(const wxPoint& pos,
wxGridWindow *gridWindow = NULL) const
{ return XYToCell(pos.x, pos.y, gridWindow); }
// these functions return the index of the row/columns corresponding to the
// given logical position in pixels
@@ -1177,8 +1198,8 @@ public:
// if clipToMinMax is false (default, wxNOT_FOUND is returned if the
// position is outside any row/column, otherwise the first/last element is
// returned in this case
int YToRow( int y, bool clipToMinMax = false ) const;
int XToCol( int x, bool clipToMinMax = false ) const;
int YToRow( int y, bool clipToMinMax = false, wxGridWindow *gridWindow = NULL ) const;
int XToCol( int x, bool clipToMinMax = false, wxGridWindow *gridWindow = NULL ) const;
int YToEdgeOfRow( int y ) const;
int XToEdgeOfCol( int x ) const;
@@ -1187,12 +1208,32 @@ public:
wxRect CellToRect( const wxGridCellCoords& coords ) const
{ return CellToRect( coords.GetRow(), coords.GetCol() ); }
wxGridWindow* CellToGridWindow( int row, int col ) const;
wxGridWindow* CellToGridWindow( const wxGridCellCoords& coords ) const
{ return CellToGridWindow( coords.GetRow(), coords.GetCol() ); }
const wxGridCellCoords& GetGridCursorCoords() const
{ return m_currentCellCoords; }
int GetGridCursorRow() const { return m_currentCellCoords.GetRow(); }
int GetGridCursorCol() const { return m_currentCellCoords.GetCol(); }
void GetGridWindowOffset(const wxGridWindow *gridWindow, int &x, int &y) const;
wxPoint GetGridWindowOffset(const wxGridWindow *gridWindow) const;
wxGridWindow* DevicePosToGridWindow(wxPoint pos) const;
wxGridWindow* DevicePosToGridWindow(int x, int y) const;
void CalcGridWindowUnscrolledPosition(int x, int y, int *xx, int *yy,
const wxGridWindow *gridWindow) const;
wxPoint CalcGridWindowUnscrolledPosition(const wxPoint& pt,
const wxGridWindow *gridWindow) const;
void CalcGridWindowScrolledPosition(int x, int y, int *xx, int *yy,
const wxGridWindow *gridWindow) const;
wxPoint CalcGridWindowScrolledPosition(const wxPoint& pt,
const wxGridWindow *gridWindow) const;
// check to see if a cell is either wholly visible (the default arg) or
// at least partially visible in the grid window
//
@@ -1256,9 +1297,11 @@ public:
wxColour GetCellHighlightColour() const { return m_cellHighlightColour; }
int GetCellHighlightPenWidth() const { return m_cellHighlightPenWidth; }
int GetCellHighlightROPenWidth() const { return m_cellHighlightROPenWidth; }
wxColor GetGridFrozenBorderColour() const { return m_gridFrozenBorderColour; }
int GetGridFrozenBorderPenWidth() const { return m_gridFrozenBorderPenWidth; }
// this one will use wxHeaderCtrl for the column labels
void UseNativeColHeader(bool native = true);
bool UseNativeColHeader(bool native = true);
// this one will still draw them manually but using the native renderer
// instead of using the same appearance as for the row labels
@@ -1280,9 +1323,10 @@ public:
void SetColLabelValue( int col, const wxString& );
void SetCornerLabelValue( const wxString& );
void SetCellHighlightColour( const wxColour& );
void SetCellHighlightPenWidth(int width);
void SetCellHighlightROPenWidth(int width);
void SetCellHighlightPenWidth( int width );
void SetCellHighlightROPenWidth( int width );
void SetGridFrozenBorderColour( const wxColour& );
void SetGridFrozenBorderPenWidth( int width );
// interactive grid mouse operations control
// -----------------------------------------
@@ -1309,7 +1353,7 @@ public:
{ return m_canDragColSize && DoCanResizeLine(col, m_setFixedCols); }
// interactive column reordering (disabled by default)
void EnableDragColMove( bool enable = true );
bool EnableDragColMove( bool enable = true );
void DisableDragColMove() { EnableDragColMove( false ); }
bool CanDragColMove() const { return m_canDragColMove; }
@@ -1635,7 +1679,8 @@ public:
// to the client size of the grid window.
//
wxRect BlockToDeviceRect( const wxGridCellCoords & topLeft,
const wxGridCellCoords & bottomRight ) const;
const wxGridCellCoords & bottomRight,
const wxGridWindow *gridWindow = NULL) const;
// Access or update the selection fore/back colours
wxColour GetSelectionBackground() const
@@ -1671,6 +1716,9 @@ public:
// Accessors for component windows
wxWindow* GetGridWindow() const { return (wxWindow*)m_gridWin; }
wxWindow* GetFrozenCornerGridWindow()const { return (wxWindow*)m_frozenCornerGridWin; }
wxWindow* GetFrozenRowGridWindow() const { return (wxWindow*)m_frozenRowGridWin; }
wxWindow* GetFrozenColGridWindow() const { return (wxWindow*)m_frozenColGridWin; }
wxWindow* GetGridRowLabelWindow() const { return (wxWindow*)m_rowLabelWin; }
wxWindow* GetGridColLabelWindow() const { return m_colLabelWin; }
wxWindow* GetGridCornerLabelWindow() const { return (wxWindow*)m_cornerLabelWin; }
@@ -1904,13 +1952,18 @@ protected:
bool m_created;
wxGridWindow *m_gridWin;
wxGridWindow *m_frozenColGridWin;
wxGridWindow *m_frozenRowGridWin;
wxGridWindow *m_frozenCornerGridWin;
wxGridCornerLabelWindow *m_cornerLabelWin;
wxGridRowLabelWindow *m_rowLabelWin;
wxGridRowLabelWindow *m_rowFrozenLabelWin;
// the real type of the column window depends on m_useNativeHeader value:
// if it is true, its dynamic type is wxHeaderCtrl, otherwise it is
// wxGridColLabelWindow, use accessors below when the real type matters
wxWindow *m_colLabelWin;
wxWindow *m_colFrozenLabelWin;
wxGridColLabelWindow *GetColLabelWindow() const
{
@@ -1925,6 +1978,10 @@ protected:
int m_numRows;
int m_numCols;
// Number of frozen rows/columns in the beginning of the grid, 0 if none.
int m_numFrozenRows;
int m_numFrozenCols;
wxGridCellCoords m_currentCellCoords;
// the corners of the block being currently selected or wxGridNoCellCoords
@@ -2014,7 +2071,8 @@ protected:
wxColour m_cellHighlightColour;
int m_cellHighlightPenWidth;
int m_cellHighlightROPenWidth;
wxColour m_gridFrozenBorderColour;
int m_gridFrozenBorderPenWidth;
// common part of AutoSizeColumn/Row() and GetBestSize()
int SetOrCalcColumnSizes(bool calcOnly, bool setAsMin = true);
@@ -2200,6 +2258,9 @@ protected:
{ UpdateBlockBeingSelected(topLeft.GetRow(), topLeft.GetCol(),
bottomRight.GetRow(), bottomRight.GetCol()); }
virtual bool ShouldScrollToChildOnFocus(wxWindow* WXUNUSED(win)) wxOVERRIDE
{ return false; }
friend class WXDLLIMPEXP_FWD_CORE wxGridSelection;
friend class wxGridRowOperations;
friend class wxGridColumnOperations;
@@ -2218,6 +2279,10 @@ private:
// implement wxScrolledWindow method to return m_gridWin size
virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size) wxOVERRIDE;
// depending on the values of m_numFrozenRows and m_numFrozenCols, it will
// create and initialize or delete the frozen windows
void InitializeFrozenWindows();
// redraw the grid lines, should be called after changing their attributes
void RedrawGridLines();
@@ -2265,8 +2330,7 @@ private:
//
// this always returns a valid position, even if the coordinate is out of
// bounds (in which case first/last column is returned)
int XToPos(int x) const;
int XToPos(int x, wxGridWindow *gridWindow) const;
// event handlers and their helpers
// --------------------------------
@@ -2277,14 +2341,27 @@ private:
bool isFirstDrag);
// process row/column resizing drag event
void DoGridLineDrag(wxMouseEvent& event, const wxGridOperations& oper);
void DoGridLineDrag(int pos,
const wxGridOperations& oper,
wxGridWindow* gridWindow);
// process mouse drag event in the grid window, return false if starting
// dragging was vetoed by the user-defined wxEVT_GRID_CELL_BEGIN_DRAG
// handler
bool DoGridDragEvent(wxMouseEvent& event,
const wxGridCellCoords& coords,
bool isFirstDrag);
bool isFirstDrag,
wxGridWindow* gridWindow);
void DrawGridDragLine(wxPoint position,
const wxGridOperations& oper,
wxGridWindow* gridWindow);
// return the current grid windows involved in the drag process
void GetDragGridWindows(int pos,
const wxGridOperations& oper,
wxGridWindow*& firstGridWindow,
wxGridWindow*& secondGridWindow);
// process different clicks on grid cells
void DoGridCellLeftDown(wxMouseEvent& event,
@@ -2293,30 +2370,38 @@ private:
void DoGridCellLeftDClick(wxMouseEvent& event,
const wxGridCellCoords& coords,
const wxPoint& pos);
void DoGridCellLeftUp(wxMouseEvent& event, const wxGridCellCoords& coords);
void DoGridCellLeftUp(wxMouseEvent& event,
const wxGridCellCoords& coords,
wxGridWindow* gridWindow);
// process movement (but not dragging) event in the grid cell area
void DoGridMouseMoveEvent(wxMouseEvent& event,
const wxGridCellCoords& coords,
const wxPoint& pos);
const wxPoint& pos,
wxGridWindow* gridWindow);
// process mouse events in the grid window
void ProcessGridCellMouseEvent(wxMouseEvent& event);
void ProcessGridCellMouseEvent(wxMouseEvent& event, wxGridWindow* gridWindow);
// process mouse events in the row/column labels/corner windows
void ProcessRowLabelMouseEvent(wxMouseEvent& event);
void ProcessColLabelMouseEvent(wxMouseEvent& event);
void ProcessRowLabelMouseEvent(wxMouseEvent& event,
wxGridRowLabelWindow* rowLabelWin);
void ProcessColLabelMouseEvent(wxMouseEvent& event,
wxGridColLabelWindow* colLabelWin);
void ProcessCornerLabelMouseEvent(wxMouseEvent& event);
void DoColHeaderClick(int col);
void DoStartResizeCol(int col);
void DoUpdateResizeCol(int x);
void DoUpdateResizeColWidth(int w);
void DoStartMoveCol(int col);
void DoEndDragResizeRow(const wxMouseEvent& event);
void DoEndDragResizeCol(const wxMouseEvent& event);
void DoEndDragResizeRow(const wxMouseEvent& event, wxGridWindow *gridWindow);
void DoEndDragResizeCol(const wxMouseEvent& event, wxGridWindow *gridWindow);
void DoEndDragResizeCol(const wxMouseEvent& event)
{
DoEndDragResizeCol(event, m_gridWin);
}
void DoEndMoveCol(int pos);
// process a TAB keypress
@@ -2324,11 +2409,13 @@ private:
// common implementations of methods defined for both rows and columns
void DeselectLine(int line, const wxGridOperations& oper);
bool DoEndDragResizeLine(const wxGridOperations& oper);
bool DoEndDragResizeLine(const wxGridOperations& oper, wxGridWindow *gridWindow);
int PosToLinePos(int pos, bool clipToMinMax,
const wxGridOperations& oper) const;
const wxGridOperations& oper,
wxGridWindow *gridWindow) const;
int PosToLine(int pos, bool clipToMinMax,
const wxGridOperations& oper) const;
const wxGridOperations& oper,
wxGridWindow *gridWindow) const;
int PosToEdgeOfLine(int pos, const wxGridOperations& oper) const;
bool DoMoveCursor(bool expandSelection,

View File

@@ -158,9 +158,9 @@ protected:
return m_columns[idx];
}
private:
wxGrid *GetOwner() const { return static_cast<wxGrid *>(GetParent()); }
private:
static wxMouseEvent GetDummyMouseEvent()
{
// make up a dummy event for the grid event to use -- unfortunately we
@@ -327,6 +327,7 @@ public:
{
}
virtual bool IsFrozen() const { return false; }
private:
void OnPaint( wxPaintEvent& event );
@@ -338,6 +339,18 @@ private:
};
class wxGridRowFrozenLabelWindow : public wxGridRowLabelWindow
{
public:
wxGridRowFrozenLabelWindow(wxGrid *parent)
: wxGridRowLabelWindow(parent)
{
}
virtual bool IsFrozen() const { return true; }
};
class WXDLLIMPEXP_ADV wxGridColLabelWindow : public wxGridSubwindow
{
public:
@@ -346,6 +359,7 @@ public:
{
}
virtual bool IsFrozen() const { return false; }
private:
void OnPaint( wxPaintEvent& event );
@@ -357,6 +371,18 @@ private:
};
class wxGridColFrozenLabelWindow : public wxGridColLabelWindow
{
public:
wxGridColFrozenLabelWindow(wxGrid *parent)
: wxGridColLabelWindow(parent)
{
}
virtual bool IsFrozen() const { return true; }
};
class WXDLLIMPEXP_ADV wxGridCornerLabelWindow : public wxGridSubwindow
{
public:
@@ -377,10 +403,21 @@ private:
class WXDLLIMPEXP_ADV wxGridWindow : public wxGridSubwindow
{
public:
wxGridWindow(wxGrid *parent)
// grid window variants for scrolling possibilities
enum wxGridWindowType
{
wxGridWindowNormal = 0,
wxGridWindowFrozenCol = 1,
wxGridWindowFrozenRow = 2,
wxGridWindowFrozenCorner = wxGridWindowFrozenCol |
wxGridWindowFrozenRow
};
wxGridWindow(wxGrid *parent, wxGridWindowType type)
: wxGridSubwindow(parent,
wxWANTS_CHARS | wxCLIP_CHILDREN,
"GridWindow")
"GridWindow"),
m_type(type)
{
}
@@ -389,7 +426,11 @@ public:
virtual bool AcceptsFocus() const wxOVERRIDE { return true; }
wxGridWindowType GetType() const { return m_type; }
private:
const wxGridWindowType m_type;
void OnPaint( wxPaintEvent &event );
void OnMouseWheel( wxMouseEvent& event );
void OnMouseEvent( wxMouseEvent& event );
@@ -467,8 +508,14 @@ public:
// 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 total number of rows or columns.
virtual int GetTotalNumberOfLines(const wxGrid *grid) const = 0;
// Return the current number of rows or columns of a grid window.
virtual int GetNumberOfLines(const wxGrid *grid, wxGridWindow *gridWindow) const = 0;
// Return the first line for this grid type.
virtual int GetFirstLine(const wxGrid *grid, wxGridWindow *gridWindow) const = 0;
// Return the selection mode which allows selecting rows or columns.
virtual wxGrid::wxGridSelectionModes GetSelectionMode() const = 0;
@@ -515,7 +562,7 @@ public:
// 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;
PosToLine(const wxGrid *grid, int pos, wxGridWindow *gridWindow, 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;
@@ -565,6 +612,8 @@ public:
// Get the width or height of the row or column label window
virtual int GetHeaderWindowSize(wxGrid *grid) const = 0;
// Get the row or column frozen grid window
virtual wxGridWindow *GetFrozenGrid(wxGrid* grid) const = 0;
// This class is never used polymorphically but give it a virtual dtor
// anyhow to suppress g++ complaints about it
@@ -576,9 +625,13 @@ class wxGridRowOperations : public wxGridOperations
public:
virtual wxGridOperations& Dual() const wxOVERRIDE;
virtual int GetNumberOfLines(const wxGrid *grid) const wxOVERRIDE
virtual int GetTotalNumberOfLines(const wxGrid *grid) const wxOVERRIDE
{ return grid->GetNumberRows(); }
virtual int GetNumberOfLines(const wxGrid *grid, wxGridWindow *gridWindow) const wxOVERRIDE;
virtual int GetFirstLine(const wxGrid *grid, wxGridWindow *gridWindow) const wxOVERRIDE;
virtual wxGrid::wxGridSelectionModes GetSelectionMode() const wxOVERRIDE
{ return wxGrid::wxGridSelectRows; }
@@ -602,8 +655,8 @@ public:
virtual void DrawParallelLine(wxDC& dc, int start, int end, int pos) const wxOVERRIDE
{ dc.DrawLine(start, pos, end, pos); }
virtual int PosToLine(const wxGrid *grid, int pos, bool clip = false) const wxOVERRIDE
{ return grid->YToRow(pos, clip); }
virtual int PosToLine(const wxGrid *grid, int pos, wxGridWindow *gridWindow , bool clip = false) const wxOVERRIDE
{ return grid->YToRow(pos, clip, gridWindow); }
virtual int GetLineStartPos(const wxGrid *grid, int line) const wxOVERRIDE
{ return grid->GetRowTop(line); }
virtual int GetLineEndPos(const wxGrid *grid, int line) const wxOVERRIDE
@@ -635,6 +688,9 @@ public:
{ return grid->GetGridRowLabelWindow(); }
virtual int GetHeaderWindowSize(wxGrid *grid) const wxOVERRIDE
{ return grid->GetRowLabelSize(); }
virtual wxGridWindow *GetFrozenGrid(wxGrid* grid) const wxOVERRIDE
{ return (wxGridWindow*)grid->GetFrozenRowGridWindow(); }
};
class wxGridColumnOperations : public wxGridOperations
@@ -642,9 +698,13 @@ class wxGridColumnOperations : public wxGridOperations
public:
virtual wxGridOperations& Dual() const wxOVERRIDE;
virtual int GetNumberOfLines(const wxGrid *grid) const wxOVERRIDE
virtual int GetTotalNumberOfLines(const wxGrid *grid) const wxOVERRIDE
{ return grid->GetNumberCols(); }
virtual int GetNumberOfLines(const wxGrid *grid, wxGridWindow *gridWindow) const wxOVERRIDE;
virtual int GetFirstLine(const wxGrid *grid, wxGridWindow *gridWindow) const wxOVERRIDE;
virtual wxGrid::wxGridSelectionModes GetSelectionMode() const wxOVERRIDE
{ return wxGrid::wxGridSelectColumns; }
@@ -668,8 +728,8 @@ public:
virtual void DrawParallelLine(wxDC& dc, int start, int end, int pos) const wxOVERRIDE
{ dc.DrawLine(pos, start, pos, end); }
virtual int PosToLine(const wxGrid *grid, int pos, bool clip = false) const wxOVERRIDE
{ return grid->XToCol(pos, clip); }
virtual int PosToLine(const wxGrid *grid, int pos, wxGridWindow *gridWindow, bool clip = false) const wxOVERRIDE
{ return grid->XToCol(pos, clip, gridWindow); }
virtual int GetLineStartPos(const wxGrid *grid, int line) const wxOVERRIDE
{ return grid->GetColLeft(line); }
virtual int GetLineEndPos(const wxGrid *grid, int line) const wxOVERRIDE
@@ -704,6 +764,9 @@ public:
{ return grid->GetGridColLabelWindow(); }
virtual int GetHeaderWindowSize(wxGrid *grid) const wxOVERRIDE
{ return grid->GetColLabelSize(); }
virtual wxGridWindow *GetFrozenGrid(wxGrid* grid) const wxOVERRIDE
{ return (wxGridWindow*)grid->GetFrozenColGridWindow(); }
};
// This class abstracts the difference between operations going forward
@@ -828,7 +891,7 @@ public:
virtual int MoveByPixelDistance(int line, int distance) const wxOVERRIDE
{
int pos = m_oper.GetLineStartPos(m_grid, line);
return m_oper.PosToLine(m_grid, pos - distance + 1, true);
return m_oper.PosToLine(m_grid, pos - distance + 1, NULL, true);
}
};
@@ -839,7 +902,7 @@ class wxGridForwardOperations : public wxGridDirectionOperations
public:
wxGridForwardOperations(wxGrid *grid, const wxGridOperations& oper)
: wxGridDirectionOperations(grid, oper),
m_numLines(oper.GetNumberOfLines(grid))
m_numLines(oper.GetTotalNumberOfLines(grid))
{
}
@@ -878,7 +941,7 @@ public:
virtual int MoveByPixelDistance(int line, int distance) const wxOVERRIDE
{
int pos = m_oper.GetLineStartPos(m_grid, line);
return m_oper.PosToLine(m_grid, pos + distance, true);
return m_oper.PosToLine(m_grid, pos + distance, NULL, true);
}
private: