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