]> git.saurik.com Git - wxWidgets.git/blame - src/generic/grid.cpp
use static_cast<> in event table macros for type safety (patch 843206)
[wxWidgets.git] / src / generic / grid.cpp
Content-type: text/html ]> git.saurik.com Git - wxWidgets.git/blame - src/generic/grid.cpp


500 - Internal Server Error

Malformed UTF-8 character (fatal) at /usr/lib/x86_64-linux-gnu/perl5/5.40/HTML/Entities.pm line 485, <$fd> line 9216.
CommitLineData
2796cce3 1///////////////////////////////////////////////////////////////////////////
d16c04bb 2// Name: generic/grid.cpp
f85afd4e
MB
3// Purpose: wxGrid and related classes
4// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
97a9929e 5// Modified by: Robin Dunn, Vadim Zeitlin
f85afd4e
MB
6// Created: 1/08/1999
7// RCS-ID: $Id$
8// Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
758cbedf
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
f85afd4e
MB
21 #pragma implementation "grid.h"
22#endif
23
f6bcfd97 24// For compilers that support precompilatixon, includes "wx/wx.h".
4d85bcd1
JS
25#include "wx/wxprec.h"
26
27#include "wx/defs.h"
f85afd4e
MB
28
29#ifdef __BORLANDC__
30 #pragma hdrstop
31#endif
32
27b92ca4
VZ
33#if wxUSE_GRID
34
f85afd4e
MB
35#ifndef WX_PRECOMP
36 #include "wx/utils.h"
37 #include "wx/dcclient.h"
38 #include "wx/settings.h"
39 #include "wx/log.h"
508011ce
VZ
40 #include "wx/textctrl.h"
41 #include "wx/checkbox.h"
4ee5fc9c 42 #include "wx/combobox.h"
816be743 43 #include "wx/valtext.h"
60d876f3 44 #include "wx/intl.h"
f85afd4e
MB
45#endif
46
cb5df486 47#include "wx/textfile.h"
816be743 48#include "wx/spinctrl.h"
c4608a8a 49#include "wx/tokenzr.h"
6d004f67 50
07296f0b 51#include "wx/grid.h"
b5808881 52#include "wx/generic/gridsel.h"
07296f0b 53
0b7e6e7d
SN
54#if defined(__WXMOTIF__)
55 #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier)
c78b3acd 56#else
0b7e6e7d 57 #define WXUNUSED_MOTIF(identifier) identifier
c78b3acd
SN
58#endif
59
60#if defined(__WXGTK__)
61 #define WXUNUSED_GTK(identifier) WXUNUSED(identifier)
62#else
63 #define WXUNUSED_GTK(identifier) identifier
64#endif
65
3f8e5072
JS
66// Required for wxIs... functions
67#include <ctype.h>
68
b99be8fb 69// ----------------------------------------------------------------------------
758cbedf 70// array classes
b99be8fb
VZ
71// ----------------------------------------------------------------------------
72
d5d29b8a 73WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridCellAttr *, wxArrayAttrs,
160ba750 74 class WXDLLIMPEXP_ADV);
758cbedf 75
b99be8fb
VZ
76struct wxGridCellWithAttr
77{
2e9a6788
VZ
78 wxGridCellWithAttr(int row, int col, wxGridCellAttr *attr_)
79 : coords(row, col), attr(attr_)
b99be8fb
VZ
80 {
81 }
82
2e9a6788
VZ
83 ~wxGridCellWithAttr()
84 {
85 attr->DecRef();
86 }
87
b99be8fb 88 wxGridCellCoords coords;
2e9a6788 89 wxGridCellAttr *attr;
22f3361e
VZ
90
91// Cannot do this:
92// DECLARE_NO_COPY_CLASS(wxGridCellWithAttr)
93// without rewriting the macros, which require a public copy constructor.
b99be8fb
VZ
94};
95
160ba750
VS
96WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr, wxGridCellWithAttrArray,
97 class WXDLLIMPEXP_ADV);
b99be8fb
VZ
98
99#include "wx/arrimpl.cpp"
100
101WX_DEFINE_OBJARRAY(wxGridCellCoordsArray)
102WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray)
103
0f442030
RR
104// ----------------------------------------------------------------------------
105// events
106// ----------------------------------------------------------------------------
107
2e4df4bf
VZ
108DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK)
109DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK)
110DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK)
111DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK)
112DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK)
113DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK)
114DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK)
115DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK)
116DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE)
117DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE)
118DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT)
119DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE)
120DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL)
121DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN)
122DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN)
bf7945ce 123DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED)
0f442030 124
b99be8fb
VZ
125// ----------------------------------------------------------------------------
126// private classes
127// ----------------------------------------------------------------------------
128
12f190b0 129class WXDLLIMPEXP_ADV wxGridRowLabelWindow : public wxWindow
b99be8fb
VZ
130{
131public:
132 wxGridRowLabelWindow() { m_owner = (wxGrid *)NULL; }
133 wxGridRowLabelWindow( wxGrid *parent, wxWindowID id,
134 const wxPoint &pos, const wxSize &size );
135
136private:
137 wxGrid *m_owner;
138
139 void OnPaint( wxPaintEvent& event );
140 void OnMouseEvent( wxMouseEvent& event );
b51c3f27 141 void OnMouseWheel( wxMouseEvent& event );
b99be8fb 142 void OnKeyDown( wxKeyEvent& event );
f6bcfd97 143 void OnKeyUp( wxKeyEvent& );
b99be8fb
VZ
144
145 DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow)
146 DECLARE_EVENT_TABLE()
22f3361e 147 DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow)
b99be8fb
VZ
148};
149
150
12f190b0 151class WXDLLIMPEXP_ADV wxGridColLabelWindow : public wxWindow
b99be8fb
VZ
152{
153public:
154 wxGridColLabelWindow() { m_owner = (wxGrid *)NULL; }
155 wxGridColLabelWindow( wxGrid *parent, wxWindowID id,
156 const wxPoint &pos, const wxSize &size );
157
158private:
159 wxGrid *m_owner;
160
161 void OnPaint( wxPaintEvent &event );
162 void OnMouseEvent( wxMouseEvent& event );
b51c3f27 163 void OnMouseWheel( wxMouseEvent& event );
b99be8fb 164 void OnKeyDown( wxKeyEvent& event );
f6bcfd97 165 void OnKeyUp( wxKeyEvent& );
b99be8fb
VZ
166
167 DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow)
168 DECLARE_EVENT_TABLE()
22f3361e 169 DECLARE_NO_COPY_CLASS(wxGridColLabelWindow)
b99be8fb
VZ
170};
171
172
12f190b0 173class WXDLLIMPEXP_ADV wxGridCornerLabelWindow : public wxWindow
b99be8fb
VZ
174{
175public:
176 wxGridCornerLabelWindow() { m_owner = (wxGrid *)NULL; }
177 wxGridCornerLabelWindow( wxGrid *parent, wxWindowID id,
178 const wxPoint &pos, const wxSize &size );
179
180private:
181 wxGrid *m_owner;
182
183 void OnMouseEvent( wxMouseEvent& event );
b51c3f27 184 void OnMouseWheel( wxMouseEvent& event );
b99be8fb 185 void OnKeyDown( wxKeyEvent& event );
f6bcfd97 186 void OnKeyUp( wxKeyEvent& );
b99be8fb
VZ
187 void OnPaint( wxPaintEvent& event );
188
189 DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow)
190 DECLARE_EVENT_TABLE()
22f3361e 191 DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow)
b99be8fb
VZ
192};
193
12f190b0 194class WXDLLIMPEXP_ADV wxGridWindow : public wxWindow
b99be8fb
VZ
195{
196public:
197 wxGridWindow()
198 {
199 m_owner = (wxGrid *)NULL;
200 m_rowLabelWin = (wxGridRowLabelWindow *)NULL;
201 m_colLabelWin = (wxGridColLabelWindow *)NULL;
202 }
203
204 wxGridWindow( wxGrid *parent,
205 wxGridRowLabelWindow *rowLblWin,
206 wxGridColLabelWindow *colLblWin,
207 wxWindowID id, const wxPoint &pos, const wxSize &size );
208 ~wxGridWindow();
209
210 void ScrollWindow( int dx, int dy, const wxRect *rect );
211
b819b854
JS
212 wxGrid* GetOwner() { return m_owner; }
213
b99be8fb
VZ
214private:
215 wxGrid *m_owner;
216 wxGridRowLabelWindow *m_rowLabelWin;
217 wxGridColLabelWindow *m_colLabelWin;
218
219 void OnPaint( wxPaintEvent &event );
b51c3f27 220 void OnMouseWheel( wxMouseEvent& event );
b99be8fb
VZ
221 void OnMouseEvent( wxMouseEvent& event );
222 void OnKeyDown( wxKeyEvent& );
f6bcfd97 223 void OnKeyUp( wxKeyEvent& );
2796cce3 224 void OnEraseBackground( wxEraseEvent& );
80acaf25 225 void OnFocus( wxFocusEvent& );
b99be8fb
VZ
226
227 DECLARE_DYNAMIC_CLASS(wxGridWindow)
228 DECLARE_EVENT_TABLE()
22f3361e 229 DECLARE_NO_COPY_CLASS(wxGridWindow)
b99be8fb
VZ
230};
231
2796cce3
RD
232
233
234class wxGridCellEditorEvtHandler : public wxEvtHandler
235{
236public:
237 wxGridCellEditorEvtHandler()
238 : m_grid(0), m_editor(0)
239 { }
240 wxGridCellEditorEvtHandler(wxGrid* grid, wxGridCellEditor* editor)
241 : m_grid(grid), m_editor(editor)
242 { }
243
244 void OnKeyDown(wxKeyEvent& event);
fb0de762 245 void OnChar(wxKeyEvent& event);
2796cce3
RD
246
247private:
248 wxGrid* m_grid;
249 wxGridCellEditor* m_editor;
250 DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler)
251 DECLARE_EVENT_TABLE()
22f3361e 252 DECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler)
2796cce3
RD
253};
254
255
256IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler, wxEvtHandler )
257BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler, wxEvtHandler )
258 EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown )
fb0de762 259 EVT_CHAR( wxGridCellEditorEvtHandler::OnChar )
2796cce3
RD
260END_EVENT_TABLE()
261
262
263
758cbedf 264// ----------------------------------------------------------------------------
b99be8fb 265// the internal data representation used by wxGridCellAttrProvider
758cbedf
VZ
266// ----------------------------------------------------------------------------
267
268// this class stores attributes set for cells
12f190b0 269class WXDLLIMPEXP_ADV wxGridCellAttrData
b99be8fb
VZ
270{
271public:
2e9a6788 272 void SetAttr(wxGridCellAttr *attr, int row, int col);
b99be8fb 273 wxGridCellAttr *GetAttr(int row, int col) const;
4d60017a
SN
274 void UpdateAttrRows( size_t pos, int numRows );
275 void UpdateAttrCols( size_t pos, int numCols );
b99be8fb
VZ
276
277private:
278 // searches for the attr for given cell, returns wxNOT_FOUND if not found
279 int FindIndex(int row, int col) const;
280
281 wxGridCellWithAttrArray m_attrs;
282};
283
758cbedf 284// this class stores attributes set for rows or columns
12f190b0 285class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
758cbedf
VZ
286{
287public:
ee6694a7
VZ
288 // empty ctor to suppress warnings
289 wxGridRowOrColAttrData() { }
758cbedf
VZ
290 ~wxGridRowOrColAttrData();
291
292 void SetAttr(wxGridCellAttr *attr, int rowOrCol);
293 wxGridCellAttr *GetAttr(int rowOrCol) const;
4d60017a 294 void UpdateAttrRowsOrCols( size_t pos, int numRowsOrCols );
758cbedf
VZ
295
296private:
297 wxArrayInt m_rowsOrCols;
298 wxArrayAttrs m_attrs;
299};
300
301// NB: this is just a wrapper around 3 objects: one which stores cell
302// attributes, and 2 others for row/col ones
12f190b0 303class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
758cbedf
VZ
304{
305public:
306 wxGridCellAttrData m_cellAttrs;
307 wxGridRowOrColAttrData m_rowAttrs,
308 m_colAttrs;
309};
310
f2d76237
RD
311
312// ----------------------------------------------------------------------------
313// data structures used for the data type registry
314// ----------------------------------------------------------------------------
315
b94ae1ea
VZ
316struct wxGridDataTypeInfo
317{
f2d76237
RD
318 wxGridDataTypeInfo(const wxString& typeName,
319 wxGridCellRenderer* renderer,
320 wxGridCellEditor* editor)
321 : m_typeName(typeName), m_renderer(renderer), m_editor(editor)
322 { }
323
39bcce60
VZ
324 ~wxGridDataTypeInfo()
325 {
326 wxSafeDecRef(m_renderer);
327 wxSafeDecRef(m_editor);
328 }
f2d76237
RD
329
330 wxString m_typeName;
331 wxGridCellRenderer* m_renderer;
332 wxGridCellEditor* m_editor;
22f3361e
VZ
333
334 DECLARE_NO_COPY_CLASS(wxGridDataTypeInfo)
f2d76237
RD
335};
336
337
d5d29b8a 338WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo*, wxGridDataTypeInfoArray,
160ba750 339 class WXDLLIMPEXP_ADV);
f2d76237
RD
340
341
12f190b0 342class WXDLLIMPEXP_ADV wxGridTypeRegistry
b94ae1ea 343{
f2d76237 344public:
c78b3acd 345 wxGridTypeRegistry() {}
f2d76237 346 ~wxGridTypeRegistry();
b94ae1ea 347
f2d76237
RD
348 void RegisterDataType(const wxString& typeName,
349 wxGridCellRenderer* renderer,
350 wxGridCellEditor* editor);
c4608a8a
VZ
351
352 // find one of already registered data types
353 int FindRegisteredDataType(const wxString& typeName);
354
355 // try to FindRegisteredDataType(), if this fails and typeName is one of
356 // standard typenames, register it and return its index
f2d76237 357 int FindDataType(const wxString& typeName);
c4608a8a
VZ
358
359 // try to FindDataType(), if it fails see if it is not one of already
360 // registered data types with some params in which case clone the
361 // registered data type and set params for it
362 int FindOrCloneDataType(const wxString& typeName);
363
f2d76237
RD
364 wxGridCellRenderer* GetRenderer(int index);
365 wxGridCellEditor* GetEditor(int index);
366
367private:
368 wxGridDataTypeInfoArray m_typeinfo;
369};
370
b99be8fb
VZ
371// ----------------------------------------------------------------------------
372// conditional compilation
373// ----------------------------------------------------------------------------
374
9496deb5
MB
375#ifndef WXGRID_DRAW_LINES
376#define WXGRID_DRAW_LINES 1
796df70a
SN
377#endif
378
0a976765
VZ
379// ----------------------------------------------------------------------------
380// globals
381// ----------------------------------------------------------------------------
382
383//#define DEBUG_ATTR_CACHE
384#ifdef DEBUG_ATTR_CACHE
385 static size_t gs_nAttrCacheHits = 0;
386 static size_t gs_nAttrCacheMisses = 0;
387#endif // DEBUG_ATTR_CACHE
f85afd4e 388
43947979
VZ
389// ----------------------------------------------------------------------------
390// constants
391// ----------------------------------------------------------------------------
392
f85afd4e
MB
393wxGridCellCoords wxGridNoCellCoords( -1, -1 );
394wxRect wxGridNoCellRect( -1, -1, -1, -1 );
395
f0102d2a 396// scroll line size
faec5a43
SN
397// TODO: this doesn't work at all, grid cells have different sizes and approx
398// calculations don't work as because of the size mismatch scrollbars
399// sometimes fail to be shown when they should be or vice versa
b51c3f27
RD
400//
401// The scroll bars may be a little flakey once in a while, but that is
402// surely much less horrible than having scroll lines of only 1!!!
403// -- Robin
97a9929e
VZ
404//
405// Well, it's still seriously broken so it might be better but needs
406// fixing anyhow
407// -- Vadim
408static const size_t GRID_SCROLL_LINE_X = 15; // 1;
409static const size_t GRID_SCROLL_LINE_Y = GRID_SCROLL_LINE_X;
f85afd4e 410
43947979
VZ
411// the size of hash tables used a bit everywhere (the max number of elements
412// in these hash tables is the number of rows/columns)
413static const int GRID_HASH_SIZE = 100;
414
97a9929e
VZ
415// ----------------------------------------------------------------------------
416// private functions
417// ----------------------------------------------------------------------------
418
d0eb7e56 419static inline int GetScrollX(int x)
97a9929e
VZ
420{
421 return (x + GRID_SCROLL_LINE_X - 1) / GRID_SCROLL_LINE_X;
422}
423
d0eb7e56 424static inline int GetScrollY(int y)
97a9929e
VZ
425{
426 return (y + GRID_SCROLL_LINE_Y - 1) / GRID_SCROLL_LINE_Y;
427}
428
ab79958a
VZ
429// ============================================================================
430// implementation
431// ============================================================================
432
2796cce3
RD
433// ----------------------------------------------------------------------------
434// wxGridCellEditor
435// ----------------------------------------------------------------------------
436
437wxGridCellEditor::wxGridCellEditor()
438{
439 m_control = NULL;
1bd71df9 440 m_attr = NULL;
2796cce3
RD
441}
442
443
444wxGridCellEditor::~wxGridCellEditor()
445{
446 Destroy();
447}
448
508011ce
VZ
449void wxGridCellEditor::Create(wxWindow* WXUNUSED(parent),
450 wxWindowID WXUNUSED(id),
451 wxEvtHandler* evtHandler)
452{
189d0213 453 if ( evtHandler )
508011ce
VZ
454 m_control->PushEventHandler(evtHandler);
455}
2796cce3 456
189d0213
VZ
457void wxGridCellEditor::PaintBackground(const wxRect& rectCell,
458 wxGridCellAttr *attr)
459{
460 // erase the background because we might not fill the cell
461 wxClientDC dc(m_control->GetParent());
b819b854
JS
462 wxGridWindow* gridWindow = wxDynamicCast(m_control->GetParent(), wxGridWindow);
463 if (gridWindow)
464 gridWindow->GetOwner()->PrepareDC(dc);
ef5df12b 465
189d0213
VZ
466 dc.SetPen(*wxTRANSPARENT_PEN);
467 dc.SetBrush(wxBrush(attr->GetBackgroundColour(), wxSOLID));
468 dc.DrawRectangle(rectCell);
469
470 // redraw the control we just painted over
471 m_control->Refresh();
472}
473
2796cce3
RD
474void wxGridCellEditor::Destroy()
475{
508011ce
VZ
476 if (m_control)
477 {
b94ae1ea
VZ
478 m_control->PopEventHandler(TRUE /* delete it*/);
479
2796cce3
RD
480 m_control->Destroy();
481 m_control = NULL;
482 }
483}
484
3da93aae 485void wxGridCellEditor::Show(bool show, wxGridCellAttr *attr)
2796cce3
RD
486{
487 wxASSERT_MSG(m_control,
488 wxT("The wxGridCellEditor must be Created first!"));
489 m_control->Show(show);
3da93aae
VZ
490
491 if ( show )
492 {
493 // set the colours/fonts if we have any
494 if ( attr )
495 {
f2d76237
RD
496 m_colFgOld = m_control->GetForegroundColour();
497 m_control->SetForegroundColour(attr->GetTextColour());
3da93aae 498
f2d76237
RD
499 m_colBgOld = m_control->GetBackgroundColour();
500 m_control->SetBackgroundColour(attr->GetBackgroundColour());
3da93aae 501
f2d76237
RD
502 m_fontOld = m_control->GetFont();
503 m_control->SetFont(attr->GetFont());
3da93aae
VZ
504
505 // can't do anything more in the base class version, the other
506 // attributes may only be used by the derived classes
507 }
508 }
509 else
510 {
511 // restore the standard colours fonts
512 if ( m_colFgOld.Ok() )
513 {
514 m_control->SetForegroundColour(m_colFgOld);
515 m_colFgOld = wxNullColour;
516 }
517
518 if ( m_colBgOld.Ok() )
519 {
520 m_control->SetBackgroundColour(m_colBgOld);
521 m_colBgOld = wxNullColour;
522 }
523
524 if ( m_fontOld.Ok() )
525 {
526 m_control->SetFont(m_fontOld);
527 m_fontOld = wxNullFont;
528 }
529 }
2796cce3
RD
530}
531
532void wxGridCellEditor::SetSize(const wxRect& rect)
533{
534 wxASSERT_MSG(m_control,
535 wxT("The wxGridCellEditor must be Created first!"));
28a77bc4 536 m_control->SetSize(rect, wxSIZE_ALLOW_MINUS_ONE);
2796cce3
RD
537}
538
539void wxGridCellEditor::HandleReturn(wxKeyEvent& event)
540{
541 event.Skip();
542}
543
f6bcfd97
BP
544bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent& event)
545{
546 // accept the simple key presses, not anything with Ctrl/Alt/Meta
a4f7bf58 547 return !(event.ControlDown() || event.AltDown());
f6bcfd97 548}
2796cce3 549
2c9a89e0
RD
550void wxGridCellEditor::StartingKey(wxKeyEvent& event)
551{
e195a54c
VZ
552 event.Skip();
553}
2c9a89e0 554
e195a54c
VZ
555void wxGridCellEditor::StartingClick()
556{
b54ba671 557}
2c9a89e0 558
3a8c693a
VZ
559#if wxUSE_TEXTCTRL
560
b54ba671
VZ
561// ----------------------------------------------------------------------------
562// wxGridCellTextEditor
563// ----------------------------------------------------------------------------
2c9a89e0 564
2796cce3
RD
565wxGridCellTextEditor::wxGridCellTextEditor()
566{
c4608a8a 567 m_maxChars = 0;
2796cce3
RD
568}
569
570void wxGridCellTextEditor::Create(wxWindow* parent,
571 wxWindowID id,
2796cce3
RD
572 wxEvtHandler* evtHandler)
573{
508011ce 574 m_control = new wxTextCtrl(parent, id, wxEmptyString,
2c9a89e0 575 wxDefaultPosition, wxDefaultSize
2796cce3 576#if defined(__WXMSW__)
aaae069f 577 , wxTE_PROCESS_TAB | wxTE_AUTO_SCROLL
2796cce3 578#endif
508011ce 579 );
2796cce3 580
46a5010a
RD
581 // set max length allowed in the textctrl, if the parameter was set
582 if (m_maxChars != 0)
583 {
584 ((wxTextCtrl*)m_control)->SetMaxLength(m_maxChars);
585 }
c4608a8a 586
508011ce 587 wxGridCellEditor::Create(parent, id, evtHandler);
2796cce3
RD
588}
589
189d0213
VZ
590void wxGridCellTextEditor::PaintBackground(const wxRect& WXUNUSED(rectCell),
591 wxGridCellAttr * WXUNUSED(attr))
592{
593 // as we fill the entire client area, don't do anything here to minimize
594 // flicker
595}
2796cce3 596
99306db2
VZ
597void wxGridCellTextEditor::SetSize(const wxRect& rectOrig)
598{
599 wxRect rect(rectOrig);
600
601 // Make the edit control large enough to allow for internal
602 // margins
603 //
604 // TODO: remove this if the text ctrl sizing is improved esp. for
605 // unix
606 //
607#if defined(__WXGTK__)
b0e282b3
RR
608 if (rect.x != 0)
609 {
610 rect.x += 1;
611 rect.y += 1;
612 rect.width -= 1;
613 rect.height -= 1;
614 }
99306db2 615#else // !GTK
cb105ad4 616 int extra_x = ( rect.x > 2 )? 2 : 1;
84912ef8
RD
617
618// MB: treat MSW separately here otherwise the caret doesn't show
619// when the editor is in the first row.
a0948e27
MB
620#if defined(__WXMSW__)
621 int extra_y = 2;
622#else
cb105ad4 623 int extra_y = ( rect.y > 2 )? 2 : 1;
a0948e27
MB
624#endif // MSW
625
99306db2 626#if defined(__WXMOTIF__)
cb105ad4
SN
627 extra_x *= 2;
628 extra_y *= 2;
99306db2 629#endif
cb105ad4
SN
630 rect.SetLeft( wxMax(0, rect.x - extra_x) );
631 rect.SetTop( wxMax(0, rect.y - extra_y) );
632 rect.SetRight( rect.GetRight() + 2*extra_x );
633 rect.SetBottom( rect.GetBottom() + 2*extra_y );
99306db2
VZ
634#endif // GTK/!GTK
635
636 wxGridCellEditor::SetSize(rect);
637}
638
3da93aae 639void wxGridCellTextEditor::BeginEdit(int row, int col, wxGrid* grid)
2796cce3
RD
640{
641 wxASSERT_MSG(m_control,
642 wxT("The wxGridCellEditor must be Created first!"));
643
644 m_startValue = grid->GetTable()->GetValue(row, col);
816be743
VZ
645
646 DoBeginEdit(m_startValue);
647}
648
649void wxGridCellTextEditor::DoBeginEdit(const wxString& startValue)
650{
651 Text()->SetValue(startValue);
b54ba671 652 Text()->SetInsertionPointEnd();
505f70de 653 Text()->SetSelection(-1,-1);
b54ba671 654 Text()->SetFocus();
2796cce3
RD
655}
656
3324d5f5 657bool wxGridCellTextEditor::EndEdit(int row, int col,
3da93aae 658 wxGrid* grid)
2796cce3
RD
659{
660 wxASSERT_MSG(m_control,
661 wxT("The wxGridCellEditor must be Created first!"));
662
663 bool changed = FALSE;
b54ba671 664 wxString value = Text()->GetValue();
2796cce3
RD
665 if (value != m_startValue)
666 changed = TRUE;
667
668 if (changed)
669 grid->GetTable()->SetValue(row, col, value);
2c9a89e0 670
3da93aae 671 m_startValue = wxEmptyString;
7b519e5e
JS
672 // No point in setting the text of the hidden control
673 //Text()->SetValue(m_startValue);
2796cce3
RD
674
675 return changed;
676}
677
678
679void wxGridCellTextEditor::Reset()
680{
681 wxASSERT_MSG(m_control,
682 wxT("The wxGridCellEditor must be Created first!"));
683
816be743
VZ
684 DoReset(m_startValue);
685}
686
687void wxGridCellTextEditor::DoReset(const wxString& startValue)
688{
689 Text()->SetValue(startValue);
b54ba671 690 Text()->SetInsertionPointEnd();
2796cce3
RD
691}
692
f6bcfd97
BP
693bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent& event)
694{
695 if ( wxGridCellEditor::IsAcceptedKey(event) )
696 {
697 int keycode = event.GetKeyCode();
698 switch ( keycode )
699 {
700 case WXK_NUMPAD0:
701 case WXK_NUMPAD1:
702 case WXK_NUMPAD2:
703 case WXK_NUMPAD3:
704 case WXK_NUMPAD4:
705 case WXK_NUMPAD5:
706 case WXK_NUMPAD6:
707 case WXK_NUMPAD7:
708 case WXK_NUMPAD8:
709 case WXK_NUMPAD9:
710 case WXK_MULTIPLY:
711 case WXK_NUMPAD_MULTIPLY:
712 case WXK_ADD:
713 case WXK_NUMPAD_ADD:
714 case WXK_SUBTRACT:
715 case WXK_NUMPAD_SUBTRACT:
716 case WXK_DECIMAL:
717 case WXK_NUMPAD_DECIMAL:
718 case WXK_DIVIDE:
719 case WXK_NUMPAD_DIVIDE:
720 return TRUE;
721
722 default:
723 // accept 8 bit chars too if isprint() agrees
1c193821 724 if ( (keycode < 255) && (wxIsprint(keycode)) )
f6bcfd97
BP
725 return TRUE;
726 }
727 }
728
729 return FALSE;
730}
731
2c9a89e0
RD
732void wxGridCellTextEditor::StartingKey(wxKeyEvent& event)
733{
94af7d45 734 if ( !Text()->EmulateKeyPress(event) )
f6bcfd97
BP
735 {
736 event.Skip();
737 }
b54ba671 738}
2c9a89e0 739
c78b3acd 740void wxGridCellTextEditor::HandleReturn( wxKeyEvent&
0b7e6e7d 741 WXUNUSED_GTK(WXUNUSED_MOTIF(event)) )
2796cce3
RD
742{
743#if defined(__WXMOTIF__) || defined(__WXGTK__)
744 // wxMotif needs a little extra help...
6fc0f38f 745 size_t pos = (size_t)( Text()->GetInsertionPoint() );
b54ba671 746 wxString s( Text()->GetValue() );
8dd8f875 747 s = s.Left(pos) + wxT("\n") + s.Mid(pos);
b54ba671
VZ
748 Text()->SetValue(s);
749 Text()->SetInsertionPoint( pos );
2796cce3
RD
750#else
751 // the other ports can handle a Return key press
752 //
753 event.Skip();
754#endif
755}
756
c4608a8a
VZ
757void wxGridCellTextEditor::SetParameters(const wxString& params)
758{
759 if ( !params )
760 {
761 // reset to default
762 m_maxChars = 0;
763 }
764 else
765 {
766 long tmp;
767 if ( !params.ToLong(&tmp) )
768 {
f6bcfd97 769 wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params.c_str());
c4608a8a
VZ
770 }
771 else
772 {
773 m_maxChars = (size_t)tmp;
774 }
775 }
776}
777
73145b0e
JS
778// return the value in the text control
779wxString wxGridCellTextEditor::GetValue() const
780{
781 return Text()->GetValue();
782}
783
816be743
VZ
784// ----------------------------------------------------------------------------
785// wxGridCellNumberEditor
786// ----------------------------------------------------------------------------
787
788wxGridCellNumberEditor::wxGridCellNumberEditor(int min, int max)
789{
790 m_min = min;
791 m_max = max;
792}
793
794void wxGridCellNumberEditor::Create(wxWindow* parent,
795 wxWindowID id,
796 wxEvtHandler* evtHandler)
797{
798 if ( HasRange() )
799 {
800 // create a spin ctrl
801 m_control = new wxSpinCtrl(parent, -1, wxEmptyString,
802 wxDefaultPosition, wxDefaultSize,
803 wxSP_ARROW_KEYS,
804 m_min, m_max);
805
806 wxGridCellEditor::Create(parent, id, evtHandler);
807 }
808 else
809 {
810 // just a text control
811 wxGridCellTextEditor::Create(parent, id, evtHandler);
812
813#if wxUSE_VALIDATORS
85bc0351 814 Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
816be743
VZ
815#endif // wxUSE_VALIDATORS
816 }
817}
818
819void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)
820{
821 // first get the value
822 wxGridTableBase *table = grid->GetTable();
823 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
824 {
825 m_valueOld = table->GetValueAsLong(row, col);
826 }
827 else
828 {
8a60ff0a 829 m_valueOld = 0;
a5777624 830 wxString sValue = table->GetValue(row, col);
8a60ff0a 831 if (! sValue.ToLong(&m_valueOld) && ! sValue.IsEmpty())
a5777624
RD
832 {
833 wxFAIL_MSG( _T("this cell doesn't have numeric value") );
834 return;
835 }
816be743
VZ
836 }
837
838 if ( HasRange() )
839 {
4a64bee4 840 Spin()->SetValue((int)m_valueOld);
f6bcfd97 841 Spin()->SetFocus();
816be743
VZ
842 }
843 else
844 {
845 DoBeginEdit(GetString());
846 }
847}
848
3324d5f5 849bool wxGridCellNumberEditor::EndEdit(int row, int col,
816be743
VZ
850 wxGrid* grid)
851{
852 bool changed;
8a60ff0a
RD
853 long value = 0;
854 wxString text;
816be743
VZ
855
856 if ( HasRange() )
857 {
858 value = Spin()->GetValue();
859 changed = value != m_valueOld;
8a60ff0a
RD
860 if (changed)
861 text = wxString::Format(wxT("%ld"), value);
816be743
VZ
862 }
863 else
864 {
8a60ff0a
RD
865 text = Text()->GetValue();
866 changed = (text.IsEmpty() || text.ToLong(&value)) && (value != m_valueOld);
816be743
VZ
867 }
868
869 if ( changed )
870 {
a5777624
RD
871 if (grid->GetTable()->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER))
872 grid->GetTable()->SetValueAsLong(row, col, value);
873 else
8a60ff0a 874 grid->GetTable()->SetValue(row, col, text);
816be743
VZ
875 }
876
877 return changed;
878}
879
880void wxGridCellNumberEditor::Reset()
881{
882 if ( HasRange() )
883 {
4a64bee4 884 Spin()->SetValue((int)m_valueOld);
816be743
VZ
885 }
886 else
887 {
888 DoReset(GetString());
889 }
890}
891
f6bcfd97
BP
892bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent& event)
893{
894 if ( wxGridCellEditor::IsAcceptedKey(event) )
895 {
896 int keycode = event.GetKeyCode();
897 switch ( keycode )
898 {
899 case WXK_NUMPAD0:
900 case WXK_NUMPAD1:
901 case WXK_NUMPAD2:
902 case WXK_NUMPAD3:
903 case WXK_NUMPAD4:
904 case WXK_NUMPAD5:
905 case WXK_NUMPAD6:
906 case WXK_NUMPAD7:
907 case WXK_NUMPAD8:
908 case WXK_NUMPAD9:
909 case WXK_ADD:
910 case WXK_NUMPAD_ADD:
911 case WXK_SUBTRACT:
912 case WXK_NUMPAD_SUBTRACT:
913 case WXK_UP:
914 case WXK_DOWN:
915 return TRUE;
916
917 default:
4676948b 918 if ( (keycode < 128) && wxIsdigit(keycode) )
f6bcfd97
BP
919 return TRUE;
920 }
921 }
922
923 return FALSE;
924}
925
816be743
VZ
926void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event)
927{
928 if ( !HasRange() )
929 {
12a3f227 930 int keycode = event.GetKeyCode();
4676948b 931 if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-'
85d8c319
JS
932 || keycode == WXK_NUMPAD0
933 || keycode == WXK_NUMPAD1
934 || keycode == WXK_NUMPAD2
935 || keycode == WXK_NUMPAD3
936 || keycode == WXK_NUMPAD4
937 || keycode == WXK_NUMPAD5
938 || keycode == WXK_NUMPAD6
939 || keycode == WXK_NUMPAD7
940 || keycode == WXK_NUMPAD8
941 || keycode == WXK_NUMPAD9
942 || keycode == WXK_ADD
943 || keycode == WXK_NUMPAD_ADD
944 || keycode == WXK_SUBTRACT
945 || keycode == WXK_NUMPAD_SUBTRACT)
816be743
VZ
946 {
947 wxGridCellTextEditor::StartingKey(event);
948
949 // skip Skip() below
950 return;
951 }
952 }
953
954 event.Skip();
955}
9c4ba614 956
c4608a8a
VZ
957void wxGridCellNumberEditor::SetParameters(const wxString& params)
958{
959 if ( !params )
960 {
961 // reset to default
962 m_min =
963 m_max = -1;
964 }
965 else
966 {
967 long tmp;
968 if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )
969 {
970 m_min = (int)tmp;
971
972 if ( params.AfterFirst(_T(',')).ToLong(&tmp) )
973 {
974 m_max = (int)tmp;
975
976 // skip the error message below
977 return;
978 }
979 }
980
f6bcfd97 981 wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params.c_str());
c4608a8a
VZ
982 }
983}
984
73145b0e
JS
985// return the value in the spin control if it is there (the text control otherwise)
986wxString wxGridCellNumberEditor::GetValue() const
987{
988 wxString s;
989
990 if( HasRange() )
991 {
14ac4f3c 992 long value = Spin()->GetValue();
73145b0e
JS
993 s.Printf(wxT("%ld"), value);
994 }
995 else
996 {
997 s = Text()->GetValue();
998 }
999 return s;
1000}
1001
816be743
VZ
1002// ----------------------------------------------------------------------------
1003// wxGridCellFloatEditor
1004// ----------------------------------------------------------------------------
1005
f6bcfd97
BP
1006wxGridCellFloatEditor::wxGridCellFloatEditor(int width, int precision)
1007{
1008 m_width = width;
1009 m_precision = precision;
1010}
1011
816be743
VZ
1012void wxGridCellFloatEditor::Create(wxWindow* parent,
1013 wxWindowID id,
1014 wxEvtHandler* evtHandler)
1015{
1016 wxGridCellTextEditor::Create(parent, id, evtHandler);
1017
1018#if wxUSE_VALIDATORS
85bc0351 1019 Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
816be743
VZ
1020#endif // wxUSE_VALIDATORS
1021}
1022
1023void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)
1024{
1025 // first get the value
1026 wxGridTableBase *table = grid->GetTable();
1027 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
1028 {
1029 m_valueOld = table->GetValueAsDouble(row, col);
1030 }
1031 else
1032 {
8a60ff0a 1033 m_valueOld = 0.0;
a5777624 1034 wxString sValue = table->GetValue(row, col);
8a60ff0a 1035 if (! sValue.ToDouble(&m_valueOld) && ! sValue.IsEmpty())
a5777624
RD
1036 {
1037 wxFAIL_MSG( _T("this cell doesn't have float value") );
1038 return;
1039 }
816be743
VZ
1040 }
1041
1042 DoBeginEdit(GetString());
1043}
1044
3324d5f5 1045bool wxGridCellFloatEditor::EndEdit(int row, int col,
816be743
VZ
1046 wxGrid* grid)
1047{
8a60ff0a
RD
1048 double value = 0.0;
1049 wxString text(Text()->GetValue());
1050
1051 if ( (text.IsEmpty() || text.ToDouble(&value)) && (value != m_valueOld) )
816be743 1052 {
a5777624
RD
1053 if (grid->GetTable()->CanSetValueAs(row, col, wxGRID_VALUE_FLOAT))
1054 grid->GetTable()->SetValueAsDouble(row, col, value);
1055 else
8a60ff0a 1056 grid->GetTable()->SetValue(row, col, text);
816be743
VZ
1057
1058 return TRUE;
1059 }
ae31cc57 1060 return FALSE;
816be743
VZ
1061}
1062
1063void wxGridCellFloatEditor::Reset()
1064{
1065 DoReset(GetString());
1066}
1067
1068void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event)
1069{
12a3f227 1070 int keycode = event.GetKeyCode();
60d876f3 1071 if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-'
c1b9e143 1072 || keycode == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER)[0u]
85d8c319
JS
1073 || keycode == WXK_NUMPAD0
1074 || keycode == WXK_NUMPAD1
1075 || keycode == WXK_NUMPAD2
1076 || keycode == WXK_NUMPAD3
1077 || keycode == WXK_NUMPAD4
1078 || keycode == WXK_NUMPAD5
1079 || keycode == WXK_NUMPAD6
1080 || keycode == WXK_NUMPAD7
1081 || keycode == WXK_NUMPAD8
1082 || keycode == WXK_NUMPAD9
1083 || keycode == WXK_ADD
1084 || keycode == WXK_NUMPAD_ADD
1085 || keycode == WXK_SUBTRACT
1086 || keycode == WXK_NUMPAD_SUBTRACT)
816be743
VZ
1087 {
1088 wxGridCellTextEditor::StartingKey(event);
1089
1090 // skip Skip() below
1091 return;
1092 }
1093
1094 event.Skip();
1095}
1096
f6bcfd97
BP
1097void wxGridCellFloatEditor::SetParameters(const wxString& params)
1098{
1099 if ( !params )
1100 {
1101 // reset to default
1102 m_width =
1103 m_precision = -1;
1104 }
1105 else
1106 {
1107 long tmp;
1108 if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )
1109 {
1110 m_width = (int)tmp;
1111
1112 if ( params.AfterFirst(_T(',')).ToLong(&tmp) )
1113 {
1114 m_precision = (int)tmp;
1115
1116 // skip the error message below
1117 return;
1118 }
1119 }
1120
1121 wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params.c_str());
1122 }
1123}
1124
1125wxString wxGridCellFloatEditor::GetString() const
1126{
1127 wxString fmt;
1128 if ( m_width == -1 )
1129 {
1130 // default width/precision
ec53826c 1131 fmt = _T("%f");
f6bcfd97
BP
1132 }
1133 else if ( m_precision == -1 )
1134 {
1135 // default precision
ec53826c 1136 fmt.Printf(_T("%%%d.f"), m_width);
f6bcfd97
BP
1137 }
1138 else
1139 {
ec53826c 1140 fmt.Printf(_T("%%%d.%df"), m_width, m_precision);
f6bcfd97
BP
1141 }
1142
1143 return wxString::Format(fmt, m_valueOld);
1144}
1145
1146bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)
1147{
1148 if ( wxGridCellEditor::IsAcceptedKey(event) )
1149 {
1150 int keycode = event.GetKeyCode();
1151 switch ( keycode )
1152 {
1153 case WXK_NUMPAD0:
1154 case WXK_NUMPAD1:
1155 case WXK_NUMPAD2:
1156 case WXK_NUMPAD3:
1157 case WXK_NUMPAD4:
1158 case WXK_NUMPAD5:
1159 case WXK_NUMPAD6:
1160 case WXK_NUMPAD7:
1161 case WXK_NUMPAD8:
1162 case WXK_NUMPAD9:
1163 case WXK_ADD:
1164 case WXK_NUMPAD_ADD:
1165 case WXK_SUBTRACT:
1166 case WXK_NUMPAD_SUBTRACT:
1167 case WXK_DECIMAL:
1168 case WXK_NUMPAD_DECIMAL:
1169 return TRUE;
1170
1171 default:
60d876f3 1172 // additionally accept 'e' as in '1e+6', also '-', '+', and '.'
f6bcfd97 1173 if ( (keycode < 128) &&
60d876f3 1174 (wxIsdigit(keycode) || tolower(keycode) == 'e' ||
c1b9e143 1175 keycode == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER)[0u] ||
60d876f3 1176 keycode == '+' || keycode == '-') )
f6bcfd97
BP
1177 return TRUE;
1178 }
1179 }
1180
1181 return FALSE;
1182}
1183
3a8c693a
VZ
1184#endif // wxUSE_TEXTCTRL
1185
1186#if wxUSE_CHECKBOX
1187
508011ce
VZ
1188// ----------------------------------------------------------------------------
1189// wxGridCellBoolEditor
1190// ----------------------------------------------------------------------------
1191
1192void wxGridCellBoolEditor::Create(wxWindow* parent,
1193 wxWindowID id,
1194 wxEvtHandler* evtHandler)
1195{
1196 m_control = new wxCheckBox(parent, id, wxEmptyString,
1197 wxDefaultPosition, wxDefaultSize,
1198 wxNO_BORDER);
1199
1200 wxGridCellEditor::Create(parent, id, evtHandler);
1201}
1202
1203void wxGridCellBoolEditor::SetSize(const wxRect& r)
1204{
b94ae1ea
VZ
1205 bool resize = FALSE;
1206 wxSize size = m_control->GetSize();
1207 wxCoord minSize = wxMin(r.width, r.height);
1208
1209 // check if the checkbox is not too big/small for this cell
1210 wxSize sizeBest = m_control->GetBestSize();
1211 if ( !(size == sizeBest) )
1212 {
1213 // reset to default size if it had been made smaller
1214 size = sizeBest;
1215
1216 resize = TRUE;
1217 }
1218
1219 if ( size.x >= minSize || size.y >= minSize )
1220 {
1221 // leave 1 pixel margin
1222 size.x = size.y = minSize - 2;
1223
1224 resize = TRUE;
1225 }
1226
1227 if ( resize )
1228 {
1229 m_control->SetSize(size);
1230 }
1231
508011ce 1232 // position it in the centre of the rectangle (TODO: support alignment?)
508011ce 1233
b94ae1ea 1234#if defined(__WXGTK__) || defined (__WXMOTIF__)
508011ce
VZ
1235 // the checkbox without label still has some space to the right in wxGTK,
1236 // so shift it to the right
b94ae1ea
VZ
1237 size.x -= 8;
1238#elif defined(__WXMSW__)
a95e38c0
VZ
1239 // here too, but in other way
1240 size.x += 1;
b94ae1ea
VZ
1241 size.y -= 2;
1242#endif
508011ce 1243
1bd71df9
JS
1244 int hAlign = wxALIGN_CENTRE;
1245 int vAlign = wxALIGN_CENTRE;
1246 if (GetCellAttr())
1247 GetCellAttr()->GetAlignment(& hAlign, & vAlign);
52d6f640 1248
1bd71df9
JS
1249 int x = 0, y = 0;
1250 if (hAlign == wxALIGN_LEFT)
1251 {
1252 x = r.x + 2;
1253#ifdef __WXMSW__
1254 x += 2;
52d6f640 1255#endif
1bd71df9
JS
1256 y = r.y + r.height/2 - size.y/2;
1257 }
1258 else if (hAlign == wxALIGN_RIGHT)
1259 {
1260 x = r.x + r.width - size.x - 2;
1261 y = r.y + r.height/2 - size.y/2;
1262 }
1263 else if (hAlign == wxALIGN_CENTRE)
1264 {
1265 x = r.x + r.width/2 - size.x/2;
1266 y = r.y + r.height/2 - size.y/2;
1267 }
52d6f640 1268
1bd71df9 1269 m_control->Move(x, y);
508011ce
VZ
1270}
1271
1272void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)
1273{
99306db2
VZ
1274 m_control->Show(show);
1275
189d0213 1276 if ( show )
508011ce 1277 {
189d0213
VZ
1278 wxColour colBg = attr ? attr->GetBackgroundColour() : *wxLIGHT_GREY;
1279 CBox()->SetBackgroundColour(colBg);
508011ce 1280 }
508011ce
VZ
1281}
1282
1283void wxGridCellBoolEditor::BeginEdit(int row, int col, wxGrid* grid)
1284{
1285 wxASSERT_MSG(m_control,
1286 wxT("The wxGridCellEditor must be Created first!"));
1287
28a77bc4 1288 if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL))
f2d76237
RD
1289 m_startValue = grid->GetTable()->GetValueAsBool(row, col);
1290 else
695a3263
MB
1291 {
1292 wxString cellval( grid->GetTable()->GetValue(row, col) );
8dd8f875 1293 m_startValue = !( !cellval || (cellval == wxT("0")) );
695a3263 1294 }
508011ce
VZ
1295 CBox()->SetValue(m_startValue);
1296 CBox()->SetFocus();
1297}
1298
1299bool wxGridCellBoolEditor::EndEdit(int row, int col,
508011ce
VZ
1300 wxGrid* grid)
1301{
1302 wxASSERT_MSG(m_control,
1303 wxT("The wxGridCellEditor must be Created first!"));
1304
1305 bool changed = FALSE;
1306 bool value = CBox()->GetValue();
1307 if ( value != m_startValue )
1308 changed = TRUE;
1309
1310 if ( changed )
1311 {
28a77bc4 1312 if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL))
f2d76237
RD
1313 grid->GetTable()->SetValueAsBool(row, col, value);
1314 else
1315 grid->GetTable()->SetValue(row, col, value ? _T("1") : wxEmptyString);
508011ce
VZ
1316 }
1317
1318 return changed;
1319}
1320
1321void wxGridCellBoolEditor::Reset()
1322{
1323 wxASSERT_MSG(m_control,
1324 wxT("The wxGridCellEditor must be Created first!"));
1325
1326 CBox()->SetValue(m_startValue);
1327}
1328
e195a54c 1329void wxGridCellBoolEditor::StartingClick()
508011ce 1330{
e195a54c 1331 CBox()->SetValue(!CBox()->GetValue());
508011ce
VZ
1332}
1333
f6bcfd97
BP
1334bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event)
1335{
1336 if ( wxGridCellEditor::IsAcceptedKey(event) )
1337 {
1338 int keycode = event.GetKeyCode();
1339 switch ( keycode )
1340 {
1341 case WXK_MULTIPLY:
1342 case WXK_NUMPAD_MULTIPLY:
1343 case WXK_ADD:
1344 case WXK_NUMPAD_ADD:
1345 case WXK_SUBTRACT:
1346 case WXK_NUMPAD_SUBTRACT:
1347 case WXK_SPACE:
1348 case '+':
1349 case '-':
1350 return TRUE;
1351 }
1352 }
1353
1354 return FALSE;
1355}
04418332 1356
73145b0e
JS
1357// return the value as "1" for true and the empty string for false
1358wxString wxGridCellBoolEditor::GetValue() const
1359{
1360 bool bSet = CBox()->GetValue();
04418332 1361 return bSet ? _T("1") : wxEmptyString;
73145b0e 1362}
f6bcfd97 1363
3a8c693a
VZ
1364#endif // wxUSE_CHECKBOX
1365
1366#if wxUSE_COMBOBOX
1367
4ee5fc9c
VZ
1368// ----------------------------------------------------------------------------
1369// wxGridCellChoiceEditor
1370// ----------------------------------------------------------------------------
1371
7db33cc3
MB
1372wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString& choices,
1373 bool allowOthers)
1374 : m_choices(choices),
1375 m_allowOthers(allowOthers) { }
1376
4ee5fc9c 1377wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count,
f6bcfd97 1378 const wxString choices[],
4ee5fc9c
VZ
1379 bool allowOthers)
1380 : m_allowOthers(allowOthers)
1381{
c4608a8a 1382 if ( count )
4ee5fc9c 1383 {
c4608a8a
VZ
1384 m_choices.Alloc(count);
1385 for ( size_t n = 0; n < count; n++ )
1386 {
1387 m_choices.Add(choices[n]);
1388 }
4ee5fc9c
VZ
1389 }
1390}
1391
c4608a8a
VZ
1392wxGridCellEditor *wxGridCellChoiceEditor::Clone() const
1393{
1394 wxGridCellChoiceEditor *editor = new wxGridCellChoiceEditor;
1395 editor->m_allowOthers = m_allowOthers;
1396 editor->m_choices = m_choices;
1397
1398 return editor;
1399}
1400
4ee5fc9c
VZ
1401void wxGridCellChoiceEditor::Create(wxWindow* parent,
1402 wxWindowID id,
1403 wxEvtHandler* evtHandler)
1404{
4ee5fc9c
VZ
1405 m_control = new wxComboBox(parent, id, wxEmptyString,
1406 wxDefaultPosition, wxDefaultSize,
584ad2a3 1407 m_choices,
4ee5fc9c
VZ
1408 m_allowOthers ? 0 : wxCB_READONLY);
1409
4ee5fc9c
VZ
1410 wxGridCellEditor::Create(parent, id, evtHandler);
1411}
1412
a5777624
RD
1413void wxGridCellChoiceEditor::PaintBackground(const wxRect& rectCell,
1414 wxGridCellAttr * attr)
4ee5fc9c
VZ
1415{
1416 // as we fill the entire client area, don't do anything here to minimize
1417 // flicker
a5777624
RD
1418
1419 // TODO: It doesn't actually fill the client area since the height of a
1420 // combo always defaults to the standard... Until someone has time to
1421 // figure out the right rectangle to paint, just do it the normal way...
1422 wxGridCellEditor::PaintBackground(rectCell, attr);
4ee5fc9c
VZ
1423}
1424
1425void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
1426{
1427 wxASSERT_MSG(m_control,
1428 wxT("The wxGridCellEditor must be Created first!"));
1429
1430 m_startValue = grid->GetTable()->GetValue(row, col);
1431
2b5f62a0
VZ
1432 if (m_allowOthers)
1433 Combo()->SetValue(m_startValue);
1434 else
28a77bc4 1435 {
2b5f62a0
VZ
1436 // find the right position, or default to the first if not found
1437 int pos = Combo()->FindString(m_startValue);
1438 if (pos == -1)
1439 pos = 0;
1440 Combo()->SetSelection(pos);
28a77bc4 1441 }
4ee5fc9c
VZ
1442 Combo()->SetInsertionPointEnd();
1443 Combo()->SetFocus();
1444}
1445
28a77bc4 1446bool wxGridCellChoiceEditor::EndEdit(int row, int col,
4ee5fc9c
VZ
1447 wxGrid* grid)
1448{
1449 wxString value = Combo()->GetValue();
1450 bool changed = value != m_startValue;
1451
1452 if ( changed )
1453 grid->GetTable()->SetValue(row, col, value);
1454
1455 m_startValue = wxEmptyString;
2b5f62a0
VZ
1456 if (m_allowOthers)
1457 Combo()->SetValue(m_startValue);
1458 else
1459 Combo()->SetSelection(0);
4ee5fc9c
VZ
1460
1461 return changed;
1462}
1463
1464void wxGridCellChoiceEditor::Reset()
1465{
1466 Combo()->SetValue(m_startValue);
1467 Combo()->SetInsertionPointEnd();
1468}
1469
c4608a8a
VZ
1470void wxGridCellChoiceEditor::SetParameters(const wxString& params)
1471{
1472 if ( !params )
1473 {
1474 // what can we do?
1475 return;
1476 }
1477
1478 m_choices.Empty();
1479
1480 wxStringTokenizer tk(params, _T(','));
1481 while ( tk.HasMoreTokens() )
1482 {
1483 m_choices.Add(tk.GetNextToken());
1484 }
1485}
1486
73145b0e
JS
1487// return the value in the text control
1488wxString wxGridCellChoiceEditor::GetValue() const
1489{
1490 return Combo()->GetValue();
1491}
04418332 1492
3a8c693a
VZ
1493#endif // wxUSE_COMBOBOX
1494
508011ce
VZ
1495// ----------------------------------------------------------------------------
1496// wxGridCellEditorEvtHandler
1497// ----------------------------------------------------------------------------
2796cce3
RD
1498
1499void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event)
1500{
12a3f227 1501 switch ( event.GetKeyCode() )
2796cce3
RD
1502 {
1503 case WXK_ESCAPE:
1504 m_editor->Reset();
b54ba671 1505 m_grid->DisableCellEditControl();
2796cce3
RD
1506 break;
1507
2c9a89e0 1508 case WXK_TAB:
b51c3f27 1509 m_grid->GetEventHandler()->ProcessEvent( event );
9b4aede2
RD
1510 break;
1511
2796cce3 1512 case WXK_RETURN:
faec5a43
SN
1513 case WXK_NUMPAD_ENTER:
1514 if (!m_grid->GetEventHandler()->ProcessEvent(event))
2796cce3
RD
1515 m_editor->HandleReturn(event);
1516 break;
1517
2796cce3
RD
1518
1519 default:
1520 event.Skip();
1521 }
1522}
1523
fb0de762
RD
1524void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event)
1525{
12a3f227 1526 switch ( event.GetKeyCode() )
fb0de762
RD
1527 {
1528 case WXK_ESCAPE:
1529 case WXK_TAB:
1530 case WXK_RETURN:
a4f7bf58 1531 case WXK_NUMPAD_ENTER:
fb0de762
RD
1532 break;
1533
1534 default:
1535 event.Skip();
1536 }
1537}
1538
c4608a8a
VZ
1539// ----------------------------------------------------------------------------
1540// wxGridCellWorker is an (almost) empty common base class for
1541// wxGridCellRenderer and wxGridCellEditor managing ref counting
1542// ----------------------------------------------------------------------------
1543
1544void wxGridCellWorker::SetParameters(const wxString& WXUNUSED(params))
1545{
1546 // nothing to do
1547}
1548
1549wxGridCellWorker::~wxGridCellWorker()
1550{
1551}
1552
508011ce
VZ
1553// ============================================================================
1554// renderer classes
1555// ============================================================================
1556
ab79958a
VZ
1557// ----------------------------------------------------------------------------
1558// wxGridCellRenderer
1559// ----------------------------------------------------------------------------
1560
1561void wxGridCellRenderer::Draw(wxGrid& grid,
2796cce3 1562 wxGridCellAttr& attr,
ab79958a
VZ
1563 wxDC& dc,
1564 const wxRect& rect,
c78b3acd 1565 int WXUNUSED(row), int WXUNUSED(col),
ab79958a
VZ
1566 bool isSelected)
1567{
1568 dc.SetBackgroundMode( wxSOLID );
1569
04418332 1570 // grey out fields if the grid is disabled
73145b0e 1571 if( grid.IsEnabled() )
ab79958a 1572 {
73145b0e
JS
1573 if ( isSelected )
1574 {
1575 dc.SetBrush( wxBrush(grid.GetSelectionBackground(), wxSOLID) );
1576 }
1577 else
1578 {
1579 dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxSOLID) );
1580 }
52d6f640 1581 }
ab79958a
VZ
1582 else
1583 {
73145b0e 1584 dc.SetBrush(wxBrush(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE), wxSOLID));
ab79958a
VZ
1585 }
1586
1587 dc.SetPen( *wxTRANSPARENT_PEN );
ab79958a
VZ
1588 dc.DrawRectangle(rect);
1589}
1590
508011ce
VZ
1591// ----------------------------------------------------------------------------
1592// wxGridCellStringRenderer
1593// ----------------------------------------------------------------------------
1594
816be743
VZ
1595void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid,
1596 wxGridCellAttr& attr,
1597 wxDC& dc,
1598 bool isSelected)
ab79958a 1599{
ab79958a
VZ
1600 dc.SetBackgroundMode( wxTRANSPARENT );
1601
283b7808
VZ
1602 // TODO some special colours for attr.IsReadOnly() case?
1603
04418332 1604 // different coloured text when the grid is disabled
73145b0e 1605 if( grid.IsEnabled() )
ab79958a 1606 {
73145b0e
JS
1607 if ( isSelected )
1608 {
1609 dc.SetTextBackground( grid.GetSelectionBackground() );
1610 dc.SetTextForeground( grid.GetSelectionForeground() );
1611 }
1612 else
1613 {
1614 dc.SetTextBackground( attr.GetBackgroundColour() );
1615 dc.SetTextForeground( attr.GetTextColour() );
1616 }
ab79958a
VZ
1617 }
1618 else
1619 {
73145b0e
JS
1620 dc.SetTextBackground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE));
1621 dc.SetTextForeground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT));
ab79958a 1622 }
816be743 1623
2796cce3 1624 dc.SetFont( attr.GetFont() );
816be743
VZ
1625}
1626
65e4e78e
VZ
1627wxSize wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr& attr,
1628 wxDC& dc,
1629 const wxString& text)
1630{
f6bcfd97 1631 wxCoord x = 0, y = 0, max_x = 0;
65e4e78e 1632 dc.SetFont(attr.GetFont());
f6bcfd97
BP
1633 wxStringTokenizer tk(text, _T('\n'));
1634 while ( tk.HasMoreTokens() )
1635 {
1636 dc.GetTextExtent(tk.GetNextToken(), &x, &y);
1637 max_x = wxMax(max_x, x);
1638 }
1639
1640 y *= 1 + text.Freq(wxT('\n')); // multiply by the number of lines.
65e4e78e 1641
f6bcfd97 1642 return wxSize(max_x, y);
65e4e78e
VZ
1643}
1644
1645wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid,
1646 wxGridCellAttr& attr,
1647 wxDC& dc,
1648 int row, int col)
1649{
1650 return DoGetBestSize(attr, dc, grid.GetCellValue(row, col));
1651}
1652
816be743
VZ
1653void wxGridCellStringRenderer::Draw(wxGrid& grid,
1654 wxGridCellAttr& attr,
1655 wxDC& dc,
1656 const wxRect& rectCell,
1657 int row, int col,
1658 bool isSelected)
1659{
27f35b66 1660 wxRect rect = rectCell;
dc1f566f
SN
1661 rect.Inflate(-1);
1662
1663 // erase only this cells background, overflow cells should have been erased
1664 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
1665
1666 int hAlign, vAlign;
1667 attr.GetAlignment(&hAlign, &vAlign);
27f35b66 1668
39b80349
SN
1669 int overflowCols = 0;
1670
27f35b66
SN
1671 if (attr.GetOverflow())
1672 {
1673 int cols = grid.GetNumberCols();
1674 int best_width = GetBestSize(grid,attr,dc,row,col).GetWidth();
1675 int cell_rows, cell_cols;
1676 attr.GetSize( &cell_rows, &cell_cols ); // shouldn't get here if <=0
1677 if ((best_width > rectCell.width) && (col < cols) && grid.GetTable())
1678 {
1679 int i, c_cols, c_rows;
1680 for (i = col+cell_cols; i < cols; i++)
1681 {
2b5f62a0 1682 bool is_empty = TRUE;
39b80349 1683 for (int j=row; j<row+cell_rows; j++)
27f35b66 1684 {
39b80349 1685 // check w/ anchor cell for multicell block
ef4d6ce8 1686 grid.GetCellSize(j, i, &c_rows, &c_cols);
39b80349 1687 if (c_rows > 0) c_rows = 0;
ef4d6ce8 1688 if (!grid.GetTable()->IsEmptyCell(j+c_rows, i))
39b80349 1689 {
2b5f62a0 1690 is_empty = FALSE;
ef4d6ce8 1691 break;
39b80349 1692 }
27f35b66 1693 }
39b80349
SN
1694 if (is_empty)
1695 rect.width += grid.GetColSize(i);
dc1f566f
SN
1696 else
1697 {
1698 i--;
1699 break;
1700 }
39b80349 1701 if (rect.width >= best_width) break;
2b5f62a0 1702 }
39b80349 1703 overflowCols = i - col - cell_cols + 1;
2b5f62a0 1704 if (overflowCols >= cols) overflowCols = cols - 1;
39b80349 1705 }
27f35b66 1706
dc1f566f
SN
1707 if (overflowCols > 0) // redraw overflow cells w/ proper hilight
1708 {
39b80349 1709 hAlign = wxALIGN_LEFT; // if oveflowed then it's left aligned
2b5f62a0 1710 wxRect clip = rect;
39b80349 1711 clip.x += rectCell.width;
dc1f566f
SN
1712 // draw each overflow cell individually
1713 int col_end = col+cell_cols+overflowCols;
1714 if (col_end >= grid.GetNumberCols())
2b5f62a0 1715 col_end = grid.GetNumberCols() - 1;
dc1f566f
SN
1716 for (int i = col+cell_cols; i <= col_end; i++)
1717 {
dc1f566f
SN
1718 clip.width = grid.GetColSize(i) - 1;
1719 dc.DestroyClippingRegion();
1720 dc.SetClippingRegion(clip);
39b80349
SN
1721
1722 SetTextColoursAndFont(grid, attr, dc,
2b5f62a0 1723 grid.IsInSelection(row,i));
39b80349 1724
dc1f566f 1725 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
2b5f62a0 1726 rect, hAlign, vAlign);
39b80349 1727 clip.x += grid.GetColSize(i) - 1;
dc1f566f 1728 }
ab79958a 1729
39b80349 1730 rect = rectCell;
2b5f62a0 1731 rect.Inflate(-1);
dc1f566f 1732 rect.width++;
39b80349 1733 dc.DestroyClippingRegion();
dc1f566f 1734 }
39b80349 1735 }
ab79958a 1736
dc1f566f
SN
1737 // now we only have to draw the text
1738 SetTextColoursAndFont(grid, attr, dc, isSelected);
39b80349 1739
ab79958a
VZ
1740 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
1741 rect, hAlign, vAlign);
1742}
1743
65e4e78e
VZ
1744// ----------------------------------------------------------------------------
1745// wxGridCellNumberRenderer
1746// ----------------------------------------------------------------------------
1747
1748wxString wxGridCellNumberRenderer::GetString(wxGrid& grid, int row, int col)
1749{
1750 wxGridTableBase *table = grid.GetTable();
1751 wxString text;
1752 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
1753 {
1754 text.Printf(_T("%ld"), table->GetValueAsLong(row, col));
1755 }
9c4ba614
VZ
1756 else
1757 {
1758 text = table->GetValue(row, col);
1759 }
65e4e78e
VZ
1760
1761 return text;
1762}
1763
816be743
VZ
1764void wxGridCellNumberRenderer::Draw(wxGrid& grid,
1765 wxGridCellAttr& attr,
1766 wxDC& dc,
1767 const wxRect& rectCell,
1768 int row, int col,
1769 bool isSelected)
1770{
1771 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
1772
1773 SetTextColoursAndFont(grid, attr, dc, isSelected);
1774
1775 // draw the text right aligned by default
1776 int hAlign, vAlign;
1777 attr.GetAlignment(&hAlign, &vAlign);
4c7277db 1778 hAlign = wxALIGN_RIGHT;
816be743
VZ
1779
1780 wxRect rect = rectCell;
1781 rect.Inflate(-1);
1782
65e4e78e
VZ
1783 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
1784}
816be743 1785
65e4e78e
VZ
1786wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
1787 wxGridCellAttr& attr,
1788 wxDC& dc,
1789 int row, int col)
1790{
1791 return DoGetBestSize(attr, dc, GetString(grid, row, col));
816be743
VZ
1792}
1793
1794// ----------------------------------------------------------------------------
1795// wxGridCellFloatRenderer
1796// ----------------------------------------------------------------------------
1797
1798wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision)
1799{
1800 SetWidth(width);
1801 SetPrecision(precision);
1802}
1803
e72b4213
VZ
1804wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const
1805{
1806 wxGridCellFloatRenderer *renderer = new wxGridCellFloatRenderer;
1807 renderer->m_width = m_width;
1808 renderer->m_precision = m_precision;
1809 renderer->m_format = m_format;
1810
1811 return renderer;
1812}
1813
65e4e78e
VZ
1814wxString wxGridCellFloatRenderer::GetString(wxGrid& grid, int row, int col)
1815{
1816 wxGridTableBase *table = grid.GetTable();
0b190b0f
VZ
1817
1818 bool hasDouble;
1819 double val;
65e4e78e
VZ
1820 wxString text;
1821 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
1822 {
0b190b0f
VZ
1823 val = table->GetValueAsDouble(row, col);
1824 hasDouble = TRUE;
65e4e78e 1825 }
9c4ba614
VZ
1826 else
1827 {
1828 text = table->GetValue(row, col);
0b190b0f 1829 hasDouble = text.ToDouble(&val);
9c4ba614 1830 }
65e4e78e 1831
0b190b0f
VZ
1832 if ( hasDouble )
1833 {
1834 if ( !m_format )
1835 {
1836 if ( m_width == -1 )
1837 {
19d7140e
VZ
1838 if ( m_precision == -1 )
1839 {
2b5f62a0
VZ
1840 // default width/precision
1841 m_format = _T("%f");
1842 }
19d7140e
VZ
1843 else
1844 {
1845 m_format.Printf(_T("%%.%df"), m_precision);
1846 }
0b190b0f
VZ
1847 }
1848 else if ( m_precision == -1 )
1849 {
1850 // default precision
1851 m_format.Printf(_T("%%%d.f"), m_width);
1852 }
1853 else
1854 {
1855 m_format.Printf(_T("%%%d.%df"), m_width, m_precision);
1856 }
1857 }
1858
1859 text.Printf(m_format, val);
19d7140e 1860
0b190b0f
VZ
1861 }
1862 //else: text already contains the string
1863
65e4e78e
VZ
1864 return text;
1865}
1866
816be743
VZ
1867void wxGridCellFloatRenderer::Draw(wxGrid& grid,
1868 wxGridCellAttr& attr,
1869 wxDC& dc,
1870 const wxRect& rectCell,
1871 int row, int col,
1872 bool isSelected)
1873{
1874 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
1875
1876 SetTextColoursAndFont(grid, attr, dc, isSelected);
1877
1878 // draw the text right aligned by default
1879 int hAlign, vAlign;
1880 attr.GetAlignment(&hAlign, &vAlign);
4c7277db 1881 hAlign = wxALIGN_RIGHT;
816be743
VZ
1882
1883 wxRect rect = rectCell;
1884 rect.Inflate(-1);
1885
65e4e78e
VZ
1886 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
1887}
816be743 1888
65e4e78e
VZ
1889wxSize wxGridCellFloatRenderer::GetBestSize(wxGrid& grid,
1890 wxGridCellAttr& attr,
1891 wxDC& dc,
1892 int row, int col)
1893{
1894 return DoGetBestSize(attr, dc, GetString(grid, row, col));
816be743
VZ
1895}
1896
0b190b0f
VZ
1897void wxGridCellFloatRenderer::SetParameters(const wxString& params)
1898{
0b190b0f
VZ
1899 if ( !params )
1900 {
1901 // reset to defaults
1902 SetWidth(-1);
1903 SetPrecision(-1);
1904 }
1905 else
1906 {
1907 wxString tmp = params.BeforeFirst(_T(','));
1908 if ( !!tmp )
1909 {
1910 long width;
19d7140e 1911 if ( tmp.ToLong(&width) )
0b190b0f 1912 {
19d7140e 1913 SetWidth((int)width);
0b190b0f
VZ
1914 }
1915 else
1916 {
19d7140e
VZ
1917 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params.c_str());
1918 }
0b190b0f 1919
19d7140e 1920 }
0b190b0f
VZ
1921 tmp = params.AfterFirst(_T(','));
1922 if ( !!tmp )
1923 {
1924 long precision;
19d7140e 1925 if ( tmp.ToLong(&precision) )
0b190b0f 1926 {
19d7140e 1927 SetPrecision((int)precision);
0b190b0f
VZ
1928 }
1929 else
1930 {
19d7140e 1931 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params.c_str());
0b190b0f
VZ
1932 }
1933
0b190b0f
VZ
1934 }
1935 }
1936}
1937
19d7140e 1938
508011ce
VZ
1939// ----------------------------------------------------------------------------
1940// wxGridCellBoolRenderer
1941// ----------------------------------------------------------------------------
1942
65e4e78e 1943wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
508011ce 1944
b94ae1ea
VZ
1945// FIXME these checkbox size calculations are really ugly...
1946
65e4e78e 1947// between checkmark and box
a95e38c0 1948static const wxCoord wxGRID_CHECKMARK_MARGIN = 2;
508011ce 1949
65e4e78e
VZ
1950wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
1951 wxGridCellAttr& WXUNUSED(attr),
1952 wxDC& WXUNUSED(dc),
1953 int WXUNUSED(row),
1954 int WXUNUSED(col))
1955{
1956 // compute it only once (no locks for MT safeness in GUI thread...)
1957 if ( !ms_sizeCheckMark.x )
297da4ba 1958 {
65e4e78e 1959 // get checkbox size
297da4ba
VZ
1960 wxCheckBox *checkbox = new wxCheckBox(&grid, -1, wxEmptyString);
1961 wxSize size = checkbox->GetBestSize();
999836aa 1962 wxCoord checkSize = size.y + 2*wxGRID_CHECKMARK_MARGIN;
297da4ba 1963
65e4e78e 1964 // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result
69d8f612 1965#if defined(__WXGTK__) || defined(__WXMOTIF__)
65e4e78e 1966 checkSize -= size.y / 2;
297da4ba
VZ
1967#endif
1968
1969 delete checkbox;
65e4e78e
VZ
1970
1971 ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize;
297da4ba
VZ
1972 }
1973
65e4e78e
VZ
1974 return ms_sizeCheckMark;
1975}
1976
1977void wxGridCellBoolRenderer::Draw(wxGrid& grid,
1978 wxGridCellAttr& attr,
1979 wxDC& dc,
1980 const wxRect& rect,
1981 int row, int col,
1982 bool isSelected)
1983{
1984 wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
1985
297da4ba 1986 // draw a check mark in the centre (ignoring alignment - TODO)
65e4e78e 1987 wxSize size = GetBestSize(grid, attr, dc, row, col);
b94ae1ea
VZ
1988
1989 // don't draw outside the cell
1990 wxCoord minSize = wxMin(rect.width, rect.height);
1991 if ( size.x >= minSize || size.y >= minSize )
1992 {
1993 // and even leave (at least) 1 pixel margin
1994 size.x = size.y = minSize - 2;
1995 }
1996
1997 // draw a border around checkmark
1bd71df9
JS
1998 int vAlign, hAlign;
1999 attr.GetAlignment(& hAlign, &vAlign);
52d6f640 2000
a95e38c0 2001 wxRect rectBorder;
1bd71df9
JS
2002 if (hAlign == wxALIGN_CENTRE)
2003 {
2004 rectBorder.x = rect.x + rect.width/2 - size.x/2;
2005 rectBorder.y = rect.y + rect.height/2 - size.y/2;
2006 rectBorder.width = size.x;
2007 rectBorder.height = size.y;
2008 }
2009 else if (hAlign == wxALIGN_LEFT)
2010 {
2011 rectBorder.x = rect.x + 2;
2012 rectBorder.y = rect.y + rect.height/2 - size.y/2;
2013 rectBorder.width = size.x;
52d6f640 2014 rectBorder.height = size.y;
1bd71df9
JS
2015 }
2016 else if (hAlign == wxALIGN_RIGHT)
2017 {
2018 rectBorder.x = rect.x + rect.width - size.x - 2;
2019 rectBorder.y = rect.y + rect.height/2 - size.y/2;
2020 rectBorder.width = size.x;
52d6f640 2021 rectBorder.height = size.y;
1bd71df9 2022 }
b94ae1ea 2023
f2d76237 2024 bool value;
b94ae1ea 2025 if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
f2d76237
RD
2026 value = grid.GetTable()->GetValueAsBool(row, col);
2027 else
695a3263
MB
2028 {
2029 wxString cellval( grid.GetTable()->GetValue(row, col) );
8dd8f875 2030 value = !( !cellval || (cellval == wxT("0")) );
695a3263 2031 }
f2d76237
RD
2032
2033 if ( value )
508011ce 2034 {
a95e38c0
VZ
2035 wxRect rectMark = rectBorder;
2036#ifdef __WXMSW__
2037 // MSW DrawCheckMark() is weird (and should probably be changed...)
2038 rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN/2);
2039 rectMark.x++;
2040 rectMark.y++;
2041#else // !MSW
2042 rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN);
2043#endif // MSW/!MSW
2044
508011ce
VZ
2045 dc.SetTextForeground(attr.GetTextColour());
2046 dc.DrawCheckMark(rectMark);
2047 }
a95e38c0
VZ
2048
2049 dc.SetBrush(*wxTRANSPARENT_BRUSH);
2050 dc.SetPen(wxPen(attr.GetTextColour(), 1, wxSOLID));
2051 dc.DrawRectangle(rectBorder);
508011ce
VZ
2052}
2053
2796cce3
RD
2054// ----------------------------------------------------------------------------
2055// wxGridCellAttr
2056// ----------------------------------------------------------------------------
2057
1df4050d
VZ
2058void wxGridCellAttr::Init(wxGridCellAttr *attrDefault)
2059{
2060 m_nRef = 1;
2061
2062 m_isReadOnly = Unset;
2063
2064 m_renderer = NULL;
2065 m_editor = NULL;
2066
2067 m_attrkind = wxGridCellAttr::Cell;
2068
27f35b66 2069 m_sizeRows = m_sizeCols = 1;
b63fce94 2070 m_overflow = UnsetOverflow;
27f35b66 2071
1df4050d
VZ
2072 SetDefAttr(attrDefault);
2073}
2074
39bcce60 2075wxGridCellAttr *wxGridCellAttr::Clone() const
a68c1246 2076{
1df4050d
VZ
2077 wxGridCellAttr *attr = new wxGridCellAttr(m_defGridAttr);
2078
a68c1246
VZ
2079 if ( HasTextColour() )
2080 attr->SetTextColour(GetTextColour());
2081 if ( HasBackgroundColour() )
2082 attr->SetBackgroundColour(GetBackgroundColour());
2083 if ( HasFont() )
2084 attr->SetFont(GetFont());
2085 if ( HasAlignment() )
2086 attr->SetAlignment(m_hAlign, m_vAlign);
2087
27f35b66
SN
2088 attr->SetSize( m_sizeRows, m_sizeCols );
2089
a68c1246
VZ
2090 if ( m_renderer )
2091 {
2092 attr->SetRenderer(m_renderer);
39bcce60 2093 m_renderer->IncRef();
a68c1246
VZ
2094 }
2095 if ( m_editor )
2096 {
2097 attr->SetEditor(m_editor);
39bcce60 2098 m_editor->IncRef();
a68c1246
VZ
2099 }
2100
2101 if ( IsReadOnly() )
2102 attr->SetReadOnly();
2103
19d7140e
VZ
2104 attr->SetKind( m_attrkind );
2105
a68c1246
VZ
2106 return attr;
2107}
2108
19d7140e
VZ
2109void wxGridCellAttr::MergeWith(wxGridCellAttr *mergefrom)
2110{
2111 if ( !HasTextColour() && mergefrom->HasTextColour() )
2112 SetTextColour(mergefrom->GetTextColour());
2113 if ( !HasBackgroundColour() && mergefrom->HasBackgroundColour() )
2114 SetBackgroundColour(mergefrom->GetBackgroundColour());
2115 if ( !HasFont() && mergefrom->HasFont() )
2116 SetFont(mergefrom->GetFont());
7e48d7d9 2117 if ( !HasAlignment() && mergefrom->HasAlignment() ){
19d7140e
VZ
2118 int hAlign, vAlign;
2119 mergefrom->GetAlignment( &hAlign, &vAlign);
2120 SetAlignment(hAlign, vAlign);
2121 }
2122
27f35b66
SN
2123 mergefrom->GetSize( &m_sizeRows, &m_sizeCols );
2124
19d7140e
VZ
2125 // Directly access member functions as GetRender/Editor don't just return
2126 // m_renderer/m_editor
2127 //
2128 // Maybe add support for merge of Render and Editor?
2129 if (!HasRenderer() && mergefrom->HasRenderer() )
bf7945ce 2130 {
19d7140e
VZ
2131 m_renderer = mergefrom->m_renderer;
2132 m_renderer->IncRef();
2133 }
2134 if ( !HasEditor() && mergefrom->HasEditor() )
2135 {
2136 m_editor = mergefrom->m_editor;
2137 m_editor->IncRef();
2138 }
2139 if ( !HasReadWriteMode() && mergefrom->HasReadWriteMode() )
2140 SetReadOnly(mergefrom->IsReadOnly());
2141
ef5df12b 2142 if (!HasOverflowMode() && mergefrom->HasOverflowMode() )
ff699386 2143 SetOverflow(mergefrom->GetOverflow());
ef5df12b 2144
19d7140e
VZ
2145 SetDefAttr(mergefrom->m_defGridAttr);
2146}
2147
27f35b66
SN
2148void wxGridCellAttr::SetSize(int num_rows, int num_cols)
2149{
2150 // The size of a cell is normally 1,1
2151
2152 // If this cell is larger (2,2) then this is the top left cell
2153 // the other cells that will be covered (lower right cells) must be
2154 // set to negative or zero values such that
2155 // row + num_rows of the covered cell points to the larger cell (this cell)
2156 // same goes for the col + num_cols.
2157
2158 // Size of 0,0 is NOT valid, neither is <=0 and any positive value
2159
2160 wxASSERT_MSG( (!((num_rows>0)&&(num_cols<=0)) ||
2161 !((num_rows<=0)&&(num_cols>0)) ||
2162 !((num_rows==0)&&(num_cols==0))),
2163 wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values"));
2164
2165 m_sizeRows = num_rows;
2166 m_sizeCols = num_cols;
2167}
2168
2796cce3
RD
2169const wxColour& wxGridCellAttr::GetTextColour() const
2170{
2171 if (HasTextColour())
508011ce 2172 {
2796cce3 2173 return m_colText;
508011ce 2174 }
0926b2fc 2175 else if (m_defGridAttr && m_defGridAttr != this)
508011ce 2176 {
2796cce3 2177 return m_defGridAttr->GetTextColour();
508011ce
VZ
2178 }
2179 else
2180 {
2796cce3
RD
2181 wxFAIL_MSG(wxT("Missing default cell attribute"));
2182 return wxNullColour;
2183 }
2184}
2185
2186
2187const wxColour& wxGridCellAttr::GetBackgroundColour() const
2188{
2189 if (HasBackgroundColour())
2190 return m_colBack;
0926b2fc 2191 else if (m_defGridAttr && m_defGridAttr != this)
2796cce3 2192 return m_defGridAttr->GetBackgroundColour();
508011ce
VZ
2193 else
2194 {
2796cce3
RD
2195 wxFAIL_MSG(wxT("Missing default cell attribute"));
2196 return wxNullColour;
2197 }
2198}
2199
2200
2201const wxFont& wxGridCellAttr::GetFont() const
2202{
2203 if (HasFont())
2204 return m_font;
0926b2fc 2205 else if (m_defGridAttr && m_defGridAttr != this)
2796cce3 2206 return m_defGridAttr->GetFont();
508011ce
VZ
2207 else
2208 {
2796cce3
RD
2209 wxFAIL_MSG(wxT("Missing default cell attribute"));
2210 return wxNullFont;
2211 }
2212}
2213
2214
2215void wxGridCellAttr::GetAlignment(int *hAlign, int *vAlign) const
2216{
508011ce
VZ
2217 if (HasAlignment())
2218 {
2796cce3
RD
2219 if ( hAlign ) *hAlign = m_hAlign;
2220 if ( vAlign ) *vAlign = m_vAlign;
2221 }
0926b2fc 2222 else if (m_defGridAttr && m_defGridAttr != this)
2796cce3 2223 m_defGridAttr->GetAlignment(hAlign, vAlign);
508011ce
VZ
2224 else
2225 {
2796cce3
RD
2226 wxFAIL_MSG(wxT("Missing default cell attribute"));
2227 }
2228}
2229
27f35b66
SN
2230void wxGridCellAttr::GetSize( int *num_rows, int *num_cols ) const
2231{
2232 if ( num_rows ) *num_rows = m_sizeRows;
2233 if ( num_cols ) *num_cols = m_sizeCols;
2234}
2796cce3 2235
f2d76237 2236// GetRenderer and GetEditor use a slightly different decision path about
28a77bc4
RD
2237// which attribute to use. If a non-default attr object has one then it is
2238// used, otherwise the default editor or renderer is fetched from the grid and
2239// used. It should be the default for the data type of the cell. If it is
2240// NULL (because the table has a type that the grid does not have in its
2241// registry,) then the grid's default editor or renderer is used.
2242
2243wxGridCellRenderer* wxGridCellAttr::GetRenderer(wxGrid* grid, int row, int col) const
2244{
3cf883a2 2245 wxGridCellRenderer *renderer;
28a77bc4 2246
3cf883a2 2247 if ( m_renderer && this != m_defGridAttr )
0b190b0f 2248 {
3cf883a2
VZ
2249 // use the cells renderer if it has one
2250 renderer = m_renderer;
2251 renderer->IncRef();
0b190b0f 2252 }
3cf883a2 2253 else // no non default cell renderer
0b190b0f 2254 {
3cf883a2
VZ
2255 // get default renderer for the data type
2256 if ( grid )
2257 {
2258 // GetDefaultRendererForCell() will do IncRef() for us
2259 renderer = grid->GetDefaultRendererForCell(row, col);
2260 }
2261 else
2262 {
2263 renderer = NULL;
2264 }
0b190b0f 2265
3cf883a2
VZ
2266 if ( !renderer )
2267 {
0926b2fc 2268 if (m_defGridAttr && this != m_defGridAttr )
3cf883a2
VZ
2269 {
2270 // if we still don't have one then use the grid default
2271 // (no need for IncRef() here neither)
2272 renderer = m_defGridAttr->GetRenderer(NULL, 0, 0);
2273 }
2274 else // default grid attr
2275 {
2276 // use m_renderer which we had decided not to use initially
2277 renderer = m_renderer;
2278 if ( renderer )
2279 renderer->IncRef();
2280 }
2281 }
0b190b0f 2282 }
28a77bc4 2283
3cf883a2
VZ
2284 // we're supposed to always find something
2285 wxASSERT_MSG(renderer, wxT("Missing default cell renderer"));
28a77bc4
RD
2286
2287 return renderer;
2796cce3
RD
2288}
2289
3cf883a2 2290// same as above, except for s/renderer/editor/g
28a77bc4 2291wxGridCellEditor* wxGridCellAttr::GetEditor(wxGrid* grid, int row, int col) const
07296f0b 2292{
3cf883a2 2293 wxGridCellEditor *editor;
0b190b0f 2294
3cf883a2 2295 if ( m_editor && this != m_defGridAttr )
0b190b0f 2296 {
3cf883a2
VZ
2297 // use the cells editor if it has one
2298 editor = m_editor;
2299 editor->IncRef();
0b190b0f 2300 }
3cf883a2 2301 else // no non default cell editor
0b190b0f 2302 {
3cf883a2
VZ
2303 // get default editor for the data type
2304 if ( grid )
2305 {
2306 // GetDefaultEditorForCell() will do IncRef() for us
2307 editor = grid->GetDefaultEditorForCell(row, col);
2308 }
2309 else
2310 {
2311 editor = NULL;
2312 }
2313
2314 if ( !editor )
2315 {
0926b2fc 2316 if ( m_defGridAttr && this != m_defGridAttr )
3cf883a2
VZ
2317 {
2318 // if we still don't have one then use the grid default
2319 // (no need for IncRef() here neither)
2320 editor = m_defGridAttr->GetEditor(NULL, 0, 0);
2321 }
2322 else // default grid attr
2323 {
2324 // use m_editor which we had decided not to use initially
2325 editor = m_editor;
2326 if ( editor )
2327 editor->IncRef();
2328 }
2329 }
0b190b0f 2330 }
28a77bc4 2331
3cf883a2
VZ
2332 // we're supposed to always find something
2333 wxASSERT_MSG(editor, wxT("Missing default cell editor"));
2334
28a77bc4 2335 return editor;
07296f0b
RD
2336}
2337
b99be8fb 2338// ----------------------------------------------------------------------------
758cbedf 2339// wxGridCellAttrData
b99be8fb
VZ
2340// ----------------------------------------------------------------------------
2341
758cbedf 2342void wxGridCellAttrData::SetAttr(wxGridCellAttr *attr, int row, int col)
b99be8fb
VZ
2343{
2344 int n = FindIndex(row, col);
2345 if ( n == wxNOT_FOUND )
2346 {
2347 // add the attribute
2348 m_attrs.Add(new wxGridCellWithAttr(row, col, attr));
2349 }
2350 else
2351 {
6f36917b
VZ
2352 // free the old attribute
2353 m_attrs[(size_t)n].attr->DecRef();
2354
b99be8fb
VZ
2355 if ( attr )
2356 {
2357 // change the attribute
2e9a6788 2358 m_attrs[(size_t)n].attr = attr;
b99be8fb
VZ
2359 }
2360 else
2361 {
2362 // remove this attribute
2363 m_attrs.RemoveAt((size_t)n);
2364 }
2365 }
b99be8fb
VZ
2366}
2367
758cbedf 2368wxGridCellAttr *wxGridCellAttrData::GetAttr(int row, int col) const
b99be8fb
VZ
2369{
2370 wxGridCellAttr *attr = (wxGridCellAttr *)NULL;
2371
2372 int n = FindIndex(row, col);
2373 if ( n != wxNOT_FOUND )
2374 {
2e9a6788
VZ
2375 attr = m_attrs[(size_t)n].attr;
2376 attr->IncRef();
b99be8fb
VZ
2377 }
2378
2379 return attr;
2380}
2381
4d60017a
SN
2382void wxGridCellAttrData::UpdateAttrRows( size_t pos, int numRows )
2383{
2384 size_t count = m_attrs.GetCount();
2385 for ( size_t n = 0; n < count; n++ )
2386 {
2387 wxGridCellCoords& coords = m_attrs[n].coords;
d1c0b4f9
VZ
2388 wxCoord row = coords.GetRow();
2389 if ((size_t)row >= pos)
2390 {
2391 if (numRows > 0)
2392 {
2393 // If rows inserted, include row counter where necessary
2394 coords.SetRow(row + numRows);
2395 }
2396 else if (numRows < 0)
2397 {
2398 // If rows deleted ...
2399 if ((size_t)row >= pos - numRows)
2400 {
2401 // ...either decrement row counter (if row still exists)...
2402 coords.SetRow(row + numRows);
2403 }
2404 else
2405 {
2406 // ...or remove the attribute
2407 m_attrs.RemoveAt((size_t)n);
2408 n--; count--;
2409 }
2410 }
4d60017a
SN
2411 }
2412 }
2413}
2414
2415void wxGridCellAttrData::UpdateAttrCols( size_t pos, int numCols )
2416{
2417 size_t count = m_attrs.GetCount();
2418 for ( size_t n = 0; n < count; n++ )
2419 {
2420 wxGridCellCoords& coords = m_attrs[n].coords;
d1c0b4f9
VZ
2421 wxCoord col = coords.GetCol();
2422 if ( (size_t)col >= pos )
2423 {
2424 if ( numCols > 0 )
2425 {
2426 // If rows inserted, include row counter where necessary
2427 coords.SetCol(col + numCols);
2428 }
2429 else if (numCols < 0)
2430 {
2431 // If rows deleted ...
2432 if ((size_t)col >= pos - numCols)
2433 {
2434 // ...either decrement row counter (if row still exists)...
2435 coords.SetCol(col + numCols);
2436 }
2437 else
2438 {
2439 // ...or remove the attribute
2440 m_attrs.RemoveAt((size_t)n);
2441 n--; count--;
2442 }
2443 }
4d60017a
SN
2444 }
2445 }
2446}
2447
758cbedf 2448int wxGridCellAttrData::FindIndex(int row, int col) const
b99be8fb
VZ
2449{
2450 size_t count = m_attrs.GetCount();
2451 for ( size_t n = 0; n < count; n++ )
2452 {
2453 const wxGridCellCoords& coords = m_attrs[n].coords;
2454 if ( (coords.GetRow() == row) && (coords.GetCol() == col) )
2455 {
2456 return n;
2457 }
2458 }
2459
2460 return wxNOT_FOUND;
2461}
2462
758cbedf
VZ
2463// ----------------------------------------------------------------------------
2464// wxGridRowOrColAttrData
2465// ----------------------------------------------------------------------------
2466
2467wxGridRowOrColAttrData::~wxGridRowOrColAttrData()
2468{
2469 size_t count = m_attrs.Count();
2470 for ( size_t n = 0; n < count; n++ )
2471 {
2472 m_attrs[n]->DecRef();
2473 }
2474}
2475
2476wxGridCellAttr *wxGridRowOrColAttrData::GetAttr(int rowOrCol) const
2477{
2478 wxGridCellAttr *attr = (wxGridCellAttr *)NULL;
2479
2480 int n = m_rowsOrCols.Index(rowOrCol);
2481 if ( n != wxNOT_FOUND )
2482 {
2483 attr = m_attrs[(size_t)n];
2484 attr->IncRef();
2485 }
2486
2487 return attr;
2488}
2489
2490void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr *attr, int rowOrCol)
2491{
a95e38c0
VZ
2492 int i = m_rowsOrCols.Index(rowOrCol);
2493 if ( i == wxNOT_FOUND )
758cbedf
VZ
2494 {
2495 // add the attribute
2496 m_rowsOrCols.Add(rowOrCol);
2497 m_attrs.Add(attr);
2498 }
2499 else
2500 {
a95e38c0 2501 size_t n = (size_t)i;
758cbedf
VZ
2502 if ( attr )
2503 {
2504 // change the attribute
a95e38c0
VZ
2505 m_attrs[n]->DecRef();
2506 m_attrs[n] = attr;
758cbedf
VZ
2507 }
2508 else
2509 {
2510 // remove this attribute
a95e38c0
VZ
2511 m_attrs[n]->DecRef();
2512 m_rowsOrCols.RemoveAt(n);
2513 m_attrs.RemoveAt(n);
758cbedf
VZ
2514 }
2515 }
2516}
2517
4d60017a
SN
2518void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos, int numRowsOrCols )
2519{
2520 size_t count = m_attrs.GetCount();
2521 for ( size_t n = 0; n < count; n++ )
2522 {
2523 int & rowOrCol = m_rowsOrCols[n];
d1c0b4f9
VZ
2524 if ( (size_t)rowOrCol >= pos )
2525 {
2526 if ( numRowsOrCols > 0 )
2527 {
2528 // If rows inserted, include row counter where necessary
2529 rowOrCol += numRowsOrCols;
2530 }
2531 else if ( numRowsOrCols < 0)
2532 {
2533 // If rows deleted, either decrement row counter (if row still exists)
2534 if ((size_t)rowOrCol >= pos - numRowsOrCols)
2535 rowOrCol += numRowsOrCols;
2536 else
2537 {
2538 m_rowsOrCols.RemoveAt((size_t)n);
2539 m_attrs.RemoveAt((size_t)n);
2540 n--; count--;
2541 }
2542 }
4d60017a
SN
2543 }
2544 }
2545}
2546
b99be8fb
VZ
2547// ----------------------------------------------------------------------------
2548// wxGridCellAttrProvider
2549// ----------------------------------------------------------------------------
2550
2551wxGridCellAttrProvider::wxGridCellAttrProvider()
2552{
2553 m_data = (wxGridCellAttrProviderData *)NULL;
2554}
2555
2556wxGridCellAttrProvider::~wxGridCellAttrProvider()
2557{
2558 delete m_data;
2559}
2560
2561void wxGridCellAttrProvider::InitData()
2562{
2563 m_data = new wxGridCellAttrProviderData;
2564}
2565
19d7140e
VZ
2566wxGridCellAttr *wxGridCellAttrProvider::GetAttr(int row, int col,
2567 wxGridCellAttr::wxAttrKind kind ) const
b99be8fb 2568{
758cbedf
VZ
2569 wxGridCellAttr *attr = (wxGridCellAttr *)NULL;
2570 if ( m_data )
2571 {
19d7140e 2572 switch(kind)
758cbedf 2573 {
19d7140e
VZ
2574 case (wxGridCellAttr::Any):
2575 //Get cached merge attributes.
2576 // Currenlty not used as no cache implemented as not mutiable
2577 // attr = m_data->m_mergeAttr.GetAttr(row, col);
2578 if(!attr)
2579 {
2580 //Basicaly implement old version.
2581 //Also check merge cache, so we don't have to re-merge every time..
999836aa
VZ
2582 wxGridCellAttr *attrcell = m_data->m_cellAttrs.GetAttr(row, col);
2583 wxGridCellAttr *attrrow = m_data->m_rowAttrs.GetAttr(row);
2584 wxGridCellAttr *attrcol = m_data->m_colAttrs.GetAttr(col);
19d7140e 2585
bf7945ce 2586 if((attrcell != attrrow) && (attrrow !=attrcol) && (attrcell != attrcol)){
19d7140e
VZ
2587 // Two or move are non NULL
2588 attr = new wxGridCellAttr;
2589 attr->SetKind(wxGridCellAttr::Merged);
2590
bf7945ce 2591 //Order important..
19d7140e
VZ
2592 if(attrcell){
2593 attr->MergeWith(attrcell);
2594 attrcell->DecRef();
2595 }
2596 if(attrcol){
2597 attr->MergeWith(attrcol);
2598 attrcol->DecRef();
2599 }
2600 if(attrrow){
2601 attr->MergeWith(attrrow);
2602 attrrow->DecRef();
2603 }
2604 //store merge attr if cache implemented
2605 //attr->IncRef();
2606 //m_data->m_mergeAttr.SetAttr(attr, row, col);
2607 }
2608 else
758cbedf 2609 {
19d7140e
VZ
2610 // one or none is non null return it or null.
2611 if(attrrow) attr = attrrow;
2612 if(attrcol) attr = attrcol;
bf7945ce 2613 if(attrcell) attr = attrcell;
19d7140e
VZ
2614 }
2615 }
2616 break;
2617 case (wxGridCellAttr::Cell):
2618 attr = m_data->m_cellAttrs.GetAttr(row, col);
2619 break;
2620 case (wxGridCellAttr::Col):
2621 attr = m_data->m_colAttrs.GetAttr(col);
2622 break;
2623 case (wxGridCellAttr::Row):
758cbedf 2624 attr = m_data->m_rowAttrs.GetAttr(row);
19d7140e
VZ
2625 break;
2626 default:
2627 // unused as yet...
2628 // (wxGridCellAttr::Default):
2629 // (wxGridCellAttr::Merged):
2630 break;
758cbedf
VZ
2631 }
2632 }
758cbedf 2633 return attr;
b99be8fb
VZ
2634}
2635
2e9a6788 2636void wxGridCellAttrProvider::SetAttr(wxGridCellAttr *attr,
b99be8fb
VZ
2637 int row, int col)
2638{
2639 if ( !m_data )
2640 InitData();
2641
758cbedf
VZ
2642 m_data->m_cellAttrs.SetAttr(attr, row, col);
2643}
2644
2645void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr *attr, int row)
2646{
2647 if ( !m_data )
2648 InitData();
2649
2650 m_data->m_rowAttrs.SetAttr(attr, row);
2651}
2652
2653void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr *attr, int col)
2654{
2655 if ( !m_data )
2656 InitData();
2657
2658 m_data->m_colAttrs.SetAttr(attr, col);
b99be8fb
VZ
2659}
2660
4d60017a
SN
2661void wxGridCellAttrProvider::UpdateAttrRows( size_t pos, int numRows )
2662{
2663 if ( m_data )
2664 {
2665 m_data->m_cellAttrs.UpdateAttrRows( pos, numRows );
2666
d1c0b4f9 2667 m_data->m_rowAttrs.UpdateAttrRowsOrCols( pos, numRows );
4d60017a
SN
2668 }
2669}
2670
2671void wxGridCellAttrProvider::UpdateAttrCols( size_t pos, int numCols )
2672{
2673 if ( m_data )
2674 {
2675 m_data->m_cellAttrs.UpdateAttrCols( pos, numCols );
2676
d1c0b4f9 2677 m_data->m_colAttrs.UpdateAttrRowsOrCols( pos, numCols );
4d60017a
SN
2678 }
2679}
2680
f2d76237
RD
2681// ----------------------------------------------------------------------------
2682// wxGridTypeRegistry
2683// ----------------------------------------------------------------------------
2684
2685wxGridTypeRegistry::~wxGridTypeRegistry()
2686{
b94ae1ea
VZ
2687 size_t count = m_typeinfo.Count();
2688 for ( size_t i = 0; i < count; i++ )
f2d76237
RD
2689 delete m_typeinfo[i];
2690}
2691
2692
2693void wxGridTypeRegistry::RegisterDataType(const wxString& typeName,
2694 wxGridCellRenderer* renderer,
2695 wxGridCellEditor* editor)
2696{
f2d76237
RD
2697 wxGridDataTypeInfo* info = new wxGridDataTypeInfo(typeName, renderer, editor);
2698
2699 // is it already registered?
c4608a8a 2700 int loc = FindRegisteredDataType(typeName);
39bcce60
VZ
2701 if ( loc != wxNOT_FOUND )
2702 {
f2d76237
RD
2703 delete m_typeinfo[loc];
2704 m_typeinfo[loc] = info;
2705 }
39bcce60
VZ
2706 else
2707 {
f2d76237
RD
2708 m_typeinfo.Add(info);
2709 }
2710}
2711
c4608a8a
VZ
2712int wxGridTypeRegistry::FindRegisteredDataType(const wxString& typeName)
2713{
2714 size_t count = m_typeinfo.GetCount();
2715 for ( size_t i = 0; i < count; i++ )
2716 {
2717 if ( typeName == m_typeinfo[i]->m_typeName )
2718 {
2719 return i;
2720 }
2721 }
2722
2723 return wxNOT_FOUND;
2724}
2725
f2d76237
RD
2726int wxGridTypeRegistry::FindDataType(const wxString& typeName)
2727{
c4608a8a
VZ
2728 int index = FindRegisteredDataType(typeName);
2729 if ( index == wxNOT_FOUND )
2730 {
2731 // check whether this is one of the standard ones, in which case
2732 // register it "on the fly"
3a8c693a 2733#if wxUSE_TEXTCTRL
c4608a8a
VZ
2734 if ( typeName == wxGRID_VALUE_STRING )
2735 {
2736 RegisterDataType(wxGRID_VALUE_STRING,
2737 new wxGridCellStringRenderer,
2738 new wxGridCellTextEditor);
3a8c693a
VZ
2739 } else
2740#endif // wxUSE_TEXTCTRL
2741#if wxUSE_CHECKBOX
2742 if ( typeName == wxGRID_VALUE_BOOL )
c4608a8a
VZ
2743 {
2744 RegisterDataType(wxGRID_VALUE_BOOL,
2745 new wxGridCellBoolRenderer,
2746 new wxGridCellBoolEditor);
3a8c693a
VZ
2747 } else
2748#endif // wxUSE_CHECKBOX
2749#if wxUSE_TEXTCTRL
2750 if ( typeName == wxGRID_VALUE_NUMBER )
c4608a8a
VZ
2751 {
2752 RegisterDataType(wxGRID_VALUE_NUMBER,
2753 new wxGridCellNumberRenderer,
2754 new wxGridCellNumberEditor);
2755 }
2756 else if ( typeName == wxGRID_VALUE_FLOAT )
2757 {
2758 RegisterDataType(wxGRID_VALUE_FLOAT,
2759 new wxGridCellFloatRenderer,
2760 new wxGridCellFloatEditor);
3a8c693a
VZ
2761 } else
2762#endif // wxUSE_TEXTCTRL
2763#if wxUSE_COMBOBOX
2764 if ( typeName == wxGRID_VALUE_CHOICE )
c4608a8a
VZ
2765 {
2766 RegisterDataType(wxGRID_VALUE_CHOICE,
2767 new wxGridCellStringRenderer,
2768 new wxGridCellChoiceEditor);
3a8c693a
VZ
2769 } else
2770#endif // wxUSE_COMBOBOX
c4608a8a
VZ
2771 {
2772 return wxNOT_FOUND;
2773 }
f2d76237 2774
c4608a8a
VZ
2775 // we get here only if just added the entry for this type, so return
2776 // the last index
2777 index = m_typeinfo.GetCount() - 1;
2778 }
2779
2780 return index;
2781}
2782
2783int wxGridTypeRegistry::FindOrCloneDataType(const wxString& typeName)
2784{
2785 int index = FindDataType(typeName);
2786 if ( index == wxNOT_FOUND )
2787 {
2788 // the first part of the typename is the "real" type, anything after ':'
2789 // are the parameters for the renderer
2790 index = FindDataType(typeName.BeforeFirst(_T(':')));
2791 if ( index == wxNOT_FOUND )
2792 {
2793 return wxNOT_FOUND;
f2d76237 2794 }
c4608a8a
VZ
2795
2796 wxGridCellRenderer *renderer = GetRenderer(index);
2797 wxGridCellRenderer *rendererOld = renderer;
2798 renderer = renderer->Clone();
2799 rendererOld->DecRef();
2800
2801 wxGridCellEditor *editor = GetEditor(index);
2802 wxGridCellEditor *editorOld = editor;
2803 editor = editor->Clone();
2804 editorOld->DecRef();
2805
2806 // do it even if there are no parameters to reset them to defaults
2807 wxString params = typeName.AfterFirst(_T(':'));
2808 renderer->SetParameters(params);
2809 editor->SetParameters(params);
2810
2811 // register the new typename
c4608a8a
VZ
2812 RegisterDataType(typeName, renderer, editor);
2813
2814 // we just registered it, it's the last one
2815 index = m_typeinfo.GetCount() - 1;
f2d76237
RD
2816 }
2817
c4608a8a 2818 return index;
f2d76237
RD
2819}
2820
2821wxGridCellRenderer* wxGridTypeRegistry::GetRenderer(int index)
2822{
2823 wxGridCellRenderer* renderer = m_typeinfo[index]->m_renderer;
faec5a43
SN
2824 if (renderer)
2825 renderer->IncRef();
f2d76237
RD
2826 return renderer;
2827}
2828
0b190b0f 2829wxGridCellEditor* wxGridTypeRegistry::GetEditor(int index)
f2d76237
RD
2830{
2831 wxGridCellEditor* editor = m_typeinfo[index]->m_editor;
faec5a43
SN
2832 if (editor)
2833 editor->IncRef();
f2d76237
RD
2834 return editor;
2835}
2836
758cbedf
VZ
2837// ----------------------------------------------------------------------------
2838// wxGridTableBase
2839// ----------------------------------------------------------------------------
2840
f85afd4e
MB
2841IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase, wxObject )
2842
2843
2844wxGridTableBase::wxGridTableBase()
f85afd4e
MB
2845{
2846 m_view = (wxGrid *) NULL;
b99be8fb 2847 m_attrProvider = (wxGridCellAttrProvider *) NULL;
f85afd4e
MB
2848}
2849
2850wxGridTableBase::~wxGridTableBase()
2851{
b99be8fb
VZ
2852 delete m_attrProvider;
2853}
2854
2855void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider *attrProvider)
2856{
2857 delete m_attrProvider;
2858 m_attrProvider = attrProvider;
f85afd4e
MB
2859}
2860
f2d76237
RD
2861bool wxGridTableBase::CanHaveAttributes()
2862{
2863 if ( ! GetAttrProvider() )
2864 {
2865 // use the default attr provider by default
2866 SetAttrProvider(new wxGridCellAttrProvider);
2867 }
2868 return TRUE;
2869}
2870
19d7140e 2871wxGridCellAttr *wxGridTableBase::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind)
b99be8fb
VZ
2872{
2873 if ( m_attrProvider )
19d7140e 2874 return m_attrProvider->GetAttr(row, col, kind);
b99be8fb
VZ
2875 else
2876 return (wxGridCellAttr *)NULL;
2877}
2878
758cbedf 2879void wxGridTableBase::SetAttr(wxGridCellAttr* attr, int row, int col)
b99be8fb
VZ
2880{
2881 if ( m_attrProvider )
2882 {
19d7140e 2883 attr->SetKind(wxGridCellAttr::Cell);
b99be8fb
VZ
2884 m_attrProvider->SetAttr(attr, row, col);
2885 }
2886 else
2887 {
2888 // as we take ownership of the pointer and don't store it, we must
2889 // free it now
39bcce60 2890 wxSafeDecRef(attr);
b99be8fb
VZ
2891 }
2892}
2893
758cbedf
VZ
2894void wxGridTableBase::SetRowAttr(wxGridCellAttr *attr, int row)
2895{
2896 if ( m_attrProvider )
2897 {
19d7140e 2898 attr->SetKind(wxGridCellAttr::Row);
758cbedf
VZ
2899 m_attrProvider->SetRowAttr(attr, row);
2900 }
2901 else
2902 {
2903 // as we take ownership of the pointer and don't store it, we must
2904 // free it now
39bcce60 2905 wxSafeDecRef(attr);
758cbedf
VZ
2906 }
2907}
2908
2909void wxGridTableBase::SetColAttr(wxGridCellAttr *attr, int col)
2910{
2911 if ( m_attrProvider )
2912 {
19d7140e 2913 attr->SetKind(wxGridCellAttr::Col);
758cbedf
VZ
2914 m_attrProvider->SetColAttr(attr, col);
2915 }
2916 else
2917 {
2918 // as we take ownership of the pointer and don't store it, we must
2919 // free it now
39bcce60 2920 wxSafeDecRef(attr);
758cbedf
VZ
2921 }
2922}
2923
aa5e1f75
SN
2924bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos),
2925 size_t WXUNUSED(numRows) )
f85afd4e 2926{
f6bcfd97 2927 wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") );
8f177c8e 2928
f85afd4e
MB
2929 return FALSE;
2930}
2931
aa5e1f75 2932bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows) )
f85afd4e 2933{
f6bcfd97 2934 wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function"));
8f177c8e 2935
f85afd4e
MB
2936 return FALSE;
2937}
2938
aa5e1f75
SN
2939bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos),
2940 size_t WXUNUSED(numRows) )
f85afd4e 2941{
f6bcfd97 2942 wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function"));
8f177c8e 2943
f85afd4e
MB
2944 return FALSE;
2945}
2946
aa5e1f75
SN
2947bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos),
2948 size_t WXUNUSED(numCols) )
f85afd4e 2949{
f6bcfd97 2950 wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function"));
8f177c8e 2951
f85afd4e
MB
2952 return FALSE;
2953}
2954
aa5e1f75 2955bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols) )
f85afd4e 2956{
f6bcfd97 2957 wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function"));
8f177c8e 2958
f85afd4e
MB
2959 return FALSE;
2960}
2961
aa5e1f75
SN
2962bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos),
2963 size_t WXUNUSED(numCols) )
f85afd4e 2964{
f6bcfd97 2965 wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function"));
8f177c8e 2966
f85afd4e
MB
2967 return FALSE;
2968}
2969
2970
2971wxString wxGridTableBase::GetRowLabelValue( int row )
2972{
2973 wxString s;
f2d76237
RD
2974 s << row + 1; // RD: Starting the rows at zero confuses users, no matter
2975 // how much it makes sense to us geeks.
f85afd4e
MB
2976 return s;
2977}
2978
2979wxString wxGridTableBase::GetColLabelValue( int col )
2980{
2981 // default col labels are:
2982 // cols 0 to 25 : A-Z
2983 // cols 26 to 675 : AA-ZZ
2984 // etc.
2985
2986 wxString s;
2987 unsigned int i, n;
2988 for ( n = 1; ; n++ )
2989 {
fef5c556 2990 s += (wxChar) (_T('A') + (wxChar)( col%26 ));
f85afd4e
MB
2991 col = col/26 - 1;
2992 if ( col < 0 ) break;
2993 }
2994
2995 // reverse the string...
2996 wxString s2;
2997 for ( i = 0; i < n; i++ )
2998 {
2999 s2 += s[n-i-1];
3000 }
3001
3002 return s2;
3003}
3004
3005
f2d76237
RD
3006wxString wxGridTableBase::GetTypeName( int WXUNUSED(row), int WXUNUSED(col) )
3007{
816be743 3008 return wxGRID_VALUE_STRING;
f2d76237
RD
3009}
3010
3011bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row), int WXUNUSED(col),
3012 const wxString& typeName )
3013{
816be743 3014 return typeName == wxGRID_VALUE_STRING;
f2d76237
RD
3015}
3016
3017bool wxGridTableBase::CanSetValueAs( int row, int col, const wxString& typeName )
3018{
3019 return CanGetValueAs(row, col, typeName);
3020}
3021
3022long wxGridTableBase::GetValueAsLong( int WXUNUSED(row), int WXUNUSED(col) )
3023{
3024 return 0;
3025}
3026
3027double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row), int WXUNUSED(col) )
3028{
3029 return 0.0;
3030}
3031
3032bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row), int WXUNUSED(col) )
3033{
3034 return FALSE;
3035}
3036
3037void wxGridTableBase::SetValueAsLong( int WXUNUSED(row), int WXUNUSED(col),
3038 long WXUNUSED(value) )
3039{
3040}
3041
3042void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row), int WXUNUSED(col),
3043 double WXUNUSED(value) )
3044{
3045}
3046
3047void wxGridTableBase::SetValueAsBool( int WXUNUSED(row), int WXUNUSED(col),
3048 bool WXUNUSED(value) )
3049{
3050}
3051
3052
3053void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row), int WXUNUSED(col),
3054 const wxString& WXUNUSED(typeName) )
3055{
3056 return NULL;
3057}
3058
3059void wxGridTableBase::SetValueAsCustom( int WXUNUSED(row), int WXUNUSED(col),
3060 const wxString& WXUNUSED(typeName),
3061 void* WXUNUSED(value) )
3062{
3063}
3064
f85afd4e
MB
3065//////////////////////////////////////////////////////////////////////
3066//
3067// Message class for the grid table to send requests and notifications
3068// to the grid view
3069//
3070
3071wxGridTableMessage::wxGridTableMessage()
3072{
3073 m_table = (wxGridTableBase *) NULL;
3074 m_id = -1;
3075 m_comInt1 = -1;
3076 m_comInt2 = -1;
3077}
3078
3079wxGridTableMessage::wxGridTableMessage( wxGridTableBase *table, int id,
3080 int commandInt1, int commandInt2 )
3081{
3082 m_table = table;
3083 m_id = id;
3084 m_comInt1 = commandInt1;
3085 m_comInt2 = commandInt2;
3086}
3087
3088
3089
3090//////////////////////////////////////////////////////////////////////
3091//
3092// A basic grid table for string data. An object of this class will
3093// created by wxGrid if you don't specify an alternative table class.
3094//
3095
223d09f6 3096WX_DEFINE_OBJARRAY(wxGridStringArray)
f85afd4e
MB
3097
3098IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable, wxGridTableBase )
3099
3100wxGridStringTable::wxGridStringTable()
3101 : wxGridTableBase()
3102{
3103}
3104
3105wxGridStringTable::wxGridStringTable( int numRows, int numCols )
3106 : wxGridTableBase()
3107{
f85afd4e
MB
3108 m_data.Alloc( numRows );
3109
3110 wxArrayString sa;
3111 sa.Alloc( numCols );
27f35b66 3112 sa.Add( wxEmptyString, numCols );
8f177c8e 3113
27f35b66 3114 m_data.Add( sa, numRows );
f85afd4e
MB
3115}
3116
3117wxGridStringTable::~wxGridStringTable()
3118{
3119}
3120
e32352cf 3121int wxGridStringTable::GetNumberRows()
f85afd4e
MB
3122{
3123 return m_data.GetCount();
3124}
3125
e32352cf 3126int wxGridStringTable::GetNumberCols()
f85afd4e
MB
3127{
3128 if ( m_data.GetCount() > 0 )
3129 return m_data[0].GetCount();
3130 else
3131 return 0;
3132}
3133
3134wxString wxGridStringTable::GetValue( int row, int col )
3135{
3e13956a
RD
3136 wxCHECK_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
3137 wxEmptyString,
3138 _T("invalid row or column index in wxGridStringTable") );
af547d51 3139
f85afd4e
MB
3140 return m_data[row][col];
3141}
3142
f2d76237 3143void wxGridStringTable::SetValue( int row, int col, const wxString& value )
f85afd4e 3144{
3e13956a
RD
3145 wxCHECK_RET( (row < GetNumberRows()) && (col < GetNumberCols()),
3146 _T("invalid row or column index in wxGridStringTable") );
af547d51 3147
f2d76237 3148 m_data[row][col] = value;
f85afd4e
MB
3149}
3150
3151bool wxGridStringTable::IsEmptyCell( int row, int col )
3152{
3e13956a
RD
3153 wxCHECK_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
3154 true,
af547d51
VZ
3155 _T("invalid row or column index in wxGridStringTable") );
3156
f85afd4e
MB
3157 return (m_data[row][col] == wxEmptyString);
3158}
3159
f85afd4e
MB
3160void wxGridStringTable::Clear()
3161{
3162 int row, col;
3163 int numRows, numCols;
8f177c8e 3164
f85afd4e
MB
3165 numRows = m_data.GetCount();
3166 if ( numRows > 0 )
3167 {
3168 numCols = m_data[0].GetCount();
3169
3170 for ( row = 0; row < numRows; row++ )
3171 {
3172 for ( col = 0; col < numCols; col++ )
3173 {
3174 m_data[row][col] = wxEmptyString;
3175 }
3176 }
3177 }
3178}
3179
3180
3181bool wxGridStringTable::InsertRows( size_t pos, size_t numRows )
3182{
f85afd4e 3183 size_t curNumRows = m_data.GetCount();
f6bcfd97
BP
3184 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
3185 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
8f177c8e 3186
f85afd4e
MB
3187 if ( pos >= curNumRows )
3188 {
3189 return AppendRows( numRows );
3190 }
8f177c8e 3191
f85afd4e
MB
3192 wxArrayString sa;
3193 sa.Alloc( curNumCols );
27f35b66
SN
3194 sa.Add( wxEmptyString, curNumCols );
3195 m_data.Insert( sa, pos, numRows );
f85afd4e
MB
3196 if ( GetView() )
3197 {
3198 wxGridTableMessage msg( this,
3199 wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
3200 pos,
3201 numRows );
8f177c8e 3202
f85afd4e
MB
3203 GetView()->ProcessTableMessage( msg );
3204 }
3205
3206 return TRUE;
3207}
3208
3209bool wxGridStringTable::AppendRows( size_t numRows )
3210{
f85afd4e 3211 size_t curNumRows = m_data.GetCount();
f6bcfd97
BP
3212 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
3213 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
8f177c8e 3214
f85afd4e
MB
3215 wxArrayString sa;
3216 if ( curNumCols > 0 )
3217 {
3218 sa.Alloc( curNumCols );
27f35b66 3219 sa.Add( wxEmptyString, curNumCols );
f85afd4e 3220 }
8f177c8e 3221
27f35b66 3222 m_data.Add( sa, numRows );
f85afd4e
MB
3223
3224 if ( GetView() )
3225 {
3226 wxGridTableMessage msg( this,
3227 wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
3228 numRows );
8f177c8e 3229
f85afd4e
MB
3230 GetView()->ProcessTableMessage( msg );
3231 }
3232
8f177c8e 3233 return TRUE;
f85afd4e
MB
3234}
3235
3236bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows )
3237{
f85afd4e 3238 size_t curNumRows = m_data.GetCount();
8f177c8e 3239
f85afd4e
MB
3240 if ( pos >= curNumRows )
3241 {
e91d2033
VZ
3242 wxFAIL_MSG( wxString::Format
3243 (
3244 wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"),
3245 (unsigned long)pos,
3246 (unsigned long)numRows,
3247 (unsigned long)curNumRows
3248 ) );
3249
f85afd4e
MB
3250 return FALSE;
3251 }
3252
3253 if ( numRows > curNumRows - pos )
3254 {
3255 numRows = curNumRows - pos;
3256 }
8f177c8e 3257
f85afd4e
MB
3258 if ( numRows >= curNumRows )
3259 {
d57ad377 3260 m_data.Clear();
f85afd4e
MB
3261 }
3262 else
3263 {
27f35b66 3264 m_data.RemoveAt( pos, numRows );
f85afd4e 3265 }
f85afd4e
MB
3266 if ( GetView() )
3267 {
3268 wxGridTableMessage msg( this,
3269 wxGRIDTABLE_NOTIFY_ROWS_DELETED,
3270 pos,
3271 numRows );
8f177c8e 3272
f85afd4e
MB
3273 GetView()->ProcessTableMessage( msg );
3274 }
3275
8f177c8e 3276 return TRUE;
f85afd4e
MB
3277}
3278
3279bool wxGridStringTable::InsertCols( size_t pos, size_t numCols )
3280{
3281 size_t row, col;
3282
3283 size_t curNumRows = m_data.GetCount();
f6bcfd97
BP
3284 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
3285 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
8f177c8e 3286
f85afd4e
MB
3287 if ( pos >= curNumCols )
3288 {
3289 return AppendCols( numCols );
3290 }
3291
3292 for ( row = 0; row < curNumRows; row++ )
3293 {
3294 for ( col = pos; col < pos + numCols; col++ )
3295 {
3296 m_data[row].Insert( wxEmptyString, col );
3297 }
3298 }
f85afd4e
MB
3299 if ( GetView() )
3300 {
3301 wxGridTableMessage msg( this,
3302 wxGRIDTABLE_NOTIFY_COLS_INSERTED,
3303 pos,
3304 numCols );
8f177c8e 3305
f85afd4e
MB
3306 GetView()->ProcessTableMessage( msg );
3307 }
3308
3309 return TRUE;
3310}
3311
3312bool wxGridStringTable::AppendCols( size_t numCols )
3313{
27f35b66 3314 size_t row;
f85afd4e
MB
3315
3316 size_t curNumRows = m_data.GetCount();
f6bcfd97 3317#if 0
f85afd4e
MB
3318 if ( !curNumRows )
3319 {
3320 // TODO: something better than this ?
3321 //
f6bcfd97 3322 wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") );
f85afd4e
MB
3323 return FALSE;
3324 }
f6bcfd97 3325#endif
8f177c8e 3326
f85afd4e
MB
3327 for ( row = 0; row < curNumRows; row++ )
3328 {
27f35b66 3329 m_data[row].Add( wxEmptyString, numCols );
f85afd4e
MB
3330 }
3331
3332 if ( GetView() )
3333 {
3334 wxGridTableMessage msg( this,
3335 wxGRIDTABLE_NOTIFY_COLS_APPENDED,
3336 numCols );
8f177c8e 3337
f85afd4e
MB
3338 GetView()->ProcessTableMessage( msg );
3339 }
3340
3341 return TRUE;
3342}
3343
3344bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
3345{
27f35b66 3346 size_t row;
f85afd4e
MB
3347
3348 size_t curNumRows = m_data.GetCount();
f6bcfd97
BP
3349 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
3350 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
8f177c8e 3351
f85afd4e
MB
3352 if ( pos >= curNumCols )
3353 {
e91d2033
VZ
3354 wxFAIL_MSG( wxString::Format
3355 (
3356 wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"),
3357 (unsigned long)pos,
3358 (unsigned long)numCols,
3359 (unsigned long)curNumCols
3360 ) );
8f177c8e 3361 return FALSE;
f85afd4e
MB
3362 }
3363
3364 if ( numCols > curNumCols - pos )
3365 {
8f177c8e 3366 numCols = curNumCols - pos;
f85afd4e
MB
3367 }
3368
3369 for ( row = 0; row < curNumRows; row++ )
3370 {
3371 if ( numCols >= curNumCols )
3372 {
dcdce64e 3373 m_data[row].Clear();
f85afd4e
MB
3374 }
3375 else
3376 {
27f35b66 3377 m_data[row].RemoveAt( pos, numCols );
f85afd4e
MB
3378 }
3379 }
f85afd4e
MB
3380 if ( GetView() )
3381 {
3382 wxGridTableMessage msg( this,
3383 wxGRIDTABLE_NOTIFY_COLS_DELETED,
3384 pos,
3385 numCols );
8f177c8e 3386
f85afd4e
MB
3387 GetView()->ProcessTableMessage( msg );
3388 }
3389
8f177c8e 3390 return TRUE;
f85afd4e
MB
3391}
3392
3393wxString wxGridStringTable::GetRowLabelValue( int row )
3394{
3395 if ( row > (int)(m_rowLabels.GetCount()) - 1 )
3396 {
3397 // using default label
3398 //
3399 return wxGridTableBase::GetRowLabelValue( row );
3400 }
3401 else
3402 {
3403 return m_rowLabels[ row ];
3404 }
3405}
3406
3407wxString wxGridStringTable::GetColLabelValue( int col )
3408{
3409 if ( col > (int)(m_colLabels.GetCount()) - 1 )
3410 {
3411 // using default label
3412 //
3413 return wxGridTableBase::GetColLabelValue( col );
3414 }
3415 else
3416 {
3417 return m_colLabels[ col ];
3418 }
3419}
3420
3421void wxGridStringTable::SetRowLabelValue( int row, const wxString& value )
3422{
3423 if ( row > (int)(m_rowLabels.GetCount()) - 1 )
3424 {
3425 int n = m_rowLabels.GetCount();
3426 int i;
3427 for ( i = n; i <= row; i++ )
3428 {
3429 m_rowLabels.Add( wxGridTableBase::GetRowLabelValue(i) );
3430 }
3431 }
3432
3433 m_rowLabels[row] = value;
3434}
3435
3436void wxGridStringTable::SetColLabelValue( int col, const wxString& value )
3437{
3438 if ( col > (int)(m_colLabels.GetCount()) - 1 )
3439 {
3440 int n = m_colLabels.GetCount();
3441 int i;
3442 for ( i = n; i <= col; i++ )
3443 {
3444 m_colLabels.Add( wxGridTableBase::GetColLabelValue(i) );
3445 }
3446 }
3447
3448 m_colLabels[col] = value;
3449}
3450
3451
3452
f85afd4e 3453//////////////////////////////////////////////////////////////////////
2d66e025
MB
3454//////////////////////////////////////////////////////////////////////
3455
3456IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow, wxWindow )
3457
3458BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxWindow )
3459 EVT_PAINT( wxGridRowLabelWindow::OnPaint )
b51c3f27 3460 EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel)
2d66e025
MB
3461 EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent )
3462 EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown )
f6bcfd97 3463 EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp )
2d66e025
MB
3464END_EVENT_TABLE()
3465
60ff3b99
VZ
3466wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid *parent,
3467 wxWindowID id,
2d66e025 3468 const wxPoint &pos, const wxSize &size )
0bbeb42d 3469 : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE )
2d66e025
MB
3470{
3471 m_owner = parent;
3472}
3473
aa5e1f75 3474void wxGridRowLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
2d66e025
MB
3475{
3476 wxPaintDC dc(this);
3477
3478 // NO - don't do this because it will set both the x and y origin
3479 // coords to match the parent scrolled window and we just want to
3480 // set the y coord - MB
3481 //
3482 // m_owner->PrepareDC( dc );
60ff3b99 3483
790ad94f 3484 int x, y;
2d66e025
MB
3485 m_owner->CalcUnscrolledPosition( 0, 0, &x, &y );
3486 dc.SetDeviceOrigin( 0, -y );
60ff3b99 3487
d10f4bf9
VZ
3488 wxArrayInt rows = m_owner->CalcRowLabelsExposed( GetUpdateRegion() );
3489 m_owner->DrawRowLabels( dc , rows );
2d66e025
MB
3490}
3491
3492
3493void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent& event )
3494{
3495 m_owner->ProcessRowLabelMouseEvent( event );
3496}
3497
3498
b51c3f27
RD
3499void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent& event )
3500{
3501 m_owner->GetEventHandler()->ProcessEvent(event);
3502}
3503
3504
2d66e025
MB
3505// This seems to be required for wxMotif otherwise the mouse
3506// cursor must be in the cell edit control to get key events
3507//
3508void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent& event )
3509{
ffdd3c98 3510 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
2d66e025
MB
3511}
3512
f6bcfd97
BP
3513void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent& event )
3514{
ffdd3c98 3515 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
f6bcfd97
BP
3516}
3517
2d66e025
MB
3518
3519
3520//////////////////////////////////////////////////////////////////////
3521
3522IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow, wxWindow )
3523
3524BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxWindow )
3525 EVT_PAINT( wxGridColLabelWindow::OnPaint )
b51c3f27 3526 EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel)
2d66e025
MB
3527 EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent )
3528 EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown )
f6bcfd97 3529 EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp )
2d66e025
MB
3530END_EVENT_TABLE()
3531
60ff3b99
VZ
3532wxGridColLabelWindow::wxGridColLabelWindow( wxGrid *parent,
3533 wxWindowID id,
2d66e025 3534 const wxPoint &pos, const wxSize &size )
0bbeb42d 3535 : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE )
2d66e025
MB
3536{
3537 m_owner = parent;
3538}
3539
aa5e1f75 3540void wxGridColLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
2d66e025
MB
3541{
3542 wxPaintDC dc(this);
3543
3544 // NO - don't do this because it will set both the x and y origin
3545 // coords to match the parent scrolled window and we just want to
3546 // set the x coord - MB
3547 //
3548 // m_owner->PrepareDC( dc );
60ff3b99 3549
790ad94f 3550 int x, y;
2d66e025
MB
3551 m_owner->CalcUnscrolledPosition( 0, 0, &x, &y );
3552 dc.SetDeviceOrigin( -x, 0 );
3553
d10f4bf9
VZ
3554 wxArrayInt cols = m_owner->CalcColLabelsExposed( GetUpdateRegion() );
3555 m_owner->DrawColLabels( dc , cols );
2d66e025
MB
3556}
3557
3558
3559void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent& event )
3560{
3561 m_owner->ProcessColLabelMouseEvent( event );
3562}
3563
b51c3f27
RD
3564void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent& event )
3565{
3566 m_owner->GetEventHandler()->ProcessEvent(event);
3567}
3568
2d66e025
MB
3569
3570// This seems to be required for wxMotif otherwise the mouse
3571// cursor must be in the cell edit control to get key events
3572//
3573void wxGridColLabelWindow::OnKeyDown( wxKeyEvent& event )
3574{
ffdd3c98 3575 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
2d66e025
MB
3576}
3577
f6bcfd97
BP
3578void wxGridColLabelWindow::OnKeyUp( wxKeyEvent& event )
3579{
ffdd3c98 3580 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
f6bcfd97
BP
3581}
3582
2d66e025
MB
3583
3584
3585//////////////////////////////////////////////////////////////////////
3586
3587IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow, wxWindow )
3588
3589BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxWindow )
b51c3f27 3590 EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel)
2d66e025 3591 EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent )
d2fdd8d2 3592 EVT_PAINT( wxGridCornerLabelWindow::OnPaint)
2d66e025 3593 EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown )
f6bcfd97 3594 EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp )
2d66e025
MB
3595END_EVENT_TABLE()
3596
60ff3b99
VZ
3597wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent,
3598 wxWindowID id,
2d66e025 3599 const wxPoint &pos, const wxSize &size )
0bbeb42d 3600 : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE )
2d66e025
MB
3601{
3602 m_owner = parent;
3603}
3604
d2fdd8d2
RR
3605void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
3606{
3607 wxPaintDC dc(this);
b99be8fb 3608
d2fdd8d2
RR
3609 int client_height = 0;
3610 int client_width = 0;
3611 GetClientSize( &client_width, &client_height );
b99be8fb 3612
73145b0e 3613 dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) );
d2fdd8d2
RR
3614 dc.DrawLine( client_width-1, client_height-1, client_width-1, 0 );
3615 dc.DrawLine( client_width-1, client_height-1, 0, client_height-1 );
d2fdd8d2
RR
3616 dc.DrawLine( 0, 0, client_width, 0 );
3617 dc.DrawLine( 0, 0, 0, client_height );
73145b0e
JS
3618
3619 dc.SetPen( *wxWHITE_PEN );
3620 dc.DrawLine( 1, 1, client_width-1, 1 );
3621 dc.DrawLine( 1, 1, 1, client_height-1 );
d2fdd8d2
RR
3622}
3623
2d66e025
MB
3624
3625void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent& event )
3626{
3627 m_owner->ProcessCornerLabelMouseEvent( event );
3628}
3629
3630
b51c3f27
RD
3631void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent& event )
3632{
3633 m_owner->GetEventHandler()->ProcessEvent(event);
3634}
3635
2d66e025
MB
3636// This seems to be required for wxMotif otherwise the mouse
3637// cursor must be in the cell edit control to get key events
3638//
3639void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent& event )
3640{
ffdd3c98 3641 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
2d66e025
MB
3642}
3643
f6bcfd97
BP
3644void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent& event )
3645{
ffdd3c98 3646 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
f6bcfd97
BP
3647}
3648
2d66e025
MB
3649
3650
f85afd4e
MB
3651//////////////////////////////////////////////////////////////////////
3652
59ddac01 3653IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxWindow )
2d66e025 3654
59ddac01 3655BEGIN_EVENT_TABLE( wxGridWindow, wxWindow )
2d66e025 3656 EVT_PAINT( wxGridWindow::OnPaint )
b51c3f27 3657 EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel)
2d66e025
MB
3658 EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent )
3659 EVT_KEY_DOWN( wxGridWindow::OnKeyDown )
f6bcfd97 3660 EVT_KEY_UP( wxGridWindow::OnKeyUp )
80acaf25
JS
3661 EVT_SET_FOCUS( wxGridWindow::OnFocus )
3662 EVT_KILL_FOCUS( wxGridWindow::OnFocus )
2796cce3 3663 EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground )
2d66e025
MB
3664END_EVENT_TABLE()
3665
60ff3b99
VZ
3666wxGridWindow::wxGridWindow( wxGrid *parent,
3667 wxGridRowLabelWindow *rowLblWin,
2d66e025 3668 wxGridColLabelWindow *colLblWin,
04418332
VZ
3669 wxWindowID id,
3670 const wxPoint &pos,
3671 const wxSize &size )
0bbeb42d 3672 : wxWindow( parent, id, pos, size, wxWANTS_CHARS | wxBORDER_NONE | wxCLIP_CHILDREN,
04418332 3673 wxT("grid window") )
73145b0e 3674
2d66e025
MB
3675{
3676 m_owner = parent;
3677 m_rowLabelWin = rowLblWin;
3678 m_colLabelWin = colLblWin;
edb89f7e 3679 SetBackgroundColour(_T("WHITE"));
2d66e025
MB
3680}
3681
3682
3683wxGridWindow::~wxGridWindow()
3684{
3685}
3686
3687
3688void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
3689{
3690 wxPaintDC dc( this );
3691 m_owner->PrepareDC( dc );
796df70a 3692 wxRegion reg = GetUpdateRegion();
d10f4bf9
VZ
3693 wxGridCellCoordsArray DirtyCells = m_owner->CalcCellsExposed( reg );
3694 m_owner->DrawGridCellArea( dc , DirtyCells);
9496deb5 3695#if WXGRID_DRAW_LINES
796df70a
SN
3696 m_owner->DrawAllGridLines( dc, reg );
3697#endif
a5777624 3698 m_owner->DrawGridSpace( dc );
d10f4bf9 3699 m_owner->DrawHighlight( dc , DirtyCells );
2d66e025
MB
3700}
3701
3702
3703void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect )
3704{
59ddac01 3705 wxWindow::ScrollWindow( dx, dy, rect );
2d66e025
MB
3706 m_rowLabelWin->ScrollWindow( 0, dy, rect );
3707 m_colLabelWin->ScrollWindow( dx, 0, rect );
3708}
3709
3710
3711void wxGridWindow::OnMouseEvent( wxMouseEvent& event )
3712{
3713 m_owner->ProcessGridCellMouseEvent( event );
3714}
3715
b51c3f27
RD
3716void wxGridWindow::OnMouseWheel( wxMouseEvent& event )
3717{
3718 m_owner->GetEventHandler()->ProcessEvent(event);
3719}
2d66e025 3720
f6bcfd97 3721// This seems to be required for wxMotif/wxGTK otherwise the mouse
2d66e025
MB
3722// cursor must be in the cell edit control to get key events
3723//
3724void wxGridWindow::OnKeyDown( wxKeyEvent& event )
3725{
ffdd3c98 3726 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
2d66e025 3727}
f85afd4e 3728
f6bcfd97
BP
3729void wxGridWindow::OnKeyUp( wxKeyEvent& event )
3730{
ffdd3c98 3731 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
f6bcfd97 3732}
7c8a8ad5 3733
aa5e1f75 3734void wxGridWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(event) )
8dd4f536 3735{
8dd4f536 3736}
025562fe 3737
80acaf25
JS
3738void wxGridWindow::OnFocus(wxFocusEvent& event)
3739{
3740 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) )
3741 event.Skip();
3742}
2d66e025
MB
3743
3744//////////////////////////////////////////////////////////////////////
3745
33188aa4
SN
3746// Internal Helper function for computing row or column from some
3747// (unscrolled) coordinate value, using either
70e8d961 3748// m_defaultRowHeight/m_defaultColWidth or binary search on array
33188aa4
SN
3749// of m_rowBottoms/m_ColRights to speed up the search!
3750
3751// Internal helper macros for simpler use of that function
3752
3753static int CoordToRowOrCol(int coord, int defaultDist, int minDist,
64e15340 3754 const wxArrayInt& BorderArray, int nMax,
a967f048 3755 bool clipToMinMax);
33188aa4
SN
3756
3757#define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \
b8d24d4e 3758 m_minAcceptableColWidth, \
64e15340 3759 m_colRights, m_numCols, TRUE)
33188aa4 3760#define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \
b8d24d4e 3761 m_minAcceptableRowHeight, \
64e15340 3762 m_rowBottoms, m_numRows, TRUE)
33188aa4 3763/////////////////////////////////////////////////////////////////////
07296f0b 3764
b0a877ec 3765#if wxUSE_EXTENDED_RTTI
73c36334
JS
3766WX_DEFINE_FLAGS( wxGridStyle )
3767
3ff066a4 3768wxBEGIN_FLAGS( wxGridStyle )
73c36334
JS
3769 // new style border flags, we put them first to
3770 // use them for streaming out
3ff066a4
SC
3771 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
3772 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
3773 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
3774 wxFLAGS_MEMBER(wxBORDER_RAISED)
3775 wxFLAGS_MEMBER(wxBORDER_STATIC)
3776 wxFLAGS_MEMBER(wxBORDER_NONE)
73c36334
JS
3777
3778 // old style border flags
3ff066a4
SC
3779 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
3780 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
3781 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
3782 wxFLAGS_MEMBER(wxRAISED_BORDER)
3783 wxFLAGS_MEMBER(wxSTATIC_BORDER)
cb0afb26 3784 wxFLAGS_MEMBER(wxBORDER)
73c36334
JS
3785
3786 // standard window styles
3ff066a4
SC
3787 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
3788 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
3789 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
3790 wxFLAGS_MEMBER(wxWANTS_CHARS)
cb0afb26 3791 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
3ff066a4
SC
3792 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
3793 wxFLAGS_MEMBER(wxVSCROLL)
3794 wxFLAGS_MEMBER(wxHSCROLL)
73c36334 3795
3ff066a4 3796wxEND_FLAGS( wxGridStyle )
73c36334 3797
b0a877ec
SC
3798IMPLEMENT_DYNAMIC_CLASS_XTI(wxGrid, wxScrolledWindow,"wx/grid.h")
3799
3ff066a4
SC
3800wxBEGIN_PROPERTIES_TABLE(wxGrid)
3801 wxHIDE_PROPERTY( Children )
3802 wxPROPERTY_FLAGS( WindowStyle , wxGridStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
3803wxEND_PROPERTIES_TABLE()
b0a877ec 3804
3ff066a4
SC
3805wxBEGIN_HANDLERS_TABLE(wxGrid)
3806wxEND_HANDLERS_TABLE()
b0a877ec 3807
3ff066a4 3808wxCONSTRUCTOR_5( wxGrid , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
b0a877ec
SC
3809
3810/*
3811