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