]> git.saurik.com Git - wxWidgets.git/blame - src/generic/gridg.cpp
wxCHECK/wxCHECK_RET changes
[wxWidgets.git] / src / generic / gridg.cpp
CommitLineData
c801d85f
KB
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
34static 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
40IMPLEMENT_DYNAMIC_CLASS(wxGenericGrid, wxPanel)
41
42BEGIN_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)
49END_EVENT_TABLE()
50
51wxCursor *wxGenericGrid::horizontalSashCursor = NULL;
52wxCursor *wxGenericGrid::verticalSashCursor = NULL;
53
54wxGenericGrid::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
108bool 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
211wxGenericGrid::~wxGenericGrid(void)
212{
213 ClearGrid();
214}
215
216void 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
254bool 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
324void 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
367wxGridCell *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
385void 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
402void 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
440void 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
460void 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
473void 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
632void 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
667void 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
685void 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
720void 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
738void 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
766void 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
782void 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
811void 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
961void 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
978bool 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
1018bool 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
1062bool 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
1114void 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
1275void 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
1311wxGridCell *wxGenericGrid::OnCreateCell(void)
1312{
1313 return new wxGridCell(this);
1314}
1315
1316void 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
1342void 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
1357void 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
1374void 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
1412void 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
1435static 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
1477void 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
1554void 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
1636void 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
1651void 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
1662void 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
1696wxString& 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
1707void wxGenericGrid::SetColumnWidth(int col, int width)
1708{
1709 if (col <= totalCols)
1710 colWidths[col] = width;
1711}
1712
1713int wxGenericGrid::GetColumnWidth(int col)
1714{
1715 if (col <= totalCols)
1716 return colWidths[col];
1717 else
1718 return 0;
1719}
1720
1721void wxGenericGrid::SetRowHeight(int row, int height)
1722{
1723 if (row <= totalRows)
1724 rowHeights[row] = height;
1725}
1726
1727int wxGenericGrid::GetRowHeight(int row)
1728{
1729 if (row <= totalRows)
1730 return rowHeights[row];
1731 else
1732 return 0;
1733}
1734
1735void 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
1745int wxGenericGrid::GetLabelSize(int orientation)
1746{
1747 if (orientation == wxHORIZONTAL)
1748 return horizontalLabelHeight;
1749 else
1750 return verticalLabelWidth;
1751}
1752
1753wxGridCell *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
1771void 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
1778wxString& 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
1788void 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
1798int wxGenericGrid::GetLabelAlignment(int orientation)
1799{
1800 if (orientation == wxHORIZONTAL)
1801 return horizontalLabelAlignment;
1802 else
1803 return verticalLabelAlignment;
1804}
1805
1806void wxGenericGrid::SetLabelTextColour(const wxColour& colour)
1807{
1808 labelTextColour = colour;
1809
1810}
1811
1812void wxGenericGrid::SetLabelBackgroundColour(const wxColour& colour)
1813{
1814 labelBackgroundColour = colour;
1815 labelBackgroundBrush = wxTheBrushList->FindOrCreateBrush(labelBackgroundColour, wxSOLID);
1816}
1817
1818void 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
1868void wxGenericGrid::SetCellAlignment(int flag, int row, int col)
1869{
1870 wxGridCell *cell = GetCell(row, col);
1871 if (cell)
1872 cell->SetAlignment(flag);
1873}
1874
1875int 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
1884void 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
1894int wxGenericGrid::GetCellAlignment(void)
1895{
1896 return cellAlignment;
1897}
1898
1899void 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
1909void 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
1919wxColour& 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
1928void 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
1938void 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
1948wxFont *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
1957wxColour& 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
1966void 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
1976void 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
1986void 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
1996wxBitmap *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
2007bool 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
2066bool 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
2129bool wxGenericGrid::AppendCols(int n, bool updateLabels)
2130{
2131 return InsertCols(GetCols(), n, updateLabels);
2132}
2133
2134bool wxGenericGrid::AppendRows(int n, bool updateLabels)
2135{
2136 return InsertRows(GetRows(), n, updateLabels);
2137}
2138
2139bool 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
2188bool 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
2241void 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
2271wxGridCell::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
2298wxGridCell::~wxGridCell(void)
2299{
2300}
2301
2302void wxGridCell::SetBackgroundColour(const wxColour& colour)
2303{
2304 backgroundColour = colour;
2305 backgroundBrush = wxTheBrushList->FindOrCreateBrush(backgroundColour, wxSOLID);
2306}
2307
2308void 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
2331void 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}