You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2264 lines
66KB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: griddemo.cpp
  3. // Purpose: Grid control wxWidgets sample
  4. // Author: Michael Bedward
  5. // Modified by: Santiago Palacios
  6. // RCS-ID: $Id$
  7. // Copyright: (c) Michael Bedward, Julian Smart, Vadim Zeitlin
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. // ============================================================================
  11. // declarations
  12. // ============================================================================
  13. // ----------------------------------------------------------------------------
  14. // headers
  15. // ----------------------------------------------------------------------------
  16. // For compilers that support precompilation, includes "wx/wx.h".
  17. #include "wx/wxprec.h"
  18. #ifdef __BORLANDC__
  19. #pragma hdrstop
  20. #endif
  21. #ifndef WX_PRECOMP
  22. #include "wx/wx.h"
  23. #endif
  24. #include "wx/colordlg.h"
  25. #include "wx/fontdlg.h"
  26. #include "wx/numdlg.h"
  27. #include "wx/aboutdlg.h"
  28. #include "wx/grid.h"
  29. #include "wx/headerctrl.h"
  30. #include "wx/generic/gridctrl.h"
  31. #include "wx/generic/grideditors.h"
  32. #include "griddemo.h"
  33. #ifndef wxHAS_IMAGES_IN_RESOURCES
  34. #include "../sample.xpm"
  35. #endif
  36. // Custom renderer that renders column header cells without borders and in
  37. // italic
  38. class CustomColumnHeaderRenderer : public wxGridColumnHeaderRenderer
  39. {
  40. public:
  41. CustomColumnHeaderRenderer(const wxColour& colFg, const wxColour& colBg)
  42. : m_colFg(colFg),
  43. m_colBg(colBg)
  44. {
  45. }
  46. virtual void DrawLabel(const wxGrid& WXUNUSED(grid),
  47. wxDC& dc,
  48. const wxString& value,
  49. const wxRect& rect,
  50. int horizAlign,
  51. int vertAlign,
  52. int WXUNUSED(textOrientation)) const
  53. {
  54. dc.SetTextForeground(m_colFg);
  55. dc.SetFont(wxITALIC_FONT->Bold());
  56. dc.DrawLabel(value, rect, horizAlign | vertAlign);
  57. }
  58. virtual void DrawBorder(const wxGrid& WXUNUSED(grid),
  59. wxDC& dc,
  60. wxRect& rect) const
  61. {
  62. dc.SetPen(*wxTRANSPARENT_PEN);
  63. dc.SetBrush(wxBrush(m_colBg));
  64. dc.DrawRectangle(rect);
  65. }
  66. private:
  67. const wxColour m_colFg, m_colBg;
  68. wxDECLARE_NO_COPY_CLASS(CustomColumnHeaderRenderer);
  69. };
  70. // And a custom attributes provider which uses custom column header renderer
  71. // defined above
  72. class CustomColumnHeadersProvider : public wxGridCellAttrProvider
  73. {
  74. public:
  75. // by default custom column renderer is not used, call
  76. // UseCustomColHeaders() to enable it
  77. CustomColumnHeadersProvider()
  78. : m_customOddRenderer(*wxYELLOW, *wxBLUE),
  79. m_customEvenRenderer(*wxWHITE, *wxBLACK),
  80. m_useCustom(false)
  81. {
  82. }
  83. // enable or disable the use of custom renderer for column headers
  84. void UseCustomColHeaders(bool use = true) { m_useCustom = use; }
  85. protected:
  86. virtual const wxGridColumnHeaderRenderer& GetColumnHeaderRenderer(int col)
  87. {
  88. // if enabled, use custom renderers
  89. if ( m_useCustom )
  90. {
  91. // and use different ones for odd and even columns -- just to show
  92. // that we can
  93. return col % 2 ? m_customOddRenderer : m_customEvenRenderer;
  94. }
  95. return wxGridCellAttrProvider::GetColumnHeaderRenderer(col);
  96. }
  97. private:
  98. CustomColumnHeaderRenderer m_customOddRenderer,
  99. m_customEvenRenderer;
  100. bool m_useCustom;
  101. wxDECLARE_NO_COPY_CLASS(CustomColumnHeadersProvider);
  102. };
  103. // ----------------------------------------------------------------------------
  104. // wxWin macros
  105. // ----------------------------------------------------------------------------
  106. IMPLEMENT_APP( GridApp )
  107. // ============================================================================
  108. // implementation
  109. // ============================================================================
  110. // ----------------------------------------------------------------------------
  111. // GridApp
  112. // ----------------------------------------------------------------------------
  113. bool GridApp::OnInit()
  114. {
  115. GridFrame *frame = new GridFrame;
  116. frame->Show(true);
  117. return true;
  118. }
  119. // ----------------------------------------------------------------------------
  120. // GridFrame
  121. // ----------------------------------------------------------------------------
  122. BEGIN_EVENT_TABLE( GridFrame, wxFrame )
  123. EVT_MENU( ID_TOGGLEROWLABELS, GridFrame::ToggleRowLabels )
  124. EVT_MENU( ID_TOGGLECOLLABELS, GridFrame::ToggleColLabels )
  125. EVT_MENU( ID_TOGGLEEDIT, GridFrame::ToggleEditing )
  126. EVT_MENU( ID_TOGGLEROWSIZING, GridFrame::ToggleRowSizing )
  127. EVT_MENU( ID_TOGGLECOLSIZING, GridFrame::ToggleColSizing )
  128. EVT_MENU( ID_TOGGLECOLMOVING, GridFrame::ToggleColMoving )
  129. EVT_MENU( ID_TOGGLEGRIDSIZING, GridFrame::ToggleGridSizing )
  130. EVT_MENU( ID_TOGGLEGRIDDRAGCELL, GridFrame::ToggleGridDragCell )
  131. EVT_MENU( ID_COLNATIVEHEADER, GridFrame::SetNativeColHeader )
  132. EVT_MENU( ID_COLDEFAULTHEADER, GridFrame::SetDefaultColHeader )
  133. EVT_MENU( ID_COLCUSTOMHEADER, GridFrame::SetCustomColHeader )
  134. EVT_MENU( ID_TOGGLEGRIDLINES, GridFrame::ToggleGridLines )
  135. EVT_MENU( ID_AUTOSIZECOLS, GridFrame::AutoSizeCols )
  136. EVT_MENU( ID_CELLOVERFLOW, GridFrame::CellOverflow )
  137. EVT_MENU( ID_RESIZECELL, GridFrame::ResizeCell )
  138. EVT_MENU( ID_SETLABELCOLOUR, GridFrame::SetLabelColour )
  139. EVT_MENU( ID_SETLABELTEXTCOLOUR, GridFrame::SetLabelTextColour )
  140. EVT_MENU( ID_SETLABEL_FONT, GridFrame::SetLabelFont )
  141. EVT_MENU( ID_ROWLABELHORIZALIGN, GridFrame::SetRowLabelHorizAlignment )
  142. EVT_MENU( ID_ROWLABELVERTALIGN, GridFrame::SetRowLabelVertAlignment )
  143. EVT_MENU( ID_COLLABELHORIZALIGN, GridFrame::SetColLabelHorizAlignment )
  144. EVT_MENU( ID_COLLABELVERTALIGN, GridFrame::SetColLabelVertAlignment )
  145. EVT_MENU( ID_GRIDLINECOLOUR, GridFrame::SetGridLineColour )
  146. EVT_MENU( ID_INSERTROW, GridFrame::InsertRow )
  147. EVT_MENU( ID_INSERTCOL, GridFrame::InsertCol )
  148. EVT_MENU( ID_DELETEROW, GridFrame::DeleteSelectedRows )
  149. EVT_MENU( ID_DELETECOL, GridFrame::DeleteSelectedCols )
  150. EVT_MENU( ID_CLEARGRID, GridFrame::ClearGrid )
  151. EVT_MENU( ID_SELCELLS, GridFrame::SelectCells )
  152. EVT_MENU( ID_SELROWS, GridFrame::SelectRows )
  153. EVT_MENU( ID_SELCOLS, GridFrame::SelectCols )
  154. EVT_MENU( ID_SELROWSORCOLS, GridFrame::SelectRowsOrCols )
  155. EVT_MENU( ID_SET_CELL_FG_COLOUR, GridFrame::SetCellFgColour )
  156. EVT_MENU( ID_SET_CELL_BG_COLOUR, GridFrame::SetCellBgColour )
  157. EVT_MENU( wxID_ABOUT, GridFrame::About )
  158. EVT_MENU( wxID_EXIT, GridFrame::OnQuit )
  159. EVT_MENU( ID_VTABLE, GridFrame::OnVTable)
  160. EVT_MENU( ID_BUGS_TABLE, GridFrame::OnBugsTable)
  161. EVT_MENU( ID_TABULAR_TABLE, GridFrame::OnTabularTable)
  162. EVT_MENU( ID_DESELECT_CELL, GridFrame::DeselectCell)
  163. EVT_MENU( ID_DESELECT_COL, GridFrame::DeselectCol)
  164. EVT_MENU( ID_DESELECT_ROW, GridFrame::DeselectRow)
  165. EVT_MENU( ID_DESELECT_ALL, GridFrame::DeselectAll)
  166. EVT_MENU( ID_SELECT_CELL, GridFrame::SelectCell)
  167. EVT_MENU( ID_SELECT_COL, GridFrame::SelectCol)
  168. EVT_MENU( ID_SELECT_ROW, GridFrame::SelectRow)
  169. EVT_MENU( ID_SELECT_ALL, GridFrame::SelectAll)
  170. EVT_MENU( ID_SELECT_UNSELECT, GridFrame::OnAddToSelectToggle)
  171. EVT_MENU( ID_SIZE_ROW, GridFrame::AutoSizeRow )
  172. EVT_MENU( ID_SIZE_COL, GridFrame::AutoSizeCol )
  173. EVT_MENU( ID_SIZE_ROW_LABEL, GridFrame::AutoSizeRowLabel )
  174. EVT_MENU( ID_SIZE_COL_LABEL, GridFrame::AutoSizeColLabel )
  175. EVT_MENU( ID_SIZE_LABELS_COL, GridFrame::AutoSizeLabelsCol )
  176. EVT_MENU( ID_SIZE_LABELS_ROW, GridFrame::AutoSizeLabelsRow )
  177. EVT_MENU( ID_SIZE_GRID, GridFrame::AutoSizeTable )
  178. EVT_MENU( ID_SET_HIGHLIGHT_WIDTH, GridFrame::OnSetHighlightWidth)
  179. EVT_MENU( ID_SET_RO_HIGHLIGHT_WIDTH, GridFrame::OnSetROHighlightWidth)
  180. EVT_MENU( wxID_PRINT, GridFrame::OnGridRender )
  181. EVT_MENU( ID_RENDER_COORDS, GridFrame::OnGridRender )
  182. EVT_GRID_LABEL_LEFT_CLICK( GridFrame::OnLabelLeftClick )
  183. EVT_GRID_CELL_LEFT_CLICK( GridFrame::OnCellLeftClick )
  184. EVT_GRID_ROW_SIZE( GridFrame::OnRowSize )
  185. EVT_GRID_COL_SIZE( GridFrame::OnColSize )
  186. EVT_GRID_SELECT_CELL( GridFrame::OnSelectCell )
  187. EVT_GRID_RANGE_SELECT( GridFrame::OnRangeSelected )
  188. EVT_GRID_CELL_CHANGING( GridFrame::OnCellValueChanging )
  189. EVT_GRID_CELL_CHANGED( GridFrame::OnCellValueChanged )
  190. EVT_GRID_CELL_BEGIN_DRAG( GridFrame::OnCellBeginDrag )
  191. EVT_GRID_EDITOR_SHOWN( GridFrame::OnEditorShown )
  192. EVT_GRID_EDITOR_HIDDEN( GridFrame::OnEditorHidden )
  193. END_EVENT_TABLE()
  194. GridFrame::GridFrame()
  195. : wxFrame( (wxFrame *)NULL, wxID_ANY, wxT("wxWidgets grid class demo"),
  196. wxDefaultPosition,
  197. wxDefaultSize )
  198. {
  199. SetIcon(wxICON(sample));
  200. wxMenu *fileMenu = new wxMenu;
  201. fileMenu->Append( ID_VTABLE, wxT("&Virtual table test\tCtrl-V"));
  202. fileMenu->Append( ID_BUGS_TABLE, wxT("&Bugs table test\tCtrl-B"));
  203. fileMenu->Append( ID_TABULAR_TABLE, wxT("&Tabular table test\tCtrl-T"));
  204. fileMenu->AppendSeparator();
  205. wxMenu* setupMenu = new wxMenu;
  206. wxMenuItem* item;
  207. item = setupMenu->AppendCheckItem( ID_RENDER_ROW_LABEL,
  208. "Render row labels" );
  209. item->Check();
  210. item = setupMenu->AppendCheckItem( ID_RENDER_COL_LABEL,
  211. "Render column labels" );
  212. item->Check();
  213. item = setupMenu->AppendCheckItem( ID_RENDER_GRID_LINES,
  214. "Render grid cell lines" );
  215. item->Check();
  216. item = setupMenu->AppendCheckItem( ID_RENDER_GRID_BORDER,
  217. "Render border" );
  218. item->Check();
  219. item = setupMenu->AppendCheckItem( ID_RENDER_SELECT_HLIGHT,
  220. "Render selection highlight" );
  221. setupMenu->AppendSeparator();
  222. setupMenu->AppendCheckItem( ID_RENDER_LOMETRIC,
  223. "Use LOMETRIC mapping mode" );
  224. setupMenu->AppendCheckItem( ID_RENDER_DEFAULT_SIZE,
  225. "Use wxDefaultSize" );
  226. setupMenu->AppendCheckItem( ID_RENDER_MARGIN,
  227. "Logical 50 unit margin" );
  228. setupMenu->AppendCheckItem( ID_RENDER_ZOOM,
  229. "Zoom 125%" );
  230. fileMenu->AppendSubMenu( setupMenu, "Render setup" );
  231. fileMenu->Append( wxID_PRINT, "Render" );
  232. fileMenu->Append( ID_RENDER_COORDS, "Render G5:P30" );
  233. fileMenu->AppendSeparator();
  234. fileMenu->Append( wxID_EXIT, wxT("E&xit\tAlt-X") );
  235. wxMenu *viewMenu = new wxMenu;
  236. viewMenu->AppendCheckItem(ID_TOGGLEROWLABELS, "&Row labels");
  237. viewMenu->AppendCheckItem(ID_TOGGLECOLLABELS, "&Col labels");
  238. viewMenu->AppendCheckItem(ID_TOGGLEEDIT,"&Editable");
  239. viewMenu->AppendCheckItem(ID_TOGGLEROWSIZING, "Ro&w drag-resize");
  240. viewMenu->AppendCheckItem(ID_TOGGLECOLSIZING, "C&ol drag-resize");
  241. viewMenu->AppendCheckItem(ID_TOGGLECOLMOVING, "Col drag-&move");
  242. viewMenu->AppendCheckItem(ID_TOGGLEGRIDSIZING, "&Grid drag-resize");
  243. viewMenu->AppendCheckItem(ID_TOGGLEGRIDDRAGCELL, "&Grid drag-cell");
  244. viewMenu->AppendCheckItem(ID_TOGGLEGRIDLINES, "&Grid Lines");
  245. viewMenu->AppendCheckItem(ID_SET_HIGHLIGHT_WIDTH, "&Set Cell Highlight Width...");
  246. viewMenu->AppendCheckItem(ID_SET_RO_HIGHLIGHT_WIDTH, "&Set Cell RO Highlight Width...");
  247. viewMenu->AppendCheckItem(ID_AUTOSIZECOLS, "&Auto-size cols");
  248. viewMenu->AppendCheckItem(ID_CELLOVERFLOW, "&Overflow cells");
  249. viewMenu->AppendCheckItem(ID_RESIZECELL, "&Resize cell (7,1)");
  250. wxMenu *rowLabelMenu = new wxMenu;
  251. viewMenu->Append( ID_ROWLABELALIGN, wxT("R&ow label alignment"),
  252. rowLabelMenu,
  253. wxT("Change alignment of row labels") );
  254. rowLabelMenu->AppendRadioItem( ID_ROWLABELHORIZALIGN, wxT("&Horizontal") );
  255. rowLabelMenu->AppendRadioItem( ID_ROWLABELVERTALIGN, wxT("&Vertical") );
  256. wxMenu *colLabelMenu = new wxMenu;
  257. viewMenu->Append( ID_COLLABELALIGN, wxT("Col l&abel alignment"),
  258. colLabelMenu,
  259. wxT("Change alignment of col labels") );
  260. colLabelMenu->AppendRadioItem( ID_COLLABELHORIZALIGN, wxT("&Horizontal") );
  261. colLabelMenu->AppendRadioItem( ID_COLLABELVERTALIGN, wxT("&Vertical") );
  262. wxMenu *colHeaderMenu = new wxMenu;
  263. viewMenu->Append( ID_ROWLABELALIGN, wxT("Col header style"),
  264. colHeaderMenu,
  265. wxT("Change style of col header") );
  266. colHeaderMenu->AppendRadioItem( ID_COLDEFAULTHEADER, wxT("&Default") );
  267. colHeaderMenu->AppendRadioItem( ID_COLNATIVEHEADER, wxT("&Native") );
  268. colHeaderMenu->AppendRadioItem( ID_COLCUSTOMHEADER, wxT("&Custom") );
  269. wxMenu *colMenu = new wxMenu;
  270. colMenu->Append( ID_SETLABELCOLOUR, wxT("Set &label colour...") );
  271. colMenu->Append( ID_SETLABELTEXTCOLOUR, wxT("Set label &text colour...") );
  272. colMenu->Append( ID_SETLABEL_FONT, wxT("Set label fo&nt...") );
  273. colMenu->Append( ID_GRIDLINECOLOUR, wxT("&Grid line colour...") );
  274. colMenu->Append( ID_SET_CELL_FG_COLOUR, wxT("Set cell &foreground colour...") );
  275. colMenu->Append( ID_SET_CELL_BG_COLOUR, wxT("Set cell &background colour...") );
  276. wxMenu *editMenu = new wxMenu;
  277. editMenu->Append( ID_INSERTROW, wxT("Insert &row") );
  278. editMenu->Append( ID_INSERTCOL, wxT("Insert &column") );
  279. editMenu->Append( ID_DELETEROW, wxT("Delete selected ro&ws") );
  280. editMenu->Append( ID_DELETECOL, wxT("Delete selected co&ls") );
  281. editMenu->Append( ID_CLEARGRID, wxT("Cl&ear grid cell contents") );
  282. wxMenu *selectMenu = new wxMenu;
  283. selectMenu->Append( ID_SELECT_UNSELECT, wxT("Add new cells to the selection"),
  284. wxT("When off, old selection is deselected before ")
  285. wxT("selecting the new cells"), wxITEM_CHECK );
  286. selectMenu->AppendSeparator();
  287. selectMenu->Append( ID_SELECT_ALL, wxT("Select all"));
  288. selectMenu->Append( ID_SELECT_ROW, wxT("Select row 2"));
  289. selectMenu->Append( ID_SELECT_COL, wxT("Select col 2"));
  290. selectMenu->Append( ID_SELECT_CELL, wxT("Select cell (3, 1)"));
  291. selectMenu->AppendSeparator();
  292. selectMenu->Append( ID_DESELECT_ALL, wxT("Deselect all"));
  293. selectMenu->Append( ID_DESELECT_ROW, wxT("Deselect row 2"));
  294. selectMenu->Append( ID_DESELECT_COL, wxT("Deselect col 2"));
  295. selectMenu->Append( ID_DESELECT_CELL, wxT("Deselect cell (3, 1)"));
  296. wxMenu *selectionMenu = new wxMenu;
  297. selectMenu->Append( ID_CHANGESEL, wxT("Change &selection mode"),
  298. selectionMenu,
  299. wxT("Change selection mode") );
  300. selectionMenu->Append( ID_SELCELLS, wxT("Select &cells") );
  301. selectionMenu->Append( ID_SELROWS, wxT("Select &rows") );
  302. selectionMenu->Append( ID_SELCOLS, wxT("Select col&umns") );
  303. selectionMenu->Append( ID_SELROWSORCOLS, wxT("Select rows &or columns") );
  304. wxMenu *autosizeMenu = new wxMenu;
  305. autosizeMenu->Append( ID_SIZE_ROW, wxT("Selected &row data") );
  306. autosizeMenu->Append( ID_SIZE_COL, wxT("Selected &column data") );
  307. autosizeMenu->Append( ID_SIZE_ROW_LABEL, wxT("Selected row la&bel") );
  308. autosizeMenu->Append( ID_SIZE_COL_LABEL, wxT("Selected column &label") );
  309. autosizeMenu->Append( ID_SIZE_LABELS_COL, wxT("Column la&bels") );
  310. autosizeMenu->Append( ID_SIZE_LABELS_ROW, wxT("Row label&s") );
  311. autosizeMenu->Append( ID_SIZE_GRID, wxT("Entire &grid") );
  312. wxMenu *helpMenu = new wxMenu;
  313. helpMenu->Append( wxID_ABOUT, wxT("&About wxGrid demo") );
  314. wxMenuBar *menuBar = new wxMenuBar;
  315. menuBar->Append( fileMenu, wxT("&File") );
  316. menuBar->Append( viewMenu, wxT("&Grid") );
  317. menuBar->Append( colMenu, wxT("&Colours") );
  318. menuBar->Append( editMenu, wxT("&Edit") );
  319. menuBar->Append( selectMenu, wxT("&Select") );
  320. menuBar->Append( autosizeMenu, wxT("&Autosize") );
  321. menuBar->Append( helpMenu, wxT("&Help") );
  322. SetMenuBar( menuBar );
  323. m_addToSel = false;
  324. grid = new wxGrid( this,
  325. wxID_ANY,
  326. wxPoint( 0, 0 ),
  327. wxSize( 400, 300 ) );
  328. #if wxUSE_LOG
  329. int gridW = 600, gridH = 300;
  330. int logW = gridW, logH = 100;
  331. logWin = new wxTextCtrl( this,
  332. wxID_ANY,
  333. wxEmptyString,
  334. wxPoint( 0, gridH + 20 ),
  335. wxSize( logW, logH ),
  336. wxTE_MULTILINE );
  337. logger = new wxLogTextCtrl( logWin );
  338. m_logOld = wxLog::SetActiveTarget( logger );
  339. wxLog::DisableTimestamp();
  340. #endif // wxUSE_LOG
  341. // this will create a grid and, by default, an associated grid
  342. // table for strings
  343. grid->CreateGrid( 0, 0 );
  344. grid->GetTable()->SetAttrProvider(new CustomColumnHeadersProvider());
  345. grid->AppendRows(100);
  346. grid->AppendCols(100);
  347. int ir = grid->GetNumberRows();
  348. grid->DeleteRows(0, ir);
  349. grid->AppendRows(ir);
  350. grid->SetRowSize( 0, 60 );
  351. grid->SetCellValue( 0, 0, wxT("Ctrl+Home\nwill go to\nthis cell") );
  352. grid->SetCellValue( 0, 1, wxT("A long piece of text to demonstrate wrapping.") );
  353. grid->SetCellRenderer(0 , 1, new wxGridCellAutoWrapStringRenderer);
  354. grid->SetCellEditor( 0, 1 , new wxGridCellAutoWrapStringEditor);
  355. grid->SetCellValue( 0, 2, wxT("Blah") );
  356. grid->SetCellValue( 0, 3, wxT("Read only") );
  357. grid->SetReadOnly( 0, 3 );
  358. grid->SetCellValue( 0, 4, wxT("Can veto edit this cell") );
  359. grid->SetCellValue( 0, 5, wxT("Press\nCtrl+arrow\nto skip over\ncells") );
  360. grid->SetRowSize( 99, 60 );
  361. grid->SetCellValue( 99, 99, wxT("Ctrl+End\nwill go to\nthis cell") );
  362. grid->SetCellValue( 1, 0, wxT("This default cell will overflow into neighboring cells, but not if you turn overflow off."));
  363. grid->SetCellTextColour(1, 2, *wxRED);
  364. grid->SetCellBackgroundColour(1, 2, *wxGREEN);
  365. grid->SetCellValue( 1, 4, wxT("I'm in the middle"));
  366. grid->SetCellValue(2, 2, wxT("red"));
  367. grid->SetCellTextColour(2, 2, *wxRED);
  368. grid->SetCellValue(3, 3, wxT("green on grey"));
  369. grid->SetCellTextColour(3, 3, *wxGREEN);
  370. grid->SetCellBackgroundColour(3, 3, *wxLIGHT_GREY);
  371. grid->SetCellValue(4, 4, wxT("a weird looking cell"));
  372. grid->SetCellAlignment(4, 4, wxALIGN_CENTRE, wxALIGN_CENTRE);
  373. grid->SetCellRenderer(4, 4, new MyGridCellRenderer);
  374. grid->SetCellRenderer(3, 0, new wxGridCellBoolRenderer);
  375. grid->SetCellEditor(3, 0, new wxGridCellBoolEditor);
  376. wxGridCellAttr *attr;
  377. attr = new wxGridCellAttr;
  378. attr->SetTextColour(*wxBLUE);
  379. grid->SetColAttr(5, attr);
  380. attr = new wxGridCellAttr;
  381. attr->SetBackgroundColour(*wxRED);
  382. grid->SetRowAttr(5, attr);
  383. grid->SetCellValue(2, 4, wxT("a wider column"));
  384. grid->SetColSize(4, 120);
  385. grid->SetColMinimalWidth(4, 120);
  386. grid->SetCellTextColour(5, 8, *wxGREEN);
  387. grid->SetCellValue(5, 8, wxT("Bg from row attr\nText col from cell attr"));
  388. grid->SetCellValue(5, 5, wxT("Bg from row attr Text col from col attr and this text is so long that it covers over many many empty cells but is broken by one that isn't"));
  389. // Some numeric columns with different formatting.
  390. grid->SetColFormatFloat(6);
  391. grid->SetCellValue(0, 6, "Default\nfloat format");
  392. grid->SetCellValue(1, 6, wxString::Format(wxT("%g"), 3.1415));
  393. grid->SetCellValue(2, 6, wxString::Format(wxT("%g"), 1415.0));
  394. grid->SetCellValue(3, 6, wxString::Format(wxT("%g"), 12345.67890));
  395. grid->SetColFormatFloat(7, 6, 2);
  396. grid->SetCellValue(0, 7, "Width 6\nprecision 2");
  397. grid->SetCellValue(1, 7, wxString::Format(wxT("%g"), 3.1415));
  398. grid->SetCellValue(2, 7, wxString::Format(wxT("%g"), 1415.0));
  399. grid->SetCellValue(3, 7, wxString::Format(wxT("%g"), 12345.67890));
  400. grid->SetColFormatCustom(8,
  401. wxString::Format("%s:%i,%i,%s", wxGRID_VALUE_FLOAT, -1, 4, "g"));
  402. grid->SetCellValue(0, 8, "Compact\nformat");
  403. grid->SetCellValue(1, 8, wxT("31415e-4"));
  404. grid->SetCellValue(2, 8, wxT("1415"));
  405. grid->SetCellValue(3, 8, wxT("123456789e-4"));
  406. grid->SetColFormatNumber(9);
  407. grid->SetCellValue(0, 9, "Integer\ncolumn");
  408. grid->SetCellValue(1, 9, "17");
  409. grid->SetCellValue(2, 9, "0");
  410. grid->SetCellValue(3, 9, "-666");
  411. grid->SetCellAlignment(3, 9, wxALIGN_CENTRE, wxALIGN_TOP);
  412. grid->SetCellValue(3, 10, "<- This numeric cell should be centred");
  413. const wxString choices[] =
  414. {
  415. wxT("Please select a choice"),
  416. wxT("This takes two cells"),
  417. wxT("Another choice"),
  418. };
  419. grid->SetCellEditor(4, 0, new wxGridCellChoiceEditor(WXSIZEOF(choices), choices));
  420. grid->SetCellSize(4, 0, 1, 2);
  421. grid->SetCellValue(4, 0, choices[0]);
  422. grid->SetCellOverflow(4, 0, false);
  423. grid->SetCellSize(7, 1, 3, 4);
  424. grid->SetCellAlignment(7, 1, wxALIGN_CENTRE, wxALIGN_CENTRE);
  425. grid->SetCellValue(7, 1, wxT("Big box!"));
  426. // create a separator-like row: it's grey and it's non-resizable
  427. grid->DisableRowResize(10);
  428. grid->SetRowSize(10, 30);
  429. attr = new wxGridCellAttr;
  430. attr->SetBackgroundColour(*wxLIGHT_GREY);
  431. grid->SetRowAttr(10, attr);
  432. grid->SetCellValue(10, 0, "You can't resize this row interactively -- try it");
  433. // this does exactly nothing except testing that SetAttr() handles NULL
  434. // attributes and does reference counting correctly
  435. grid->SetAttr(11, 11, NULL);
  436. grid->SetAttr(11, 11, new wxGridCellAttr);
  437. grid->SetAttr(11, 11, NULL);
  438. wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
  439. topSizer->Add( grid,
  440. 1,
  441. wxEXPAND );
  442. #if wxUSE_LOG
  443. topSizer->Add( logWin,
  444. 0,
  445. wxEXPAND );
  446. #endif // wxUSE_LOG
  447. SetSizerAndFit( topSizer );
  448. Centre();
  449. SetDefaults();
  450. }
  451. GridFrame::~GridFrame()
  452. {
  453. #if wxUSE_LOG
  454. delete wxLog::SetActiveTarget(m_logOld);
  455. #endif // wxUSE_LOG
  456. }
  457. void GridFrame::SetDefaults()
  458. {
  459. GetMenuBar()->Check( ID_TOGGLEROWLABELS, true );
  460. GetMenuBar()->Check( ID_TOGGLECOLLABELS, true );
  461. GetMenuBar()->Check( ID_TOGGLEEDIT, true );
  462. GetMenuBar()->Check( ID_TOGGLEROWSIZING, true );
  463. GetMenuBar()->Check( ID_TOGGLECOLSIZING, true );
  464. GetMenuBar()->Check( ID_TOGGLECOLMOVING, false );
  465. GetMenuBar()->Check( ID_TOGGLEGRIDSIZING, true );
  466. GetMenuBar()->Check( ID_TOGGLEGRIDDRAGCELL, false );
  467. GetMenuBar()->Check( ID_TOGGLEGRIDLINES, true );
  468. GetMenuBar()->Check( ID_CELLOVERFLOW, true );
  469. }
  470. void GridFrame::ToggleRowLabels( wxCommandEvent& WXUNUSED(ev) )
  471. {
  472. if ( GetMenuBar()->IsChecked( ID_TOGGLEROWLABELS ) )
  473. {
  474. grid->SetRowLabelSize( grid->GetDefaultRowLabelSize() );
  475. }
  476. else
  477. {
  478. grid->SetRowLabelSize( 0 );
  479. }
  480. }
  481. void GridFrame::ToggleColLabels( wxCommandEvent& WXUNUSED(ev) )
  482. {
  483. if ( GetMenuBar()->IsChecked( ID_TOGGLECOLLABELS ) )
  484. {
  485. grid->SetColLabelSize( grid->GetDefaultColLabelSize() );
  486. }
  487. else
  488. {
  489. grid->SetColLabelSize( 0 );
  490. }
  491. }
  492. void GridFrame::ToggleEditing( wxCommandEvent& WXUNUSED(ev) )
  493. {
  494. grid->EnableEditing(
  495. GetMenuBar()->IsChecked( ID_TOGGLEEDIT ) );
  496. }
  497. void GridFrame::ToggleRowSizing( wxCommandEvent& WXUNUSED(ev) )
  498. {
  499. grid->EnableDragRowSize(
  500. GetMenuBar()->IsChecked( ID_TOGGLEROWSIZING ) );
  501. }
  502. void GridFrame::ToggleColSizing( wxCommandEvent& WXUNUSED(ev) )
  503. {
  504. grid->EnableDragColSize(
  505. GetMenuBar()->IsChecked( ID_TOGGLECOLSIZING ) );
  506. }
  507. void GridFrame::ToggleColMoving( wxCommandEvent& WXUNUSED(ev) )
  508. {
  509. grid->EnableDragColMove(
  510. GetMenuBar()->IsChecked( ID_TOGGLECOLMOVING ) );
  511. }
  512. void GridFrame::ToggleGridSizing( wxCommandEvent& WXUNUSED(ev) )
  513. {
  514. grid->EnableDragGridSize(
  515. GetMenuBar()->IsChecked( ID_TOGGLEGRIDSIZING ) );
  516. }
  517. void GridFrame::ToggleGridDragCell( wxCommandEvent& WXUNUSED(ev) )
  518. {
  519. grid->EnableDragCell(
  520. GetMenuBar()->IsChecked( ID_TOGGLEGRIDDRAGCELL ) );
  521. }
  522. void GridFrame::SetNativeColHeader( wxCommandEvent& WXUNUSED(ev) )
  523. {
  524. CustomColumnHeadersProvider* provider =
  525. static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
  526. provider->UseCustomColHeaders(false);
  527. grid->SetUseNativeColLabels(true);
  528. }
  529. void GridFrame::SetCustomColHeader( wxCommandEvent& WXUNUSED(ev) )
  530. {
  531. CustomColumnHeadersProvider* provider =
  532. static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
  533. provider->UseCustomColHeaders(true);
  534. grid->SetUseNativeColLabels(false);
  535. }
  536. void GridFrame::SetDefaultColHeader( wxCommandEvent& WXUNUSED(ev) )
  537. {
  538. CustomColumnHeadersProvider* provider =
  539. static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
  540. provider->UseCustomColHeaders(false);
  541. grid->SetUseNativeColLabels(false);
  542. }
  543. void GridFrame::ToggleGridLines( wxCommandEvent& WXUNUSED(ev) )
  544. {
  545. grid->EnableGridLines(
  546. GetMenuBar()->IsChecked( ID_TOGGLEGRIDLINES ) );
  547. }
  548. void GridFrame::OnSetHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
  549. {
  550. wxString choices[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"), wxT("7"), wxT("8"), wxT("9"), wxT("10")};
  551. wxSingleChoiceDialog dlg(this, wxT("Choose the thickness of the highlight pen:"),
  552. wxT("Pen Width"), 11, choices);
  553. int current = grid->GetCellHighlightPenWidth();
  554. dlg.SetSelection(current);
  555. if (dlg.ShowModal() == wxID_OK) {
  556. grid->SetCellHighlightPenWidth(dlg.GetSelection());
  557. }
  558. }
  559. void GridFrame::OnSetROHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
  560. {
  561. wxString choices[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"), wxT("7"), wxT("8"), wxT("9"), wxT("10")};
  562. wxSingleChoiceDialog dlg(this, wxT("Choose the thickness of the highlight pen:"),
  563. wxT("Pen Width"), 11, choices);
  564. int current = grid->GetCellHighlightROPenWidth();
  565. dlg.SetSelection(current);
  566. if (dlg.ShowModal() == wxID_OK) {
  567. grid->SetCellHighlightROPenWidth(dlg.GetSelection());
  568. }
  569. }
  570. void GridFrame::AutoSizeCols( wxCommandEvent& WXUNUSED(ev) )
  571. {
  572. grid->AutoSizeColumns();
  573. grid->Refresh();
  574. }
  575. void GridFrame::CellOverflow( wxCommandEvent& ev )
  576. {
  577. grid->SetDefaultCellOverflow(ev.IsChecked());
  578. grid->Refresh();
  579. }
  580. void GridFrame::ResizeCell( wxCommandEvent& ev )
  581. {
  582. if (ev.IsChecked())
  583. grid->SetCellSize( 7, 1, 5, 5 );
  584. else
  585. grid->SetCellSize( 7, 1, 1, 5 );
  586. grid->Refresh();
  587. }
  588. void GridFrame::SetLabelColour( wxCommandEvent& WXUNUSED(ev) )
  589. {
  590. wxColourDialog dlg( NULL );
  591. if ( dlg.ShowModal() == wxID_OK )
  592. {
  593. wxColourData retData;
  594. retData = dlg.GetColourData();
  595. wxColour colour = retData.GetColour();
  596. grid->SetLabelBackgroundColour( colour );
  597. }
  598. }
  599. void GridFrame::SetLabelTextColour( wxCommandEvent& WXUNUSED(ev) )
  600. {
  601. wxColourDialog dlg( NULL );
  602. if ( dlg.ShowModal() == wxID_OK )
  603. {
  604. wxColourData retData;
  605. retData = dlg.GetColourData();
  606. wxColour colour = retData.GetColour();
  607. grid->SetLabelTextColour( colour );
  608. }
  609. }
  610. void GridFrame::SetLabelFont( wxCommandEvent& WXUNUSED(ev) )
  611. {
  612. wxFont font = wxGetFontFromUser(this);
  613. if ( font.IsOk() )
  614. {
  615. grid->SetLabelFont(font);
  616. }
  617. }
  618. void GridFrame::SetRowLabelHorizAlignment( wxCommandEvent& WXUNUSED(ev) )
  619. {
  620. int horiz, vert;
  621. grid->GetRowLabelAlignment( &horiz, &vert );
  622. switch ( horiz )
  623. {
  624. case wxALIGN_LEFT:
  625. horiz = wxALIGN_CENTRE;
  626. break;
  627. case wxALIGN_CENTRE:
  628. horiz = wxALIGN_RIGHT;
  629. break;
  630. case wxALIGN_RIGHT:
  631. horiz = wxALIGN_LEFT;
  632. break;
  633. }
  634. grid->SetRowLabelAlignment( horiz, vert );
  635. }
  636. void GridFrame::SetRowLabelVertAlignment( wxCommandEvent& WXUNUSED(ev) )
  637. {
  638. int horiz, vert;
  639. grid->GetRowLabelAlignment( &horiz, &vert );
  640. switch ( vert )
  641. {
  642. case wxALIGN_TOP:
  643. vert = wxALIGN_CENTRE;
  644. break;
  645. case wxALIGN_CENTRE:
  646. vert = wxALIGN_BOTTOM;
  647. break;
  648. case wxALIGN_BOTTOM:
  649. vert = wxALIGN_TOP;
  650. break;
  651. }
  652. grid->SetRowLabelAlignment( horiz, vert );
  653. }
  654. void GridFrame::SetColLabelHorizAlignment( wxCommandEvent& WXUNUSED(ev) )
  655. {
  656. int horiz, vert;
  657. grid->GetColLabelAlignment( &horiz, &vert );
  658. switch ( horiz )
  659. {
  660. case wxALIGN_LEFT:
  661. horiz = wxALIGN_CENTRE;
  662. break;
  663. case wxALIGN_CENTRE:
  664. horiz = wxALIGN_RIGHT;
  665. break;
  666. case wxALIGN_RIGHT:
  667. horiz = wxALIGN_LEFT;
  668. break;
  669. }
  670. grid->SetColLabelAlignment( horiz, vert );
  671. }
  672. void GridFrame::SetColLabelVertAlignment( wxCommandEvent& WXUNUSED(ev) )
  673. {
  674. int horiz, vert;
  675. grid->GetColLabelAlignment( &horiz, &vert );
  676. switch ( vert )
  677. {
  678. case wxALIGN_TOP:
  679. vert = wxALIGN_CENTRE;
  680. break;
  681. case wxALIGN_CENTRE:
  682. vert = wxALIGN_BOTTOM;
  683. break;
  684. case wxALIGN_BOTTOM:
  685. vert = wxALIGN_TOP;
  686. break;
  687. }
  688. grid->SetColLabelAlignment( horiz, vert );
  689. }
  690. void GridFrame::SetGridLineColour( wxCommandEvent& WXUNUSED(ev) )
  691. {
  692. wxColourDialog dlg( NULL );
  693. if ( dlg.ShowModal() == wxID_OK )
  694. {
  695. wxColourData retData;
  696. retData = dlg.GetColourData();
  697. wxColour colour = retData.GetColour();
  698. grid->SetGridLineColour( colour );
  699. }
  700. }
  701. void GridFrame::InsertRow( wxCommandEvent& WXUNUSED(ev) )
  702. {
  703. grid->InsertRows( grid->GetGridCursorRow(), 1 );
  704. }
  705. void GridFrame::InsertCol( wxCommandEvent& WXUNUSED(ev) )
  706. {
  707. grid->InsertCols( grid->GetGridCursorCol(), 1 );
  708. }
  709. void GridFrame::DeleteSelectedRows( wxCommandEvent& WXUNUSED(ev) )
  710. {
  711. if ( grid->IsSelection() )
  712. {
  713. wxGridUpdateLocker locker(grid);
  714. for ( int n = 0; n < grid->GetNumberRows(); )
  715. {
  716. if ( grid->IsInSelection( n , 0 ) )
  717. grid->DeleteRows( n, 1 );
  718. else
  719. n++;
  720. }
  721. }
  722. }
  723. void GridFrame::AutoSizeRow(wxCommandEvent& WXUNUSED(event))
  724. {
  725. wxGridUpdateLocker locker(grid);
  726. const wxArrayInt sels = grid->GetSelectedRows();
  727. for ( size_t n = 0, count = sels.size(); n < count; n++ )
  728. {
  729. grid->AutoSizeRow( sels[n], false );
  730. }
  731. }
  732. void GridFrame::AutoSizeCol(wxCommandEvent& WXUNUSED(event))
  733. {
  734. wxGridUpdateLocker locker(grid);
  735. const wxArrayInt sels = grid->GetSelectedCols();
  736. for ( size_t n = 0, count = sels.size(); n < count; n++ )
  737. {
  738. grid->AutoSizeColumn( sels[n], false );
  739. }
  740. }
  741. void GridFrame::AutoSizeRowLabel(wxCommandEvent& WXUNUSED(event))
  742. {
  743. wxGridUpdateLocker locker(grid);
  744. const wxArrayInt sels = grid->GetSelectedRows();
  745. for ( size_t n = 0, count = sels.size(); n < count; n++ )
  746. {
  747. grid->AutoSizeRowLabelSize( sels[n] );
  748. }
  749. }
  750. void GridFrame::AutoSizeColLabel(wxCommandEvent& WXUNUSED(event))
  751. {
  752. wxGridUpdateLocker locker(grid);
  753. const wxArrayInt sels = grid->GetSelectedCols();
  754. for ( size_t n = 0, count = sels.size(); n < count; n++ )
  755. {
  756. grid->AutoSizeColLabelSize( sels[n] );
  757. }
  758. }
  759. void GridFrame::AutoSizeLabelsCol(wxCommandEvent& WXUNUSED(event))
  760. {
  761. grid->SetColLabelSize( wxGRID_AUTOSIZE );
  762. }
  763. void GridFrame::AutoSizeLabelsRow(wxCommandEvent& WXUNUSED(event))
  764. {
  765. grid->SetRowLabelSize( wxGRID_AUTOSIZE );
  766. }
  767. void GridFrame::AutoSizeTable(wxCommandEvent& WXUNUSED(event))
  768. {
  769. grid->AutoSize();
  770. }
  771. void GridFrame::DeleteSelectedCols( wxCommandEvent& WXUNUSED(ev) )
  772. {
  773. if ( grid->IsSelection() )
  774. {
  775. wxGridUpdateLocker locker(grid);
  776. for ( int n = 0; n < grid->GetNumberCols(); )
  777. {
  778. if ( grid->IsInSelection( 0 , n ) )
  779. grid->DeleteCols( n, 1 );
  780. else
  781. n++;
  782. }
  783. }
  784. }
  785. void GridFrame::ClearGrid( wxCommandEvent& WXUNUSED(ev) )
  786. {
  787. grid->ClearGrid();
  788. }
  789. void GridFrame::SelectCells( wxCommandEvent& WXUNUSED(ev) )
  790. {
  791. grid->SetSelectionMode( wxGrid::wxGridSelectCells );
  792. }
  793. void GridFrame::SelectRows( wxCommandEvent& WXUNUSED(ev) )
  794. {
  795. grid->SetSelectionMode( wxGrid::wxGridSelectRows );
  796. }
  797. void GridFrame::SelectCols( wxCommandEvent& WXUNUSED(ev) )
  798. {
  799. grid->SetSelectionMode( wxGrid::wxGridSelectColumns );
  800. }
  801. void GridFrame::SelectRowsOrCols( wxCommandEvent& WXUNUSED(ev) )
  802. {
  803. grid->SetSelectionMode( wxGrid::wxGridSelectRowsOrColumns );
  804. }
  805. void GridFrame::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) )
  806. {
  807. wxColour col = wxGetColourFromUser(this);
  808. if ( col.IsOk() )
  809. {
  810. grid->SetDefaultCellTextColour(col);
  811. grid->Refresh();
  812. }
  813. }
  814. void GridFrame::SetCellBgColour( wxCommandEvent& WXUNUSED(ev) )
  815. {
  816. wxColour col = wxGetColourFromUser(this);
  817. if ( col.IsOk() )
  818. {
  819. // Check the new Refresh function by passing it a rectangle
  820. // which exactly fits the grid.
  821. wxPoint pt(0, 0);
  822. wxRect r(pt, grid->GetSize());
  823. grid->SetDefaultCellBackgroundColour(col);
  824. grid->Refresh(true, &r);
  825. }
  826. }
  827. void GridFrame::DeselectCell(wxCommandEvent& WXUNUSED(event))
  828. {
  829. grid->DeselectCell(3, 1);
  830. }
  831. void GridFrame::DeselectCol(wxCommandEvent& WXUNUSED(event))
  832. {
  833. grid->DeselectCol(2);
  834. }
  835. void GridFrame::DeselectRow(wxCommandEvent& WXUNUSED(event))
  836. {
  837. grid->DeselectRow(2);
  838. }
  839. void GridFrame::DeselectAll(wxCommandEvent& WXUNUSED(event))
  840. {
  841. grid->ClearSelection();
  842. }
  843. void GridFrame::SelectCell(wxCommandEvent& WXUNUSED(event))
  844. {
  845. grid->SelectBlock(3, 1, 3, 1, m_addToSel);
  846. }
  847. void GridFrame::SelectCol(wxCommandEvent& WXUNUSED(event))
  848. {
  849. grid->SelectCol(2, m_addToSel);
  850. }
  851. void GridFrame::SelectRow(wxCommandEvent& WXUNUSED(event))
  852. {
  853. grid->SelectRow(2, m_addToSel);
  854. }
  855. void GridFrame::SelectAll(wxCommandEvent& WXUNUSED(event))
  856. {
  857. grid->SelectAll();
  858. }
  859. void GridFrame::OnAddToSelectToggle(wxCommandEvent& event)
  860. {
  861. m_addToSel = event.IsChecked();
  862. }
  863. void GridFrame::OnLabelLeftClick( wxGridEvent& ev )
  864. {
  865. wxString logBuf;
  866. if ( ev.GetRow() != -1 )
  867. {
  868. logBuf << wxT("Left click on row label ") << ev.GetRow();
  869. }
  870. else if ( ev.GetCol() != -1 )
  871. {
  872. logBuf << wxT("Left click on col label ") << ev.GetCol();
  873. }
  874. else
  875. {
  876. logBuf << wxT("Left click on corner label");
  877. }
  878. if ( ev.ShiftDown() )
  879. logBuf << wxT(" (shift down)");
  880. if ( ev.ControlDown() )
  881. logBuf << wxT(" (control down)");
  882. wxLogMessage( wxT("%s"), logBuf.c_str() );
  883. // you must call event skip if you want default grid processing
  884. //
  885. ev.Skip();
  886. }
  887. void GridFrame::OnCellLeftClick( wxGridEvent& ev )
  888. {
  889. wxLogMessage(wxT("Left click at row %d, col %d"), ev.GetRow(), ev.GetCol());
  890. // you must call event skip if you want default grid processing
  891. // (cell highlighting etc.)
  892. //
  893. ev.Skip();
  894. }
  895. void GridFrame::OnRowSize( wxGridSizeEvent& ev )
  896. {
  897. const int row = ev.GetRowOrCol();
  898. wxLogMessage("Resized row %d, new height = %d",
  899. row, grid->GetRowSize(row));
  900. ev.Skip();
  901. }
  902. void GridFrame::OnColSize( wxGridSizeEvent& ev )
  903. {
  904. const int col = ev.GetRowOrCol();
  905. wxLogMessage("Resized column %d, new width = %d",
  906. col, grid->GetColSize(col));
  907. ev.Skip();
  908. }
  909. void GridFrame::OnSelectCell( wxGridEvent& ev )
  910. {
  911. wxString logBuf;
  912. if ( ev.Selecting() )
  913. logBuf << wxT("Selected ");
  914. else
  915. logBuf << wxT("Deselected ");
  916. logBuf << wxT("cell at row ") << ev.GetRow()
  917. << wxT(" col ") << ev.GetCol()
  918. << wxT(" ( ControlDown: ")<< (ev.ControlDown() ? 'T':'F')
  919. << wxT(", ShiftDown: ")<< (ev.ShiftDown() ? 'T':'F')
  920. << wxT(", AltDown: ")<< (ev.AltDown() ? 'T':'F')
  921. << wxT(", MetaDown: ")<< (ev.MetaDown() ? 'T':'F') << wxT(" )");
  922. //Indicate whether this column was moved
  923. if ( ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() ) != ev.GetCol() )
  924. logBuf << wxT(" *** Column moved, current position: ") << ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() );
  925. wxLogMessage( wxT("%s"), logBuf.c_str() );
  926. // you must call Skip() if you want the default processing
  927. // to occur in wxGrid
  928. ev.Skip();
  929. }
  930. void GridFrame::OnRangeSelected( wxGridRangeSelectEvent& ev )
  931. {
  932. wxString logBuf;
  933. if ( ev.Selecting() )
  934. logBuf << wxT("Selected ");
  935. else
  936. logBuf << wxT("Deselected ");
  937. logBuf << wxT("cells from row ") << ev.GetTopRow()
  938. << wxT(" col ") << ev.GetLeftCol()
  939. << wxT(" to row ") << ev.GetBottomRow()
  940. << wxT(" col ") << ev.GetRightCol()
  941. << wxT(" ( ControlDown: ")<< (ev.ControlDown() ? 'T':'F')
  942. << wxT(", ShiftDown: ")<< (ev.ShiftDown() ? 'T':'F')
  943. << wxT(", AltDown: ")<< (ev.AltDown() ? 'T':'F')
  944. << wxT(", MetaDown: ")<< (ev.MetaDown() ? 'T':'F') << wxT(" )");
  945. wxLogMessage( wxT("%s"), logBuf.c_str() );
  946. ev.Skip();
  947. }
  948. void GridFrame::OnCellValueChanging( wxGridEvent& ev )
  949. {
  950. int row = ev.GetRow(),
  951. col = ev.GetCol();
  952. wxLogMessage("Value of cell at (%d, %d): about to change "
  953. "from \"%s\" to \"%s\"",
  954. row, col,
  955. grid->GetCellValue(row, col), ev.GetString());
  956. // test how vetoing works
  957. if ( ev.GetString() == "42" )
  958. {
  959. wxLogMessage("Vetoing the change.");
  960. ev.Veto();
  961. return;
  962. }
  963. ev.Skip();
  964. }
  965. void GridFrame::OnCellValueChanged( wxGridEvent& ev )
  966. {
  967. int row = ev.GetRow(),
  968. col = ev.GetCol();
  969. wxLogMessage("Value of cell at (%d, %d) changed and is now \"%s\" "
  970. "(was \"%s\")",
  971. row, col,
  972. grid->GetCellValue(row, col), ev.GetString());
  973. ev.Skip();
  974. }
  975. void GridFrame::OnCellBeginDrag( wxGridEvent& ev )
  976. {
  977. wxLogMessage(wxT("Got request to drag cell at row %d, col %d"),
  978. ev.GetRow(), ev.GetCol());
  979. ev.Skip();
  980. }
  981. void GridFrame::OnEditorShown( wxGridEvent& ev )
  982. {
  983. if ( (ev.GetCol() == 4) &&
  984. (ev.GetRow() == 0) &&
  985. (wxMessageBox(wxT("Are you sure you wish to edit this cell"),
  986. wxT("Checking"),wxYES_NO) == wxNO ) ) {
  987. ev.Veto();
  988. return;
  989. }
  990. wxLogMessage( wxT("Cell editor shown.") );
  991. ev.Skip();
  992. }
  993. void GridFrame::OnEditorHidden( wxGridEvent& ev )
  994. {
  995. if ( (ev.GetCol() == 4) &&
  996. (ev.GetRow() == 0) &&
  997. (wxMessageBox(wxT("Are you sure you wish to finish editing this cell"),
  998. wxT("Checking"),wxYES_NO) == wxNO ) ) {
  999. ev.Veto();
  1000. return;
  1001. }
  1002. wxLogMessage( wxT("Cell editor hidden.") );
  1003. ev.Skip();
  1004. }
  1005. void GridFrame::About( wxCommandEvent& WXUNUSED(ev) )
  1006. {
  1007. wxAboutDialogInfo aboutInfo;
  1008. aboutInfo.SetName(wxT("wxGrid demo"));
  1009. aboutInfo.SetDescription(_("wxGrid sample program"));
  1010. aboutInfo.AddDeveloper(wxT("Michael Bedward"));
  1011. aboutInfo.AddDeveloper(wxT("Julian Smart"));
  1012. aboutInfo.AddDeveloper(wxT("Vadim Zeitlin"));
  1013. // this is just to force the generic version of the about
  1014. // dialog under wxMSW so that it's easy to test if the grid
  1015. // repaints correctly when it has lost focus and a dialog
  1016. // (different from the Windows standard message box -- it doesn't
  1017. // work with it for some reason) is moved over it.
  1018. aboutInfo.SetWebSite(wxT("http://www.wxwidgets.org"));
  1019. wxAboutBox(aboutInfo);
  1020. }
  1021. void GridFrame::OnQuit( wxCommandEvent& WXUNUSED(ev) )
  1022. {
  1023. Close( true );
  1024. }
  1025. void GridFrame::OnBugsTable(wxCommandEvent& )
  1026. {
  1027. BugsGridFrame *frame = new BugsGridFrame;
  1028. frame->Show(true);
  1029. }
  1030. // ----------------------------------------------------------------------------
  1031. // MyGridCellAttrProvider
  1032. // ----------------------------------------------------------------------------
  1033. MyGridCellAttrProvider::MyGridCellAttrProvider()
  1034. {
  1035. m_attrForOddRows = new wxGridCellAttr;
  1036. m_attrForOddRows->SetBackgroundColour(*wxLIGHT_GREY);
  1037. }
  1038. MyGridCellAttrProvider::~MyGridCellAttrProvider()
  1039. {
  1040. m_attrForOddRows->DecRef();
  1041. }
  1042. wxGridCellAttr *MyGridCellAttrProvider::GetAttr(int row, int col,
  1043. wxGridCellAttr::wxAttrKind kind /* = wxGridCellAttr::Any */) const
  1044. {
  1045. wxGridCellAttr *attr = wxGridCellAttrProvider::GetAttr(row, col, kind);
  1046. if ( row % 2 )
  1047. {
  1048. if ( !attr )
  1049. {
  1050. attr = m_attrForOddRows;
  1051. attr->IncRef();
  1052. }
  1053. else
  1054. {
  1055. if ( !attr->HasBackgroundColour() )
  1056. {
  1057. wxGridCellAttr *attrNew = attr->Clone();
  1058. attr->DecRef();
  1059. attr = attrNew;
  1060. attr->SetBackgroundColour(*wxLIGHT_GREY);
  1061. }
  1062. }
  1063. }
  1064. return attr;
  1065. }
  1066. void GridFrame::OnVTable(wxCommandEvent& )
  1067. {
  1068. static long s_sizeGrid = 10000;
  1069. s_sizeGrid = wxGetNumberFromUser(wxT("Size of the table to create"),
  1070. wxT("Size: "),
  1071. wxT("wxGridDemo question"),
  1072. s_sizeGrid,
  1073. 0, 32000, this);
  1074. if ( s_sizeGrid != -1 )
  1075. {
  1076. BigGridFrame* win = new BigGridFrame(s_sizeGrid);
  1077. win->Show(true);
  1078. }
  1079. }
  1080. // ----------------------------------------------------------------------------
  1081. // MyGridCellRenderer
  1082. // ----------------------------------------------------------------------------
  1083. // do something that the default renderer doesn't here just to show that it is
  1084. // possible to alter the appearance of the cell beyond what the attributes
  1085. // allow
  1086. void MyGridCellRenderer::Draw(wxGrid& grid,
  1087. wxGridCellAttr& attr,
  1088. wxDC& dc,
  1089. const wxRect& rect,
  1090. int row, int col,
  1091. bool isSelected)
  1092. {
  1093. wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
  1094. dc.SetPen(*wxGREEN_PEN);
  1095. dc.SetBrush(*wxTRANSPARENT_BRUSH);
  1096. dc.DrawEllipse(rect);
  1097. }
  1098. // ============================================================================
  1099. // BigGridFrame and BigGridTable: Sample of a non-standard table
  1100. // ============================================================================
  1101. BigGridFrame::BigGridFrame(long sizeGrid)
  1102. : wxFrame(NULL, wxID_ANY, wxT("Plugin Virtual Table"),
  1103. wxDefaultPosition, wxSize(500, 450))
  1104. {
  1105. m_grid = new wxGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
  1106. m_table = new BigGridTable(sizeGrid);
  1107. // VZ: I don't understand why this slows down the display that much,
  1108. // must profile it...
  1109. //m_table->SetAttrProvider(new MyGridCellAttrProvider);
  1110. m_grid->SetTable(m_table, true);
  1111. #if defined __WXMOTIF__
  1112. // MB: the grid isn't getting a sensible default size under wxMotif
  1113. int cw, ch;
  1114. GetClientSize( &cw, &ch );
  1115. m_grid->SetSize( cw, ch );
  1116. #endif
  1117. }
  1118. // ============================================================================
  1119. // BugsGridFrame: a "realistic" table
  1120. // ============================================================================
  1121. // ----------------------------------------------------------------------------
  1122. // bugs table data
  1123. // ----------------------------------------------------------------------------
  1124. enum Columns
  1125. {
  1126. Col_Id,
  1127. Col_Summary,
  1128. Col_Severity,
  1129. Col_Priority,
  1130. Col_Platform,
  1131. Col_Opened,
  1132. Col_Max
  1133. };
  1134. enum Severity
  1135. {
  1136. Sev_Wish,
  1137. Sev_Minor,
  1138. Sev_Normal,
  1139. Sev_Major,
  1140. Sev_Critical,
  1141. Sev_Max
  1142. };
  1143. static const wxString severities[] =
  1144. {
  1145. wxT("wishlist"),
  1146. wxT("minor"),
  1147. wxT("normal"),
  1148. wxT("major"),
  1149. wxT("critical"),
  1150. };
  1151. static struct BugsGridData
  1152. {
  1153. int id;
  1154. wxChar summary[80];
  1155. Severity severity;
  1156. int prio;
  1157. wxChar platform[12];
  1158. bool opened;
  1159. } gs_dataBugsGrid [] =
  1160. {
  1161. { 18, wxT("foo doesn't work"), Sev_Major, 1, wxT("wxMSW"), true },
  1162. { 27, wxT("bar crashes"), Sev_Critical, 1, wxT("all"), false },
  1163. { 45, wxT("printing is slow"), Sev_Minor, 3, wxT("wxMSW"), true },
  1164. { 68, wxT("Rectangle() fails"), Sev_Normal, 1, wxT("wxMSW"), false },
  1165. };
  1166. static const wxChar *headers[Col_Max] =
  1167. {
  1168. wxT("Id"),
  1169. wxT("Summary"),
  1170. wxT("Severity"),
  1171. wxT("Priority"),
  1172. wxT("Platform"),
  1173. wxT("Opened?"),
  1174. };
  1175. // ----------------------------------------------------------------------------
  1176. // BugsGridTable
  1177. // ----------------------------------------------------------------------------
  1178. wxString BugsGridTable::GetTypeName(int WXUNUSED(row), int col)
  1179. {
  1180. switch ( col )
  1181. {
  1182. case Col_Id:
  1183. case Col_Priority:
  1184. return wxGRID_VALUE_NUMBER;;
  1185. case Col_Severity:
  1186. // fall thorugh (TODO should be a list)
  1187. case Col_Summary:
  1188. return wxString::Format(wxT("%s:80"), wxGRID_VALUE_STRING);
  1189. case Col_Platform:
  1190. return wxString::Format(wxT("%s:all,MSW,GTK,other"), wxGRID_VALUE_CHOICE);
  1191. case Col_Opened:
  1192. return wxGRID_VALUE_BOOL;
  1193. }
  1194. wxFAIL_MSG(wxT("unknown column"));
  1195. return wxEmptyString;
  1196. }
  1197. int BugsGridTable::GetNumberRows()
  1198. {
  1199. return WXSIZEOF(gs_dataBugsGrid);
  1200. }
  1201. int BugsGridTable::GetNumberCols()
  1202. {
  1203. return Col_Max;
  1204. }
  1205. bool BugsGridTable::IsEmptyCell( int WXUNUSED(row), int WXUNUSED(col) )
  1206. {
  1207. return false;
  1208. }
  1209. wxString BugsGridTable::GetValue( int row, int col )
  1210. {
  1211. const BugsGridData& gd = gs_dataBugsGrid[row];
  1212. switch ( col )
  1213. {
  1214. case Col_Id:
  1215. return wxString::Format(wxT("%d"), gd.id);
  1216. case Col_Priority:
  1217. return wxString::Format(wxT("%d"), gd.prio);
  1218. case Col_Opened:
  1219. return gd.opened ? wxT("1") : wxT("0");
  1220. case Col_Severity:
  1221. return severities[gd.severity];
  1222. case Col_Summary:
  1223. return gd.summary;
  1224. case Col_Platform:
  1225. return gd.platform;
  1226. }
  1227. return wxEmptyString;
  1228. }
  1229. void BugsGridTable::SetValue( int row, int col, const wxString& value )
  1230. {
  1231. BugsGridData& gd = gs_dataBugsGrid[row];
  1232. switch ( col )
  1233. {
  1234. case Col_Id:
  1235. case Col_Priority:
  1236. case Col_Opened:
  1237. wxFAIL_MSG(wxT("unexpected column"));
  1238. break;
  1239. case Col_Severity:
  1240. {
  1241. size_t n;
  1242. for ( n = 0; n < WXSIZEOF(severities); n++ )
  1243. {
  1244. if ( severities[n] == value )
  1245. {
  1246. gd.severity = (Severity)n;
  1247. break;
  1248. }
  1249. }
  1250. if ( n == WXSIZEOF(severities) )
  1251. {
  1252. wxLogWarning(wxT("Invalid severity value '%s'."),
  1253. value.c_str());
  1254. gd.severity = Sev_Normal;
  1255. }
  1256. }
  1257. break;
  1258. case Col_Summary:
  1259. wxStrncpy(gd.summary, value, WXSIZEOF(gd.summary));
  1260. break;
  1261. case Col_Platform:
  1262. wxStrncpy(gd.platform, value, WXSIZEOF(gd.platform));
  1263. break;
  1264. }
  1265. }
  1266. bool
  1267. BugsGridTable::CanGetValueAs(int WXUNUSED(row),
  1268. int col,
  1269. const wxString& typeName)
  1270. {
  1271. if ( typeName == wxGRID_VALUE_STRING )
  1272. {
  1273. return true;
  1274. }
  1275. else if ( typeName == wxGRID_VALUE_BOOL )
  1276. {
  1277. return col == Col_Opened;
  1278. }
  1279. else if ( typeName == wxGRID_VALUE_NUMBER )
  1280. {
  1281. return col == Col_Id || col == Col_Priority || col == Col_Severity;
  1282. }
  1283. else
  1284. {
  1285. return false;
  1286. }
  1287. }
  1288. bool BugsGridTable::CanSetValueAs( int row, int col, const wxString& typeName )
  1289. {
  1290. return CanGetValueAs(row, col, typeName);
  1291. }
  1292. long BugsGridTable::GetValueAsLong( int row, int col )
  1293. {
  1294. const BugsGridData& gd = gs_dataBugsGrid[row];
  1295. switch ( col )
  1296. {
  1297. case Col_Id:
  1298. return gd.id;
  1299. case Col_Priority:
  1300. return gd.prio;
  1301. case Col_Severity:
  1302. return gd.severity;
  1303. default:
  1304. wxFAIL_MSG(wxT("unexpected column"));
  1305. return -1;
  1306. }
  1307. }
  1308. bool BugsGridTable::GetValueAsBool( int row, int col )
  1309. {
  1310. if ( col == Col_Opened )
  1311. {
  1312. return gs_dataBugsGrid[row].opened;
  1313. }
  1314. else
  1315. {
  1316. wxFAIL_MSG(wxT("unexpected column"));
  1317. return false;
  1318. }
  1319. }
  1320. void BugsGridTable::SetValueAsLong( int row, int col, long value )
  1321. {
  1322. BugsGridData& gd = gs_dataBugsGrid[row];
  1323. switch ( col )
  1324. {
  1325. case Col_Priority:
  1326. gd.prio = value;
  1327. break;
  1328. default:
  1329. wxFAIL_MSG(wxT("unexpected column"));
  1330. }
  1331. }
  1332. void BugsGridTable::SetValueAsBool( int row, int col, bool value )
  1333. {
  1334. if ( col == Col_Opened )
  1335. {
  1336. gs_dataBugsGrid[row].opened = value;
  1337. }
  1338. else
  1339. {
  1340. wxFAIL_MSG(wxT("unexpected column"));
  1341. }
  1342. }
  1343. wxString BugsGridTable::GetColLabelValue( int col )
  1344. {
  1345. return headers[col];
  1346. }
  1347. // ----------------------------------------------------------------------------
  1348. // BugsGridFrame
  1349. // ----------------------------------------------------------------------------
  1350. BugsGridFrame::BugsGridFrame()
  1351. : wxFrame(NULL, wxID_ANY, wxT("Bugs table"))
  1352. {
  1353. wxGrid *grid = new wxGrid(this, wxID_ANY);
  1354. wxGridTableBase *table = new BugsGridTable();
  1355. table->SetAttrProvider(new MyGridCellAttrProvider);
  1356. grid->SetTable(table, true);
  1357. wxGridCellAttr *attrRO = new wxGridCellAttr,
  1358. *attrRangeEditor = new wxGridCellAttr,
  1359. *attrCombo = new wxGridCellAttr;
  1360. attrRO->SetReadOnly();
  1361. attrRangeEditor->SetEditor(new wxGridCellNumberEditor(1, 5));
  1362. attrCombo->SetEditor(new wxGridCellChoiceEditor(WXSIZEOF(severities),
  1363. severities));
  1364. grid->SetColAttr(Col_Id, attrRO);
  1365. grid->SetColAttr(Col_Priority, attrRangeEditor);
  1366. grid->SetColAttr(Col_Severity, attrCombo);
  1367. grid->Fit();
  1368. SetClientSize(grid->GetSize());
  1369. }
  1370. // ============================================================================
  1371. // TabularGrid: grid used for display of tabular data
  1372. // ============================================================================
  1373. class TabularGridTable : public wxGridTableBase
  1374. {
  1375. public:
  1376. enum
  1377. {
  1378. COL_NAME,
  1379. COL_EXT,
  1380. COL_SIZE,
  1381. COL_DATE,
  1382. COL_MAX
  1383. };
  1384. enum
  1385. {
  1386. ROW_MAX = 3
  1387. };
  1388. TabularGridTable() { m_sortOrder = NULL; }
  1389. virtual int GetNumberRows() { return ROW_MAX; }
  1390. virtual int GetNumberCols() { return COL_MAX; }
  1391. virtual wxString GetValue(int row, int col)
  1392. {
  1393. if ( m_sortOrder )
  1394. row = m_sortOrder[row];
  1395. switch ( col )
  1396. {
  1397. case COL_NAME:
  1398. case COL_EXT:
  1399. return GetNameOrExt(row, col);
  1400. case COL_SIZE:
  1401. return wxString::Format("%lu", GetSize(row));
  1402. case COL_DATE:
  1403. return GetDate(row).FormatDate();
  1404. case COL_MAX:
  1405. default:
  1406. wxFAIL_MSG( "unknown column" );
  1407. }
  1408. return wxString();
  1409. }
  1410. virtual void SetValue(int, int, const wxString&)
  1411. {
  1412. wxFAIL_MSG( "shouldn't be called" );
  1413. }
  1414. virtual wxString GetColLabelValue(int col)
  1415. {
  1416. // notice that column parameter here always refers to the internal
  1417. // column index, independently of its position on the screen
  1418. static const char *labels[] = { "Name", "Extension", "Size", "Date" };
  1419. wxCOMPILE_TIME_ASSERT( WXSIZEOF(labels) == COL_MAX, LabelsMismatch );
  1420. return labels[col];
  1421. }
  1422. virtual void SetColLabelValue(int, const wxString&)
  1423. {
  1424. wxFAIL_MSG( "shouldn't be called" );
  1425. }
  1426. void Sort(int col, bool ascending)
  1427. {
  1428. // we hardcode all sorting orders for simplicity here
  1429. static int sortOrders[COL_MAX][2][ROW_MAX] =
  1430. {
  1431. // descending ascending
  1432. { { 2, 1, 0 }, { 0, 1, 2 } },
  1433. { { 2, 1, 0 }, { 0, 1, 2 } },
  1434. { { 2, 1, 0 }, { 0, 1, 2 } },
  1435. { { 1, 0, 2 }, { 2, 0, 1 } },
  1436. };
  1437. m_sortOrder = col == wxNOT_FOUND ? NULL : sortOrders[col][ascending];
  1438. }
  1439. private:
  1440. wxString GetNameOrExt(int row, int col) const
  1441. {
  1442. static const char *
  1443. names[] = { "autoexec.bat", "boot.ini", "io.sys" };
  1444. wxCOMPILE_TIME_ASSERT( WXSIZEOF(names) == ROW_MAX, NamesMismatch );
  1445. const wxString s(names[row]);
  1446. return col == COL_NAME ? s.BeforeFirst('.') : s.AfterLast('.');
  1447. }
  1448. unsigned long GetSize(int row) const
  1449. {
  1450. static const unsigned long
  1451. sizes[] = { 412, 604, 40774 };
  1452. wxCOMPILE_TIME_ASSERT( WXSIZEOF(sizes) == ROW_MAX, SizesMismatch );
  1453. return sizes[row];
  1454. }
  1455. wxDateTime GetDate(int row) const
  1456. {
  1457. static const char *
  1458. dates[] = { "2004-04-17", "2006-05-27", "1994-05-31" };
  1459. wxCOMPILE_TIME_ASSERT( WXSIZEOF(dates) == ROW_MAX, DatesMismatch );
  1460. wxDateTime dt;
  1461. dt.ParseISODate(dates[row]);
  1462. return dt;
  1463. }
  1464. int *m_sortOrder;
  1465. };
  1466. // specialized text control for column indexes entry
  1467. class ColIndexEntry : public wxTextCtrl
  1468. {
  1469. public:
  1470. ColIndexEntry(wxWindow *parent)
  1471. : wxTextCtrl(parent, wxID_ANY, "")
  1472. {
  1473. SetValidator(wxTextValidator(wxFILTER_NUMERIC));
  1474. }
  1475. int GetCol()
  1476. {
  1477. unsigned long col;
  1478. if ( !GetValue().ToULong(&col) || col > TabularGridTable::COL_MAX )
  1479. {
  1480. SetFocus();
  1481. return -1;
  1482. }
  1483. return col;
  1484. }
  1485. protected:
  1486. virtual wxSize DoGetBestSize() const
  1487. {
  1488. wxSize size = wxTextCtrl::DoGetBestSize();
  1489. size.x = 3*GetCharWidth();
  1490. return size;
  1491. }
  1492. };
  1493. class TabularGridFrame : public wxFrame
  1494. {
  1495. public:
  1496. TabularGridFrame();
  1497. private:
  1498. enum // control ids
  1499. {
  1500. Id_Check_UseNativeHeader,
  1501. Id_Check_DrawNativeLabels,
  1502. Id_Check_ShowRowLabels,
  1503. Id_Check_EnableColMove
  1504. };
  1505. // event handlers
  1506. void OnToggleUseNativeHeader(wxCommandEvent&)
  1507. {
  1508. m_grid->UseNativeColHeader(m_chkUseNative->IsChecked());
  1509. }
  1510. void OnUpdateDrawNativeLabelsUI(wxUpdateUIEvent& event)
  1511. {
  1512. // we don't draw labels at all, native or otherwise, if we use the
  1513. // native header control
  1514. event.Enable( !m_chkUseNative->GetValue() );
  1515. }
  1516. void OnToggleDrawNativeLabels(wxCommandEvent&)
  1517. {
  1518. m_grid->SetUseNativeColLabels(m_chkDrawNative->IsChecked());
  1519. }
  1520. void OnToggleShowRowLabels(wxCommandEvent&)
  1521. {
  1522. m_grid->SetRowLabelSize(m_chkShowRowLabels->IsChecked()
  1523. ? wxGRID_AUTOSIZE
  1524. : 0);
  1525. }
  1526. void OnToggleColMove(wxCommandEvent&)
  1527. {
  1528. m_grid->EnableDragColMove(m_chkEnableColMove->IsChecked());
  1529. }
  1530. void OnShowHideColumn(wxCommandEvent& event)
  1531. {
  1532. int col = m_txtColShowHide->GetCol();
  1533. if ( col != -1 )
  1534. {
  1535. m_grid->SetColSize(col,
  1536. event.GetId() == wxID_ADD ? wxGRID_AUTOSIZE : 0);
  1537. UpdateOrderAndVisibility();
  1538. }
  1539. }
  1540. void OnMoveColumn(wxCommandEvent&)
  1541. {
  1542. int col = m_txtColIndex->GetCol();
  1543. int pos = m_txtColPos->GetCol();
  1544. if ( col == -1 || pos == -1 )
  1545. return;
  1546. m_grid->SetColPos(col, pos);
  1547. UpdateOrderAndVisibility();
  1548. }
  1549. void OnResetColumnOrder(wxCommandEvent&)
  1550. {
  1551. m_grid->ResetColPos();
  1552. UpdateOrderAndVisibility();
  1553. }
  1554. void OnGridColSort(wxGridEvent& event)
  1555. {
  1556. const int col = event.GetCol();
  1557. m_table->Sort(col, !(m_grid->IsSortingBy(col) &&
  1558. m_grid->IsSortOrderAscending()));
  1559. }
  1560. void OnGridColMove(wxGridEvent& event)
  1561. {
  1562. // can't update it yet as the order hasn't been changed, so do it a bit
  1563. // later
  1564. m_shouldUpdateOrder = true;
  1565. event.Skip();
  1566. }
  1567. void OnGridColSize(wxGridSizeEvent& event)
  1568. {
  1569. // we only catch this event to react to the user showing or hiding this
  1570. // column using the header control menu and not because we're
  1571. // interested in column resizing
  1572. UpdateOrderAndVisibility();
  1573. event.Skip();
  1574. }
  1575. void OnIdle(wxIdleEvent& event)
  1576. {
  1577. if ( m_shouldUpdateOrder )
  1578. {
  1579. m_shouldUpdateOrder = false;
  1580. UpdateOrderAndVisibility();
  1581. }
  1582. event.Skip();
  1583. }
  1584. void UpdateOrderAndVisibility()
  1585. {
  1586. wxString s;
  1587. for ( int pos = 0; pos < TabularGridTable::COL_MAX; pos++ )
  1588. {
  1589. const int col = m_grid->GetColAt(pos);
  1590. const bool isHidden = m_grid->GetColSize(col) == 0;
  1591. if ( isHidden )
  1592. s << '[';
  1593. s << col;
  1594. if ( isHidden )
  1595. s << ']';
  1596. s << ' ';
  1597. }
  1598. m_statOrder->SetLabel(s);
  1599. }
  1600. // controls
  1601. wxGrid *m_grid;
  1602. TabularGridTable *m_table;
  1603. wxCheckBox *m_chkUseNative,
  1604. *m_chkDrawNative,
  1605. *m_chkShowRowLabels,
  1606. *m_chkEnableColMove;
  1607. ColIndexEntry *m_txtColIndex,
  1608. *m_txtColPos,
  1609. *m_txtColShowHide;
  1610. wxStaticText *m_statOrder;
  1611. // fla for EVT_IDLE handler
  1612. bool m_shouldUpdateOrder;
  1613. wxDECLARE_NO_COPY_CLASS(TabularGridFrame);
  1614. DECLARE_EVENT_TABLE()
  1615. };
  1616. BEGIN_EVENT_TABLE(TabularGridFrame, wxFrame)
  1617. EVT_CHECKBOX(Id_Check_UseNativeHeader,
  1618. TabularGridFrame::OnToggleUseNativeHeader)
  1619. EVT_CHECKBOX(Id_Check_DrawNativeLabels,
  1620. TabularGridFrame::OnToggleDrawNativeLabels)
  1621. EVT_CHECKBOX(Id_Check_ShowRowLabels,
  1622. TabularGridFrame::OnToggleShowRowLabels)
  1623. EVT_CHECKBOX(Id_Check_EnableColMove,
  1624. TabularGridFrame::OnToggleColMove)
  1625. EVT_UPDATE_UI(Id_Check_DrawNativeLabels,
  1626. TabularGridFrame::OnUpdateDrawNativeLabelsUI)
  1627. EVT_BUTTON(wxID_APPLY, TabularGridFrame::OnMoveColumn)
  1628. EVT_BUTTON(wxID_RESET, TabularGridFrame::OnResetColumnOrder)
  1629. EVT_BUTTON(wxID_ADD, TabularGridFrame::OnShowHideColumn)
  1630. EVT_BUTTON(wxID_DELETE, TabularGridFrame::OnShowHideColumn)
  1631. EVT_GRID_COL_SORT(TabularGridFrame::OnGridColSort)
  1632. EVT_GRID_COL_MOVE(TabularGridFrame::OnGridColMove)
  1633. EVT_GRID_COL_SIZE(TabularGridFrame::OnGridColSize)
  1634. EVT_IDLE(TabularGridFrame::OnIdle)
  1635. END_EVENT_TABLE()
  1636. TabularGridFrame::TabularGridFrame()
  1637. : wxFrame(NULL, wxID_ANY, "Tabular table")
  1638. {
  1639. m_shouldUpdateOrder = false;
  1640. wxPanel * const panel = new wxPanel(this);
  1641. // create and initialize the grid with the specified data
  1642. m_table = new TabularGridTable;
  1643. m_grid = new wxGrid(panel, wxID_ANY,
  1644. wxDefaultPosition, wxDefaultSize,
  1645. wxBORDER_STATIC | wxWANTS_CHARS);
  1646. m_grid->SetTable(m_table, true, wxGrid::wxGridSelectRows);
  1647. m_grid->EnableDragColMove();
  1648. m_grid->UseNativeColHeader();
  1649. m_grid->HideRowLabels();
  1650. // add it and the other controls to the frame
  1651. wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
  1652. sizerTop->Add(m_grid, wxSizerFlags(1).Expand().Border());
  1653. wxSizer * const sizerControls = new wxBoxSizer(wxHORIZONTAL);
  1654. wxSizer * const sizerStyles = new wxBoxSizer(wxVERTICAL);
  1655. m_chkUseNative = new wxCheckBox(panel, Id_Check_UseNativeHeader,
  1656. "&Use native header");
  1657. m_chkUseNative->SetValue(true);
  1658. sizerStyles->Add(m_chkUseNative, wxSizerFlags().Border());
  1659. m_chkDrawNative = new wxCheckBox(panel, Id_Check_DrawNativeLabels,
  1660. "&Draw native column labels");
  1661. sizerStyles->Add(m_chkDrawNative, wxSizerFlags().Border());
  1662. m_chkShowRowLabels = new wxCheckBox(panel, Id_Check_ShowRowLabels,
  1663. "Show &row labels");
  1664. sizerStyles->Add(m_chkShowRowLabels, wxSizerFlags().Border());
  1665. m_chkEnableColMove = new wxCheckBox(panel, Id_Check_EnableColMove,
  1666. "Allow column re&ordering");
  1667. m_chkEnableColMove->SetValue(true);
  1668. sizerStyles->Add(m_chkEnableColMove, wxSizerFlags().Border());
  1669. sizerControls->Add(sizerStyles);
  1670. sizerControls->AddSpacer(10);
  1671. wxSizer * const sizerColumns = new wxBoxSizer(wxVERTICAL);
  1672. wxSizer * const sizerMoveCols = new wxBoxSizer(wxHORIZONTAL);
  1673. const wxSizerFlags
  1674. flagsHorz(wxSizerFlags().Border(wxLEFT | wxRIGHT).Centre());
  1675. sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&Move column"),
  1676. flagsHorz);
  1677. m_txtColIndex = new ColIndexEntry(panel);
  1678. sizerMoveCols->Add(m_txtColIndex, flagsHorz);
  1679. sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&to"), flagsHorz);
  1680. m_txtColPos = new ColIndexEntry(panel);
  1681. sizerMoveCols->Add(m_txtColPos, flagsHorz);
  1682. sizerMoveCols->Add(new wxButton(panel, wxID_APPLY), flagsHorz);
  1683. sizerColumns->Add(sizerMoveCols, wxSizerFlags().Expand().Border(wxBOTTOM));
  1684. wxSizer * const sizerShowCols = new wxBoxSizer(wxHORIZONTAL);
  1685. sizerShowCols->Add(new wxStaticText(panel, wxID_ANY, "Current order:"),
  1686. flagsHorz);
  1687. m_statOrder = new wxStaticText(panel, wxID_ANY, "<<< default >>>");
  1688. sizerShowCols->Add(m_statOrder, flagsHorz);
  1689. sizerShowCols->Add(new wxButton(panel, wxID_RESET, "&Reset order"));
  1690. sizerColumns->Add(sizerShowCols, wxSizerFlags().Expand().Border(wxTOP));
  1691. wxSizer * const sizerShowHide = new wxBoxSizer(wxHORIZONTAL);
  1692. sizerShowHide->Add(new wxStaticText(panel, wxID_ANY, "Show/hide column:"),
  1693. flagsHorz);
  1694. m_txtColShowHide = new ColIndexEntry(panel);
  1695. sizerShowHide->Add(m_txtColShowHide, flagsHorz);
  1696. sizerShowHide->Add(new wxButton(panel, wxID_ADD, "&Show"), flagsHorz);
  1697. sizerShowHide->Add(new wxButton(panel, wxID_DELETE, "&Hide"), flagsHorz);
  1698. sizerColumns->Add(sizerShowHide, wxSizerFlags().Expand().Border(wxTOP));
  1699. sizerControls->Add(sizerColumns, wxSizerFlags(1).Expand().Border());
  1700. sizerTop->Add(sizerControls, wxSizerFlags().Expand().Border());
  1701. panel->SetSizer(sizerTop);
  1702. SetClientSize(panel->GetBestSize());
  1703. SetSizeHints(GetSize());
  1704. Show();
  1705. }
  1706. void GridFrame::OnTabularTable(wxCommandEvent&)
  1707. {
  1708. new TabularGridFrame;
  1709. }
  1710. // Example using wxGrid::Render
  1711. // Displays a preset selection or, if it exists, a selection block
  1712. // Draws the selection to a wxBitmap and displays the bitmap
  1713. void GridFrame::OnGridRender( wxCommandEvent& event )
  1714. {
  1715. int styleRender = 0, i;
  1716. bool useLometric = false, defSize = false;
  1717. double zoom = 1;
  1718. wxSize sizeMargin( 0, 0 );
  1719. wxPoint pointOrigin( 0, 0 );
  1720. wxMenu* menu = GetMenuBar()->GetMenu( 0 );
  1721. wxMenuItem* menuItem = menu->FindItem( ID_RENDER_ROW_LABEL );
  1722. menu = menuItem->GetMenu();
  1723. if ( menu->FindItem( ID_RENDER_ROW_LABEL )->IsChecked() )
  1724. styleRender |= wxGRID_DRAW_ROWS_HEADER;
  1725. if ( menu->FindItem( ID_RENDER_COL_LABEL )->IsChecked() )
  1726. styleRender |= wxGRID_DRAW_COLS_HEADER;
  1727. if ( menu->FindItem( ID_RENDER_GRID_LINES )->IsChecked() )
  1728. styleRender |= wxGRID_DRAW_CELL_LINES;
  1729. if ( menu->FindItem( ID_RENDER_GRID_BORDER )->IsChecked() )
  1730. styleRender |= wxGRID_DRAW_BOX_RECT;
  1731. if ( menu->FindItem( ID_RENDER_SELECT_HLIGHT )->IsChecked() )
  1732. styleRender |= wxGRID_DRAW_SELECTION;
  1733. if ( menu->FindItem( ID_RENDER_LOMETRIC )->IsChecked() )
  1734. useLometric = true;
  1735. if ( menu->FindItem( ID_RENDER_MARGIN )->IsChecked() )
  1736. {
  1737. pointOrigin.x += 50;
  1738. pointOrigin.y += 50;
  1739. sizeMargin.IncBy( 50 );
  1740. }
  1741. if ( menu->FindItem( ID_RENDER_ZOOM )->IsChecked() )
  1742. zoom = 1.25;
  1743. if ( menu->FindItem( ID_RENDER_DEFAULT_SIZE )->IsChecked() )
  1744. defSize = true;
  1745. // init render area coords with a default row and col selection
  1746. wxGridCellCoords topLeft( 0, 0 ), bottomRight( 8, 6 );
  1747. // check whether we are printing a block selection
  1748. // other selection types not catered for here
  1749. if ( event.GetId() == ID_RENDER_COORDS )
  1750. {
  1751. topLeft.SetCol( 6 );
  1752. topLeft.SetRow( 4 );
  1753. bottomRight.SetCol( 15 );
  1754. bottomRight.SetRow( 29 );
  1755. }
  1756. else if ( grid->IsSelection() && grid->GetSelectionBlockTopLeft().Count() )
  1757. {
  1758. wxGridCellCoordsArray cells = grid->GetSelectionBlockTopLeft();
  1759. if ( grid->GetSelectionBlockBottomRight().Count() )
  1760. {
  1761. cells.Add( grid->GetSelectionBlockBottomRight()[ 0 ] );
  1762. topLeft.Set( cells[ 0 ].GetRow(),
  1763. cells[ 0 ].GetCol() );
  1764. bottomRight.Set( cells[ 1 ].GetRow(),
  1765. cells[ 1 ].GetCol() );
  1766. }
  1767. }
  1768. // sum col widths
  1769. wxSize sizeRender( 0, 0 );
  1770. wxGridSizesInfo sizeinfo = grid->GetColSizes();
  1771. for ( i = topLeft.GetCol(); i <= bottomRight.GetCol(); i++ )
  1772. {
  1773. sizeRender.x += sizeinfo.GetSize( i );
  1774. }
  1775. // sum row heights
  1776. sizeinfo = grid->GetRowSizes();
  1777. for ( i = topLeft.GetRow(); i <= bottomRight.GetRow(); i++ )
  1778. {
  1779. sizeRender.y += sizeinfo.GetSize( i );
  1780. }
  1781. if ( styleRender & wxGRID_DRAW_ROWS_HEADER )
  1782. sizeRender.x += grid->GetRowLabelSize();
  1783. if ( styleRender & wxGRID_DRAW_COLS_HEADER )
  1784. sizeRender.y += grid->GetColLabelSize();
  1785. sizeRender.x *= zoom;
  1786. sizeRender.y *= zoom;
  1787. // delete any existing render frame and create new one
  1788. wxWindow* win = FindWindow( "frameRender" );
  1789. if ( win )
  1790. win->Destroy();
  1791. wxFrame* frame = new wxFrame( this, wxID_ANY, "Grid Render" );
  1792. frame->SetClientSize( 780, 400 );
  1793. frame->SetName( "frameRender" );
  1794. wxPanel* canvas = new wxPanel( frame, wxID_ANY );
  1795. // make bitmap large enough for margins if any
  1796. if ( !defSize )
  1797. sizeRender.IncBy( sizeMargin * 2 );
  1798. else
  1799. sizeRender.IncBy( sizeMargin );
  1800. wxBitmap bmp( sizeRender );
  1801. // don't leave it larger or drawing will be scaled
  1802. sizeRender.DecBy( sizeMargin * 2 );
  1803. wxMemoryDC memDc(bmp);
  1804. // default row labels have no background colour so set background
  1805. memDc.SetBackground( wxBrush( canvas->GetBackgroundColour() ) );
  1806. memDc.Clear();
  1807. // convert sizeRender to mapping mode units if necessary
  1808. if ( useLometric )
  1809. {
  1810. memDc.SetMapMode( wxMM_LOMETRIC );
  1811. wxSize sizePPI = memDc.GetPPI();
  1812. sizeRender.x = memDc.DeviceToLogicalXRel( sizeRender.x );
  1813. sizeRender.y = memDc.DeviceToLogicalYRel( sizeRender.y );
  1814. }
  1815. // pass wxDefaultSize if menu item is checked
  1816. if ( defSize )
  1817. sizeRender = wxDefaultSize;
  1818. grid->Render( memDc,
  1819. pointOrigin,
  1820. sizeRender,
  1821. topLeft, bottomRight,
  1822. wxGridRenderStyle( styleRender ) );
  1823. m_gridBitmap = bmp;
  1824. canvas->Connect( wxEVT_PAINT,
  1825. wxPaintEventHandler(GridFrame::OnRenderPaint),
  1826. NULL,
  1827. this );
  1828. frame->Show();
  1829. }
  1830. void GridFrame::OnRenderPaint( wxPaintEvent& event )
  1831. {
  1832. wxPanel* canvas = ( wxPanel* )event.GetEventObject();
  1833. wxPaintDC dc( canvas );
  1834. canvas->PrepareDC( dc );
  1835. if ( !m_gridBitmap.IsOk() )
  1836. return;;
  1837. wxMemoryDC memDc( m_gridBitmap );
  1838. dc.Blit( 0, 0,
  1839. m_gridBitmap.GetWidth(),
  1840. m_gridBitmap.GetHeight(),
  1841. &memDc, 0, 0 );
  1842. }