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