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