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