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