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