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