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