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