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