1 ///////////////////////////////////////////////////////////////////////////// 2 // Name: wx/generic/private/grid.h 3 // Purpose: Private wxGrid structures 4 // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) 5 // Modified by: Santiago Palacios 6 // Created: 1/08/1999 7 // Copyright: (c) Michael Bedward 8 // Licence: wxWindows licence 9 ///////////////////////////////////////////////////////////////////////////// 10 11 #ifndef _WX_GENERIC_GRID_PRIVATE_H_ 12 #define _WX_GENERIC_GRID_PRIVATE_H_ 13 14 #include "wx/defs.h" 15 16 #if wxUSE_GRID 17 18 #include "wx/headerctrl.h" 19 20 // ---------------------------------------------------------------------------- 21 // array classes 22 // ---------------------------------------------------------------------------- 23 24 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridCellAttr *, wxArrayAttrs, 25 class WXDLLIMPEXP_ADV); 26 27 WX_DECLARE_HASH_MAP_WITH_DECL(wxLongLong_t, wxGridCellAttr*, 28 wxIntegerHash, wxIntegerEqual, 29 wxGridCoordsToAttrMap, class WXDLLIMPEXP_CORE); 30 31 32 // ---------------------------------------------------------------------------- 33 // private classes 34 // ---------------------------------------------------------------------------- 35 36 // header column providing access to the column information stored in wxGrid 37 // via wxHeaderColumn interface 38 class wxGridHeaderColumn : public wxHeaderColumn 39 { 40 public: wxGridHeaderColumn(wxGrid * grid,int col)41 wxGridHeaderColumn(wxGrid *grid, int col) 42 : m_grid(grid), 43 m_col(col) 44 { 45 } 46 GetTitle()47 virtual wxString GetTitle() const wxOVERRIDE { return m_grid->GetColLabelValue(m_col); } GetBitmap()48 virtual wxBitmap GetBitmap() const wxOVERRIDE { return wxNullBitmap; } GetWidth()49 virtual int GetWidth() const wxOVERRIDE { return m_grid->GetColSize(m_col); } GetMinWidth()50 virtual int GetMinWidth() const wxOVERRIDE { return m_grid->GetColMinimalWidth(m_col); } GetAlignment()51 virtual wxAlignment GetAlignment() const wxOVERRIDE 52 { 53 int horz, 54 vert; 55 m_grid->GetColLabelAlignment(&horz, &vert); 56 57 return static_cast<wxAlignment>(horz); 58 } 59 GetFlags()60 virtual int GetFlags() const wxOVERRIDE 61 { 62 // we can't know in advance whether we can sort by this column or not 63 // with wxGrid API so suppose we can by default 64 int flags = wxCOL_SORTABLE; 65 if ( m_grid->CanDragColSize(m_col) ) 66 flags |= wxCOL_RESIZABLE; 67 if ( m_grid->CanDragColMove() ) 68 flags |= wxCOL_REORDERABLE; 69 if ( GetWidth() == 0 ) 70 flags |= wxCOL_HIDDEN; 71 72 return flags; 73 } 74 IsSortKey()75 virtual bool IsSortKey() const wxOVERRIDE 76 { 77 return m_grid->IsSortingBy(m_col); 78 } 79 IsSortOrderAscending()80 virtual bool IsSortOrderAscending() const wxOVERRIDE 81 { 82 return m_grid->IsSortOrderAscending(); 83 } 84 85 private: 86 // these really should be const but are not because the column needs to be 87 // assignable to be used in a wxVector (in STL build, in non-STL build we 88 // avoid the need for this) 89 wxGrid *m_grid; 90 int m_col; 91 }; 92 93 // header control retrieving column information from the grid 94 class wxGridHeaderCtrl : public wxHeaderCtrl 95 { 96 public: wxGridHeaderCtrl(wxGrid * owner)97 wxGridHeaderCtrl(wxGrid *owner) 98 : wxHeaderCtrl(owner, 99 wxID_ANY, 100 wxDefaultPosition, 101 wxDefaultSize, 102 (owner->CanHideColumns() ? wxHD_ALLOW_HIDE : 0) | 103 (owner->CanDragColMove() ? wxHD_ALLOW_REORDER : 0)) 104 { 105 m_inResizing = 0; 106 } 107 108 // Special method to call from wxGrid::DoSetColSize(), see comments there. UpdateIfNotResizing(unsigned int idx)109 void UpdateIfNotResizing(unsigned int idx) 110 { 111 if ( !m_inResizing ) 112 UpdateColumn(idx); 113 } 114 115 protected: GetColumn(unsigned int idx)116 virtual const wxHeaderColumn& GetColumn(unsigned int idx) const wxOVERRIDE 117 { 118 return m_columns[idx]; 119 } 120 GetOwner()121 wxGrid *GetOwner() const { return static_cast<wxGrid *>(GetParent()); } 122 123 private: GetDummyMouseEvent()124 wxMouseEvent GetDummyMouseEvent() const 125 { 126 // make up a dummy event for the grid event to use -- unfortunately we 127 // can't do anything else here 128 wxMouseEvent e; 129 e.SetState(wxGetMouseState()); 130 GetOwner()->ScreenToClient(&e.m_x, &e.m_y); 131 return e; 132 } 133 134 // override the base class method to update our m_columns array OnColumnCountChanging(unsigned int count)135 virtual void OnColumnCountChanging(unsigned int count) wxOVERRIDE 136 { 137 const unsigned countOld = m_columns.size(); 138 if ( count < countOld ) 139 { 140 // just discard the columns which don't exist any more (notice that 141 // we can't use resize() here as it would require the vector 142 // value_type, i.e. wxGridHeaderColumn to be default constructible, 143 // which it is not) 144 m_columns.erase(m_columns.begin() + count, m_columns.end()); 145 } 146 else // new columns added 147 { 148 // add columns for the new elements 149 for ( unsigned n = countOld; n < count; n++ ) 150 m_columns.push_back(wxGridHeaderColumn(GetOwner(), n)); 151 } 152 } 153 154 // override to implement column auto sizing UpdateColumnWidthToFit(unsigned int idx,int WXUNUSED (widthTitle))155 virtual bool UpdateColumnWidthToFit(unsigned int idx, int WXUNUSED(widthTitle)) wxOVERRIDE 156 { 157 GetOwner()->HandleColumnAutosize(idx, GetDummyMouseEvent()); 158 159 return true; 160 } 161 162 // overridden to react to the actions using the columns popup menu UpdateColumnVisibility(unsigned int idx,bool show)163 virtual void UpdateColumnVisibility(unsigned int idx, bool show) wxOVERRIDE 164 { 165 GetOwner()->SetColSize(idx, show ? wxGRID_AUTOSIZE : 0); 166 167 // as this is done by the user we should notify the main program about 168 // it 169 GetOwner()->SendGridSizeEvent(wxEVT_GRID_COL_SIZE, -1, idx, 170 GetDummyMouseEvent()); 171 } 172 173 // overridden to react to the columns order changes in the customization 174 // dialog UpdateColumnsOrder(const wxArrayInt & order)175 virtual void UpdateColumnsOrder(const wxArrayInt& order) wxOVERRIDE 176 { 177 GetOwner()->SetColumnsOrder(order); 178 } 179 180 181 // event handlers forwarding wxHeaderCtrl events to wxGrid OnClick(wxHeaderCtrlEvent & event)182 void OnClick(wxHeaderCtrlEvent& event) 183 { 184 GetOwner()->SendEvent(wxEVT_GRID_LABEL_LEFT_CLICK, 185 -1, event.GetColumn(), 186 GetDummyMouseEvent()); 187 188 GetOwner()->DoColHeaderClick(event.GetColumn()); 189 } 190 OnDoubleClick(wxHeaderCtrlEvent & event)191 void OnDoubleClick(wxHeaderCtrlEvent& event) 192 { 193 if ( !GetOwner()->SendEvent(wxEVT_GRID_LABEL_LEFT_DCLICK, 194 -1, event.GetColumn(), 195 GetDummyMouseEvent()) ) 196 { 197 event.Skip(); 198 } 199 } 200 OnRightClick(wxHeaderCtrlEvent & event)201 void OnRightClick(wxHeaderCtrlEvent& event) 202 { 203 if ( !GetOwner()->SendEvent(wxEVT_GRID_LABEL_RIGHT_CLICK, 204 -1, event.GetColumn(), 205 GetDummyMouseEvent()) ) 206 { 207 event.Skip(); 208 } 209 } 210 OnBeginResize(wxHeaderCtrlEvent & event)211 void OnBeginResize(wxHeaderCtrlEvent& event) 212 { 213 GetOwner()->DoHeaderStartDragResizeCol(event.GetColumn()); 214 215 event.Skip(); 216 } 217 OnResizing(wxHeaderCtrlEvent & event)218 void OnResizing(wxHeaderCtrlEvent& event) 219 { 220 // Calling wxGrid method results in a call to our own UpdateColumn() 221 // because it ends up in wxGrid::SetColSize() which must indeed update 222 // the column when it's called by the program -- but in the case where 223 // the size change comes from the column itself, it is useless and, in 224 // fact, harmful, as it results in extra flicker due to the inefficient 225 // implementation of UpdateColumn() in wxMSW wxHeaderCtrl, so skip 226 // calling it from our overridden version by setting this flag for the 227 // duration of this function execution and checking it in our 228 // UpdateIfNotResizing(). 229 m_inResizing++; 230 231 GetOwner()->DoHeaderDragResizeCol(event.GetWidth()); 232 233 m_inResizing--; 234 } 235 OnEndResize(wxHeaderCtrlEvent & event)236 void OnEndResize(wxHeaderCtrlEvent& event) 237 { 238 GetOwner()->DoHeaderEndDragResizeCol(event.GetWidth()); 239 240 event.Skip(); 241 } 242 OnBeginReorder(wxHeaderCtrlEvent & event)243 void OnBeginReorder(wxHeaderCtrlEvent& event) 244 { 245 GetOwner()->DoStartMoveCol(event.GetColumn()); 246 } 247 OnEndReorder(wxHeaderCtrlEvent & event)248 void OnEndReorder(wxHeaderCtrlEvent& event) 249 { 250 GetOwner()->DoEndMoveCol(event.GetNewOrder()); 251 } 252 253 wxVector<wxGridHeaderColumn> m_columns; 254 255 // The count of OnResizing() call nesting, 0 if not inside it. 256 int m_inResizing; 257 258 wxDECLARE_EVENT_TABLE(); 259 wxDECLARE_NO_COPY_CLASS(wxGridHeaderCtrl); 260 }; 261 262 // common base class for various grid subwindows 263 class WXDLLIMPEXP_ADV wxGridSubwindow : public wxWindow 264 { 265 public: 266 wxGridSubwindow(wxGrid *owner, 267 int additionalStyle = 0, 268 const wxString& name = wxASCII_STR(wxPanelNameStr)) 269 : wxWindow(owner, wxID_ANY, 270 wxDefaultPosition, wxDefaultSize, 271 wxBORDER_NONE | additionalStyle, 272 name) 273 { 274 m_owner = owner; 275 } 276 GetMainWindowOfCompositeControl()277 virtual wxWindow *GetMainWindowOfCompositeControl() wxOVERRIDE { return m_owner; } 278 AcceptsFocus()279 virtual bool AcceptsFocus() const wxOVERRIDE { return false; } 280 GetOwner()281 wxGrid *GetOwner() { return m_owner; } 282 283 protected: 284 void OnMouseCaptureLost(wxMouseCaptureLostEvent& event); 285 286 wxGrid *m_owner; 287 288 wxDECLARE_EVENT_TABLE(); 289 wxDECLARE_NO_COPY_CLASS(wxGridSubwindow); 290 }; 291 292 class WXDLLIMPEXP_ADV wxGridRowLabelWindow : public wxGridSubwindow 293 { 294 public: wxGridRowLabelWindow(wxGrid * parent)295 wxGridRowLabelWindow(wxGrid *parent) 296 : wxGridSubwindow(parent) 297 { 298 } 299 IsFrozen()300 virtual bool IsFrozen() const { return false; } 301 302 private: 303 void OnPaint( wxPaintEvent& event ); 304 void OnMouseEvent( wxMouseEvent& event ); 305 void OnMouseWheel( wxMouseEvent& event ); 306 307 wxDECLARE_EVENT_TABLE(); 308 wxDECLARE_NO_COPY_CLASS(wxGridRowLabelWindow); 309 }; 310 311 312 class wxGridRowFrozenLabelWindow : public wxGridRowLabelWindow 313 { 314 public: wxGridRowFrozenLabelWindow(wxGrid * parent)315 wxGridRowFrozenLabelWindow(wxGrid *parent) 316 : wxGridRowLabelWindow(parent) 317 { 318 } 319 IsFrozen()320 virtual bool IsFrozen() const wxOVERRIDE { return true; } 321 }; 322 323 324 class WXDLLIMPEXP_ADV wxGridColLabelWindow : public wxGridSubwindow 325 { 326 public: wxGridColLabelWindow(wxGrid * parent)327 wxGridColLabelWindow(wxGrid *parent) 328 : wxGridSubwindow(parent) 329 { 330 } 331 IsFrozen()332 virtual bool IsFrozen() const { return false; } 333 334 private: 335 void OnPaint( wxPaintEvent& event ); 336 void OnMouseEvent( wxMouseEvent& event ); 337 void OnMouseWheel( wxMouseEvent& event ); 338 339 wxDECLARE_EVENT_TABLE(); 340 wxDECLARE_NO_COPY_CLASS(wxGridColLabelWindow); 341 }; 342 343 344 class wxGridColFrozenLabelWindow : public wxGridColLabelWindow 345 { 346 public: wxGridColFrozenLabelWindow(wxGrid * parent)347 wxGridColFrozenLabelWindow(wxGrid *parent) 348 : wxGridColLabelWindow(parent) 349 { 350 } 351 IsFrozen()352 virtual bool IsFrozen() const wxOVERRIDE { return true; } 353 }; 354 355 356 class WXDLLIMPEXP_ADV wxGridCornerLabelWindow : public wxGridSubwindow 357 { 358 public: wxGridCornerLabelWindow(wxGrid * parent)359 wxGridCornerLabelWindow(wxGrid *parent) 360 : wxGridSubwindow(parent) 361 { 362 } 363 364 private: 365 void OnMouseEvent( wxMouseEvent& event ); 366 void OnMouseWheel( wxMouseEvent& event ); 367 void OnPaint( wxPaintEvent& event ); 368 369 wxDECLARE_EVENT_TABLE(); 370 wxDECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow); 371 }; 372 373 class WXDLLIMPEXP_ADV wxGridWindow : public wxGridSubwindow 374 { 375 public: 376 // grid window variants for scrolling possibilities 377 enum wxGridWindowType 378 { 379 wxGridWindowNormal = 0, 380 wxGridWindowFrozenCol = 1, 381 wxGridWindowFrozenRow = 2, 382 wxGridWindowFrozenCorner = wxGridWindowFrozenCol | 383 wxGridWindowFrozenRow 384 }; 385 wxGridWindow(wxGrid * parent,wxGridWindowType type)386 wxGridWindow(wxGrid *parent, wxGridWindowType type) 387 : wxGridSubwindow(parent, 388 wxWANTS_CHARS | wxCLIP_CHILDREN, 389 "GridWindow"), 390 m_type(type) 391 { 392 SetBackgroundStyle(wxBG_STYLE_PAINT); 393 } 394 395 396 virtual void ScrollWindow( int dx, int dy, const wxRect *rect ) wxOVERRIDE; 397 AcceptsFocus()398 virtual bool AcceptsFocus() const wxOVERRIDE { return true; } 399 GetType()400 wxGridWindowType GetType() const { return m_type; } 401 402 private: 403 const wxGridWindowType m_type; 404 405 void OnPaint( wxPaintEvent &event ); 406 void OnMouseWheel( wxMouseEvent& event ); 407 void OnMouseEvent( wxMouseEvent& event ); 408 void OnKeyDown( wxKeyEvent& ); 409 void OnKeyUp( wxKeyEvent& ); 410 void OnChar( wxKeyEvent& ); 411 void OnFocus( wxFocusEvent& ); 412 413 wxDECLARE_EVENT_TABLE(); 414 wxDECLARE_NO_COPY_CLASS(wxGridWindow); 415 }; 416 417 // ---------------------------------------------------------------------------- 418 // the internal data representation used by wxGridCellAttrProvider 419 // ---------------------------------------------------------------------------- 420 421 // this class stores attributes set for cells 422 class WXDLLIMPEXP_ADV wxGridCellAttrData 423 { 424 public: 425 ~wxGridCellAttrData(); 426 427 void SetAttr(wxGridCellAttr *attr, int row, int col); 428 wxGridCellAttr *GetAttr(int row, int col) const; 429 void UpdateAttrRows( size_t pos, int numRows ); 430 void UpdateAttrCols( size_t pos, int numCols ); 431 432 private: 433 // Tries to search for the attr for given cell. 434 wxGridCoordsToAttrMap::iterator FindIndex(int row, int col) const; 435 436 mutable wxGridCoordsToAttrMap m_attrs; 437 }; 438 439 // this class stores attributes set for rows or columns 440 class WXDLLIMPEXP_ADV wxGridRowOrColAttrData 441 { 442 public: 443 // empty ctor to suppress warnings wxGridRowOrColAttrData()444 wxGridRowOrColAttrData() {} 445 ~wxGridRowOrColAttrData(); 446 447 void SetAttr(wxGridCellAttr *attr, int rowOrCol); 448 wxGridCellAttr *GetAttr(int rowOrCol) const; 449 void UpdateAttrRowsOrCols( size_t pos, int numRowsOrCols ); 450 451 private: 452 wxArrayInt m_rowsOrCols; 453 wxArrayAttrs m_attrs; 454 }; 455 456 // NB: this is just a wrapper around 3 objects: one which stores cell 457 // attributes, and 2 others for row/col ones 458 class WXDLLIMPEXP_ADV wxGridCellAttrProviderData 459 { 460 public: 461 wxGridCellAttrData m_cellAttrs; 462 wxGridRowOrColAttrData m_rowAttrs, 463 m_colAttrs; 464 }; 465 466 // ---------------------------------------------------------------------------- 467 // operations classes abstracting the difference between operating on rows and 468 // columns 469 // ---------------------------------------------------------------------------- 470 471 // This class allows to write a function only once because by using its methods 472 // it will apply to both columns and rows. 473 // 474 // This is an abstract interface definition, the two concrete implementations 475 // below should be used when working with rows and columns respectively. 476 class wxGridOperations 477 { 478 public: 479 // Returns the operations in the other direction, i.e. wxGridRowOperations 480 // if this object is a wxGridColumnOperations and vice versa. 481 virtual wxGridOperations& Dual() const = 0; 482 483 // Return the total number of rows or columns. 484 virtual int GetTotalNumberOfLines(const wxGrid *grid) const = 0; 485 486 // Return the current number of rows or columns of a grid window. 487 virtual int GetNumberOfLines(const wxGrid *grid, wxGridWindow *gridWindow) const = 0; 488 489 // Return the first line for this grid type. 490 virtual int GetFirstLine(const wxGrid *grid, wxGridWindow *gridWindow) const = 0; 491 492 // Return the selection mode which allows selecting rows or columns. 493 virtual wxGrid::wxGridSelectionModes GetSelectionMode() const = 0; 494 495 // Make a wxGridCellCoords from the given components: thisDir is row or 496 // column and otherDir is column or row 497 virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const = 0; 498 499 // Calculate the scrolled position of the given abscissa or ordinate. 500 virtual int CalcScrolledPosition(wxGrid *grid, int pos) const = 0; 501 502 // Selects the horizontal or vertical component from the given object. 503 virtual int Select(const wxGridCellCoords& coords) const = 0; 504 virtual int Select(const wxPoint& pt) const = 0; 505 virtual int Select(const wxSize& sz) const = 0; 506 virtual int Select(const wxRect& r) const = 0; 507 virtual int& Select(wxRect& r) const = 0; 508 509 // Return or set left/top or right/bottom component of a block. 510 virtual int SelectFirst(const wxGridBlockCoords& block) const = 0; 511 virtual int SelectLast(const wxGridBlockCoords& block) const = 0; 512 virtual void SetFirst(wxGridBlockCoords& block, int line) const = 0; 513 virtual void SetLast(wxGridBlockCoords& block, int line) const = 0; 514 515 // Returns width or height of the rectangle 516 virtual int& SelectSize(wxRect& r) const = 0; 517 518 // Make a wxSize such that Select() applied to it returns first component 519 virtual wxSize MakeSize(int first, int second) const = 0; 520 521 // Sets the row or column component of the given cell coordinates 522 virtual void Set(wxGridCellCoords& coords, int line) const = 0; 523 524 525 // Draws a line parallel to the row or column, i.e. horizontal or vertical: 526 // pos is the horizontal or vertical position of the line and start and end 527 // are the coordinates of the line extremities in the other direction 528 virtual void 529 DrawParallelLine(wxDC& dc, int start, int end, int pos) const = 0; 530 531 // Draw a horizontal or vertical line across the given rectangle 532 // (this is implemented in terms of above and uses Select() to extract 533 // start and end from the given rectangle) DrawParallelLineInRect(wxDC & dc,const wxRect & rect,int pos)534 void DrawParallelLineInRect(wxDC& dc, const wxRect& rect, int pos) const 535 { 536 const int posStart = Select(rect.GetPosition()); 537 DrawParallelLine(dc, posStart, posStart + Select(rect.GetSize()), pos); 538 } 539 540 541 // Return the index of the row or column at the given pixel coordinate. 542 virtual int 543 PosToLine(const wxGrid *grid, int pos, wxGridWindow *gridWindow, bool clip = false) const = 0; 544 545 // Get the top/left position, in pixels, of the given row or column 546 virtual int GetLineStartPos(const wxGrid *grid, int line) const = 0; 547 548 // Get the bottom/right position, in pixels, of the given row or column 549 virtual int GetLineEndPos(const wxGrid *grid, int line) const = 0; 550 551 // Get the height/width of the given row/column 552 virtual int GetLineSize(const wxGrid *grid, int line) const = 0; 553 554 // Get wxGrid::m_rowBottoms/m_colRights array 555 virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const = 0; 556 557 // Get default height row height or column width 558 virtual int GetDefaultLineSize(const wxGrid *grid) const = 0; 559 560 // Return the minimal acceptable row height or column width 561 virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const = 0; 562 563 // Return the minimal row height or column width 564 virtual int GetMinimalLineSize(const wxGrid *grid, int line) const = 0; 565 566 // Set the row height or column width 567 virtual void SetLineSize(wxGrid *grid, int line, int size) const = 0; 568 569 // Set the row default height or column default width 570 virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const = 0; 571 572 573 // Return the index of the line at the given position 574 // 575 // NB: currently this is always identity for the rows as reordering is only 576 // implemented for the lines 577 virtual int GetLineAt(const wxGrid *grid, int pos) const = 0; 578 579 // Return the display position of the line with the given index. 580 // 581 // NB: As GetLineAt(), currently this is always identity for rows. 582 virtual int GetLinePos(const wxGrid *grid, int line) const = 0; 583 584 // Return the index of the line just before the given one or wxNOT_FOUND. 585 virtual int GetLineBefore(const wxGrid* grid, int line) const = 0; 586 587 // Get the row or column label window 588 virtual wxWindow *GetHeaderWindow(wxGrid *grid) const = 0; 589 590 // Get the width or height of the row or column label window 591 virtual int GetHeaderWindowSize(wxGrid *grid) const = 0; 592 593 // Get the row or column frozen grid window 594 virtual wxGridWindow *GetFrozenGrid(wxGrid* grid) const = 0; 595 596 // This class is never used polymorphically but give it a virtual dtor 597 // anyhow to suppress g++ complaints about it ~wxGridOperations()598 virtual ~wxGridOperations() { } 599 }; 600 601 class wxGridRowOperations : public wxGridOperations 602 { 603 public: 604 virtual wxGridOperations& Dual() const wxOVERRIDE; 605 GetTotalNumberOfLines(const wxGrid * grid)606 virtual int GetTotalNumberOfLines(const wxGrid *grid) const wxOVERRIDE 607 { return grid->GetNumberRows(); } 608 609 virtual int GetNumberOfLines(const wxGrid *grid, wxGridWindow *gridWindow) const wxOVERRIDE; 610 611 virtual int GetFirstLine(const wxGrid *grid, wxGridWindow *gridWindow) const wxOVERRIDE; 612 GetSelectionMode()613 virtual wxGrid::wxGridSelectionModes GetSelectionMode() const wxOVERRIDE 614 { return wxGrid::wxGridSelectRows; } 615 MakeCoords(int thisDir,int otherDir)616 virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const wxOVERRIDE 617 { return wxGridCellCoords(thisDir, otherDir); } 618 CalcScrolledPosition(wxGrid * grid,int pos)619 virtual int CalcScrolledPosition(wxGrid *grid, int pos) const wxOVERRIDE 620 { return grid->CalcScrolledPosition(wxPoint(pos, 0)).x; } 621 Select(const wxGridCellCoords & c)622 virtual int Select(const wxGridCellCoords& c) const wxOVERRIDE { return c.GetRow(); } Select(const wxPoint & pt)623 virtual int Select(const wxPoint& pt) const wxOVERRIDE { return pt.x; } Select(const wxSize & sz)624 virtual int Select(const wxSize& sz) const wxOVERRIDE { return sz.x; } Select(const wxRect & r)625 virtual int Select(const wxRect& r) const wxOVERRIDE { return r.x; } Select(wxRect & r)626 virtual int& Select(wxRect& r) const wxOVERRIDE { return r.x; } SelectFirst(const wxGridBlockCoords & block)627 virtual int SelectFirst(const wxGridBlockCoords& block) const wxOVERRIDE 628 { return block.GetTopRow(); } SelectLast(const wxGridBlockCoords & block)629 virtual int SelectLast(const wxGridBlockCoords& block) const wxOVERRIDE 630 { return block.GetBottomRow(); } SetFirst(wxGridBlockCoords & block,int line)631 virtual void SetFirst(wxGridBlockCoords& block, int line) const wxOVERRIDE 632 { block.SetTopRow(line); } SetLast(wxGridBlockCoords & block,int line)633 virtual void SetLast(wxGridBlockCoords& block, int line) const wxOVERRIDE 634 { block.SetBottomRow(line); } SelectSize(wxRect & r)635 virtual int& SelectSize(wxRect& r) const wxOVERRIDE { return r.width; } MakeSize(int first,int second)636 virtual wxSize MakeSize(int first, int second) const wxOVERRIDE 637 { return wxSize(first, second); } Set(wxGridCellCoords & coords,int line)638 virtual void Set(wxGridCellCoords& coords, int line) const wxOVERRIDE 639 { coords.SetRow(line); } 640 DrawParallelLine(wxDC & dc,int start,int end,int pos)641 virtual void DrawParallelLine(wxDC& dc, int start, int end, int pos) const wxOVERRIDE 642 { dc.DrawLine(start, pos, end, pos); } 643 644 virtual int PosToLine(const wxGrid *grid, int pos, wxGridWindow *gridWindow , bool clip = false) const wxOVERRIDE 645 { return grid->YToRow(pos, clip, gridWindow); } GetLineStartPos(const wxGrid * grid,int line)646 virtual int GetLineStartPos(const wxGrid *grid, int line) const wxOVERRIDE 647 { return grid->GetRowTop(line); } GetLineEndPos(const wxGrid * grid,int line)648 virtual int GetLineEndPos(const wxGrid *grid, int line) const wxOVERRIDE 649 { return grid->GetRowBottom(line); } GetLineSize(const wxGrid * grid,int line)650 virtual int GetLineSize(const wxGrid *grid, int line) const wxOVERRIDE 651 { return grid->GetRowHeight(line); } GetLineEnds(const wxGrid * grid)652 virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const wxOVERRIDE 653 { return grid->m_rowBottoms; } GetDefaultLineSize(const wxGrid * grid)654 virtual int GetDefaultLineSize(const wxGrid *grid) const wxOVERRIDE 655 { return grid->GetDefaultRowSize(); } GetMinimalAcceptableLineSize(const wxGrid * grid)656 virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const wxOVERRIDE 657 { return grid->GetRowMinimalAcceptableHeight(); } GetMinimalLineSize(const wxGrid * grid,int line)658 virtual int GetMinimalLineSize(const wxGrid *grid, int line) const wxOVERRIDE 659 { return grid->GetRowMinimalHeight(line); } SetLineSize(wxGrid * grid,int line,int size)660 virtual void SetLineSize(wxGrid *grid, int line, int size) const wxOVERRIDE 661 { grid->SetRowSize(line, size); } SetDefaultLineSize(wxGrid * grid,int size,bool resizeExisting)662 virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const wxOVERRIDE 663 { grid->SetDefaultRowSize(size, resizeExisting); } 664 GetLineAt(const wxGrid * WXUNUSED (grid),int pos)665 virtual int GetLineAt(const wxGrid * WXUNUSED(grid), int pos) const wxOVERRIDE 666 { return pos; } // TODO: implement row reordering GetLinePos(const wxGrid * WXUNUSED (grid),int line)667 virtual int GetLinePos(const wxGrid * WXUNUSED(grid), int line) const wxOVERRIDE 668 { return line; } // TODO: implement row reordering 669 GetLineBefore(const wxGrid * WXUNUSED (grid),int line)670 virtual int GetLineBefore(const wxGrid* WXUNUSED(grid), int line) const wxOVERRIDE 671 { return line - 1; } 672 GetHeaderWindow(wxGrid * grid)673 virtual wxWindow *GetHeaderWindow(wxGrid *grid) const wxOVERRIDE 674 { return grid->GetGridRowLabelWindow(); } GetHeaderWindowSize(wxGrid * grid)675 virtual int GetHeaderWindowSize(wxGrid *grid) const wxOVERRIDE 676 { return grid->GetRowLabelSize(); } 677 GetFrozenGrid(wxGrid * grid)678 virtual wxGridWindow *GetFrozenGrid(wxGrid* grid) const wxOVERRIDE 679 { return (wxGridWindow*)grid->GetFrozenRowGridWindow(); } 680 }; 681 682 class wxGridColumnOperations : public wxGridOperations 683 { 684 public: 685 virtual wxGridOperations& Dual() const wxOVERRIDE; 686 GetTotalNumberOfLines(const wxGrid * grid)687 virtual int GetTotalNumberOfLines(const wxGrid *grid) const wxOVERRIDE 688 { return grid->GetNumberCols(); } 689 690 virtual int GetNumberOfLines(const wxGrid *grid, wxGridWindow *gridWindow) const wxOVERRIDE; 691 692 virtual int GetFirstLine(const wxGrid *grid, wxGridWindow *gridWindow) const wxOVERRIDE; 693 GetSelectionMode()694 virtual wxGrid::wxGridSelectionModes GetSelectionMode() const wxOVERRIDE 695 { return wxGrid::wxGridSelectColumns; } 696 MakeCoords(int thisDir,int otherDir)697 virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const wxOVERRIDE 698 { return wxGridCellCoords(otherDir, thisDir); } 699 CalcScrolledPosition(wxGrid * grid,int pos)700 virtual int CalcScrolledPosition(wxGrid *grid, int pos) const wxOVERRIDE 701 { return grid->CalcScrolledPosition(wxPoint(0, pos)).y; } 702 Select(const wxGridCellCoords & c)703 virtual int Select(const wxGridCellCoords& c) const wxOVERRIDE { return c.GetCol(); } Select(const wxPoint & pt)704 virtual int Select(const wxPoint& pt) const wxOVERRIDE { return pt.y; } Select(const wxSize & sz)705 virtual int Select(const wxSize& sz) const wxOVERRIDE { return sz.y; } Select(const wxRect & r)706 virtual int Select(const wxRect& r) const wxOVERRIDE { return r.y; } Select(wxRect & r)707 virtual int& Select(wxRect& r) const wxOVERRIDE { return r.y; } SelectFirst(const wxGridBlockCoords & block)708 virtual int SelectFirst(const wxGridBlockCoords& block) const wxOVERRIDE 709 { return block.GetLeftCol(); } SelectLast(const wxGridBlockCoords & block)710 virtual int SelectLast(const wxGridBlockCoords& block) const wxOVERRIDE 711 { return block.GetRightCol(); } SetFirst(wxGridBlockCoords & block,int line)712 virtual void SetFirst(wxGridBlockCoords& block, int line) const wxOVERRIDE 713 { block.SetLeftCol(line); } SetLast(wxGridBlockCoords & block,int line)714 virtual void SetLast(wxGridBlockCoords& block, int line) const wxOVERRIDE 715 { block.SetRightCol(line); } SelectSize(wxRect & r)716 virtual int& SelectSize(wxRect& r) const wxOVERRIDE { return r.height; } MakeSize(int first,int second)717 virtual wxSize MakeSize(int first, int second) const wxOVERRIDE 718 { return wxSize(second, first); } Set(wxGridCellCoords & coords,int line)719 virtual void Set(wxGridCellCoords& coords, int line) const wxOVERRIDE 720 { coords.SetCol(line); } 721 DrawParallelLine(wxDC & dc,int start,int end,int pos)722 virtual void DrawParallelLine(wxDC& dc, int start, int end, int pos) const wxOVERRIDE 723 { dc.DrawLine(pos, start, pos, end); } 724 725 virtual int PosToLine(const wxGrid *grid, int pos, wxGridWindow *gridWindow, bool clip = false) const wxOVERRIDE 726 { return grid->XToCol(pos, clip, gridWindow); } GetLineStartPos(const wxGrid * grid,int line)727 virtual int GetLineStartPos(const wxGrid *grid, int line) const wxOVERRIDE 728 { return grid->GetColLeft(line); } GetLineEndPos(const wxGrid * grid,int line)729 virtual int GetLineEndPos(const wxGrid *grid, int line) const wxOVERRIDE 730 { return grid->GetColRight(line); } GetLineSize(const wxGrid * grid,int line)731 virtual int GetLineSize(const wxGrid *grid, int line) const wxOVERRIDE 732 { return grid->GetColWidth(line); } GetLineEnds(const wxGrid * grid)733 virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const wxOVERRIDE 734 { return grid->m_colRights; } GetDefaultLineSize(const wxGrid * grid)735 virtual int GetDefaultLineSize(const wxGrid *grid) const wxOVERRIDE 736 { return grid->GetDefaultColSize(); } GetMinimalAcceptableLineSize(const wxGrid * grid)737 virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const wxOVERRIDE 738 { return grid->GetColMinimalAcceptableWidth(); } GetMinimalLineSize(const wxGrid * grid,int line)739 virtual int GetMinimalLineSize(const wxGrid *grid, int line) const wxOVERRIDE 740 { return grid->GetColMinimalWidth(line); } SetLineSize(wxGrid * grid,int line,int size)741 virtual void SetLineSize(wxGrid *grid, int line, int size) const wxOVERRIDE 742 { grid->SetColSize(line, size); } SetDefaultLineSize(wxGrid * grid,int size,bool resizeExisting)743 virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const wxOVERRIDE 744 { grid->SetDefaultColSize(size, resizeExisting); } 745 GetLineAt(const wxGrid * grid,int pos)746 virtual int GetLineAt(const wxGrid *grid, int pos) const wxOVERRIDE 747 { return grid->GetColAt(pos); } GetLinePos(const wxGrid * grid,int line)748 virtual int GetLinePos(const wxGrid *grid, int line) const wxOVERRIDE 749 { return grid->GetColPos(line); } 750 GetLineBefore(const wxGrid * grid,int line)751 virtual int GetLineBefore(const wxGrid* grid, int line) const wxOVERRIDE 752 { 753 int posBefore = grid->GetColPos(line) - 1; 754 return posBefore >= 0 ? grid->GetColAt(posBefore) : wxNOT_FOUND; 755 } 756 GetHeaderWindow(wxGrid * grid)757 virtual wxWindow *GetHeaderWindow(wxGrid *grid) const wxOVERRIDE 758 { return grid->GetGridColLabelWindow(); } GetHeaderWindowSize(wxGrid * grid)759 virtual int GetHeaderWindowSize(wxGrid *grid) const wxOVERRIDE 760 { return grid->GetColLabelSize(); } 761 GetFrozenGrid(wxGrid * grid)762 virtual wxGridWindow *GetFrozenGrid(wxGrid* grid) const wxOVERRIDE 763 { return (wxGridWindow*)grid->GetFrozenColGridWindow(); } 764 }; 765 766 // This class abstracts the difference between operations going forward 767 // (down/right) and backward (up/left) and allows to use the same code for 768 // functions which differ only in the direction of grid traversal. 769 // 770 // Notice that all operations in this class work with display positions and not 771 // internal indices which can be different if the columns were reordered. 772 // 773 // Like wxGridOperations it's an ABC with two concrete subclasses below. Unlike 774 // it, this is a normal object and not just a function dispatch table and has a 775 // non-default ctor. 776 // 777 // Note: the explanation of this discrepancy is the existence of (very useful) 778 // Dual() method in wxGridOperations which forces us to make wxGridOperations a 779 // function dispatcher only. 780 class wxGridDirectionOperations 781 { 782 public: 783 // The oper parameter to ctor selects whether we work with rows or columns wxGridDirectionOperations(wxGrid * grid,const wxGridOperations & oper)784 wxGridDirectionOperations(wxGrid *grid, const wxGridOperations& oper) 785 : m_grid(grid), 786 m_oper(oper) 787 { 788 } 789 790 // Check if the component of this point in our direction is at the 791 // boundary, i.e. is the first/last row/column 792 virtual bool IsAtBoundary(const wxGridCellCoords& coords) const = 0; 793 794 // Check if the component of this point in our direction is 795 // valid, i.e. not -1 IsValid(const wxGridCellCoords & coords)796 bool IsValid(const wxGridCellCoords& coords) const 797 { 798 return m_oper.Select(coords) != -1; 799 } 800 801 // Make the coordinates with the other component value of -1. MakeWholeLineCoords(const wxGridCellCoords & coords)802 wxGridCellCoords MakeWholeLineCoords(const wxGridCellCoords& coords) const 803 { 804 return m_oper.MakeCoords(m_oper.Select(coords), -1); 805 } 806 807 // Increment the component of this point in our direction 808 // 809 // Note that this can't be called if IsAtBoundary() is true, use 810 // TryToAdvance() if this might be the case. 811 virtual void Advance(wxGridCellCoords& coords) const = 0; 812 813 // Try to advance in our direction, return true if succeeded or false 814 // otherwise, i.e. if the coordinates are already at the grid boundary. TryToAdvance(wxGridCellCoords & coords)815 bool TryToAdvance(wxGridCellCoords& coords) const 816 { 817 if ( IsAtBoundary(coords) ) 818 return false; 819 820 Advance(coords); 821 822 return true; 823 } 824 825 // Find the line at the given distance, in pixels, away from this one 826 // (this uses clipping, i.e. anything after the last line is counted as the 827 // last one and anything before the first one as 0) 828 // 829 // TODO: Implementation of this method currently doesn't support column 830 // reordering as it mixes up indices and positions. But this doesn't 831 // really matter as it's only called for rows (Page Up/Down only work 832 // vertically) and row reordering is not currently supported. We'd 833 // need to fix it if this ever changes however. 834 virtual int MoveByPixelDistance(int line, int distance) const = 0; 835 836 // This class is never used polymorphically but give it a virtual dtor 837 // anyhow to suppress g++ complaints about it ~wxGridDirectionOperations()838 virtual ~wxGridDirectionOperations() { } 839 840 protected: 841 // Get the position of the row or column from the given coordinates pair. 842 // 843 // This is just a shortcut to avoid repeating m_oper and m_grid multiple 844 // times in the derived classes code. GetLinePos(const wxGridCellCoords & coords)845 int GetLinePos(const wxGridCellCoords& coords) const 846 { 847 return m_oper.GetLinePos(m_grid, m_oper.Select(coords)); 848 } 849 850 // Get the index of the row or column from the position. GetLineAt(int pos)851 int GetLineAt(int pos) const 852 { 853 return m_oper.GetLineAt(m_grid, pos); 854 } 855 856 // Check if the given line is visible, i.e. has non 0 size. IsLineVisible(int line)857 bool IsLineVisible(int line) const 858 { 859 return m_oper.GetLineSize(m_grid, line) != 0; 860 } 861 862 863 wxGrid * const m_grid; 864 const wxGridOperations& m_oper; 865 }; 866 867 class wxGridBackwardOperations : public wxGridDirectionOperations 868 { 869 public: wxGridBackwardOperations(wxGrid * grid,const wxGridOperations & oper)870 wxGridBackwardOperations(wxGrid *grid, const wxGridOperations& oper) 871 : wxGridDirectionOperations(grid, oper) 872 { 873 } 874 IsAtBoundary(const wxGridCellCoords & coords)875 virtual bool IsAtBoundary(const wxGridCellCoords& coords) const wxOVERRIDE 876 { 877 wxASSERT_MSG( m_oper.Select(coords) >= 0, "invalid row/column" ); 878 879 int pos = GetLinePos(coords); 880 while ( pos ) 881 { 882 // Check the previous line. 883 int line = GetLineAt(--pos); 884 if ( IsLineVisible(line) ) 885 { 886 // There is another visible line before this one, hence it's 887 // not at boundary. 888 return false; 889 } 890 } 891 892 // We reached the boundary without finding any visible lines. 893 return true; 894 } 895 Advance(wxGridCellCoords & coords)896 virtual void Advance(wxGridCellCoords& coords) const wxOVERRIDE 897 { 898 int pos = GetLinePos(coords); 899 for ( ;; ) 900 { 901 // This is not supposed to happen if IsAtBoundary() returned false. 902 wxCHECK_RET( pos, "can't advance when already at boundary" ); 903 904 int line = GetLineAt(--pos); 905 if ( IsLineVisible(line) ) 906 { 907 m_oper.Set(coords, line); 908 break; 909 } 910 } 911 } 912 MoveByPixelDistance(int line,int distance)913 virtual int MoveByPixelDistance(int line, int distance) const wxOVERRIDE 914 { 915 int pos = m_oper.GetLineStartPos(m_grid, line); 916 return m_oper.PosToLine(m_grid, pos - distance + 1, NULL, true); 917 } 918 }; 919 920 // Please refer to the comments above when reading this class code, it's 921 // absolutely symmetrical to wxGridBackwardOperations. 922 class wxGridForwardOperations : public wxGridDirectionOperations 923 { 924 public: wxGridForwardOperations(wxGrid * grid,const wxGridOperations & oper)925 wxGridForwardOperations(wxGrid *grid, const wxGridOperations& oper) 926 : wxGridDirectionOperations(grid, oper), 927 m_numLines(oper.GetTotalNumberOfLines(grid)) 928 { 929 } 930 IsAtBoundary(const wxGridCellCoords & coords)931 virtual bool IsAtBoundary(const wxGridCellCoords& coords) const wxOVERRIDE 932 { 933 wxASSERT_MSG( m_oper.Select(coords) < m_numLines, "invalid row/column" ); 934 935 int pos = GetLinePos(coords); 936 while ( pos < m_numLines - 1 ) 937 { 938 int line = GetLineAt(++pos); 939 if ( IsLineVisible(line) ) 940 return false; 941 } 942 943 return true; 944 } 945 Advance(wxGridCellCoords & coords)946 virtual void Advance(wxGridCellCoords& coords) const wxOVERRIDE 947 { 948 int pos = GetLinePos(coords); 949 for ( ;; ) 950 { 951 wxCHECK_RET( pos < m_numLines - 1, 952 "can't advance when already at boundary" ); 953 954 int line = GetLineAt(++pos); 955 if ( IsLineVisible(line) ) 956 { 957 m_oper.Set(coords, line); 958 break; 959 } 960 } 961 } 962 MoveByPixelDistance(int line,int distance)963 virtual int MoveByPixelDistance(int line, int distance) const wxOVERRIDE 964 { 965 int pos = m_oper.GetLineStartPos(m_grid, line); 966 return m_oper.PosToLine(m_grid, pos + distance, NULL, true); 967 } 968 969 private: 970 const int m_numLines; 971 }; 972 973 // ---------------------------------------------------------------------------- 974 // data structures used for the data type registry 975 // ---------------------------------------------------------------------------- 976 977 struct wxGridDataTypeInfo 978 { wxGridDataTypeInfowxGridDataTypeInfo979 wxGridDataTypeInfo(const wxString& typeName, 980 wxGridCellRenderer* renderer, 981 wxGridCellEditor* editor) 982 : m_typeName(typeName), m_renderer(renderer), m_editor(editor) 983 {} 984 ~wxGridDataTypeInfowxGridDataTypeInfo985 ~wxGridDataTypeInfo() 986 { 987 wxSafeDecRef(m_renderer); 988 wxSafeDecRef(m_editor); 989 } 990 991 wxString m_typeName; 992 wxGridCellRenderer* m_renderer; 993 wxGridCellEditor* m_editor; 994 995 wxDECLARE_NO_COPY_CLASS(wxGridDataTypeInfo); 996 }; 997 998 999 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo*, wxGridDataTypeInfoArray, 1000 class WXDLLIMPEXP_ADV); 1001 1002 1003 class WXDLLIMPEXP_ADV wxGridTypeRegistry 1004 { 1005 public: wxGridTypeRegistry()1006 wxGridTypeRegistry() {} 1007 ~wxGridTypeRegistry(); 1008 1009 void RegisterDataType(const wxString& typeName, 1010 wxGridCellRenderer* renderer, 1011 wxGridCellEditor* editor); 1012 1013 // find one of already registered data types 1014 int FindRegisteredDataType(const wxString& typeName); 1015 1016 // try to FindRegisteredDataType(), if this fails and typeName is one of 1017 // standard typenames, register it and return its index 1018 int FindDataType(const wxString& typeName); 1019 1020 // try to FindDataType(), if it fails see if it is not one of already 1021 // registered data types with some params in which case clone the 1022 // registered data type and set params for it 1023 int FindOrCloneDataType(const wxString& typeName); 1024 1025 wxGridCellRenderer* GetRenderer(int index); 1026 wxGridCellEditor* GetEditor(int index); 1027 1028 private: 1029 wxGridDataTypeInfoArray m_typeinfo; 1030 }; 1031 1032 // Returns the rectangle for showing something of the given size in a cell with 1033 // the given alignment. 1034 // 1035 // The function is used by wxGridCellBoolEditor and wxGridCellBoolRenderer to 1036 // draw a check mark and position wxCheckBox respectively. 1037 wxRect 1038 wxGetContentRect(wxSize contentSize, 1039 const wxRect& cellRect, 1040 int hAlign, 1041 int vAlign); 1042 1043 namespace wxGridPrivate 1044 { 1045 1046 #if wxUSE_DATETIME 1047 1048 // This is used as TryGetValueAsDate() parameter. 1049 class DateParseParams 1050 { 1051 public: 1052 // Unfortunately we have to provide the default ctor (and also make the 1053 // members non-const) because we use these objects as out-parameters as 1054 // they are not fully declared in the public headers. The factory functions 1055 // below must be used to create a really usable object. DateParseParams()1056 DateParseParams() : fallbackParseDate(false) { } 1057 1058 // Use these functions to really initialize the object. WithFallback(const wxString & format)1059 static DateParseParams WithFallback(const wxString& format) 1060 { 1061 return DateParseParams(format, true); 1062 } 1063 WithoutFallback(const wxString & format)1064 static DateParseParams WithoutFallback(const wxString& format) 1065 { 1066 return DateParseParams(format, false); 1067 } 1068 1069 // The usual format, e.g. "%x" or "%Y-%m-%d". 1070 wxString format; 1071 1072 // Whether fall back to ParseDate() is allowed. 1073 bool fallbackParseDate; 1074 1075 private: DateParseParams(const wxString & format_,bool fallbackParseDate_)1076 DateParseParams(const wxString& format_, bool fallbackParseDate_) 1077 : format(format_), 1078 fallbackParseDate(fallbackParseDate_) 1079 { 1080 } 1081 }; 1082 1083 // Helper function trying to get a date from the given cell: if possible, get 1084 // the date value from the table directly, otherwise get the string value for 1085 // this cell and try to parse it using the specified date format and, if this 1086 // doesn't work and fallbackParseDate is true, try using ParseDate() as a 1087 // fallback. If this still fails, returns false. 1088 bool 1089 TryGetValueAsDate(wxDateTime& result, 1090 const DateParseParams& params, 1091 const wxGrid& grid, 1092 int row, int col); 1093 1094 #endif // wxUSE_DATETIME 1095 1096 } // namespace wxGridPrivate 1097 1098 #endif // wxUSE_GRID 1099 #endif // _WX_GENERIC_GRID_PRIVATE_H_ 1100