]> git.saurik.com Git - wxWidgets.git/blob - src/generic/gridg.cpp
8fae3103b21eff8e6d584bc16ad66b0e5492404c
[wxWidgets.git] / src / generic / gridg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gridg.cpp
3 // Purpose: wxGenericGrid
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "gridg.h"
14 #pragma interface
15 #endif
16
17 // For compilers that support precompilation, includes "wx/wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/wx.h"
26 #endif
27
28 #include <string.h>
29
30 #include "wx/string.h"
31 #include "wx/generic/gridg.h"
32 #include "wx/settings.h"
33
34 // Set to zero to use no double-buffering
35 #ifdef __WXMSW__
36 #define wxUSE_DOUBLE_BUFFERING 1
37 #else
38 #define wxUSE_DOUBLE_BUFFERING 0
39 #endif
40
41 #define wxGRID_DRAG_NONE 0
42 #define wxGRID_DRAG_LEFT_RIGHT 1
43 #define wxGRID_DRAG_UP_DOWN 2
44
45 IMPLEMENT_DYNAMIC_CLASS(wxGenericGrid, wxPanel)
46 IMPLEMENT_DYNAMIC_CLASS(wxGridEvent, wxEvent)
47
48 BEGIN_EVENT_TABLE(wxGenericGrid, wxPanel)
49 EVT_SIZE(wxGenericGrid::OnSize)
50 EVT_PAINT(wxGenericGrid::OnPaint)
51 EVT_ERASE_BACKGROUND(wxGenericGrid::OnEraseBackground)
52 EVT_MOUSE_EVENTS(wxGenericGrid::OnMouseEvent)
53 EVT_TEXT(wxGRID_TEXT_CTRL, wxGenericGrid::OnText)
54 EVT_COMMAND_SCROLL(wxGRID_HSCROLL, wxGenericGrid::OnGridScroll)
55 EVT_COMMAND_SCROLL(wxGRID_VSCROLL, wxGenericGrid::OnGridScroll)
56
57 // default wxGridEvent handlers
58 EVT_GRID_SELECT_CELL(wxGenericGrid::_OnSelectCell)
59 EVT_GRID_CREATE_CELL(wxGenericGrid::_OnCreateCell)
60 EVT_GRID_CHANGE_LABELS(wxGenericGrid::_OnChangeLabels)
61 EVT_GRID_CHANGE_SEL_LABEL(wxGenericGrid::_OnChangeSelectionLabel)
62 EVT_GRID_CELL_CHANGE(wxGenericGrid::_OnCellChange)
63 EVT_GRID_CELL_LCLICK(wxGenericGrid::_OnCellLeftClick)
64 EVT_GRID_CELL_RCLICK(wxGenericGrid::_OnCellRightClick)
65 EVT_GRID_LABEL_LCLICK(wxGenericGrid::_OnLabelLeftClick)
66 EVT_GRID_LABEL_RCLICK(wxGenericGrid::_OnLabelRightClick)
67
68 END_EVENT_TABLE()
69
70
71
72
73 wxGenericGrid::wxGenericGrid(void)
74 {
75 m_batchCount = 0;
76 m_hScrollBar = (wxScrollBar *) NULL;
77 m_vScrollBar = (wxScrollBar *) NULL;
78 m_cellTextColour = *wxBLACK;
79 m_cellBackgroundColour = *wxWHITE;
80 m_labelTextColour = *wxBLACK;
81 // m_labelBackgroundColour = *wxLIGHT_GREY;
82 m_labelBackgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
83 m_labelBackgroundBrush = (wxBrush *) NULL;
84 m_labelTextFont = (wxFont *) NULL;
85 m_cellTextFont = (wxFont *) NULL;
86 m_textItem = (wxTextCtrl *) NULL;
87 m_currentRectVisible = FALSE;
88 m_editable = TRUE;
89 #if defined(__WIN95__)
90 m_scrollWidth = wxSystemSettings::GetSystemMetric(wxSYS_VSCROLL_X);
91 #else
92 m_scrollWidth = 16;
93 #endif
94 m_dragStatus = wxGRID_DRAG_NONE;
95 m_dragRowOrCol = 0;
96 m_dragStartPosition = 0;
97 m_dragLastPosition = 0;
98 m_divisionPen = (wxPen *) NULL;
99 m_leftOfSheet = wxGRID_DEFAULT_SHEET_LEFT;
100 m_topOfSheet = wxGRID_DEFAULT_SHEET_TOP;
101 m_cellHeight = wxGRID_DEFAULT_CELL_HEIGHT;
102 m_totalGridWidth = 0;
103 m_totalGridHeight = 0;
104 m_colWidths = (short *) NULL;
105 m_rowHeights = (short *) NULL;
106 m_verticalLabelWidth = wxGRID_DEFAULT_VERTICAL_LABEL_WIDTH;
107 m_horizontalLabelHeight = wxGRID_DEFAULT_HORIZONAL_LABEL_HEIGHT;
108 m_verticalLabelAlignment = wxCENTRE;
109 m_horizontalLabelAlignment = wxCENTRE;
110 m_editControlPosition.x = wxGRID_DEFAULT_EDIT_X;
111 m_editControlPosition.y = wxGRID_DEFAULT_EDIT_Y;
112 m_editControlPosition.width = wxGRID_DEFAULT_EDIT_WIDTH;
113 m_editControlPosition.height = wxGRID_DEFAULT_EDIT_HEIGHT;
114 m_wCursorRow = 0;
115 m_wCursorColumn = 0;
116 m_scrollPosX = 0;
117 m_scrollPosY = 0;
118 m_editCreated = FALSE;
119 m_totalRows = 0;
120 m_totalCols = 0;
121 m_gridCells = (wxGridCell ***) NULL;
122 m_rowLabelCells = (wxGridCell **) NULL;
123 m_colLabelCells = (wxGridCell **) NULL;
124 m_textItem = (wxTextCtrl *) NULL;
125 m_horizontalSashCursor = (wxCursor *) NULL;
126 m_verticalSashCursor = (wxCursor *) NULL;
127 }
128
129 bool wxGenericGrid::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
130 long style, const wxString& name)
131 {
132 m_batchCount = 0;
133 m_editingPanel = (wxPanel *) NULL;
134 m_hScrollBar = (wxScrollBar *) NULL;
135 m_vScrollBar = (wxScrollBar *) NULL;
136 m_horizontalSashCursor = (wxCursor *) NULL;
137 m_verticalSashCursor = (wxCursor *) NULL;
138 m_cellTextColour = *wxBLACK;
139 m_cellBackgroundColour = *wxWHITE;
140 m_labelTextColour = *wxBLACK;
141 // m_labelBackgroundColour = *wxLIGHT_GREY;
142 m_labelBackgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
143 m_labelBackgroundBrush = (wxBrush *) NULL;
144 m_labelTextFont = wxTheFontList->FindOrCreateFont(10, wxSWISS, wxNORMAL, wxBOLD);
145 m_cellTextFont = wxTheFontList->FindOrCreateFont(10, wxSWISS, wxNORMAL, wxNORMAL);
146 m_textItem = (wxTextCtrl *) NULL;
147 m_currentRectVisible = FALSE;
148 m_editable = TRUE;
149 #if defined(__WIN95__)
150 m_scrollWidth = wxSystemSettings::GetSystemMetric(wxSYS_VSCROLL_X);
151 #else
152 m_scrollWidth = 16;
153 #endif
154 m_dragStatus = wxGRID_DRAG_NONE;
155 m_dragRowOrCol = 0;
156 m_dragStartPosition = 0;
157 m_dragLastPosition = 0;
158 m_divisionPen = wxThePenList->FindOrCreatePen("LIGHT GREY", 1, wxSOLID);
159 m_doubleBufferingBitmap = (wxBitmap *) NULL;
160
161 if (!m_horizontalSashCursor)
162 {
163 m_horizontalSashCursor = new wxCursor(wxCURSOR_SIZEWE);
164 m_verticalSashCursor = new wxCursor(wxCURSOR_SIZENS);
165 }
166
167 SetLabelBackgroundColour(m_labelBackgroundColour);
168
169 m_leftOfSheet = wxGRID_DEFAULT_SHEET_LEFT;
170 m_topOfSheet = wxGRID_DEFAULT_SHEET_TOP;
171 m_cellHeight = wxGRID_DEFAULT_CELL_HEIGHT;
172 m_totalGridWidth = 0;
173 m_totalGridHeight = 0;
174 m_colWidths = (short *) NULL;
175 m_rowHeights = (short *) NULL;
176
177 m_verticalLabelWidth = wxGRID_DEFAULT_VERTICAL_LABEL_WIDTH;
178 m_horizontalLabelHeight = wxGRID_DEFAULT_HORIZONAL_LABEL_HEIGHT;
179 m_verticalLabelAlignment = wxCENTRE;
180 m_horizontalLabelAlignment = wxCENTRE;
181 m_editControlPosition.x = wxGRID_DEFAULT_EDIT_X;
182 m_editControlPosition.y = wxGRID_DEFAULT_EDIT_Y;
183 m_editControlPosition.width = wxGRID_DEFAULT_EDIT_WIDTH;
184 m_editControlPosition.height = wxGRID_DEFAULT_EDIT_HEIGHT;
185
186 m_wCursorRow = 0;
187 m_wCursorColumn = 0;
188
189 m_scrollPosX = 0;
190 m_scrollPosY = 0;
191
192 /* Store the rect. coordinates for the current cell */
193 SetCurrentRect(m_wCursorRow, m_wCursorColumn);
194
195 m_editCreated = FALSE;
196
197 m_totalRows = 0;
198 m_totalCols = 0;
199 m_gridCells = (wxGridCell ***) NULL;
200 m_rowLabelCells = (wxGridCell **) NULL;
201 m_colLabelCells = (wxGridCell **) NULL;
202 m_textItem = (wxTextCtrl *) NULL;
203
204 wxPanel::Create(parent, id, pos, size, style, name);
205
206 m_editingPanel = new wxPanel(this);
207
208 m_textItem = new wxTextCtrl(m_editingPanel, wxGRID_TEXT_CTRL, "",
209 wxPoint(m_editControlPosition.x, m_editControlPosition.y), wxSize(m_editControlPosition.width, -1),
210 0);
211 m_textItem->Show(TRUE);
212 m_textItem->SetFocus();
213 int controlW, controlH;
214
215 m_textItem->GetSize(&controlW, &controlH);
216 m_editControlPosition.height = controlH;
217
218 m_topOfSheet = m_editControlPosition.y + controlH + 2;
219
220 m_editCreated = TRUE;
221
222 m_hScrollBar = new wxScrollBar(this, wxGRID_HSCROLL, wxPoint(0, 0), wxSize(20, 100), wxHORIZONTAL);
223 m_vScrollBar = new wxScrollBar(this, wxGRID_VSCROLL, wxPoint(0, 0), wxSize(100, 20), wxVERTICAL);
224
225 return TRUE;
226 }
227
228 wxGenericGrid::~wxGenericGrid(void)
229 {
230 ClearGrid();
231 }
232
233 void wxGenericGrid::ClearGrid(void)
234 {
235 int i,j;
236 if (m_gridCells)
237 {
238 for (i = 0; i < m_totalRows; i++)
239 {
240 for (j = 0; j < m_totalCols; j++)
241 if (m_gridCells[i][j])
242 delete m_gridCells[i][j];
243 delete[] m_gridCells[i];
244 }
245 delete[] m_gridCells;
246 m_gridCells = (wxGridCell ***) NULL;
247 }
248 if (m_colWidths)
249 delete[] m_colWidths;
250 m_colWidths = (short *) NULL;
251 if (m_rowHeights)
252 delete[] m_rowHeights;
253 m_rowHeights = (short *) NULL;
254
255 if (m_rowLabelCells)
256 {
257 for (i = 0; i < m_totalRows; i++)
258 delete m_rowLabelCells[i];
259 delete[] m_rowLabelCells;
260 m_rowLabelCells = (wxGridCell **) NULL;
261 }
262 if (m_colLabelCells)
263 {
264 for (i = 0; i < m_totalCols; i++)
265 delete m_colLabelCells[i];
266 delete[] m_colLabelCells;
267 m_colLabelCells = (wxGridCell **) NULL;
268 }
269 if (m_doubleBufferingBitmap)
270 {
271 delete m_doubleBufferingBitmap;
272 m_doubleBufferingBitmap = (wxBitmap *) NULL;
273 }
274 }
275
276 bool wxGenericGrid::CreateGrid(int nRows, int nCols, wxString **cellValues, short *widths,
277 short defaultWidth, short defaultHeight)
278 {
279 m_totalRows = nRows;
280 m_totalCols = nCols;
281
282 int i,j;
283 m_colWidths = new short[nCols];
284 m_rowHeights = new short[nRows];
285 for (i = 0; i < nCols; i++)
286 if (widths)
287 m_colWidths[i] = widths[i];
288 else
289 m_colWidths[i] = defaultWidth;
290 for (i = 0; i < nRows; i++)
291 m_rowHeights[i] = defaultHeight;
292
293 m_gridCells = new wxGridCell **[nRows];
294
295 for (i = 0; i < nRows; i++)
296 m_gridCells[i] = new wxGridCell *[nCols];
297
298 for (i = 0; i < nRows; i++)
299 for (j = 0; j < nCols; j++)
300 if (cellValues)
301 {
302 //m_gridCells[i][j] = OnCreateCell();
303 wxGridEvent g_evt(GetId(), wxEVT_GRID_CREATE_CELL, this, i, j);
304 GetEventHandler()->ProcessEvent(g_evt);
305 m_gridCells[i][j] = g_evt.m_cell;
306 m_gridCells[i][j]->SetTextValue(cellValues[i][j]);
307 }
308 else
309 m_gridCells[i][j] = (wxGridCell *) NULL;
310
311 m_rowLabelCells = new wxGridCell *[nRows];
312 for (i = 0; i < nRows; i++)
313 m_rowLabelCells[i] = new wxGridCell(this);
314 m_colLabelCells = new wxGridCell *[nCols];
315 for (i = 0; i < nCols; i++)
316 m_colLabelCells[i] = new wxGridCell(this);
317
318 m_wCursorRow = m_wCursorColumn = 0;
319 SetCurrentRect(0, 0);
320
321 // Need to determine various dimensions
322 UpdateDimensions();
323
324 // Number of 'lines'
325 int objectSizeX = m_totalCols;
326 int pageSizeX = 1;
327 int viewLengthX = m_totalCols;
328
329 /*
330 m_hScrollBar->SetViewLength(viewLengthX);
331 m_hScrollBar->SetObjectLength(objectSizeX);
332 m_hScrollBar->SetPageSize(pageSizeX);
333 */
334 m_hScrollBar->SetScrollbar(m_hScrollBar->GetThumbPosition(), pageSizeX, objectSizeX, viewLengthX);
335
336 int objectSizeY = m_totalRows;
337 int pageSizeY = 1;
338 int viewLengthY = m_totalRows;
339
340 /*
341 m_vScrollBar->SetViewLength(viewLengthY);
342 m_vScrollBar->SetObjectLength(objectSizeY);
343 m_vScrollBar->SetPageSize(pageSizeY);
344 */
345
346 m_vScrollBar->SetScrollbar(m_vScrollBar->GetThumbPosition(), pageSizeY, objectSizeY, viewLengthY);
347
348 AdjustScrollbars();
349
350 //OnChangeLabels();
351 wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this);
352 GetEventHandler()->ProcessEvent(g_evt);
353
354 //OnChangeSelectionLabel();
355 wxGridEvent g_evt2(GetId(), wxEVT_GRID_CHANGE_SEL_LABEL, this);
356 GetEventHandler()->ProcessEvent(g_evt2);
357
358 return TRUE;
359 }
360
361 // Need to determine various dimensions
362 void wxGenericGrid::UpdateDimensions(void)
363 {
364 int canvasWidth, canvasHeight;
365 GetSize(&canvasWidth, &canvasHeight);
366
367 if (m_editCreated && m_editable)
368 {
369 int controlW, controlH;
370 GetTextItem()->GetSize(&controlW, &controlH);
371 m_topOfSheet = m_editControlPosition.y + controlH + 2;
372 }
373 else
374 m_topOfSheet = 0;
375 m_rightOfSheet = m_leftOfSheet + m_verticalLabelWidth;
376 int i;
377 for (i = m_scrollPosX; i < m_totalCols; i++)
378 {
379 if (m_rightOfSheet > canvasWidth)
380 break;
381 else
382 m_rightOfSheet += m_colWidths[i];
383 }
384 m_bottomOfSheet = m_topOfSheet + m_horizontalLabelHeight;
385 for (i = m_scrollPosY; i < m_totalRows; i++)
386 {
387 if (m_bottomOfSheet > canvasHeight)
388 break;
389 else
390 m_bottomOfSheet += m_rowHeights[i];
391 }
392
393 m_totalGridWidth = m_leftOfSheet + m_verticalLabelWidth;
394 for (i = 0; i < m_totalCols; i++)
395 {
396 m_totalGridWidth += m_colWidths[i];
397 }
398 m_totalGridHeight = m_topOfSheet + m_horizontalLabelHeight;
399 for (i = 0; i < m_totalRows; i++)
400 {
401 m_totalGridHeight += m_rowHeights[i];
402 }
403 }
404
405 wxGridCell *wxGenericGrid::GetCell(int row, int col)
406 {
407 if (!m_gridCells)
408 return (wxGridCell *) NULL;
409
410 if ((row >= m_totalRows) || (col >= m_totalCols))
411 return (wxGridCell *) NULL;
412
413 wxGridCell *cell = m_gridCells[row][col];
414 if (!cell)
415 {
416 // m_gridCells[row][col] = OnCreateCell();
417 wxGridEvent g_evt(GetId(), wxEVT_GRID_CREATE_CELL, this, row, col);
418 GetEventHandler()->ProcessEvent(g_evt);
419 m_gridCells[row][col] = g_evt.m_cell;
420 return m_gridCells[row][col];
421 }
422 else
423 return cell;
424 }
425
426 void wxGenericGrid::SetGridClippingRegion(wxDC *dc)
427 {
428 int m_scrollWidthHoriz = 0;
429 int m_scrollWidthVert = 0;
430 int cw, ch;
431 GetClientSize(&cw, &ch);
432
433 if (m_hScrollBar && m_hScrollBar->IsShown())
434 m_scrollWidthHoriz = m_scrollWidth;
435 if (m_vScrollBar && m_vScrollBar->IsShown())
436 m_scrollWidthVert = m_scrollWidth;
437
438 // Don't paint over the scrollbars
439 dc->SetClippingRegion(m_leftOfSheet, m_topOfSheet,
440 cw - m_scrollWidthVert - m_leftOfSheet, ch - m_scrollWidthHoriz - m_topOfSheet);
441 }
442
443 void wxGenericGrid::OnPaint(wxPaintEvent& WXUNUSED(event))
444 {
445 int w, h;
446 GetClientSize(&w, &h);
447
448 bool useDoubleBuffering = (bool) wxUSE_DOUBLE_BUFFERING;
449 if (useDoubleBuffering)
450 {
451 // Reuse the old bitmap if possible
452
453 if (!m_doubleBufferingBitmap ||
454 (m_doubleBufferingBitmap->GetWidth() < w || m_doubleBufferingBitmap->GetHeight() < h))
455 {
456 if (m_doubleBufferingBitmap)
457 delete m_doubleBufferingBitmap;
458 m_doubleBufferingBitmap = new wxBitmap(w, h);
459 }
460 if (!m_doubleBufferingBitmap || !m_doubleBufferingBitmap->Ok())
461 {
462 // If we couldn't create a new bitmap, perhaps because resources were low,
463 // then don't complain, just don't double-buffer
464 if (m_doubleBufferingBitmap)
465 delete m_doubleBufferingBitmap;
466 m_doubleBufferingBitmap = (wxBitmap *) NULL;
467 useDoubleBuffering = FALSE;
468 }
469 }
470
471 if (useDoubleBuffering)
472 {
473 wxPaintDC paintDC(this);
474 wxMemoryDC dc(& paintDC);
475 dc.SelectObject(* m_doubleBufferingBitmap);
476
477 PaintGrid(dc);
478
479 int vertScrollBarWidth = m_scrollWidth;
480 int horizScrollBarHeight = m_scrollWidth;
481 if (m_vScrollBar && !m_vScrollBar->IsShown())
482 vertScrollBarWidth = 0;
483 if (m_hScrollBar && !m_hScrollBar->IsShown())
484 horizScrollBarHeight = 0;
485
486 paintDC.Blit(m_leftOfSheet, m_topOfSheet, w - vertScrollBarWidth - m_leftOfSheet, h - horizScrollBarHeight - m_topOfSheet,
487 &dc, m_leftOfSheet, m_topOfSheet, wxCOPY);
488
489 dc.SelectObject(wxNullBitmap);
490 }
491 else
492 {
493 wxPaintDC dc(this);
494 PaintGrid(dc);
495 }
496 }
497
498 void wxGenericGrid::PaintGrid(wxDC& dc)
499 {
500 dc.BeginDrawing();
501 dc.SetOptimization(FALSE);
502
503 SetGridClippingRegion(& dc);
504
505 DrawLabelAreas(& dc);
506
507 DrawEditableArea(& dc);
508 DrawColumnLabels(& dc);
509 DrawRowLabels(& dc);
510 DrawCells(& dc);
511 DrawGridLines(& dc);
512
513 /* Hilight present cell */
514 SetCurrentRect(m_wCursorRow, m_wCursorColumn);
515 if (m_currentRectVisible)
516 HighlightCell(& dc);
517
518 dc.DestroyClippingRegion();
519 dc.SetOptimization(TRUE);
520 dc.EndDrawing();
521 }
522
523 // Erase (some of) the background.
524 // Currently, a Windows-only optimisation.
525 void wxGenericGrid::OnEraseBackground(wxEraseEvent& WXUNUSED(event) )
526 {
527 wxClientDC dc(this);
528 dc.BeginDrawing();
529 dc.SetOptimization(FALSE);
530
531 int w, h;
532 GetClientSize(& w, & h);
533 dc.SetBrush(*wxLIGHT_GREY_BRUSH);
534 dc.SetPen(*wxLIGHT_GREY_PEN);
535
536 if (m_hScrollBar && m_hScrollBar->IsShown() && m_vScrollBar && m_vScrollBar->IsShown())
537 {
538 dc.DrawRectangle(w - m_scrollWidth, h - m_scrollWidth, m_scrollWidth, m_scrollWidth);
539 }
540
541 dc.SetOptimization(TRUE);
542 dc.EndDrawing();
543 }
544
545
546 void wxGenericGrid::DrawLabelAreas(wxDC *dc)
547 {
548 int cw, ch;
549 GetClientSize(&cw, &ch);
550
551 dc->SetPen(*wxTRANSPARENT_PEN);
552 // dc->SetBrush(*dc->GetBackground());
553
554 // Should blank out any area which isn't going to be painted over.
555 // dc->DrawRectangle(m_leftOfSheet, m_bottomOfSheet, cw - m_leftOfSheet, ch - m_bottomOfSheet);
556 // dc->DrawRectangle(m_rightOfSheet, m_topOfSheet, cw - m_rightOfSheet, ch - m_topOfSheet);
557
558 // Paint the label areas
559 dc->SetBrush(*m_labelBackgroundBrush);
560 // dc->DrawRectangle(m_leftOfSheet, m_topOfSheet, m_rightOfSheet - m_leftOfSheet + 1, m_horizontalLabelHeight + 1);
561 dc->DrawRectangle(m_leftOfSheet, m_topOfSheet, cw-m_leftOfSheet, m_horizontalLabelHeight + 1);
562 // dc->DrawRectangle(m_leftOfSheet, m_topOfSheet, m_verticalLabelWidth + 1, m_bottomOfSheet - m_topOfSheet + 1);
563 dc->DrawRectangle(m_leftOfSheet, m_topOfSheet, m_verticalLabelWidth + 1, ch-m_topOfSheet);
564 }
565
566 void wxGenericGrid::DrawEditableArea(wxDC *dc)
567 {
568 int cw, ch;
569 GetClientSize(&cw, &ch);
570
571 dc->SetPen(*wxTRANSPARENT_PEN);
572 dc->SetBrush(*wxTheBrushList->FindOrCreateBrush(m_cellBackgroundColour, wxSOLID));
573 // dc->DrawRectangle(m_leftOfSheet+m_verticalLabelWidth, m_topOfSheet+m_horizontalLabelHeight,
574 // m_rightOfSheet-(m_leftOfSheet+m_verticalLabelWidth) + 1, m_bottomOfSheet - (m_topOfSheet+m_horizontalLabelHeight) + 1);
575 dc->DrawRectangle(m_leftOfSheet+m_verticalLabelWidth, m_topOfSheet+m_horizontalLabelHeight,
576 cw-(m_leftOfSheet+m_verticalLabelWidth), ch - (m_topOfSheet+m_horizontalLabelHeight));
577 }
578
579 void wxGenericGrid::DrawGridLines(wxDC *dc)
580 {
581 int cw, ch;
582 GetClientSize(&cw, &ch);
583
584 int i;
585
586 if (m_divisionPen)
587 {
588 dc->SetPen(*m_divisionPen);
589
590 int heightCount = m_topOfSheet + m_horizontalLabelHeight;
591
592 // Draw horizontal grey lines for cells
593 for (i = m_scrollPosY; i < (m_totalRows+1); i++)
594 {
595 if (heightCount > ch)
596 break;
597 else
598 {
599 dc->DrawLine(m_leftOfSheet, heightCount,
600 cw, heightCount);
601 if (i < m_totalRows)
602 heightCount += m_rowHeights[i];
603 }
604 }
605 }
606
607 if (m_verticalLabelWidth > 0)
608 {
609 dc->SetPen(*wxBLACK_PEN);
610
611 // Draw horizontal black lines for row labels
612 int heightCount = m_topOfSheet + m_horizontalLabelHeight;
613 for (i = m_scrollPosY; i < (m_totalRows+1); i++)
614 {
615 if (heightCount > ch)
616 break;
617 else
618 {
619 dc->DrawLine(m_leftOfSheet, heightCount,
620 m_verticalLabelWidth, heightCount);
621 if (i < m_totalRows)
622 heightCount += m_rowHeights[i];
623 }
624 }
625 // Draw a black vertical line for row number cells
626 dc->DrawLine(m_leftOfSheet + m_verticalLabelWidth, m_topOfSheet,
627 m_leftOfSheet + m_verticalLabelWidth, ch);
628 // First vertical line
629 dc->DrawLine(m_leftOfSheet, m_topOfSheet, m_leftOfSheet, ch);
630
631 dc->SetPen(*wxWHITE_PEN);
632
633 // Draw highlights on row labels
634 heightCount = m_topOfSheet + m_horizontalLabelHeight;
635 for (i = m_scrollPosY; i < m_totalRows; i++)
636 {
637 if (heightCount > ch)
638 break;
639 else
640 {
641 dc->DrawLine(m_leftOfSheet+1, heightCount+1,
642 m_verticalLabelWidth, heightCount+1);
643 dc->DrawLine(m_leftOfSheet+1, heightCount+1,
644 m_leftOfSheet+1, heightCount + m_rowHeights[i] - 1);
645 heightCount += m_rowHeights[i];
646 }
647 }
648 // Last one - down to the floor.
649 dc->DrawLine(m_leftOfSheet+1, heightCount+1,
650 m_verticalLabelWidth, heightCount+1);
651 dc->DrawLine(m_leftOfSheet+1, heightCount+1,
652 m_leftOfSheet+1, ch);
653
654 }
655
656 if (m_divisionPen)
657 {
658 dc->SetPen(*m_divisionPen);
659
660 // Draw vertical grey lines for cells
661 int widthCount = m_leftOfSheet + m_verticalLabelWidth;
662 for (i = m_scrollPosX; i < m_totalCols; i++)
663 {
664 if (widthCount > cw)
665 break;
666 else
667 {
668 // Skip the first one
669 if (i != m_scrollPosX)
670 {
671 dc->DrawLine(widthCount, m_topOfSheet + m_horizontalLabelHeight,
672 widthCount, m_bottomOfSheet);
673 }
674 widthCount += m_colWidths[i];
675 }
676 }
677 // Last one
678 dc->DrawLine(widthCount, m_topOfSheet + m_horizontalLabelHeight,
679 widthCount, m_bottomOfSheet);
680 }
681
682 dc->SetPen(*wxBLACK_PEN);
683
684 // Draw two black horizontal lines for column number cells
685 dc->DrawLine(
686 m_leftOfSheet, m_topOfSheet,
687 cw, m_topOfSheet);
688 dc->DrawLine(m_leftOfSheet, m_topOfSheet + m_horizontalLabelHeight,
689 cw, m_topOfSheet + m_horizontalLabelHeight);
690
691 if (m_horizontalLabelHeight > 0)
692 {
693 int widthCount = m_leftOfSheet + m_verticalLabelWidth;
694
695 // Draw black vertical lines for column number cells
696 for (i = m_scrollPosX; i < m_totalCols; i++)
697 {
698 if (widthCount > cw)
699 break;
700 else
701 {
702 dc->DrawLine(widthCount, m_topOfSheet,
703 widthCount, m_topOfSheet + m_horizontalLabelHeight);
704 widthCount += m_colWidths[i];
705 }
706 }
707
708 // Last one
709 dc->DrawLine(widthCount, m_topOfSheet,
710 widthCount, m_topOfSheet + m_horizontalLabelHeight);
711
712 // Draw highlights
713 dc->SetPen(*wxWHITE_PEN);
714 widthCount = m_leftOfSheet + m_verticalLabelWidth;
715
716 for (i = m_scrollPosX; i < m_totalCols; i++)
717 {
718 if (widthCount > cw)
719 break;
720 else
721 {
722 dc->DrawLine(widthCount+1, m_topOfSheet+1,
723 widthCount+m_colWidths[i], m_topOfSheet+1);
724 dc->DrawLine(widthCount+1, m_topOfSheet+1,
725 widthCount+1, m_topOfSheet+m_horizontalLabelHeight);
726 widthCount += m_colWidths[i];
727 }
728 }
729 // Last one - to the right side of the canvas.
730 dc->DrawLine(widthCount+1, m_topOfSheet+1,
731 cw, m_topOfSheet+1);
732 dc->DrawLine(widthCount+1, m_topOfSheet+1,
733 widthCount+1, m_topOfSheet+m_horizontalLabelHeight);
734
735 }
736 }
737
738 void wxGenericGrid::DrawColumnLabels(wxDC *dc)
739 {
740 int cw, ch;
741 GetClientSize(&cw, &ch);
742
743 if (m_horizontalLabelHeight == 0)
744 return;
745
746 int i;
747 wxRect rect;
748
749 // Draw letters for columns
750 rect.y = m_topOfSheet + 1;
751 rect.height = m_horizontalLabelHeight - 1;
752
753 dc->SetTextBackground(m_labelBackgroundColour);
754 dc->SetBackgroundMode(wxTRANSPARENT);
755 // dc->SetTextForeground(m_labelTextColour);
756
757 int widthCount = m_leftOfSheet + m_verticalLabelWidth;
758 for (i = m_scrollPosX; i < m_totalCols; i++)
759 {
760 if (widthCount > cw)
761 break;
762 else
763 {
764 rect.x = 1 + widthCount;
765 rect.width = m_colWidths[i];
766 DrawColumnLabel(dc, &rect, i);
767
768 widthCount += m_colWidths[i];
769 }
770 }
771 }
772
773 void wxGenericGrid::DrawColumnLabel(wxDC *dc, wxRect *rect, int col)
774 {
775 wxGridCell *cell = GetLabelCell(wxHORIZONTAL, col);
776 if (cell)
777 {
778 wxRect rect2;
779 rect2 = *rect;
780 rect2.x += 3;
781 rect2.y += 2;
782 rect2.width -= 5;
783 rect2.height -= 4;
784 dc->SetTextForeground(GetLabelTextColour());
785 dc->SetFont(*GetLabelTextFont());
786 if ( !cell->GetTextValue().IsNull() )
787 DrawTextRect(dc, cell->GetTextValue(), &rect2, GetLabelAlignment(wxHORIZONTAL));
788 }
789 }
790
791 void wxGenericGrid::DrawRowLabels(wxDC *dc)
792 {
793 int cw, ch;
794 GetClientSize(&cw, &ch);
795
796 if (m_verticalLabelWidth == 0)
797 return;
798
799 int i;
800 wxRect rect;
801
802 // Draw numbers for rows
803 rect.x = m_leftOfSheet;
804 rect.width = m_verticalLabelWidth;
805
806 int heightCount = m_topOfSheet + m_horizontalLabelHeight;
807
808 dc->SetTextBackground(m_labelBackgroundColour);
809 dc->SetBackgroundMode(wxTRANSPARENT);
810
811 for (i = m_scrollPosY; i < m_totalRows; i++)
812 {
813 if (heightCount > ch)
814 break;
815 else
816 {
817 rect.y = 1 + heightCount;
818 rect.height = m_rowHeights[i];
819 DrawRowLabel(dc, &rect, i);
820
821 heightCount += m_rowHeights[i];
822 }
823 }
824 }
825
826 void wxGenericGrid::DrawRowLabel(wxDC *dc, wxRect *rect, int row)
827 {
828 wxGridCell *cell = GetLabelCell(wxVERTICAL, row);
829 if (cell)
830 {
831 wxRect rect2;
832 rect2 = *rect;
833 rect2.x += 3;
834 rect2.y += 2;
835 rect2.width -= 5;
836 rect2.height -= 4;
837 dc->SetTextForeground(GetLabelTextColour());
838 dc->SetFont(*GetLabelTextFont());
839 if ( !cell->GetTextValue().IsNull() )
840 DrawTextRect(dc, cell->GetTextValue(), &rect2, GetLabelAlignment(wxVERTICAL));
841 }
842 }
843
844 void wxGenericGrid::DrawCells(wxDC *dc)
845 {
846 int cw, ch;
847 GetClientSize(&cw, &ch);
848
849 int i,j;
850
851 // Draw value corresponding to each cell
852 for (i = m_scrollPosY; i < m_totalRows; i++)
853 {
854 for (j = m_scrollPosX; j < m_totalCols; j++)
855 {
856 SetCurrentRect(i, j, cw, ch);
857 if (m_currentRectVisible)
858 {
859 DrawCellBackground(dc, &m_currentRect, i, j);
860 DrawCellValue(dc, &m_currentRect, i, j);
861 }
862 if (m_currentRect.x > cw)
863 break;
864 }
865 if (m_currentRect.y > ch)
866 break;
867 }
868 dc->SetBackgroundMode(wxSOLID);
869 dc->SetPen(*wxBLACK_PEN);
870 }
871
872 void wxGenericGrid::DrawCellBackground(wxDC *dc, wxRect *rect, int row, int col)
873 {
874 wxGridCell *cell = GetCell(row, col);
875 if (cell)
876 {
877 dc->SetBrush(*cell->GetBackgroundBrush());
878 dc->SetPen(*wxTRANSPARENT_PEN);
879
880 #if 0 // In wxWin 2.0 the dc code is exact. RR.
881 #ifdef __WXMOTIF__
882 dc->DrawRectangle(rect->x+1, rect->y+1, rect->width-1, rect->height-1);
883 #else
884 dc->DrawRectangle(rect->x+1, rect->y+1, rect->width, rect->height);
885 #endif
886 #endif
887
888 dc->DrawRectangle(rect->x+1, rect->y+1, rect->width-1, rect->height-1);
889
890 dc->SetPen(*wxBLACK_PEN);
891 }
892 }
893
894 void wxGenericGrid::DrawCellValue(wxDC *dc, wxRect *rect, int row, int col)
895 {
896 wxGridCell *cell = GetCell(row, col);
897 if (cell)
898 {
899 wxBitmap *bitmap = cell->GetCellBitmap();
900 wxRect rect2;
901 rect2 = *rect;
902 rect2.x += 3;
903 rect2.y += 2;
904 rect2.width -= 5;
905 rect2.height -= 4;
906
907 if (bitmap)
908 {
909 DrawBitmapRect(dc, bitmap, &rect2, cell->GetAlignment());
910 }
911 else
912 {
913 dc->SetBackgroundMode(wxTRANSPARENT);
914 dc->SetTextForeground(cell->GetTextColour());
915 dc->SetFont(*cell->GetFont());
916
917 if ( !cell->GetTextValue().IsNull() )
918 DrawTextRect(dc, cell->GetTextValue(), &rect2, cell->GetAlignment());
919 }
920 }
921 }
922
923 void wxGenericGrid::AdjustScrollbars(void)
924 {
925 int cw, ch;
926 GetClientSize(&cw, &ch);
927
928 // We find the view size by seeing how many rows/cols fit on
929 // the current view.
930 // BUT... this means that the scrollbar should be adjusted every time
931 // it's scrolled, as well as when sized, because with variable size rows/cols,
932 // the number of rows/col visible on the view differs according to what bit
933 // you're looking at. The object length is always the same, but the
934 // view length differs.
935
936 // Since this may not be known until the end of this function, we should probably call AdjustScrollbars
937 // twice.
938 int vertScrollBarWidth = m_scrollWidth;
939 int horizScrollBarHeight = m_scrollWidth;
940 if (m_vScrollBar && !m_vScrollBar->IsShown())
941 vertScrollBarWidth = 0;
942 if (m_hScrollBar && !m_hScrollBar->IsShown())
943 horizScrollBarHeight = 0;
944
945 int noHorizSteps = 0;
946 int noVertSteps = 0;
947
948 if (m_totalGridWidth + vertScrollBarWidth <= cw)
949 noHorizSteps = 0;
950 else
951 {
952 noHorizSteps = 0;
953 int widthCount = 0;
954
955 int i;
956 int nx = 0;
957 for (i = m_scrollPosX ; i < m_totalCols; i++)
958 {
959 widthCount += m_colWidths[i];
960 // A partial bit doesn't count, we still have to scroll to see the
961 // rest of it
962 if (widthCount + m_leftOfSheet + m_verticalLabelWidth > (cw-vertScrollBarWidth))
963 break;
964 else
965 nx ++;
966
967 }
968
969 noHorizSteps += nx;
970 }
971 if (m_totalGridHeight + horizScrollBarHeight <= ch)
972 noVertSteps = 0;
973 else
974 {
975 noVertSteps = 0;
976 int heightCount = 0;
977
978 int i;
979 int ny = 0;
980 for (i = m_scrollPosY ; i < m_totalRows; i++)
981 {
982 heightCount += m_rowHeights[i];
983 // A partial bit doesn't count, we still have to scroll to see the
984 // rest of it
985 if (heightCount + m_topOfSheet + m_horizontalLabelHeight > (ch-horizScrollBarHeight))
986 break;
987 else
988 ny ++;
989 }
990
991 noVertSteps += ny;
992 }
993
994 if (m_totalGridWidth + vertScrollBarWidth <= cw)
995 {
996 if ( m_hScrollBar )
997 m_hScrollBar->Show(FALSE);
998 SetScrollPosX(0);
999 }
1000 else
1001 {
1002 if ( m_hScrollBar )
1003 m_hScrollBar->Show(TRUE);
1004 }
1005
1006 if (m_totalGridHeight + horizScrollBarHeight <= ch)
1007 {
1008 if ( m_vScrollBar )
1009 m_vScrollBar->Show(FALSE);
1010 SetScrollPosY(0);
1011 }
1012 else
1013 {
1014 if ( m_vScrollBar )
1015 m_vScrollBar->Show(TRUE);
1016 }
1017
1018 UpdateDimensions(); // Necessary in case m_scrollPosX/Y changed
1019
1020 vertScrollBarWidth = m_scrollWidth;
1021 horizScrollBarHeight = m_scrollWidth;
1022 if (m_vScrollBar && !m_vScrollBar->IsShown())
1023 vertScrollBarWidth = 0;
1024 if (m_hScrollBar && !m_hScrollBar->IsShown())
1025 horizScrollBarHeight = 0;
1026
1027 if (m_hScrollBar)
1028 {
1029 int nCols = GetCols();
1030 m_hScrollBar->SetScrollbar(m_hScrollBar->GetThumbPosition(), wxMax(noHorizSteps, 1), (noHorizSteps == 0) ? 1 : nCols, wxMax(noHorizSteps, 1));
1031
1032 m_hScrollBar->SetSize(m_leftOfSheet, ch - m_scrollWidth -2,
1033 cw - vertScrollBarWidth - m_leftOfSheet, m_scrollWidth);
1034 }
1035
1036 if (m_vScrollBar)
1037 {
1038 int nRows = GetRows();
1039
1040 m_vScrollBar->SetScrollbar(m_vScrollBar->GetThumbPosition(), wxMax(noVertSteps, 1), (noVertSteps == 0) ? 1 : nRows, wxMax(noVertSteps, 1));
1041 m_vScrollBar->SetSize(cw - m_scrollWidth, m_topOfSheet,
1042 m_scrollWidth, ch - m_topOfSheet - horizScrollBarHeight);
1043 }
1044 }
1045
1046 void wxGenericGrid::OnSize(wxSizeEvent& WXUNUSED(event) )
1047 {
1048 if (!m_vScrollBar || !m_hScrollBar)
1049 return;
1050
1051 AdjustScrollbars();
1052
1053 int cw, ch;
1054 GetClientSize(&cw, &ch);
1055
1056 if (m_editCreated && m_editingPanel && GetTextItem() && GetTextItem()->IsShown())
1057 {
1058 m_editingPanel->SetSize(0, 0, cw, m_editControlPosition.height + m_editControlPosition.y + 2);
1059 GetTextItem()->SetSize(m_editControlPosition.x, m_editControlPosition.y,
1060 cw - m_editControlPosition.x, m_editControlPosition.height);
1061 }
1062 }
1063
1064 bool wxGenericGrid::CellHitTest(int x, int y, int *row, int *col)
1065 {
1066 // Find the selected cell and call OnSelectCell
1067 if (x >= (m_leftOfSheet + m_verticalLabelWidth) && y >= (m_topOfSheet + m_horizontalLabelHeight) &&
1068 x <= m_rightOfSheet && y <= m_bottomOfSheet)
1069 {
1070 // Calculate the cell number from x and y
1071 x -= (m_verticalLabelWidth + m_leftOfSheet);
1072 y -= (m_topOfSheet + m_horizontalLabelHeight);
1073
1074 int i;
1075
1076 // Now we need to do a hit test for which row we're on
1077 int currentHeight = 0;
1078 for (i = m_scrollPosY; i < m_totalRows; i++)
1079 {
1080 if (y >= currentHeight && y <= (currentHeight + m_rowHeights[i]))
1081 {
1082 *row = i;
1083 break;
1084 }
1085 currentHeight += m_rowHeights[i];
1086 }
1087
1088 // Now we need to do a hit test for which column we're on
1089 int currentWidth = 0;
1090 for (i = m_scrollPosX; i < m_totalCols; i++)
1091 {
1092 if (x >= currentWidth && x <= (currentWidth + m_colWidths[i]))
1093 {
1094 *col = i;
1095 break;
1096 }
1097 currentWidth += m_colWidths[i];
1098 }
1099 return TRUE;
1100 }
1101 return FALSE;
1102 }
1103
1104 bool wxGenericGrid::LabelSashHitTest(int x, int y, int *orientation, int *rowOrCol, int *startPos)
1105 {
1106 int i;
1107 int tolerance = 3;
1108
1109 if (x >= (m_leftOfSheet + m_verticalLabelWidth) && y >= m_topOfSheet &&
1110 x <= m_rightOfSheet && y <= (m_topOfSheet + m_horizontalLabelHeight))
1111 {
1112 // We may be on a column label sash.
1113 int currentWidth = m_leftOfSheet + m_verticalLabelWidth;
1114 for (i = m_scrollPosX; i < m_totalCols; i++)
1115 {
1116 if (x >= (currentWidth + m_colWidths[i] - tolerance) && x <= (currentWidth + m_colWidths[i] + tolerance))
1117 {
1118 *orientation = wxHORIZONTAL;
1119 *rowOrCol = i;
1120 *startPos = currentWidth;
1121 return TRUE;
1122 }
1123 currentWidth += m_colWidths[i];
1124 }
1125 return FALSE;
1126 }
1127 else if (x >= m_leftOfSheet && y >= (m_topOfSheet + m_horizontalLabelHeight) &&
1128 x <= (m_leftOfSheet + m_verticalLabelWidth) && y <= m_bottomOfSheet)
1129 {
1130 // We may be on a row label sash.
1131 int currentHeight = m_topOfSheet + m_horizontalLabelHeight;
1132 for (i = m_scrollPosY; i < m_totalRows; i++)
1133 {
1134 if (y >= (currentHeight + m_rowHeights[i] - tolerance) && y <= (currentHeight + m_rowHeights[i] + tolerance))
1135 {
1136 *orientation = wxVERTICAL;
1137 *rowOrCol = i;
1138 *startPos = currentHeight;
1139 return TRUE;
1140 }
1141 currentHeight += m_rowHeights[i];
1142 }
1143 return FALSE;
1144 }
1145 return FALSE;
1146 }
1147
1148 bool wxGenericGrid::LabelHitTest(int x, int y, int *row, int *col)
1149 {
1150 // Find the selected label
1151 if (x >= m_leftOfSheet && y >= m_topOfSheet &&
1152 x <= m_rightOfSheet && y <= m_bottomOfSheet)
1153 {
1154 // Calculate the cell number from x and y
1155 x -= m_leftOfSheet;
1156 y -= m_topOfSheet;
1157
1158 int i;
1159
1160 // Now we need to do a hit test for which row we're on
1161 int currentHeight = m_horizontalLabelHeight;
1162 for (i = m_scrollPosY; i < m_totalRows; i++)
1163 {
1164 if (y >= currentHeight && y <= (currentHeight + m_rowHeights[i]))
1165 {
1166 *row = i;
1167 break;
1168 }
1169 currentHeight += m_rowHeights[i];
1170 }
1171 if (y >= 0 && y <= m_horizontalLabelHeight)
1172 {
1173 *row = -1;
1174 }
1175
1176 // Now we need to do a hit test for which column we're on
1177 int currentWidth = m_verticalLabelWidth;
1178 for (i = m_scrollPosX; i < m_totalCols; i++)
1179 {
1180 if (x >= currentWidth && x <= (currentWidth + m_colWidths[i]))
1181 {
1182 *col = i;
1183 break;
1184 }
1185 currentWidth += m_colWidths[i];
1186 }
1187 if (x >= 0 && x <= m_verticalLabelWidth)
1188 {
1189 *col = -1;
1190 }
1191
1192 if ((*col == -1) || (*row == -1))
1193 {
1194 return TRUE;
1195 }
1196 }
1197 return FALSE;
1198 }
1199
1200 void wxGenericGrid::OnMouseEvent(wxMouseEvent& ev)
1201 {
1202 if (ev.LeftDown())
1203 {
1204 wxClientDC dc(this);
1205 dc.BeginDrawing();
1206
1207 int row, col;
1208 if (CellHitTest((int)ev.GetX(), (int)ev.GetY(), &row, &col))
1209 {
1210 OnSelectCellImplementation(& dc, row, col);
1211
1212 //OnCellLeftClick(row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown());
1213 wxGridEvent g_evt(GetId(), wxEVT_GRID_CELL_LCLICK, this,
1214 row, col, (int)ev.GetX(), (int)ev.GetY(),
1215 ev.ControlDown(), ev.ShiftDown());
1216 GetEventHandler()->ProcessEvent(g_evt);
1217
1218 }
1219 if (LabelHitTest((int)ev.GetX(), (int)ev.GetY(), &row, &col))
1220 {
1221 //OnLabelLeftClick(row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown());
1222 wxGridEvent g_evt(GetId(), wxEVT_GRID_LABEL_LCLICK, this,
1223 row, col, (int)ev.GetX(), (int)ev.GetY(),
1224 ev.ControlDown(), ev.ShiftDown());
1225 GetEventHandler()->ProcessEvent(g_evt);
1226
1227 }
1228 dc.EndDrawing();
1229 }
1230 else if (ev.Dragging() && ev.LeftIsDown())
1231 {
1232 switch (m_dragStatus)
1233 {
1234 case wxGRID_DRAG_NONE:
1235 {
1236 int orientation;
1237 if (LabelSashHitTest((int)ev.GetX(), (int)ev.GetY(), &orientation, &m_dragRowOrCol, &m_dragStartPosition))
1238 {
1239 if (orientation == wxHORIZONTAL)
1240 {
1241 m_dragStatus = wxGRID_DRAG_LEFT_RIGHT;
1242 SetCursor(*m_horizontalSashCursor);
1243 m_dragLastPosition = (int)ev.GetX();
1244 }
1245 else
1246 {
1247 m_dragStatus = wxGRID_DRAG_UP_DOWN;
1248 SetCursor(*m_verticalSashCursor);
1249 m_dragLastPosition = (int)ev.GetY();
1250 }
1251 wxClientDC dc(this);
1252 dc.BeginDrawing();
1253 dc.SetLogicalFunction(wxINVERT);
1254 if (orientation == wxHORIZONTAL)
1255 dc.DrawLine((int)ev.GetX(), m_topOfSheet, (int)ev.GetX(), m_bottomOfSheet);
1256 else
1257 dc.DrawLine(m_leftOfSheet, (int)ev.GetY(), m_rightOfSheet, (int)ev.GetY());
1258 dc.EndDrawing();
1259
1260 CaptureMouse();
1261 }
1262 break;
1263 }
1264 case wxGRID_DRAG_LEFT_RIGHT:
1265 {
1266 wxClientDC dc(this);
1267 dc.BeginDrawing();
1268 dc.SetLogicalFunction(wxINVERT);
1269 dc.DrawLine(m_dragLastPosition, m_topOfSheet, m_dragLastPosition, m_bottomOfSheet);
1270
1271 dc.DrawLine((int)ev.GetX(), m_topOfSheet, (int)ev.GetX(), m_bottomOfSheet);
1272 dc.EndDrawing();
1273
1274 m_dragLastPosition = (int)ev.GetX();
1275 SetCursor(*m_horizontalSashCursor);
1276 break;
1277 }
1278 case wxGRID_DRAG_UP_DOWN:
1279 {
1280 wxClientDC dc(this);
1281 dc.BeginDrawing();
1282 dc.SetLogicalFunction(wxINVERT);
1283 dc.DrawLine(m_leftOfSheet, m_dragLastPosition, m_rightOfSheet, m_dragLastPosition);
1284
1285 dc.DrawLine(m_leftOfSheet, (int)ev.GetY(), m_rightOfSheet, (int)ev.GetY());
1286 dc.EndDrawing();
1287
1288 m_dragLastPosition = (int)ev.GetY();
1289 SetCursor(*m_verticalSashCursor);
1290 break;
1291 }
1292 }
1293 }
1294 else if (ev.Moving())
1295 {
1296 int rowOrCol, orientation, startPos;
1297 if (LabelSashHitTest((int)ev.GetX(), (int)ev.GetY(), &orientation, &rowOrCol, &startPos))
1298 {
1299 if (orientation == wxHORIZONTAL)
1300 SetCursor(*m_horizontalSashCursor);
1301 else
1302 SetCursor(*m_verticalSashCursor);
1303 }
1304 else
1305 SetCursor(*wxSTANDARD_CURSOR);
1306 }
1307 else if (ev.LeftUp())
1308 {
1309 switch (m_dragStatus)
1310 {
1311 case wxGRID_DRAG_LEFT_RIGHT:
1312 {
1313 wxClientDC dc(this);
1314 dc.BeginDrawing();
1315 dc.SetLogicalFunction(wxINVERT);
1316 dc.DrawLine(m_dragLastPosition, m_topOfSheet, m_dragLastPosition, m_bottomOfSheet);
1317 dc.SetLogicalFunction(wxCOPY);
1318 dc.EndDrawing();
1319
1320 ReleaseMouse();
1321 if (ev.GetX() > m_dragStartPosition)
1322 {
1323 m_colWidths[m_dragRowOrCol] = (short)(ev.GetX() - m_dragStartPosition);
1324 UpdateDimensions();
1325 AdjustScrollbars();
1326 Refresh();
1327 }
1328 SetCursor(*wxSTANDARD_CURSOR);
1329 int cw, ch;
1330 GetClientSize(&cw, &ch);
1331 wxSizeEvent evt;
1332 OnSize(evt);
1333 break;
1334 }
1335 case wxGRID_DRAG_UP_DOWN:
1336 {
1337 wxClientDC dc(this);
1338 dc.BeginDrawing();
1339 dc.SetLogicalFunction(wxINVERT);
1340 dc.DrawLine(m_leftOfSheet, m_dragLastPosition, m_rightOfSheet, m_dragLastPosition);
1341 dc.SetLogicalFunction(wxCOPY);
1342 dc.EndDrawing();
1343
1344 ReleaseMouse();
1345 if (ev.GetY() > m_dragStartPosition)
1346 {
1347 m_rowHeights[m_dragRowOrCol] = (short)(ev.GetY() - m_dragStartPosition);
1348 UpdateDimensions();
1349 AdjustScrollbars();
1350 Refresh();
1351 }
1352 SetCursor(*wxSTANDARD_CURSOR);
1353 break;
1354 }
1355 }
1356 m_dragStatus = wxGRID_DRAG_NONE;
1357 }
1358 else if (ev.RightDown())
1359 {
1360 int row, col;
1361 if (CellHitTest((int)ev.GetX(), (int)ev.GetY(), &row, &col))
1362 {
1363 //OnCellRightClick(row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown());
1364 wxGridEvent g_evt(GetId(), wxEVT_GRID_CELL_RCLICK, this,
1365 row, col, (int)ev.GetX(), (int)ev.GetY(),
1366 ev.ControlDown(), ev.ShiftDown());
1367 GetEventHandler()->ProcessEvent(g_evt);
1368
1369 }
1370 if (LabelHitTest((int)ev.GetX(), (int)ev.GetY(), &row, &col))
1371 {
1372 //OnLabelRightClick(row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown());
1373 wxGridEvent g_evt(GetId(), wxEVT_GRID_LABEL_RCLICK, this,
1374 row, col, (int)ev.GetX(), (int)ev.GetY(),
1375 ev.ControlDown(), ev.ShiftDown());
1376 GetEventHandler()->ProcessEvent(g_evt);
1377 }
1378 }
1379 }
1380
1381 void wxGenericGrid::OnSelectCellImplementation(wxDC *dc, int row, int col)
1382 {
1383 m_wCursorColumn = col;
1384 m_wCursorRow = row;
1385
1386 //OnChangeSelectionLabel();
1387 wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_SEL_LABEL, this);
1388 GetEventHandler()->ProcessEvent(g_evt);
1389
1390 SetGridClippingRegion(dc);
1391
1392 // Remove the highlight from the old cell
1393 if (m_currentRectVisible)
1394 HighlightCell(dc);
1395
1396 // Highlight the new cell and copy its content to the edit control
1397 SetCurrentRect(m_wCursorRow, m_wCursorColumn);
1398 wxGridCell *cell = GetCell(m_wCursorRow, m_wCursorColumn);
1399 if (cell)
1400 {
1401 if ( cell->GetTextValue().IsNull() )
1402 m_textItem->SetValue("");
1403 else
1404 m_textItem->SetValue(cell->GetTextValue());
1405 }
1406
1407 SetGridClippingRegion(dc);
1408
1409 // 1) Why isn't this needed for Windows??
1410 // Probably because of the SetValue?? JS.
1411 // 2) Arrrrrgh. This isn't needed anywhere,
1412 // of course. One hour of debugging... RR.
1413 #ifndef __WXMSW__
1414 // HighlightCell(dc);
1415 #endif
1416 dc->DestroyClippingRegion();
1417
1418 //OnSelectCell(row, col);
1419 wxGridEvent g_evt2(GetId(), wxEVT_GRID_SELECT_CELL, this, row, col);
1420 GetEventHandler()->ProcessEvent(g_evt2);
1421 }
1422
1423 wxGridCell *wxGenericGrid::OnCreateCell(void)
1424 {
1425 return new wxGridCell(this);
1426 }
1427
1428 void wxGenericGrid::OnChangeLabels(void)
1429 {
1430 char buf[100];
1431 int i;
1432 for (i = 0; i < m_totalRows; i++)
1433 {
1434 sprintf(buf, "%d", i+1);
1435 SetLabelValue(wxVERTICAL, buf, i);
1436 }
1437 // A...Z,AA...ZZ,AAA...ZZZ, etc.
1438 for (i = 0; i < m_totalCols; i++)
1439 {
1440 int j;
1441 int noTimes = (i/26 + 1);
1442 int ch = (i % 26) + 65;
1443 buf[0] = 0;
1444 for (j = 0; j < noTimes; j++)
1445 {
1446 char buf2[20];
1447 sprintf(buf2, "%c", (char)ch);
1448 strcat(buf, buf2);
1449 }
1450 SetLabelValue(wxHORIZONTAL, buf, i);
1451 }
1452 }
1453
1454 void wxGenericGrid::OnChangeSelectionLabel(void)
1455 {
1456 if (!GetEditable())
1457 return;
1458
1459 wxString rowLabel(GetLabelValue(wxVERTICAL, GetCursorRow()));
1460 wxString colLabel(GetLabelValue(wxHORIZONTAL, GetCursorColumn()));
1461
1462 wxString newLabel = colLabel + rowLabel;
1463 if ((newLabel.Length() > 0) && (newLabel.Length() <= 8) && GetTextItem())
1464 {
1465 // GetTextItem()->SetLabel(newLabel);
1466 }
1467 }
1468
1469 void wxGenericGrid::HighlightCell(wxDC *dc)
1470 {
1471 dc->SetLogicalFunction(wxINVERT);
1472
1473 // Top
1474 dc->DrawLine( m_currentRect.x + 1,
1475 m_currentRect.y + 1,
1476 m_currentRect.x + m_currentRect.width - 1,
1477 m_currentRect.y + 1);
1478 // Right
1479 dc->DrawLine( m_currentRect.x + m_currentRect.width - 1,
1480 m_currentRect.y + 1,
1481 m_currentRect.x + m_currentRect.width - 1,
1482 m_currentRect.y +m_currentRect.height - 1 );
1483 // Bottom
1484 dc->DrawLine( m_currentRect.x + m_currentRect.width - 1,
1485 m_currentRect.y + m_currentRect.height - 1,
1486 m_currentRect.x + 1,
1487 m_currentRect.y + m_currentRect.height - 1);
1488 // Left
1489 dc->DrawLine( m_currentRect.x + 1,
1490 m_currentRect.y + m_currentRect.height - 1,
1491 m_currentRect.x + 1,
1492 m_currentRect.y + 1);
1493
1494 dc->SetLogicalFunction(wxCOPY);
1495 }
1496
1497 void wxGenericGrid::DrawCellText(void)
1498 {
1499 if (!m_currentRectVisible)
1500 return;
1501
1502 wxGridCell *cell = GetCell(GetCursorRow(), GetCursorColumn());
1503 if (!cell)
1504 return;
1505
1506 static char szEdit[300];
1507
1508 wxClientDC dc(this);
1509 dc.BeginDrawing();
1510
1511 SetGridClippingRegion(& dc);
1512
1513 dc.SetBackgroundMode(wxTRANSPARENT);
1514 dc.SetBrush(*cell->GetBackgroundBrush());
1515
1516 strcpy(szEdit, m_textItem->GetValue());
1517
1518 wxRect rect;
1519 rect = m_currentRect;
1520 rect.x += 3;
1521 rect.y += 2;
1522 rect.width -= 5;
1523 rect.height -= 4;
1524
1525 DrawTextRect(& dc, " ", &rect, wxLEFT);
1526 DrawTextRect(& dc, szEdit, &rect, cell->GetAlignment());
1527
1528 dc.DestroyClippingRegion();
1529
1530 dc.SetBackgroundMode(wxSOLID);
1531
1532 dc.EndDrawing();
1533 }
1534
1535 void wxGenericGrid::SetCurrentRect(int Row, int Column, int canvasW, int canvasH)
1536 {
1537 int currentWidth = m_leftOfSheet + m_verticalLabelWidth;
1538 int i;
1539 for (i = m_scrollPosX; i < Column; i++)
1540 currentWidth += m_colWidths[i];
1541
1542 int currentHeight = m_topOfSheet + m_horizontalLabelHeight;
1543 for (i = m_scrollPosY; i < Row; i++)
1544 currentHeight += m_rowHeights[i];
1545
1546 m_currentRect.x = currentWidth;
1547 m_currentRect.y = currentHeight;
1548 m_currentRect.width = m_colWidths ? (m_colWidths[Column]) : 0;
1549 m_currentRect.height = m_rowHeights ? (m_rowHeights[Row]) : 0;
1550
1551 if (Row < m_scrollPosY || Column < m_scrollPosX)
1552 m_currentRectVisible = FALSE;
1553 else if ((canvasW != -1 && canvasH != -1) && (m_currentRect.x > canvasW || m_currentRect.y > canvasH))
1554 m_currentRectVisible = FALSE;
1555 else m_currentRectVisible = TRUE;
1556 }
1557
1558 static bool wxRectIntersection(wxRect *rect1, wxRect *rect2, wxRect *rect3)
1559 {
1560 int x2_1 = rect1->x + rect1->width;
1561 int y2_1 = rect1->y + rect1->height;
1562
1563 int x2_2 = rect2->x + rect2->width;
1564 int y2_2 = rect2->y + rect2->height;
1565
1566 int x2_3, y2_3;
1567
1568 // Check for intersection
1569 if ((rect1->x > x2_2) || (rect2->x > x2_1) ||
1570 (rect1->y > y2_2) || (rect2->y > y2_1))
1571 {
1572 // No intersection
1573 rect3->x = rect3->y = rect3->width = rect3->height = 0;
1574 return FALSE;
1575 }
1576
1577 if (rect1->x > rect2->x)
1578 rect3->x = rect1->x;
1579 else
1580 rect3->x = rect2->x;
1581 if (rect1->y > rect2->y)
1582 rect3->y = rect1->y;
1583 else
1584 rect3->y = rect2->y;
1585
1586 if (x2_1 > x2_2)
1587 x2_3 = x2_2;
1588 else
1589 x2_3 = x2_1;
1590 if (y2_1 > y2_2)
1591 y2_3 = y2_2;
1592 else
1593 y2_3 = y2_1;
1594
1595 rect3->width = (int)(x2_3 - rect3->x);
1596 rect3->height = (int)(y2_3 - rect3->y);
1597 return TRUE;
1598 }
1599
1600 void wxGenericGrid::DrawTextRect(wxDC *dc, const wxString& text, wxRect *rect, int flag)
1601 {
1602 dc->BeginDrawing();
1603
1604 // Ultimately, this functionality should be built into wxWindows,
1605 // and optimized for each platform. E.g. on Windows, use DrawText
1606 // passing a clipping rectangle, so that the wxWindows clipping region
1607 // does not have to be used to implement this.
1608
1609 // If we're already clipping, we need to find the intersection
1610 // between current clipping area and text clipping area.
1611
1612 wxRect clipRect;
1613 wxRect clipRect2;
1614 long clipX, clipY, clipW, clipH;
1615 dc->GetClippingBox(&clipX, &clipY, &clipW, &clipH);
1616 clipRect.x = (int)clipX; clipRect.y = (int)clipY;
1617 clipRect.width = (int)clipW; clipRect.height = (int)clipH;
1618
1619 bool alreadyClipping = TRUE;
1620
1621 if (clipRect.x == 0 && clipRect.y == 0 && clipRect.width == 0 && clipRect.height == 0)
1622 {
1623 alreadyClipping = FALSE;
1624 clipRect2.x = rect->x; clipRect2.y = rect->y;
1625 clipRect2.width = rect->width; clipRect2.height = rect->height;
1626 }
1627 else
1628 {
1629 // Find intersection.
1630 if (!wxRectIntersection(rect, &clipRect, &clipRect2))
1631 return;
1632 }
1633
1634 if (alreadyClipping)
1635 dc->DestroyClippingRegion();
1636
1637 dc->SetClippingRegion(clipRect2.x, clipRect2.y, clipRect2.width, clipRect2.height);
1638 long textWidth, textHeight;
1639
1640 dc->GetTextExtent(text, &textWidth, &textHeight);
1641
1642 // Do alignment
1643 float x,y;
1644 switch (flag)
1645 {
1646 case wxRIGHT:
1647 {
1648 x = (rect->x + rect->width - textWidth - 1.0);
1649 y = (rect->y + (rect->height - textHeight)/2.0);
1650 break;
1651 }
1652 case wxCENTRE:
1653 {
1654 x = (rect->x + (rect->width - textWidth)/2.0);
1655 y = (rect->y + (rect->height - textHeight)/2.0);
1656 break;
1657 }
1658 case wxLEFT:
1659 default:
1660 {
1661 x = (rect->x + 1.0);
1662 y = (rect->y + (rect->height - textHeight)/2.0);
1663 break;
1664 }
1665 }
1666 dc->DrawText(text, (long)x, (long)y );
1667
1668 dc->DestroyClippingRegion();
1669
1670 // Restore old clipping
1671 if (alreadyClipping)
1672 dc->SetClippingRegion(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1673
1674 dc->EndDrawing();
1675 }
1676
1677 void wxGenericGrid::DrawBitmapRect(wxDC *dc, wxBitmap *bitmap, wxRect *rect, int flag)
1678 {
1679 dc->BeginDrawing();
1680
1681 // Ultimately, this functionality should be built into wxWindows,
1682 // and optimized for each platform. E.g. on Windows, use DrawText
1683 // passing a clipping rectangle, so that the wxWindows clipping region
1684 // does not have to be used to implement this.
1685
1686 // If we're already clipping, we need to find the intersection
1687 // between current clipping area and text clipping area.
1688
1689 wxRect clipRect;
1690 wxRect clipRect2;
1691 long clipX, clipY, clipW, clipH;
1692 dc->GetClippingBox(&clipX, &clipY, &clipW, &clipH);
1693 clipRect.x = (int)clipX; clipRect.y = (int)clipY;
1694 clipRect.width = (int)clipW; clipRect.height = (int)clipH;
1695
1696 bool alreadyClipping = TRUE;
1697
1698 if (clipRect.x == 0 && clipRect.y == 0 && clipRect.width == 0 && clipRect.height == 0)
1699 {
1700 alreadyClipping = FALSE;
1701 clipRect2.x = rect->x; clipRect2.y = rect->y;
1702 clipRect2.width = rect->width; clipRect2.height = rect->height;
1703 }
1704 else
1705 {
1706 // Find intersection.
1707 if (!wxRectIntersection(rect, &clipRect, &clipRect2))
1708 return;
1709 }
1710
1711 if (alreadyClipping)
1712 dc->DestroyClippingRegion();
1713
1714 dc->SetClippingRegion(clipRect2.x, clipRect2.y, clipRect2.width, clipRect2.height);
1715 float bitmapWidth, bitmapHeight;
1716
1717 bitmapWidth = bitmap->GetWidth();
1718 bitmapHeight = bitmap->GetHeight();
1719
1720 // Do alignment
1721 long x,y;
1722 switch (flag)
1723 {
1724 case wxRIGHT:
1725 {
1726 x = (long)(rect->x + rect->width - bitmapWidth - 1);
1727 y = (long)(rect->y + (rect->height - bitmapHeight)/2.0);
1728 break;
1729 }
1730 case wxCENTRE:
1731 {
1732 x = (long)(rect->x + (rect->width - bitmapWidth)/2.0);
1733 y = (long)(rect->y + (rect->height - bitmapHeight)/2.0);
1734 break;
1735 }
1736 case wxLEFT:
1737 default:
1738 {
1739 x = (long)(rect->x + 1);
1740 y = (long)(rect->y + (rect->height - bitmapHeight)/2.0);
1741 break;
1742 }
1743 }
1744 wxMemoryDC dcTemp;
1745 dcTemp.SelectObject(*bitmap);
1746
1747 dc->Blit( (long)x, (long)y, (long)bitmapWidth, (long)bitmapHeight, &dcTemp, 0, 0);
1748 dcTemp.SelectObject(wxNullBitmap);
1749
1750 dc->DestroyClippingRegion();
1751
1752 // Restore old clipping
1753 if (alreadyClipping)
1754 dc->SetClippingRegion(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
1755
1756 dc->EndDrawing();
1757 }
1758
1759 void wxGenericGrid::OnActivate(bool active)
1760 {
1761 if (active)
1762 {
1763 // Edit control should always have the focus
1764 if (GetTextItem() && GetEditable())
1765 {
1766 GetTextItem()->SetFocus();
1767 wxGridCell *cell = GetCell(GetCursorRow(), GetCursorColumn());
1768 if (cell)
1769 GetTextItem()->SetValue(cell->GetTextValue());
1770 }
1771 }
1772 }
1773
1774 void wxGenericGrid::SetCellValue(const wxString& val, int row, int col)
1775 {
1776 wxGridCell *cell = GetCell(row, col);
1777 if (cell)
1778 {
1779 cell->SetTextValue(val);
1780
1781 RefreshCell(row, col, TRUE);
1782 }
1783 }
1784
1785 void wxGenericGrid::RefreshCell(int row, int col, bool setText)
1786 {
1787 // Don't refresh within a pair of batch brackets
1788 if (GetBatchCount() > 0)
1789 return;
1790
1791 int cw, ch;
1792 GetClientSize(&cw, &ch);
1793
1794 SetCurrentRect(row, col, cw, ch);
1795 if (m_currentRectVisible)
1796 {
1797 wxGridCell *cell = GetCell(row, col);
1798
1799 bool currentPos = FALSE;
1800 if (row == m_wCursorRow && col == m_wCursorColumn && GetTextItem() && GetTextItem()->IsShown() && setText)
1801 {
1802 GetTextItem()->SetValue(cell->GetTextValue());
1803 currentPos = TRUE;
1804 }
1805 // Gets refreshed anyway in MSW
1806 #ifdef __WXMSW__
1807 if (!currentPos)
1808 #endif
1809 {
1810 wxClientDC dc(this);
1811 dc.BeginDrawing();
1812 DrawCellBackground(& dc, &m_currentRect, row, col);
1813 DrawCellValue(& dc, &m_currentRect, row, col);
1814 dc.EndDrawing();
1815 }
1816 }
1817 }
1818
1819 wxString& wxGenericGrid::GetCellValue(int row, int col)
1820 {
1821 static wxString emptyString("");
1822
1823 wxGridCell *cell = GetCell(row, col);
1824 if (cell)
1825 return cell->GetTextValue();
1826 else
1827 return emptyString;
1828 }
1829
1830 void wxGenericGrid::SetColumnWidth(int col, int width)
1831 {
1832 if (col <= m_totalCols)
1833 m_colWidths[col] = width;
1834 }
1835
1836 int wxGenericGrid::GetColumnWidth(int col)
1837 {
1838 if (col <= m_totalCols)
1839 return m_colWidths[col];
1840 else
1841 return 0;
1842 }
1843
1844 void wxGenericGrid::SetRowHeight(int row, int height)
1845 {
1846 if (row <= m_totalRows)
1847 m_rowHeights[row] = height;
1848 }
1849
1850 int wxGenericGrid::GetRowHeight(int row)
1851 {
1852 if (row <= m_totalRows)
1853 return m_rowHeights[row];
1854 else
1855 return 0;
1856 }
1857
1858 void wxGenericGrid::SetLabelSize(int orientation, int sz)
1859 {
1860 if (orientation == wxHORIZONTAL)
1861 m_horizontalLabelHeight = sz;
1862 else
1863 m_verticalLabelWidth = sz;
1864 UpdateDimensions();
1865 SetCurrentRect(GetCursorRow(), GetCursorColumn());
1866 }
1867
1868 int wxGenericGrid::GetLabelSize(int orientation)
1869 {
1870 if (orientation == wxHORIZONTAL)
1871 return m_horizontalLabelHeight;
1872 else
1873 return m_verticalLabelWidth;
1874 }
1875
1876 wxGridCell *wxGenericGrid::GetLabelCell(int orientation, int pos)
1877 {
1878 if (orientation == wxHORIZONTAL)
1879 {
1880 if (m_colLabelCells && pos < m_totalCols)
1881 return m_colLabelCells[pos];
1882 else
1883 return (wxGridCell *) NULL;
1884 }
1885 else
1886 {
1887 if (m_rowLabelCells && pos < m_totalRows)
1888 return m_rowLabelCells[pos];
1889 else
1890 return (wxGridCell *) NULL;
1891 }
1892 }
1893
1894 void wxGenericGrid::SetLabelValue(int orientation, const wxString& val, int pos)
1895 {
1896 wxGridCell *cell = GetLabelCell(orientation, pos);
1897 if (cell)
1898 cell->SetTextValue(val);
1899 }
1900
1901 wxString& wxGenericGrid::GetLabelValue(int orientation, int pos)
1902 {
1903 static wxString emptyString = "";
1904 wxGridCell *cell = GetLabelCell(orientation, pos);
1905 if (cell)
1906 return cell->GetTextValue();
1907 else
1908 return emptyString;
1909 }
1910
1911 void wxGenericGrid::SetLabelAlignment(int orientation, int align)
1912 {
1913 if (orientation == wxHORIZONTAL)
1914 m_horizontalLabelAlignment = align;
1915 else
1916 m_verticalLabelAlignment = align;
1917 UpdateDimensions();
1918 SetCurrentRect(GetCursorRow(), GetCursorColumn());
1919 }
1920
1921 int wxGenericGrid::GetLabelAlignment(int orientation)
1922 {
1923 if (orientation == wxHORIZONTAL)
1924 return m_horizontalLabelAlignment;
1925 else
1926 return m_verticalLabelAlignment;
1927 }
1928
1929 void wxGenericGrid::SetLabelTextColour(const wxColour& colour)
1930 {
1931 m_labelTextColour = colour;
1932
1933 }
1934
1935 void wxGenericGrid::SetLabelBackgroundColour(const wxColour& colour)
1936 {
1937 m_labelBackgroundColour = colour;
1938 m_labelBackgroundBrush = wxTheBrushList->FindOrCreateBrush(m_labelBackgroundColour, wxSOLID);
1939 }
1940
1941 void wxGenericGrid::SetEditable(bool edit)
1942 {
1943 m_editable = edit;
1944 if (edit)
1945 {
1946 int controlW, controlH;
1947 m_textItem->GetSize(&controlW, &controlH);
1948 m_editControlPosition.height = controlH;
1949
1950 m_topOfSheet = m_editControlPosition.x + controlH + 2;
1951 if (m_textItem)
1952 {
1953 m_editingPanel->Show(TRUE);
1954 m_textItem->Show(TRUE);
1955 m_textItem->SetFocus();
1956 }
1957 }
1958 else
1959 {
1960 m_topOfSheet = 0;
1961 if (m_textItem)
1962 {
1963 m_textItem->Show(FALSE);
1964 m_editingPanel->Show(FALSE);
1965 }
1966 }
1967 UpdateDimensions();
1968 SetCurrentRect(GetCursorRow(), GetCursorColumn());
1969
1970 int cw, ch;
1971 GetClientSize(&cw, &ch);
1972 wxSizeEvent evt;
1973 OnSize(evt);
1974 /*
1975 int cw, ch;
1976 int m_scrollWidth = 16;
1977 GetClientSize(&cw, &ch);
1978
1979 if (m_vScrollBar)
1980 m_vScrollBar->SetSize(cw - m_scrollWidth, m_topOfSheet,
1981 m_scrollWidth, ch - m_topOfSheet - m_scrollWidth);
1982 */
1983 }
1984
1985 void wxGenericGrid::SetCellAlignment(int flag, int row, int col)
1986 {
1987 wxGridCell *cell = GetCell(row, col);
1988 if (cell)
1989 cell->SetAlignment(flag);
1990 }
1991
1992 int wxGenericGrid::GetCellAlignment(int row, int col)
1993 {
1994 wxGridCell *cell = GetCell(row, col);
1995 if (cell)
1996 return cell->GetAlignment();
1997 else
1998 return m_cellAlignment;
1999 }
2000
2001 void wxGenericGrid::SetCellAlignment(int flag)
2002 {
2003 m_cellAlignment = flag;
2004 int i,j;
2005 for (i = 0; i < GetRows(); i++)
2006 for (j = 0; j < GetCols(); j++)
2007 if (GetCell(i, j))
2008 GetCell(i, j)->SetAlignment(flag);
2009 }
2010
2011 int wxGenericGrid::GetCellAlignment(void)
2012 {
2013 return m_cellAlignment;
2014 }
2015
2016 void wxGenericGrid::SetCellBackgroundColour(const wxColour& col)
2017 {
2018 m_cellBackgroundColour = col;
2019 int i,j;
2020 for (i = 0; i < GetRows(); i++)
2021 for (j = 0; j < GetCols(); j++)
2022 if (GetCell(i, j))
2023 GetCell(i, j)->SetBackgroundColour(col);
2024 }
2025
2026 void wxGenericGrid::SetCellBackgroundColour(const wxColour& val, int row, int col)
2027 {
2028 wxGridCell *cell = GetCell(row, col);
2029 if (cell)
2030 {
2031 cell->SetBackgroundColour(val);
2032 RefreshCell(row, col);
2033 }
2034 }
2035
2036 wxColour& wxGenericGrid::GetCellBackgroundColour(int row, int col)
2037 {
2038 wxGridCell *cell = GetCell(row, col);
2039 if (cell)
2040 return cell->GetBackgroundColour();
2041 else
2042 return m_cellBackgroundColour;
2043 }
2044
2045 void wxGenericGrid::SetCellTextColour(const wxColour& val, int row, int col)
2046 {
2047 wxGridCell *cell = GetCell(row, col);
2048 if (cell)
2049 {
2050 cell->SetTextColour(val);
2051 RefreshCell(row, col);
2052 }
2053 }
2054
2055 void wxGenericGrid::SetCellTextFont(wxFont *fnt, int row, int col)
2056 {
2057 wxGridCell *cell = GetCell(row, col);
2058 if (cell)
2059 {
2060 cell->SetFont(fnt);
2061 RefreshCell(row, col);
2062 }
2063 }
2064
2065 wxFont *wxGenericGrid::GetCellTextFont(int row, int col)
2066 {
2067 wxGridCell *cell = GetCell(row, col);
2068 if (cell)
2069 return cell->GetFont();
2070 else
2071 return m_cellTextFont;
2072 }
2073
2074 wxColour& wxGenericGrid::GetCellTextColour(int row, int col)
2075 {
2076 wxGridCell *cell = GetCell(row, col);
2077 if (cell)
2078 return cell->GetTextColour();
2079 else
2080 return m_cellTextColour;
2081 }
2082
2083 void wxGenericGrid::SetCellTextColour(const wxColour& val)
2084 {
2085 m_cellTextColour = val;
2086 int i,j;
2087 for (i = 0; i < GetRows(); i++)
2088 for (j = 0; j < GetCols(); j++)
2089 if (GetCell(i, j))
2090 GetCell(i, j)->SetTextColour(val);
2091 }
2092
2093 void wxGenericGrid::SetCellTextFont(wxFont *fnt)
2094 {
2095 m_cellTextFont = fnt;
2096 int i,j;
2097 for (i = 0; i < GetRows(); i++)
2098 for (j = 0; j < GetCols(); j++)
2099 if (GetCell(i, j))
2100 GetCell(i, j)->SetFont(fnt);
2101 }
2102
2103 void wxGenericGrid::SetCellBitmap(wxBitmap *bitmap, int row, int col)
2104 {
2105 wxGridCell *cell = GetCell(row, col);
2106 if (cell)
2107 {
2108 cell->SetCellBitmap(bitmap);
2109 RefreshCell(row, col);
2110 }
2111 }
2112
2113 wxBitmap *wxGenericGrid::GetCellBitmap(int row, int col)
2114 {
2115 wxGridCell *cell = GetCell(row, col);
2116 if (cell)
2117 {
2118 return cell->GetCellBitmap();
2119 }
2120 else
2121 return (wxBitmap *) NULL;
2122 }
2123
2124 bool wxGenericGrid::InsertCols(int pos, int n, bool updateLabels)
2125 {
2126 if (pos > m_totalCols)
2127 return FALSE;
2128
2129 if (!m_gridCells)
2130 return CreateGrid(1, n);
2131 else
2132 {
2133 int i, j;
2134 // Cells
2135 for (i = 0; i < m_totalRows; i++)
2136 {
2137 wxGridCell **cols = m_gridCells[i];
2138 wxGridCell **newCols = new wxGridCell *[m_totalCols + n];
2139 for (j = 0; j < pos; j++)
2140 newCols[j] = cols[j];
2141 for (j = pos; j < pos + n; j++)
2142 newCols[j] = new wxGridCell(this);
2143 for (j = pos + n; j < m_totalCols + n; j++)
2144 newCols[j] = cols[j - n];
2145
2146 delete[] cols;
2147 m_gridCells[i] = newCols;
2148 }
2149
2150 // Column widths
2151 short *newColWidths = new short[m_totalCols + n];
2152 for (j = 0; j < pos; j++)
2153 newColWidths[j] = m_colWidths[j];
2154 for (j = pos; j < pos + n; j++)
2155 newColWidths[j] = wxGRID_DEFAULT_CELL_WIDTH;
2156 for (j = pos + n; j < m_totalCols + n; j++)
2157 newColWidths[j] = m_colWidths[j - n];
2158 delete[] m_colWidths;
2159 m_colWidths = newColWidths;
2160
2161 // Column labels
2162 wxGridCell **newLabels = new wxGridCell *[m_totalCols + n];
2163 for (j = 0; j < pos; j++)
2164 newLabels[j] = m_colLabelCells[j];
2165 for (j = pos; j < pos + n; j++)
2166 newLabels[j] = new wxGridCell(this);
2167 for (j = pos + n; j < m_totalCols + n; j++)
2168 newLabels[j] = m_colLabelCells[j - n];
2169
2170 delete[] m_colLabelCells;
2171 m_colLabelCells = newLabels;
2172
2173 m_totalCols += n;
2174
2175 if (updateLabels) {
2176 //OnChangeLabels();
2177 wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this);
2178 GetEventHandler()->ProcessEvent(g_evt);
2179 }
2180
2181 UpdateDimensions();
2182 AdjustScrollbars();
2183 return TRUE;
2184 }
2185 }
2186
2187 bool wxGenericGrid::InsertRows(int pos, int n, bool updateLabels)
2188 {
2189 if (pos > m_totalRows)
2190 return FALSE;
2191
2192 if (!m_gridCells)
2193 return CreateGrid(n, 1);
2194 else
2195 {
2196 int i, j;
2197
2198 wxGridCell ***rows = new wxGridCell **[m_totalRows + n];
2199
2200 // Cells
2201 for (i = 0; i < pos; i++)
2202 rows[i] = m_gridCells[i];
2203
2204 for (i = pos; i < pos + n; i++)
2205 {
2206 rows[i] = new wxGridCell *[m_totalCols];
2207 for (j = 0; j < m_totalCols; j++)
2208 rows[i][j] = new wxGridCell(this);
2209 }
2210
2211 for (i = pos + n; i < m_totalRows + n; i++)
2212 rows[i] = m_gridCells[i - n];
2213
2214 delete[] m_gridCells;
2215 m_gridCells = rows;
2216
2217 // Row heights
2218 short *newRowHeights = new short[m_totalRows + n];
2219 for (i = 0; i < pos; i++)
2220 newRowHeights[i] = m_rowHeights[i];
2221 for (i = pos; i < pos + n; i++)
2222 newRowHeights[i] = wxGRID_DEFAULT_CELL_HEIGHT;
2223 for (i = pos + n; i < m_totalRows + n; i++)
2224 newRowHeights[i] = m_rowHeights[i - n];
2225 delete[] m_rowHeights;
2226 m_rowHeights = newRowHeights;
2227
2228 // Column labels
2229 wxGridCell **newLabels = new wxGridCell *[m_totalRows + n];
2230 for (i = 0; i < pos; i++)
2231 newLabels[i] = m_rowLabelCells[i];
2232 for (i = pos; i < pos + n; i++)
2233 newLabels[i] = new wxGridCell(this);
2234 for (i = pos + n; i < m_totalRows + n; i++)
2235 newLabels[i] = m_rowLabelCells[i - n];
2236
2237 delete[] m_rowLabelCells;
2238 m_rowLabelCells = newLabels;
2239
2240 m_totalRows += n;
2241
2242 if (updateLabels) {
2243 //OnChangeLabels();
2244 wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this);
2245 GetEventHandler()->ProcessEvent(g_evt);
2246 }
2247
2248 UpdateDimensions();
2249 AdjustScrollbars();
2250 return TRUE;
2251 }
2252 }
2253
2254 bool wxGenericGrid::AppendCols(int n, bool updateLabels)
2255 {
2256 return InsertCols(GetCols(), n, updateLabels);
2257 }
2258
2259 bool wxGenericGrid::AppendRows(int n, bool updateLabels)
2260 {
2261 return InsertRows(GetRows(), n, updateLabels);
2262 }
2263
2264 bool wxGenericGrid::DeleteRows(int pos, int n, bool updateLabels)
2265 {
2266 if (pos > m_totalRows)
2267 return FALSE;
2268 if (!m_gridCells)
2269 return FALSE;
2270
2271 int i;
2272
2273 wxGridCell ***rows = new wxGridCell **[m_totalRows - n];
2274
2275 // Cells
2276 for (i = 0; i < pos; i++)
2277 rows[i] = m_gridCells[i];
2278
2279 for (i = pos + n; i < m_totalRows; i++)
2280 rows[i-n] = m_gridCells[i];
2281
2282 delete[] m_gridCells;
2283 m_gridCells = rows;
2284
2285 // Row heights
2286 short *newRowHeights = new short[m_totalRows - n];
2287 for (i = 0; i < pos; i++)
2288 newRowHeights[i] = m_rowHeights[i];
2289 for (i = pos + n; i < m_totalRows; i++)
2290 newRowHeights[i-n] = m_rowHeights[i];
2291 delete[] m_rowHeights;
2292 m_rowHeights = newRowHeights;
2293
2294 // Column labels
2295 wxGridCell **newLabels = new wxGridCell *[m_totalRows - n];
2296 for (i = 0; i < pos; i++)
2297 newLabels[i] = m_rowLabelCells[i];
2298 for (i = pos + n; i < m_totalRows; i++)
2299 newLabels[i-n] = m_rowLabelCells[i];
2300
2301 delete[] m_rowLabelCells;
2302 m_rowLabelCells = newLabels;
2303
2304 m_totalRows -= n;
2305
2306 if (updateLabels){
2307 //OnChangeLabels();
2308 wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this);
2309 GetEventHandler()->ProcessEvent(g_evt);
2310 }
2311 UpdateDimensions();
2312 AdjustScrollbars();
2313 return TRUE;
2314 }
2315
2316 bool wxGenericGrid::DeleteCols(int pos, int n, bool updateLabels)
2317 {
2318 if (pos + n > m_totalCols)
2319 return FALSE;
2320 if (!m_gridCells)
2321 return FALSE;
2322
2323 int i, j;
2324
2325 // Cells
2326 for (i = 0; i < m_totalRows; i++)
2327 {
2328 wxGridCell **cols = m_gridCells[i];
2329 wxGridCell **newCols = new wxGridCell *[m_totalCols - n];
2330 for (j = 0; j < pos; j++)
2331 newCols[j] = cols[j];
2332 for (j = pos; j < pos + n; j++)
2333 delete cols[j];
2334 for (j = pos + n; j < m_totalCols; j++)
2335 newCols[j-n] = cols[j];
2336
2337 delete[] cols;
2338 m_gridCells[i] = newCols;
2339 }
2340
2341 // Column widths
2342 short *newColWidths = new short[m_totalCols - n];
2343 for (j = 0; j < pos; j++)
2344 newColWidths[j] = m_colWidths[j];
2345 for (j = pos + n; j < m_totalCols; j++)
2346 newColWidths[j-n] = m_colWidths[j];
2347 delete[] m_colWidths;
2348 m_colWidths = newColWidths;
2349
2350 // Column labels
2351 wxGridCell **newLabels = new wxGridCell *[m_totalCols - n];
2352 for (j = 0; j < pos; j++)
2353 newLabels[j] = m_colLabelCells[j];
2354 for (j = pos + n; j < m_totalCols; j++)
2355 newLabels[j-n] = m_colLabelCells[j];
2356
2357 delete[] m_colLabelCells;
2358 m_colLabelCells = newLabels;
2359
2360 m_totalCols -= n;
2361
2362 if (updateLabels) {
2363 //OnChangeLabels();
2364 wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this);
2365 GetEventHandler()->ProcessEvent(g_evt);
2366 }
2367 UpdateDimensions();
2368 AdjustScrollbars();
2369 return TRUE;
2370 }
2371
2372 void wxGenericGrid::SetGridCursor(int row, int col)
2373 {
2374 if (row >= m_totalRows || col >= m_totalCols)
2375 return;
2376
2377 if (row == GetCursorRow() && col == GetCursorColumn())
2378 return;
2379
2380 wxClientDC dc(this);
2381 dc.BeginDrawing();
2382
2383 SetGridClippingRegion(& dc);
2384
2385 if (m_currentRectVisible)
2386 HighlightCell(& dc);
2387
2388 m_wCursorRow = row;
2389 m_wCursorColumn = col;
2390
2391 int cw, ch;
2392 GetClientSize(&cw, &ch);
2393
2394 SetCurrentRect(row, col, cw, ch);
2395
2396 if (m_currentRectVisible)
2397 HighlightCell(& dc);
2398
2399 dc.DestroyClippingRegion();
2400 dc.EndDrawing();
2401 }
2402
2403 /*
2404 * Grid cell
2405 */
2406
2407 wxGridCell::wxGridCell(wxGenericGrid *window)
2408 {
2409 cellBitmap = (wxBitmap *) NULL;
2410 font = (wxFont *) NULL;
2411 backgroundBrush = (wxBrush *) NULL;
2412 if (window)
2413 textColour = window->GetCellTextColour();
2414 else
2415 textColour.Set(0,0,0);
2416 if (window)
2417 backgroundColour = window->GetCellBackgroundColour();
2418 else
2419 backgroundColour.Set(255,255,255);
2420
2421 if (window)
2422 font = window->GetCellTextFont();
2423 else
2424 font = wxTheFontList->FindOrCreateFont(12, wxSWISS, wxNORMAL, wxNORMAL);
2425
2426 SetBackgroundColour(backgroundColour);
2427
2428 if (window)
2429 alignment = window->GetCellAlignment();
2430 else
2431 alignment = wxLEFT;
2432 }
2433
2434 wxGridCell::~wxGridCell(void)
2435 {
2436 }
2437
2438 void wxGridCell::SetBackgroundColour(const wxColour& colour)
2439 {
2440 backgroundColour = colour;
2441 backgroundBrush = wxTheBrushList->FindOrCreateBrush(backgroundColour, wxSOLID);
2442 }
2443
2444 void wxGenericGrid::OnText(wxCommandEvent& WXUNUSED(ev) )
2445 {
2446 wxGenericGrid *grid = this;
2447 wxGridCell *cell = grid->GetCell(grid->GetCursorRow(), grid->GetCursorColumn());
2448 if (cell && grid->CurrentCellVisible())
2449 {
2450 cell->SetTextValue(grid->GetTextItem()->GetValue());
2451 wxClientDC dc(grid);
2452
2453 dc.BeginDrawing();
2454 grid->SetGridClippingRegion(& dc);
2455 grid->DrawCellBackground(& dc, &grid->GetCurrentRect(), grid->GetCursorRow(), grid->GetCursorColumn());
2456 grid->DrawCellValue(& dc, &grid->GetCurrentRect(), grid->GetCursorRow(), grid->GetCursorColumn());
2457 grid->HighlightCell(& dc);
2458 dc.DestroyClippingRegion();
2459 dc.EndDrawing();
2460
2461 //grid->OnCellChange(grid->GetCursorRow(), grid->GetCursorColumn());
2462 wxGridEvent g_evt(GetId(), wxEVT_GRID_CELL_CHANGE, grid,
2463 grid->GetCursorRow(), grid->GetCursorColumn());
2464 GetEventHandler()->ProcessEvent(g_evt);
2465
2466 // grid->DrawCellText();
2467 }
2468 }
2469
2470 void wxGenericGrid::OnGridScroll(wxScrollEvent& ev)
2471 {
2472 static bool inScroll = FALSE;
2473
2474 if ( inScroll )
2475 return;
2476
2477 inScroll = TRUE;
2478 wxGenericGrid *win = this;
2479
2480 bool change = FALSE;
2481
2482 if (ev.GetEventObject() == win->GetHorizScrollBar())
2483 {
2484 change = (ev.GetPosition() != m_scrollPosX);
2485 win->SetScrollPosX(ev.GetPosition());
2486 }
2487 else
2488 {
2489 change = (ev.GetPosition() != m_scrollPosY);
2490 win->SetScrollPosY(ev.GetPosition());
2491 }
2492
2493 win->UpdateDimensions();
2494
2495 win->SetCurrentRect(win->GetCursorRow(), win->GetCursorColumn());
2496
2497 // Because rows and columns can be arbitrary sizes,
2498 // the scrollbars will need to be adjusted to reflect the
2499 // current view.
2500 AdjustScrollbars();
2501
2502 if (change) win->Refresh(FALSE);
2503 inScroll = FALSE;
2504
2505 }
2506
2507
2508 //----------------------------------------------------------------------
2509 // Default wxGridEvent handlers
2510 // (just redirect to the pre-existing virtual methods)
2511
2512 void wxGenericGrid::_OnSelectCell(wxGridEvent& ev)
2513 {
2514 OnSelectCell(ev.m_row, ev.m_col);
2515 }
2516
2517 void wxGenericGrid::_OnCreateCell(wxGridEvent& ev)
2518 {
2519 ev.m_cell = OnCreateCell();
2520 }
2521
2522 void wxGenericGrid::_OnChangeLabels(wxGridEvent& WXUNUSED(ev))
2523 {
2524 OnChangeLabels();
2525 }
2526
2527 void wxGenericGrid::_OnChangeSelectionLabel(wxGridEvent& WXUNUSED(ev))
2528 {
2529 OnChangeSelectionLabel();
2530 }
2531
2532 void wxGenericGrid::_OnCellChange(wxGridEvent& ev)
2533 {
2534 OnCellChange(ev.m_row, ev.m_col);
2535 }
2536
2537 void wxGenericGrid::_OnCellLeftClick(wxGridEvent& ev)
2538 {
2539 OnCellLeftClick(ev.m_row, ev.m_col, ev.m_x, ev.m_y, ev.m_control, ev.m_shift);
2540 }
2541
2542 void wxGenericGrid::_OnCellRightClick(wxGridEvent& ev)
2543 {
2544 OnCellRightClick(ev.m_row, ev.m_col, ev.m_x, ev.m_y, ev.m_control, ev.m_shift);
2545 }
2546
2547 void wxGenericGrid::_OnLabelLeftClick(wxGridEvent& ev)
2548 {
2549 OnLabelLeftClick(ev.m_row, ev.m_col, ev.m_x, ev.m_y, ev.m_control, ev.m_shift);
2550 }
2551
2552 void wxGenericGrid::_OnLabelRightClick(wxGridEvent& ev)
2553 {
2554 OnLabelRightClick(ev.m_row, ev.m_col, ev.m_x, ev.m_y, ev.m_control, ev.m_shift);
2555 }
2556
2557