]> git.saurik.com Git - wxWidgets.git/blame - src/generic/grid.cpp
use CmdDown() instead of #ifdefs for Mac
[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 9251.
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)
65571936 9// Licence: wxWindows licence
f85afd4e
MB
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 {
ca65c044 478 m_control->PopEventHandler(true /* delete it*/);
b94ae1ea 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
ca65c044 663 bool changed = false;
b54ba671 664 wxString value = Text()->GetValue();
2796cce3 665 if (value != m_startValue)
ca65c044 666 changed = true;
2796cce3
RD
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:
ca65c044 720 return true;
f6bcfd97
BP
721
722 default:
723 // accept 8 bit chars too if isprint() agrees
1c193821 724 if ( (keycode < 255) && (wxIsprint(keycode)) )
ca65c044 725 return true;
f6bcfd97
BP
726 }
727 }
728
ca65c044 729 return false;
f6bcfd97
BP
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
ca65c044 801 m_control = new wxSpinCtrl(parent, wxID_ANY, wxEmptyString,
816be743
VZ
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:
ca65c044 915 return true;
f6bcfd97
BP
916
917 default:
4676948b 918 if ( (keycode < 128) && wxIsdigit(keycode) )
ca65c044 919 return true;
f6bcfd97
BP
920 }
921 }
922
ca65c044 923 return false;
f6bcfd97
BP
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 1057
ca65c044 1058 return true;
816be743 1059 }
ca65c044 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();
3fe73755
SN
1071 char tmpbuf[2];
1072 tmpbuf[0] = (char) keycode;
1073 tmpbuf[1] = '\0';
ca65c044 1074 bool is_decimal_point = ( wxString(tmpbuf, *wxConvCurrent) ==
3fe73755 1075 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) );
60d876f3 1076 if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-'
3fe73755 1077 || is_decimal_point
85d8c319
JS
1078 || keycode == WXK_NUMPAD0
1079 || keycode == WXK_NUMPAD1
1080 || keycode == WXK_NUMPAD2
1081 || keycode == WXK_NUMPAD3
1082 || keycode == WXK_NUMPAD4
1083 || keycode == WXK_NUMPAD5
1084 || keycode == WXK_NUMPAD6
1085 || keycode == WXK_NUMPAD7
1086 || keycode == WXK_NUMPAD8
1087 || keycode == WXK_NUMPAD9
1088 || keycode == WXK_ADD
1089 || keycode == WXK_NUMPAD_ADD
1090 || keycode == WXK_SUBTRACT
1091 || keycode == WXK_NUMPAD_SUBTRACT)
816be743
VZ
1092 {
1093 wxGridCellTextEditor::StartingKey(event);
1094
1095 // skip Skip() below
1096 return;
1097 }
1098
1099 event.Skip();
1100}
1101
f6bcfd97
BP
1102void wxGridCellFloatEditor::SetParameters(const wxString& params)
1103{
1104 if ( !params )
1105 {
1106 // reset to default
1107 m_width =
1108 m_precision = -1;
1109 }
1110 else
1111 {
1112 long tmp;
1113 if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )
1114 {
1115 m_width = (int)tmp;
1116
1117 if ( params.AfterFirst(_T(',')).ToLong(&tmp) )
1118 {
1119 m_precision = (int)tmp;
1120
1121 // skip the error message below
1122 return;
1123 }
1124 }
1125
1126 wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params.c_str());
1127 }
1128}
1129
1130wxString wxGridCellFloatEditor::GetString() const
1131{
1132 wxString fmt;
1133 if ( m_width == -1 )
1134 {
1135 // default width/precision
ec53826c 1136 fmt = _T("%f");
f6bcfd97
BP
1137 }
1138 else if ( m_precision == -1 )
1139 {
1140 // default precision
ec53826c 1141 fmt.Printf(_T("%%%d.f"), m_width);
f6bcfd97
BP
1142 }
1143 else
1144 {
ec53826c 1145 fmt.Printf(_T("%%%d.%df"), m_width, m_precision);
f6bcfd97
BP
1146 }
1147
1148 return wxString::Format(fmt, m_valueOld);
1149}
1150
1151bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)
1152{
1153 if ( wxGridCellEditor::IsAcceptedKey(event) )
1154 {
1155 int keycode = event.GetKeyCode();
1156 switch ( keycode )
1157 {
1158 case WXK_NUMPAD0:
1159 case WXK_NUMPAD1:
1160 case WXK_NUMPAD2:
1161 case WXK_NUMPAD3:
1162 case WXK_NUMPAD4:
1163 case WXK_NUMPAD5:
1164 case WXK_NUMPAD6:
1165 case WXK_NUMPAD7:
1166 case WXK_NUMPAD8:
1167 case WXK_NUMPAD9:
1168 case WXK_ADD:
1169 case WXK_NUMPAD_ADD:
1170 case WXK_SUBTRACT:
1171 case WXK_NUMPAD_SUBTRACT:
1172 case WXK_DECIMAL:
1173 case WXK_NUMPAD_DECIMAL:
ca65c044 1174 return true;
f6bcfd97 1175
ca65c044 1176 default:
3fe73755
SN
1177 {
1178 // additionally accept 'e' as in '1e+6', also '-', '+', and '.'
1179 char tmpbuf[2];
1180 tmpbuf[0] = (char) keycode;
1181 tmpbuf[1] = '\0';
1182 bool is_decimal_point =
ca65c044 1183 ( wxString(tmpbuf, *wxConvCurrent) ==
3fe73755
SN
1184 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT,
1185 wxLOCALE_CAT_NUMBER) );
f6bcfd97 1186 if ( (keycode < 128) &&
60d876f3 1187 (wxIsdigit(keycode) || tolower(keycode) == 'e' ||
3fe73755 1188 is_decimal_point || keycode == '+' || keycode == '-') )
ca65c044 1189 return true;
3fe73755 1190 }
f6bcfd97
BP
1191 }
1192 }
1193
ca65c044 1194 return false;
f6bcfd97
BP
1195}
1196
3a8c693a
VZ
1197#endif // wxUSE_TEXTCTRL
1198
1199#if wxUSE_CHECKBOX
1200
508011ce
VZ
1201// ----------------------------------------------------------------------------
1202// wxGridCellBoolEditor
1203// ----------------------------------------------------------------------------
1204
1205void wxGridCellBoolEditor::Create(wxWindow* parent,
1206 wxWindowID id,
1207 wxEvtHandler* evtHandler)
1208{
1209 m_control = new wxCheckBox(parent, id, wxEmptyString,
1210 wxDefaultPosition, wxDefaultSize,
1211 wxNO_BORDER);
1212
1213 wxGridCellEditor::Create(parent, id, evtHandler);
1214}
1215
1216void wxGridCellBoolEditor::SetSize(const wxRect& r)
1217{
ca65c044 1218 bool resize = false;
b94ae1ea
VZ
1219 wxSize size = m_control->GetSize();
1220 wxCoord minSize = wxMin(r.width, r.height);
1221
1222 // check if the checkbox is not too big/small for this cell
1223 wxSize sizeBest = m_control->GetBestSize();
1224 if ( !(size == sizeBest) )
1225 {
1226 // reset to default size if it had been made smaller
1227 size = sizeBest;
1228
ca65c044 1229 resize = true;
b94ae1ea
VZ
1230 }
1231
1232 if ( size.x >= minSize || size.y >= minSize )
1233 {
1234 // leave 1 pixel margin
1235 size.x = size.y = minSize - 2;
1236
ca65c044 1237 resize = true;
b94ae1ea
VZ
1238 }
1239
1240 if ( resize )
1241 {
1242 m_control->SetSize(size);
1243 }
1244
508011ce 1245 // position it in the centre of the rectangle (TODO: support alignment?)
508011ce 1246
b94ae1ea 1247#if defined(__WXGTK__) || defined (__WXMOTIF__)
508011ce
VZ
1248 // the checkbox without label still has some space to the right in wxGTK,
1249 // so shift it to the right
b94ae1ea
VZ
1250 size.x -= 8;
1251#elif defined(__WXMSW__)
a95e38c0
VZ
1252 // here too, but in other way
1253 size.x += 1;
b94ae1ea
VZ
1254 size.y -= 2;
1255#endif
508011ce 1256
1bd71df9
JS
1257 int hAlign = wxALIGN_CENTRE;
1258 int vAlign = wxALIGN_CENTRE;
1259 if (GetCellAttr())
1260 GetCellAttr()->GetAlignment(& hAlign, & vAlign);
52d6f640 1261
1bd71df9
JS
1262 int x = 0, y = 0;
1263 if (hAlign == wxALIGN_LEFT)
1264 {
1265 x = r.x + 2;
1266#ifdef __WXMSW__
1267 x += 2;
52d6f640 1268#endif
1bd71df9
JS
1269 y = r.y + r.height/2 - size.y/2;
1270 }
1271 else if (hAlign == wxALIGN_RIGHT)
1272 {
1273 x = r.x + r.width - size.x - 2;
1274 y = r.y + r.height/2 - size.y/2;
1275 }
1276 else if (hAlign == wxALIGN_CENTRE)
1277 {
1278 x = r.x + r.width/2 - size.x/2;
1279 y = r.y + r.height/2 - size.y/2;
1280 }
52d6f640 1281
1bd71df9 1282 m_control->Move(x, y);
508011ce
VZ
1283}
1284
1285void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)
1286{
99306db2
VZ
1287 m_control->Show(show);
1288
189d0213 1289 if ( show )
508011ce 1290 {
189d0213
VZ
1291 wxColour colBg = attr ? attr->GetBackgroundColour() : *wxLIGHT_GREY;
1292 CBox()->SetBackgroundColour(colBg);
508011ce 1293 }
508011ce
VZ
1294}
1295
1296void wxGridCellBoolEditor::BeginEdit(int row, int col, wxGrid* grid)
1297{
1298 wxASSERT_MSG(m_control,
1299 wxT("The wxGridCellEditor must be Created first!"));
1300
28a77bc4 1301 if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL))
f2d76237
RD
1302 m_startValue = grid->GetTable()->GetValueAsBool(row, col);
1303 else
695a3263
MB
1304 {
1305 wxString cellval( grid->GetTable()->GetValue(row, col) );
8dd8f875 1306 m_startValue = !( !cellval || (cellval == wxT("0")) );
695a3263 1307 }
508011ce
VZ
1308 CBox()->SetValue(m_startValue);
1309 CBox()->SetFocus();
1310}
1311
1312bool wxGridCellBoolEditor::EndEdit(int row, int col,
508011ce
VZ
1313 wxGrid* grid)
1314{
1315 wxASSERT_MSG(m_control,
1316 wxT("The wxGridCellEditor must be Created first!"));
1317
ca65c044 1318 bool changed = false;
508011ce
VZ
1319 bool value = CBox()->GetValue();
1320 if ( value != m_startValue )
ca65c044 1321 changed = true;
508011ce
VZ
1322
1323 if ( changed )
1324 {
28a77bc4 1325 if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL))
f2d76237
RD
1326 grid->GetTable()->SetValueAsBool(row, col, value);
1327 else
1328 grid->GetTable()->SetValue(row, col, value ? _T("1") : wxEmptyString);
508011ce
VZ
1329 }
1330
1331 return changed;
1332}
1333
1334void wxGridCellBoolEditor::Reset()
1335{
1336 wxASSERT_MSG(m_control,
1337 wxT("The wxGridCellEditor must be Created first!"));
1338
1339 CBox()->SetValue(m_startValue);
1340}
1341
e195a54c 1342void wxGridCellBoolEditor::StartingClick()
508011ce 1343{
e195a54c 1344 CBox()->SetValue(!CBox()->GetValue());
508011ce
VZ
1345}
1346
f6bcfd97
BP
1347bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event)
1348{
1349 if ( wxGridCellEditor::IsAcceptedKey(event) )
1350 {
1351 int keycode = event.GetKeyCode();
1352 switch ( keycode )
1353 {
1354 case WXK_MULTIPLY:
1355 case WXK_NUMPAD_MULTIPLY:
1356 case WXK_ADD:
1357 case WXK_NUMPAD_ADD:
1358 case WXK_SUBTRACT:
1359 case WXK_NUMPAD_SUBTRACT:
1360 case WXK_SPACE:
1361 case '+':
1362 case '-':
ca65c044 1363 return true;
f6bcfd97
BP
1364 }
1365 }
1366
ca65c044 1367 return false;
f6bcfd97 1368}
04418332 1369
73145b0e
JS
1370// return the value as "1" for true and the empty string for false
1371wxString wxGridCellBoolEditor::GetValue() const
1372{
1373 bool bSet = CBox()->GetValue();
04418332 1374 return bSet ? _T("1") : wxEmptyString;
73145b0e 1375}
f6bcfd97 1376
3a8c693a
VZ
1377#endif // wxUSE_CHECKBOX
1378
1379#if wxUSE_COMBOBOX
1380
4ee5fc9c
VZ
1381// ----------------------------------------------------------------------------
1382// wxGridCellChoiceEditor
1383// ----------------------------------------------------------------------------
1384
7db33cc3
MB
1385wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString& choices,
1386 bool allowOthers)
1387 : m_choices(choices),
1388 m_allowOthers(allowOthers) { }
1389
4ee5fc9c 1390wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count,
f6bcfd97 1391 const wxString choices[],
4ee5fc9c
VZ
1392 bool allowOthers)
1393 : m_allowOthers(allowOthers)
1394{
c4608a8a 1395 if ( count )
4ee5fc9c 1396 {
c4608a8a
VZ
1397 m_choices.Alloc(count);
1398 for ( size_t n = 0; n < count; n++ )
1399 {
1400 m_choices.Add(choices[n]);
1401 }
4ee5fc9c
VZ
1402 }
1403}
1404
c4608a8a
VZ
1405wxGridCellEditor *wxGridCellChoiceEditor::Clone() const
1406{
1407 wxGridCellChoiceEditor *editor = new wxGridCellChoiceEditor;
1408 editor->m_allowOthers = m_allowOthers;
1409 editor->m_choices = m_choices;
1410
1411 return editor;
1412}
1413
4ee5fc9c
VZ
1414void wxGridCellChoiceEditor::Create(wxWindow* parent,
1415 wxWindowID id,
1416 wxEvtHandler* evtHandler)
1417{
4ee5fc9c
VZ
1418 m_control = new wxComboBox(parent, id, wxEmptyString,
1419 wxDefaultPosition, wxDefaultSize,
584ad2a3 1420 m_choices,
4ee5fc9c
VZ
1421 m_allowOthers ? 0 : wxCB_READONLY);
1422
4ee5fc9c
VZ
1423 wxGridCellEditor::Create(parent, id, evtHandler);
1424}
1425
a5777624
RD
1426void wxGridCellChoiceEditor::PaintBackground(const wxRect& rectCell,
1427 wxGridCellAttr * attr)
4ee5fc9c
VZ
1428{
1429 // as we fill the entire client area, don't do anything here to minimize
1430 // flicker
a5777624
RD
1431
1432 // TODO: It doesn't actually fill the client area since the height of a
1433 // combo always defaults to the standard... Until someone has time to
1434 // figure out the right rectangle to paint, just do it the normal way...
1435 wxGridCellEditor::PaintBackground(rectCell, attr);
4ee5fc9c
VZ
1436}
1437
1438void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
1439{
1440 wxASSERT_MSG(m_control,
1441 wxT("The wxGridCellEditor must be Created first!"));
1442
1443 m_startValue = grid->GetTable()->GetValue(row, col);
1444
2b5f62a0
VZ
1445 if (m_allowOthers)
1446 Combo()->SetValue(m_startValue);
1447 else
28a77bc4 1448 {
2b5f62a0
VZ
1449 // find the right position, or default to the first if not found
1450 int pos = Combo()->FindString(m_startValue);
1451 if (pos == -1)
1452 pos = 0;
1453 Combo()->SetSelection(pos);
28a77bc4 1454 }
4ee5fc9c
VZ
1455 Combo()->SetInsertionPointEnd();
1456 Combo()->SetFocus();
1457}
1458
28a77bc4 1459bool wxGridCellChoiceEditor::EndEdit(int row, int col,
4ee5fc9c
VZ
1460 wxGrid* grid)
1461{
1462 wxString value = Combo()->GetValue();
1463 bool changed = value != m_startValue;
1464
1465 if ( changed )
1466 grid->GetTable()->SetValue(row, col, value);
1467
1468 m_startValue = wxEmptyString;
2b5f62a0
VZ
1469 if (m_allowOthers)
1470 Combo()->SetValue(m_startValue);
1471 else
1472 Combo()->SetSelection(0);
4ee5fc9c
VZ
1473
1474 return changed;
1475}
1476
1477void wxGridCellChoiceEditor::Reset()
1478{
1479 Combo()->SetValue(m_startValue);
1480 Combo()->SetInsertionPointEnd();
1481}
1482
c4608a8a
VZ
1483void wxGridCellChoiceEditor::SetParameters(const wxString& params)
1484{
1485 if ( !params )
1486 {
1487 // what can we do?
1488 return;
1489 }
1490
1491 m_choices.Empty();
1492
1493 wxStringTokenizer tk(params, _T(','));
1494 while ( tk.HasMoreTokens() )
1495 {
1496 m_choices.Add(tk.GetNextToken());
1497 }
1498}
1499
73145b0e
JS
1500// return the value in the text control
1501wxString wxGridCellChoiceEditor::GetValue() const
1502{
1503 return Combo()->GetValue();
1504}
04418332 1505
3a8c693a
VZ
1506#endif // wxUSE_COMBOBOX
1507
508011ce
VZ
1508// ----------------------------------------------------------------------------
1509// wxGridCellEditorEvtHandler
1510// ----------------------------------------------------------------------------
2796cce3
RD
1511
1512void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event)
1513{
12a3f227 1514 switch ( event.GetKeyCode() )
2796cce3
RD
1515 {
1516 case WXK_ESCAPE:
1517 m_editor->Reset();
b54ba671 1518 m_grid->DisableCellEditControl();
2796cce3
RD
1519 break;
1520
2c9a89e0 1521 case WXK_TAB:
b51c3f27 1522 m_grid->GetEventHandler()->ProcessEvent( event );
9b4aede2
RD
1523 break;
1524
2796cce3 1525 case WXK_RETURN:
faec5a43
SN
1526 case WXK_NUMPAD_ENTER:
1527 if (!m_grid->GetEventHandler()->ProcessEvent(event))
2796cce3
RD
1528 m_editor->HandleReturn(event);
1529 break;
1530
2796cce3
RD
1531
1532 default:
1533 event.Skip();
1534 }
1535}
1536
fb0de762
RD
1537void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event)
1538{
12a3f227 1539 switch ( event.GetKeyCode() )
fb0de762
RD
1540 {
1541 case WXK_ESCAPE:
1542 case WXK_TAB:
1543 case WXK_RETURN:
a4f7bf58 1544 case WXK_NUMPAD_ENTER:
fb0de762
RD
1545 break;
1546
1547 default:
1548 event.Skip();
1549 }
1550}
1551
c4608a8a
VZ
1552// ----------------------------------------------------------------------------
1553// wxGridCellWorker is an (almost) empty common base class for
1554// wxGridCellRenderer and wxGridCellEditor managing ref counting
1555// ----------------------------------------------------------------------------
1556
1557void wxGridCellWorker::SetParameters(const wxString& WXUNUSED(params))
1558{
1559 // nothing to do
1560}
1561
1562wxGridCellWorker::~wxGridCellWorker()
1563{
1564}
1565
508011ce
VZ
1566// ============================================================================
1567// renderer classes
1568// ============================================================================
1569
ab79958a
VZ
1570// ----------------------------------------------------------------------------
1571// wxGridCellRenderer
1572// ----------------------------------------------------------------------------
1573
1574void wxGridCellRenderer::Draw(wxGrid& grid,
2796cce3 1575 wxGridCellAttr& attr,
ab79958a
VZ
1576 wxDC& dc,
1577 const wxRect& rect,
c78b3acd 1578 int WXUNUSED(row), int WXUNUSED(col),
ab79958a
VZ
1579 bool isSelected)
1580{
1581 dc.SetBackgroundMode( wxSOLID );
1582
04418332 1583 // grey out fields if the grid is disabled
73145b0e 1584 if( grid.IsEnabled() )
ab79958a 1585 {
73145b0e
JS
1586 if ( isSelected )
1587 {
1588 dc.SetBrush( wxBrush(grid.GetSelectionBackground(), wxSOLID) );
1589 }
1590 else
1591 {
1592 dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxSOLID) );
1593 }
52d6f640 1594 }
ab79958a
VZ
1595 else
1596 {
73145b0e 1597 dc.SetBrush(wxBrush(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE), wxSOLID));
ab79958a
VZ
1598 }
1599
1600 dc.SetPen( *wxTRANSPARENT_PEN );
ab79958a
VZ
1601 dc.DrawRectangle(rect);
1602}
1603
508011ce
VZ
1604// ----------------------------------------------------------------------------
1605// wxGridCellStringRenderer
1606// ----------------------------------------------------------------------------
1607
816be743
VZ
1608void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid,
1609 wxGridCellAttr& attr,
1610 wxDC& dc,
1611 bool isSelected)
ab79958a 1612{
ab79958a
VZ
1613 dc.SetBackgroundMode( wxTRANSPARENT );
1614
283b7808
VZ
1615 // TODO some special colours for attr.IsReadOnly() case?
1616
04418332 1617 // different coloured text when the grid is disabled
73145b0e 1618 if( grid.IsEnabled() )
ab79958a 1619 {
73145b0e
JS
1620 if ( isSelected )
1621 {
1622 dc.SetTextBackground( grid.GetSelectionBackground() );
1623 dc.SetTextForeground( grid.GetSelectionForeground() );
1624 }
1625 else
1626 {
1627 dc.SetTextBackground( attr.GetBackgroundColour() );
1628 dc.SetTextForeground( attr.GetTextColour() );
1629 }
ab79958a
VZ
1630 }
1631 else
1632 {
73145b0e
JS
1633 dc.SetTextBackground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE));
1634 dc.SetTextForeground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT));
ab79958a 1635 }
816be743 1636
2796cce3 1637 dc.SetFont( attr.GetFont() );
816be743
VZ
1638}
1639
65e4e78e
VZ
1640wxSize wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr& attr,
1641 wxDC& dc,
1642 const wxString& text)
1643{
f6bcfd97 1644 wxCoord x = 0, y = 0, max_x = 0;
65e4e78e 1645 dc.SetFont(attr.GetFont());
f6bcfd97
BP
1646 wxStringTokenizer tk(text, _T('\n'));
1647 while ( tk.HasMoreTokens() )
1648 {
1649 dc.GetTextExtent(tk.GetNextToken(), &x, &y);
1650 max_x = wxMax(max_x, x);
1651 }
1652
1653 y *= 1 + text.Freq(wxT('\n')); // multiply by the number of lines.
65e4e78e 1654
f6bcfd97 1655 return wxSize(max_x, y);
65e4e78e
VZ
1656}
1657
1658wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid,
1659 wxGridCellAttr& attr,
1660 wxDC& dc,
1661 int row, int col)
1662{
1663 return DoGetBestSize(attr, dc, grid.GetCellValue(row, col));
1664}
1665
816be743
VZ
1666void wxGridCellStringRenderer::Draw(wxGrid& grid,
1667 wxGridCellAttr& attr,
1668 wxDC& dc,
1669 const wxRect& rectCell,
1670 int row, int col,
1671 bool isSelected)
1672{
27f35b66 1673 wxRect rect = rectCell;
dc1f566f
SN
1674 rect.Inflate(-1);
1675
1676 // erase only this cells background, overflow cells should have been erased
1677 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
1678
1679 int hAlign, vAlign;
1680 attr.GetAlignment(&hAlign, &vAlign);
27f35b66 1681
39b80349
SN
1682 int overflowCols = 0;
1683
27f35b66
SN
1684 if (attr.GetOverflow())
1685 {
1686 int cols = grid.GetNumberCols();
1687 int best_width = GetBestSize(grid,attr,dc,row,col).GetWidth();
1688 int cell_rows, cell_cols;
1689 attr.GetSize( &cell_rows, &cell_cols ); // shouldn't get here if <=0
1690 if ((best_width > rectCell.width) && (col < cols) && grid.GetTable())
1691 {
1692 int i, c_cols, c_rows;
1693 for (i = col+cell_cols; i < cols; i++)
1694 {
ca65c044 1695 bool is_empty = true;
39b80349 1696 for (int j=row; j<row+cell_rows; j++)
27f35b66 1697 {
39b80349 1698 // check w/ anchor cell for multicell block
ef4d6ce8 1699 grid.GetCellSize(j, i, &c_rows, &c_cols);
39b80349 1700 if (c_rows > 0) c_rows = 0;
ef4d6ce8 1701 if (!grid.GetTable()->IsEmptyCell(j+c_rows, i))
39b80349 1702 {
ca65c044 1703 is_empty = false;
ef4d6ce8 1704 break;
39b80349 1705 }
27f35b66 1706 }
39b80349
SN
1707 if (is_empty)
1708 rect.width += grid.GetColSize(i);
dc1f566f
SN
1709 else
1710 {
1711 i--;
1712 break;
1713 }
39b80349 1714 if (rect.width >= best_width) break;
2b5f62a0 1715 }
39b80349 1716 overflowCols = i - col - cell_cols + 1;
2b5f62a0 1717 if (overflowCols >= cols) overflowCols = cols - 1;
39b80349 1718 }
27f35b66 1719
dc1f566f
SN
1720 if (overflowCols > 0) // redraw overflow cells w/ proper hilight
1721 {
39b80349 1722 hAlign = wxALIGN_LEFT; // if oveflowed then it's left aligned
2b5f62a0 1723 wxRect clip = rect;
39b80349 1724 clip.x += rectCell.width;
dc1f566f
SN
1725 // draw each overflow cell individually
1726 int col_end = col+cell_cols+overflowCols;
1727 if (col_end >= grid.GetNumberCols())
2b5f62a0 1728 col_end = grid.GetNumberCols() - 1;
dc1f566f
SN
1729 for (int i = col+cell_cols; i <= col_end; i++)
1730 {
dc1f566f
SN
1731 clip.width = grid.GetColSize(i) - 1;
1732 dc.DestroyClippingRegion();
1733 dc.SetClippingRegion(clip);
39b80349
SN
1734
1735 SetTextColoursAndFont(grid, attr, dc,
2b5f62a0 1736 grid.IsInSelection(row,i));
39b80349 1737
dc1f566f 1738 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
2b5f62a0 1739 rect, hAlign, vAlign);
39b80349 1740 clip.x += grid.GetColSize(i) - 1;
dc1f566f 1741 }
ab79958a 1742
39b80349 1743 rect = rectCell;
2b5f62a0 1744 rect.Inflate(-1);
dc1f566f 1745 rect.width++;
39b80349 1746 dc.DestroyClippingRegion();
dc1f566f 1747 }
39b80349 1748 }
ab79958a 1749
dc1f566f
SN
1750 // now we only have to draw the text
1751 SetTextColoursAndFont(grid, attr, dc, isSelected);
39b80349 1752
ab79958a
VZ
1753 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
1754 rect, hAlign, vAlign);
1755}
1756
65e4e78e
VZ
1757// ----------------------------------------------------------------------------
1758// wxGridCellNumberRenderer
1759// ----------------------------------------------------------------------------
1760
1761wxString wxGridCellNumberRenderer::GetString(wxGrid& grid, int row, int col)
1762{
1763 wxGridTableBase *table = grid.GetTable();
1764 wxString text;
1765 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
1766 {
1767 text.Printf(_T("%ld"), table->GetValueAsLong(row, col));
1768 }
9c4ba614
VZ
1769 else
1770 {
1771 text = table->GetValue(row, col);
1772 }
65e4e78e
VZ
1773
1774 return text;
1775}
1776
816be743
VZ
1777void wxGridCellNumberRenderer::Draw(wxGrid& grid,
1778 wxGridCellAttr& attr,
1779 wxDC& dc,
1780 const wxRect& rectCell,
1781 int row, int col,
1782 bool isSelected)
1783{
1784 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
1785
1786 SetTextColoursAndFont(grid, attr, dc, isSelected);
1787
1788 // draw the text right aligned by default
1789 int hAlign, vAlign;
1790 attr.GetAlignment(&hAlign, &vAlign);
4c7277db 1791 hAlign = wxALIGN_RIGHT;
816be743
VZ
1792
1793 wxRect rect = rectCell;
1794 rect.Inflate(-1);
1795
65e4e78e
VZ
1796 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
1797}
816be743 1798
65e4e78e
VZ
1799wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
1800 wxGridCellAttr& attr,
1801 wxDC& dc,
1802 int row, int col)
1803{
1804 return DoGetBestSize(attr, dc, GetString(grid, row, col));
816be743
VZ
1805}
1806
1807// ----------------------------------------------------------------------------
1808// wxGridCellFloatRenderer
1809// ----------------------------------------------------------------------------
1810
1811wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision)
1812{
1813 SetWidth(width);
1814 SetPrecision(precision);
1815}
1816
e72b4213
VZ
1817wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const
1818{
1819 wxGridCellFloatRenderer *renderer = new wxGridCellFloatRenderer;
1820 renderer->m_width = m_width;
1821 renderer->m_precision = m_precision;
1822 renderer->m_format = m_format;
1823
1824 return renderer;
1825}
1826
65e4e78e
VZ
1827wxString wxGridCellFloatRenderer::GetString(wxGrid& grid, int row, int col)
1828{
1829 wxGridTableBase *table = grid.GetTable();
0b190b0f
VZ
1830
1831 bool hasDouble;
1832 double val;
65e4e78e
VZ
1833 wxString text;
1834 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
1835 {
0b190b0f 1836 val = table->GetValueAsDouble(row, col);
ca65c044 1837 hasDouble = true;
65e4e78e 1838 }
9c4ba614
VZ
1839 else
1840 {
1841 text = table->GetValue(row, col);
0b190b0f 1842 hasDouble = text.ToDouble(&val);
9c4ba614 1843 }
65e4e78e 1844
0b190b0f
VZ
1845 if ( hasDouble )
1846 {
1847 if ( !m_format )
1848 {
1849 if ( m_width == -1 )
1850 {
19d7140e
VZ
1851 if ( m_precision == -1 )
1852 {
2b5f62a0
VZ
1853 // default width/precision
1854 m_format = _T("%f");
1855 }
19d7140e
VZ
1856 else
1857 {
1858 m_format.Printf(_T("%%.%df"), m_precision);
1859 }
0b190b0f
VZ
1860 }
1861 else if ( m_precision == -1 )
1862 {
1863 // default precision
1864 m_format.Printf(_T("%%%d.f"), m_width);
1865 }
1866 else
1867 {
1868 m_format.Printf(_T("%%%d.%df"), m_width, m_precision);
1869 }
1870 }
1871
1872 text.Printf(m_format, val);
19d7140e 1873
0b190b0f
VZ
1874 }
1875 //else: text already contains the string
1876
65e4e78e
VZ
1877 return text;
1878}
1879
816be743
VZ
1880void wxGridCellFloatRenderer::Draw(wxGrid& grid,
1881 wxGridCellAttr& attr,
1882 wxDC& dc,
1883 const wxRect& rectCell,
1884 int row, int col,
1885 bool isSelected)
1886{
1887 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
1888
1889 SetTextColoursAndFont(grid, attr, dc, isSelected);
1890
1891 // draw the text right aligned by default
1892 int hAlign, vAlign;
1893 attr.GetAlignment(&hAlign, &vAlign);
4c7277db 1894 hAlign = wxALIGN_RIGHT;
816be743
VZ
1895
1896 wxRect rect = rectCell;
1897 rect.Inflate(-1);
1898
65e4e78e
VZ
1899 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
1900}
816be743 1901
65e4e78e
VZ
1902wxSize wxGridCellFloatRenderer::GetBestSize(wxGrid& grid,
1903 wxGridCellAttr& attr,
1904 wxDC& dc,
1905 int row, int col)
1906{
1907 return DoGetBestSize(attr, dc, GetString(grid, row, col));
816be743
VZ
1908}
1909
0b190b0f
VZ
1910void wxGridCellFloatRenderer::SetParameters(const wxString& params)
1911{
0b190b0f
VZ
1912 if ( !params )
1913 {
1914 // reset to defaults
1915 SetWidth(-1);
1916 SetPrecision(-1);
1917 }
1918 else
1919 {
1920 wxString tmp = params.BeforeFirst(_T(','));
1921 if ( !!tmp )
1922 {
1923 long width;
19d7140e 1924 if ( tmp.ToLong(&width) )
0b190b0f 1925 {
19d7140e 1926 SetWidth((int)width);
0b190b0f
VZ
1927 }
1928 else
1929 {
19d7140e
VZ
1930 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params.c_str());
1931 }
0b190b0f 1932
19d7140e 1933 }
0b190b0f
VZ
1934 tmp = params.AfterFirst(_T(','));
1935 if ( !!tmp )
1936 {
1937 long precision;
19d7140e 1938 if ( tmp.ToLong(&precision) )
0b190b0f 1939 {
19d7140e 1940 SetPrecision((int)precision);
0b190b0f
VZ
1941 }
1942 else
1943 {
19d7140e 1944 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params.c_str());
0b190b0f
VZ
1945 }
1946
0b190b0f
VZ
1947 }
1948 }
1949}
1950
19d7140e 1951
508011ce
VZ
1952// ----------------------------------------------------------------------------
1953// wxGridCellBoolRenderer
1954// ----------------------------------------------------------------------------
1955
65e4e78e 1956wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
508011ce 1957
b94ae1ea
VZ
1958// FIXME these checkbox size calculations are really ugly...
1959
65e4e78e 1960// between checkmark and box
a95e38c0 1961static const wxCoord wxGRID_CHECKMARK_MARGIN = 2;
508011ce 1962
65e4e78e
VZ
1963wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
1964 wxGridCellAttr& WXUNUSED(attr),
1965 wxDC& WXUNUSED(dc),
1966 int WXUNUSED(row),
1967 int WXUNUSED(col))
1968{
1969 // compute it only once (no locks for MT safeness in GUI thread...)
1970 if ( !ms_sizeCheckMark.x )
297da4ba 1971 {
65e4e78e 1972 // get checkbox size
ca65c044 1973 wxCheckBox *checkbox = new wxCheckBox(&grid, wxID_ANY, wxEmptyString);
297da4ba 1974 wxSize size = checkbox->GetBestSize();
999836aa 1975 wxCoord checkSize = size.y + 2*wxGRID_CHECKMARK_MARGIN;
297da4ba 1976
65e4e78e 1977 // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result
69d8f612 1978#if defined(__WXGTK__) || defined(__WXMOTIF__)
65e4e78e 1979 checkSize -= size.y / 2;
297da4ba
VZ
1980#endif
1981
1982 delete checkbox;
65e4e78e
VZ
1983
1984 ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize;
297da4ba
VZ
1985 }
1986
65e4e78e
VZ
1987 return ms_sizeCheckMark;
1988}
1989
1990void wxGridCellBoolRenderer::Draw(wxGrid& grid,
1991 wxGridCellAttr& attr,
1992 wxDC& dc,
1993 const wxRect& rect,
1994 int row, int col,
1995 bool isSelected)
1996{
1997 wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
1998
297da4ba 1999 // draw a check mark in the centre (ignoring alignment - TODO)
65e4e78e 2000 wxSize size = GetBestSize(grid, attr, dc, row, col);
b94ae1ea
VZ
2001
2002 // don't draw outside the cell
2003 wxCoord minSize = wxMin(rect.width, rect.height);
2004 if ( size.x >= minSize || size.y >= minSize )
2005 {
2006 // and even leave (at least) 1 pixel margin
2007 size.x = size.y = minSize - 2;
2008 }
2009
2010 // draw a border around checkmark
1bd71df9
JS
2011 int vAlign, hAlign;
2012 attr.GetAlignment(& hAlign, &vAlign);
52d6f640 2013
a95e38c0 2014 wxRect rectBorder;
1bd71df9
JS
2015 if (hAlign == wxALIGN_CENTRE)
2016 {
2017 rectBorder.x = rect.x + rect.width/2 - size.x/2;
2018 rectBorder.y = rect.y + rect.height/2 - size.y/2;
2019 rectBorder.width = size.x;
2020 rectBorder.height = size.y;
2021 }
2022 else if (hAlign == wxALIGN_LEFT)
2023 {
2024 rectBorder.x = rect.x + 2;
2025 rectBorder.y = rect.y + rect.height/2 - size.y/2;
2026 rectBorder.width = size.x;
52d6f640 2027 rectBorder.height = size.y;
1bd71df9
JS
2028 }
2029 else if (hAlign == wxALIGN_RIGHT)
2030 {
2031 rectBorder.x = rect.x + rect.width - size.x - 2;
2032 rectBorder.y = rect.y + rect.height/2 - size.y/2;
2033 rectBorder.width = size.x;
52d6f640 2034 rectBorder.height = size.y;
1bd71df9 2035 }
b94ae1ea 2036
f2d76237 2037 bool value;
b94ae1ea 2038 if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
f2d76237
RD
2039 value = grid.GetTable()->GetValueAsBool(row, col);
2040 else
695a3263
MB
2041 {
2042 wxString cellval( grid.GetTable()->GetValue(row, col) );
8dd8f875 2043 value = !( !cellval || (cellval == wxT("0")) );
695a3263 2044 }
f2d76237
RD
2045
2046 if ( value )
508011ce 2047 {
a95e38c0
VZ
2048 wxRect rectMark = rectBorder;
2049#ifdef __WXMSW__
2050 // MSW DrawCheckMark() is weird (and should probably be changed...)
2051 rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN/2);
2052 rectMark.x++;
2053 rectMark.y++;
2054#else // !MSW
2055 rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN);
2056#endif // MSW/!MSW
2057
508011ce
VZ
2058 dc.SetTextForeground(attr.GetTextColour());
2059 dc.DrawCheckMark(rectMark);
2060 }
a95e38c0
VZ
2061
2062 dc.SetBrush(*wxTRANSPARENT_BRUSH);
2063 dc.SetPen(wxPen(attr.GetTextColour(), 1, wxSOLID));
2064 dc.DrawRectangle(rectBorder);
508011ce
VZ
2065}
2066
2796cce3
RD
2067// ----------------------------------------------------------------------------
2068// wxGridCellAttr
2069// ----------------------------------------------------------------------------
2070
1df4050d
VZ
2071void wxGridCellAttr::Init(wxGridCellAttr *attrDefault)
2072{
2073 m_nRef = 1;
2074
2075 m_isReadOnly = Unset;
2076
2077 m_renderer = NULL;
2078 m_editor = NULL;
2079
2080 m_attrkind = wxGridCellAttr::Cell;
2081
27f35b66 2082 m_sizeRows = m_sizeCols = 1;
b63fce94 2083 m_overflow = UnsetOverflow;
27f35b66 2084
1df4050d
VZ
2085 SetDefAttr(attrDefault);
2086}
2087
39bcce60 2088wxGridCellAttr *wxGridCellAttr::Clone() const
a68c1246 2089{
1df4050d
VZ
2090 wxGridCellAttr *attr = new wxGridCellAttr(m_defGridAttr);
2091
a68c1246
VZ
2092 if ( HasTextColour() )
2093 attr->SetTextColour(GetTextColour());
2094 if ( HasBackgroundColour() )
2095 attr->SetBackgroundColour(GetBackgroundColour());
2096 if ( HasFont() )
2097 attr->SetFont(GetFont());
2098 if ( HasAlignment() )
2099 attr->SetAlignment(m_hAlign, m_vAlign);
2100
27f35b66
SN
2101 attr->SetSize( m_sizeRows, m_sizeCols );
2102
a68c1246
VZ
2103 if ( m_renderer )
2104 {
2105 attr->SetRenderer(m_renderer);
39bcce60 2106 m_renderer->IncRef();
a68c1246
VZ
2107 }
2108 if ( m_editor )
2109 {
2110 attr->SetEditor(m_editor);
39bcce60 2111 m_editor->IncRef();
a68c1246
VZ
2112 }
2113
2114 if ( IsReadOnly() )
2115 attr->SetReadOnly();
2116
19d7140e
VZ
2117 attr->SetKind( m_attrkind );
2118
a68c1246
VZ
2119 return attr;
2120}
2121
19d7140e
VZ
2122void wxGridCellAttr::MergeWith(wxGridCellAttr *mergefrom)
2123{
2124 if ( !HasTextColour() && mergefrom->HasTextColour() )
2125 SetTextColour(mergefrom->GetTextColour());
2126 if ( !HasBackgroundColour() && mergefrom->HasBackgroundColour() )
2127 SetBackgroundColour(mergefrom->GetBackgroundColour());
2128 if ( !HasFont() && mergefrom->HasFont() )
2129 SetFont(mergefrom->GetFont());
7e48d7d9 2130 if ( !HasAlignment() && mergefrom->HasAlignment() ){
19d7140e
VZ
2131 int hAlign, vAlign;
2132 mergefrom->GetAlignment( &hAlign, &vAlign);
2133 SetAlignment(hAlign, vAlign);
2134 }
2135
27f35b66
SN
2136 mergefrom->GetSize( &m_sizeRows, &m_sizeCols );
2137
19d7140e
VZ
2138 // Directly access member functions as GetRender/Editor don't just return
2139 // m_renderer/m_editor
2140 //
2141 // Maybe add support for merge of Render and Editor?
2142 if (!HasRenderer() && mergefrom->HasRenderer() )
bf7945ce 2143 {
19d7140e
VZ
2144 m_renderer = mergefrom->m_renderer;
2145 m_renderer->IncRef();
2146 }
2147 if ( !HasEditor() && mergefrom->HasEditor() )
2148 {
2149 m_editor = mergefrom->m_editor;
2150 m_editor->IncRef();
2151 }
2152 if ( !HasReadWriteMode() && mergefrom->HasReadWriteMode() )
2153 SetReadOnly(mergefrom->IsReadOnly());
2154
ef5df12b 2155 if (!HasOverflowMode() && mergefrom->HasOverflowMode() )
ff699386 2156 SetOverflow(mergefrom->GetOverflow());
ef5df12b 2157
19d7140e
VZ
2158 SetDefAttr(mergefrom->m_defGridAttr);
2159}
2160
27f35b66
SN
2161void wxGridCellAttr::SetSize(int num_rows, int num_cols)
2162{
2163 // The size of a cell is normally 1,1
2164
2165 // If this cell is larger (2,2) then this is the top left cell
2166 // the other cells that will be covered (lower right cells) must be
2167 // set to negative or zero values such that
2168 // row + num_rows of the covered cell points to the larger cell (this cell)
2169 // same goes for the col + num_cols.
2170
2171 // Size of 0,0 is NOT valid, neither is <=0 and any positive value
2172
2173 wxASSERT_MSG( (!((num_rows>0)&&(num_cols<=0)) ||
2174 !((num_rows<=0)&&(num_cols>0)) ||
2175 !((num_rows==0)&&(num_cols==0))),
2176 wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values"));
2177
2178 m_sizeRows = num_rows;
2179 m_sizeCols = num_cols;
2180}
2181
2796cce3
RD
2182const wxColour& wxGridCellAttr::GetTextColour() const
2183{
2184 if (HasTextColour())
508011ce 2185 {
2796cce3 2186 return m_colText;
508011ce 2187 }
0926b2fc 2188 else if (m_defGridAttr && m_defGridAttr != this)
508011ce 2189 {
2796cce3 2190 return m_defGridAttr->GetTextColour();
508011ce
VZ
2191 }
2192 else
2193 {
2796cce3
RD
2194 wxFAIL_MSG(wxT("Missing default cell attribute"));
2195 return wxNullColour;
2196 }
2197}
2198
2199
2200const wxColour& wxGridCellAttr::GetBackgroundColour() const
2201{
2202 if (HasBackgroundColour())
2203 return m_colBack;
0926b2fc 2204 else if (m_defGridAttr && m_defGridAttr != this)
2796cce3 2205 return m_defGridAttr->GetBackgroundColour();
508011ce
VZ
2206 else
2207 {
2796cce3
RD
2208 wxFAIL_MSG(wxT("Missing default cell attribute"));
2209 return wxNullColour;
2210 }
2211}
2212
2213
2214const wxFont& wxGridCellAttr::GetFont() const
2215{
2216 if (HasFont())
2217 return m_font;
0926b2fc 2218 else if (m_defGridAttr && m_defGridAttr != this)
2796cce3 2219 return m_defGridAttr->GetFont();
508011ce
VZ
2220 else
2221 {
2796cce3
RD
2222 wxFAIL_MSG(wxT("Missing default cell attribute"));
2223 return wxNullFont;
2224 }
2225}
2226
2227
2228void wxGridCellAttr::GetAlignment(int *hAlign, int *vAlign) const
2229{
508011ce
VZ
2230 if (HasAlignment())
2231 {
2796cce3
RD
2232 if ( hAlign ) *hAlign = m_hAlign;
2233 if ( vAlign ) *vAlign = m_vAlign;
2234 }
0926b2fc 2235 else if (m_defGridAttr && m_defGridAttr != this)
2796cce3 2236 m_defGridAttr->GetAlignment(hAlign, vAlign);
508011ce
VZ
2237 else
2238 {
2796cce3
RD
2239 wxFAIL_MSG(wxT("Missing default cell attribute"));
2240 }
2241}
2242
27f35b66
SN
2243void wxGridCellAttr::GetSize( int *num_rows, int *num_cols ) const
2244{
2245 if ( num_rows ) *num_rows = m_sizeRows;
2246 if ( num_cols ) *num_cols = m_sizeCols;
2247}
2796cce3 2248
f2d76237 2249// GetRenderer and GetEditor use a slightly different decision path about
28a77bc4
RD
2250// which attribute to use. If a non-default attr object has one then it is
2251// used, otherwise the default editor or renderer is fetched from the grid and
2252// used. It should be the default for the data type of the cell. If it is
2253// NULL (because the table has a type that the grid does not have in its
2254// registry,) then the grid's default editor or renderer is used.
2255
2256wxGridCellRenderer* wxGridCellAttr::GetRenderer(wxGrid* grid, int row, int col) const
2257{
3cf883a2 2258 wxGridCellRenderer *renderer;
28a77bc4 2259
3cf883a2 2260 if ( m_renderer && this != m_defGridAttr )
0b190b0f 2261 {
3cf883a2
VZ
2262 // use the cells renderer if it has one
2263 renderer = m_renderer;
2264 renderer->IncRef();
0b190b0f 2265 }
3cf883a2 2266 else // no non default cell renderer
0b190b0f 2267 {
3cf883a2
VZ
2268 // get default renderer for the data type
2269 if ( grid )
2270 {
2271 // GetDefaultRendererForCell() will do IncRef() for us
2272 renderer = grid->GetDefaultRendererForCell(row, col);
2273 }
2274 else
2275 {
2276 renderer = NULL;
2277 }
0b190b0f 2278
3cf883a2
VZ
2279 if ( !renderer )
2280 {
0926b2fc 2281 if (m_defGridAttr && this != m_defGridAttr )
3cf883a2
VZ
2282 {
2283 // if we still don't have one then use the grid default
2284 // (no need for IncRef() here neither)
2285 renderer = m_defGridAttr->GetRenderer(NULL, 0, 0);
2286 }
2287 else // default grid attr
2288 {
2289 // use m_renderer which we had decided not to use initially
2290 renderer = m_renderer;
2291 if ( renderer )
2292 renderer->IncRef();
2293 }
2294 }
0b190b0f 2295 }
28a77bc4 2296
3cf883a2
VZ
2297 // we're supposed to always find something
2298 wxASSERT_MSG(renderer, wxT("Missing default cell renderer"));
28a77bc4
RD
2299
2300 return renderer;
2796cce3
RD
2301}
2302
3cf883a2 2303// same as above, except for s/renderer/editor/g
28a77bc4 2304wxGridCellEditor* wxGridCellAttr::GetEditor(wxGrid* grid, int row, int col) const
07296f0b 2305{
3cf883a2 2306 wxGridCellEditor *editor;
0b190b0f 2307
3cf883a2 2308 if ( m_editor && this != m_defGridAttr )
0b190b0f 2309 {
3cf883a2
VZ
2310 // use the cells editor if it has one
2311 editor = m_editor;
2312 editor->IncRef();
0b190b0f 2313 }
3cf883a2 2314 else // no non default cell editor
0b190b0f 2315 {
3cf883a2
VZ
2316 // get default editor for the data type
2317 if ( grid )
2318 {
2319 // GetDefaultEditorForCell() will do IncRef() for us
2320 editor = grid->GetDefaultEditorForCell(row, col);
2321 }
2322 else
2323 {
2324 editor = NULL;
2325 }
2326
2327 if ( !editor )
2328 {
0926b2fc 2329 if ( m_defGridAttr && this != m_defGridAttr )
3cf883a2
VZ
2330 {
2331 // if we still don't have one then use the grid default
2332 // (no need for IncRef() here neither)
2333 editor = m_defGridAttr->GetEditor(NULL, 0, 0);
2334 }
2335 else // default grid attr
2336 {
2337 // use m_editor which we had decided not to use initially
2338 editor = m_editor;
2339 if ( editor )
2340 editor->IncRef();
2341 }
2342 }
0b190b0f 2343 }
28a77bc4 2344
3cf883a2
VZ
2345 // we're supposed to always find something
2346 wxASSERT_MSG(editor, wxT("Missing default cell editor"));
2347
28a77bc4 2348 return editor;
07296f0b
RD
2349}
2350
b99be8fb 2351// ----------------------------------------------------------------------------
758cbedf 2352// wxGridCellAttrData
b99be8fb
VZ
2353// ----------------------------------------------------------------------------
2354
758cbedf 2355void wxGridCellAttrData::SetAttr(wxGridCellAttr *attr, int row, int col)
b99be8fb
VZ
2356{
2357 int n = FindIndex(row, col);
2358 if ( n == wxNOT_FOUND )
2359 {
2360 // add the attribute
2361 m_attrs.Add(new wxGridCellWithAttr(row, col, attr));
2362 }
2363 else
2364 {
6f36917b
VZ
2365 // free the old attribute
2366 m_attrs[(size_t)n].attr->DecRef();
2367
b99be8fb
VZ
2368 if ( attr )
2369 {
2370 // change the attribute
2e9a6788 2371 m_attrs[(size_t)n].attr = attr;
b99be8fb
VZ
2372 }
2373 else
2374 {
2375 // remove this attribute
2376 m_attrs.RemoveAt((size_t)n);
2377 }
2378 }
b99be8fb
VZ
2379}
2380
758cbedf 2381wxGridCellAttr *wxGridCellAttrData::GetAttr(int row, int col) const
b99be8fb
VZ
2382{
2383 wxGridCellAttr *attr = (wxGridCellAttr *)NULL;
2384
2385 int n = FindIndex(row, col);
2386 if ( n != wxNOT_FOUND )
2387 {
2e9a6788
VZ
2388 attr = m_attrs[(size_t)n].attr;
2389 attr->IncRef();
b99be8fb
VZ
2390 }
2391
2392 return attr;
2393}
2394
4d60017a
SN
2395void wxGridCellAttrData::UpdateAttrRows( size_t pos, int numRows )
2396{
2397 size_t count = m_attrs.GetCount();
2398 for ( size_t n = 0; n < count; n++ )
2399 {
2400 wxGridCellCoords& coords = m_attrs[n].coords;
d1c0b4f9
VZ
2401 wxCoord row = coords.GetRow();
2402 if ((size_t)row >= pos)
2403 {
2404 if (numRows > 0)
2405 {
2406 // If rows inserted, include row counter where necessary
2407 coords.SetRow(row + numRows);
2408 }
2409 else if (numRows < 0)
2410 {
2411 // If rows deleted ...
2412 if ((size_t)row >= pos - numRows)
2413 {
2414 // ...either decrement row counter (if row still exists)...
2415 coords.SetRow(row + numRows);
2416 }
2417 else
2418 {
2419 // ...or remove the attribute
2420 m_attrs.RemoveAt((size_t)n);
2421 n--; count--;
2422 }
2423 }
4d60017a
SN
2424 }
2425 }
2426}
2427
2428void wxGridCellAttrData::UpdateAttrCols( size_t pos, int numCols )
2429{
2430 size_t count = m_attrs.GetCount();
2431 for ( size_t n = 0; n < count; n++ )
2432 {
2433 wxGridCellCoords& coords = m_attrs[n].coords;
d1c0b4f9
VZ
2434 wxCoord col = coords.GetCol();
2435 if ( (size_t)col >= pos )
2436 {
2437 if ( numCols > 0 )
2438 {
2439 // If rows inserted, include row counter where necessary
2440 coords.SetCol(col + numCols);
2441 }
2442 else if (numCols < 0)
2443 {
2444 // If rows deleted ...
2445 if ((size_t)col >= pos - numCols)
2446 {
2447 // ...either decrement row counter (if row still exists)...
2448 coords.SetCol(col + numCols);
2449 }
2450 else
2451 {
2452 // ...or remove the attribute
2453 m_attrs.RemoveAt((size_t)n);
2454 n--; count--;
2455 }
2456 }
4d60017a
SN
2457 }
2458 }
2459}
2460
758cbedf 2461int wxGridCellAttrData::FindIndex(int row, int col) const
b99be8fb
VZ
2462{
2463 size_t count = m_attrs.GetCount();
2464 for ( size_t n = 0; n < count; n++ )
2465 {
2466 const wxGridCellCoords& coords = m_attrs[n].coords;
2467 if ( (coords.GetRow() == row) && (coords.GetCol() == col) )
2468 {
2469 return n;
2470 }
2471 }
2472
2473 return wxNOT_FOUND;
2474}
2475
758cbedf
VZ
2476// ----------------------------------------------------------------------------
2477// wxGridRowOrColAttrData
2478// ----------------------------------------------------------------------------
2479
2480wxGridRowOrColAttrData::~wxGridRowOrColAttrData()
2481{
2482 size_t count = m_attrs.Count();
2483 for ( size_t n = 0; n < count; n++ )
2484 {
2485 m_attrs[n]->DecRef();
2486 }
2487}
2488
2489wxGridCellAttr *wxGridRowOrColAttrData::GetAttr(int rowOrCol) const
2490{
2491 wxGridCellAttr *attr = (wxGridCellAttr *)NULL;
2492
2493 int n = m_rowsOrCols.Index(rowOrCol);
2494 if ( n != wxNOT_FOUND )
2495 {
2496 attr = m_attrs[(size_t)n];
2497 attr->IncRef();
2498 }
2499
2500 return attr;
2501}
2502
2503void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr *attr, int rowOrCol)
2504{
a95e38c0
VZ
2505 int i = m_rowsOrCols.Index(rowOrCol);
2506 if ( i == wxNOT_FOUND )
758cbedf
VZ
2507 {
2508 // add the attribute
2509 m_rowsOrCols.Add(rowOrCol);
2510 m_attrs.Add(attr);
2511 }
2512 else
2513 {
a95e38c0 2514 size_t n = (size_t)i;
758cbedf
VZ
2515 if ( attr )
2516 {
2517 // change the attribute
a95e38c0
VZ
2518 m_attrs[n]->DecRef();
2519 m_attrs[n] = attr;
758cbedf
VZ
2520 }
2521 else
2522 {
2523 // remove this attribute
a95e38c0
VZ
2524 m_attrs[n]->DecRef();
2525 m_rowsOrCols.RemoveAt(n);
2526 m_attrs.RemoveAt(n);
758cbedf
VZ
2527 }
2528 }
2529}
2530
4d60017a
SN
2531void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos, int numRowsOrCols )
2532{
2533 size_t count = m_attrs.GetCount();
2534 for ( size_t n = 0; n < count; n++ )
2535 {
2536 int & rowOrCol = m_rowsOrCols[n];
d1c0b4f9
VZ
2537 if ( (size_t)rowOrCol >= pos )
2538 {
2539 if ( numRowsOrCols > 0 )
2540 {
2541 // If rows inserted, include row counter where necessary
2542 rowOrCol += numRowsOrCols;
2543 }
2544 else if ( numRowsOrCols < 0)
2545 {
2546 // If rows deleted, either decrement row counter (if row still exists)
2547 if ((size_t)rowOrCol >= pos - numRowsOrCols)
2548 rowOrCol += numRowsOrCols;
2549 else
2550 {
2551 m_rowsOrCols.RemoveAt((size_t)n);
2552 m_attrs.RemoveAt((size_t)n);
2553 n--; count--;
2554 }
2555 }
4d60017a
SN
2556 }
2557 }
2558}
2559
b99be8fb
VZ
2560// ----------------------------------------------------------------------------
2561// wxGridCellAttrProvider
2562// ----------------------------------------------------------------------------
2563
2564wxGridCellAttrProvider::wxGridCellAttrProvider()
2565{
2566 m_data = (wxGridCellAttrProviderData *)NULL;
2567}
2568
2569wxGridCellAttrProvider::~wxGridCellAttrProvider()
2570{
2571 delete m_data;
2572}
2573
2574void wxGridCellAttrProvider::InitData()
2575{
2576 m_data = new wxGridCellAttrProviderData;
2577}
2578
19d7140e
VZ
2579wxGridCellAttr *wxGridCellAttrProvider::GetAttr(int row, int col,
2580 wxGridCellAttr::wxAttrKind kind ) const
b99be8fb 2581{
758cbedf
VZ
2582 wxGridCellAttr *attr = (wxGridCellAttr *)NULL;
2583 if ( m_data )
2584 {
19d7140e 2585 switch(kind)
758cbedf 2586 {
19d7140e
VZ
2587 case (wxGridCellAttr::Any):
2588 //Get cached merge attributes.
2589 // Currenlty not used as no cache implemented as not mutiable
2590 // attr = m_data->m_mergeAttr.GetAttr(row, col);
2591 if(!attr)
2592 {
2593 //Basicaly implement old version.
2594 //Also check merge cache, so we don't have to re-merge every time..
999836aa
VZ
2595 wxGridCellAttr *attrcell = m_data->m_cellAttrs.GetAttr(row, col);
2596 wxGridCellAttr *attrrow = m_data->m_rowAttrs.GetAttr(row);
2597 wxGridCellAttr *attrcol = m_data->m_colAttrs.GetAttr(col);
19d7140e 2598
bf7945ce 2599 if((attrcell != attrrow) && (attrrow !=attrcol) && (attrcell != attrcol)){
19d7140e
VZ
2600 // Two or move are non NULL
2601 attr = new wxGridCellAttr;
2602 attr->SetKind(wxGridCellAttr::Merged);
2603
bf7945ce 2604 //Order important..
19d7140e
VZ
2605 if(attrcell){
2606 attr->MergeWith(attrcell);
2607 attrcell->DecRef();
2608 }
2609 if(attrcol){
2610 attr->MergeWith(attrcol);
2611 attrcol->DecRef();
2612 }
2613 if(attrrow){
2614 attr->MergeWith(attrrow);
2615 attrrow->DecRef();
2616 }
2617 //store merge attr if cache implemented
2618 //attr->IncRef();
2619 //m_data->m_mergeAttr.SetAttr(attr, row, col);
2620 }
2621 else
758cbedf 2622 {
19d7140e
VZ
2623 // one or none is non null return it or null.
2624 if(attrrow) attr = attrrow;
2625 if(attrcol) attr = attrcol;
bf7945ce 2626 if(attrcell) attr = attrcell;
19d7140e
VZ
2627 }
2628 }
2629 break;
2630 case (wxGridCellAttr::Cell):
2631 attr = m_data->m_cellAttrs.GetAttr(row, col);
2632 break;
2633 case (wxGridCellAttr::Col):
2634 attr = m_data->m_colAttrs.GetAttr(col);
2635 break;
2636 case (wxGridCellAttr::Row):
758cbedf 2637 attr = m_data->m_rowAttrs.GetAttr(row);
19d7140e
VZ
2638 break;
2639 default:
2640 // unused as yet...
2641 // (wxGridCellAttr::Default):
2642 // (wxGridCellAttr::Merged):
2643 break;
758cbedf
VZ
2644 }
2645 }
758cbedf 2646 return attr;
b99be8fb
VZ
2647}
2648
2e9a6788 2649void wxGridCellAttrProvider::SetAttr(wxGridCellAttr *attr,
b99be8fb
VZ
2650 int row, int col)
2651{
2652 if ( !m_data )
2653 InitData();
2654
758cbedf
VZ
2655 m_data->m_cellAttrs.SetAttr(attr, row, col);
2656}
2657
2658void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr *attr, int row)
2659{
2660 if ( !m_data )
2661 InitData();
2662
2663 m_data->m_rowAttrs.SetAttr(attr, row);
2664}
2665
2666void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr *attr, int col)
2667{
2668 if ( !m_data )
2669 InitData();
2670
2671 m_data->m_colAttrs.SetAttr(attr, col);
b99be8fb
VZ
2672}
2673
4d60017a
SN
2674void wxGridCellAttrProvider::UpdateAttrRows( size_t pos, int numRows )
2675{
2676 if ( m_data )
2677 {
2678 m_data->m_cellAttrs.UpdateAttrRows( pos, numRows );
2679
d1c0b4f9 2680 m_data->m_rowAttrs.UpdateAttrRowsOrCols( pos, numRows );
4d60017a
SN
2681 }
2682}
2683
2684void wxGridCellAttrProvider::UpdateAttrCols( size_t pos, int numCols )
2685{
2686 if ( m_data )
2687 {
2688 m_data->m_cellAttrs.UpdateAttrCols( pos, numCols );
2689
d1c0b4f9 2690 m_data->m_colAttrs.UpdateAttrRowsOrCols( pos, numCols );
4d60017a
SN
2691 }
2692}
2693
f2d76237
RD
2694// ----------------------------------------------------------------------------
2695// wxGridTypeRegistry
2696// ----------------------------------------------------------------------------
2697
2698wxGridTypeRegistry::~wxGridTypeRegistry()
2699{
b94ae1ea
VZ
2700 size_t count = m_typeinfo.Count();
2701 for ( size_t i = 0; i < count; i++ )
f2d76237
RD
2702 delete m_typeinfo[i];
2703}
2704
2705
2706void wxGridTypeRegistry::RegisterDataType(const wxString& typeName,
2707 wxGridCellRenderer* renderer,
2708 wxGridCellEditor* editor)
2709{
f2d76237
RD
2710 wxGridDataTypeInfo* info = new wxGridDataTypeInfo(typeName, renderer, editor);
2711
2712 // is it already registered?
c4608a8a 2713 int loc = FindRegisteredDataType(typeName);
39bcce60
VZ
2714 if ( loc != wxNOT_FOUND )
2715 {
f2d76237
RD
2716 delete m_typeinfo[loc];
2717 m_typeinfo[loc] = info;
2718 }
39bcce60
VZ
2719 else
2720 {
f2d76237
RD
2721 m_typeinfo.Add(info);
2722 }
2723}
2724
c4608a8a
VZ
2725int wxGridTypeRegistry::FindRegisteredDataType(const wxString& typeName)
2726{
2727 size_t count = m_typeinfo.GetCount();
2728 for ( size_t i = 0; i < count; i++ )
2729 {
2730 if ( typeName == m_typeinfo[i]->m_typeName )
2731 {
2732 return i;
2733 }
2734 }
2735
2736 return wxNOT_FOUND;
2737}
2738
f2d76237
RD
2739int wxGridTypeRegistry::FindDataType(const wxString& typeName)
2740{
c4608a8a
VZ
2741 int index = FindRegisteredDataType(typeName);
2742 if ( index == wxNOT_FOUND )
2743 {
2744 // check whether this is one of the standard ones, in which case
2745 // register it "on the fly"
3a8c693a 2746#if wxUSE_TEXTCTRL
c4608a8a
VZ
2747 if ( typeName == wxGRID_VALUE_STRING )
2748 {
2749 RegisterDataType(wxGRID_VALUE_STRING,
2750 new wxGridCellStringRenderer,
2751 new wxGridCellTextEditor);
3a8c693a
VZ
2752 } else
2753#endif // wxUSE_TEXTCTRL
2754#if wxUSE_CHECKBOX
2755 if ( typeName == wxGRID_VALUE_BOOL )
c4608a8a
VZ
2756 {
2757 RegisterDataType(wxGRID_VALUE_BOOL,
2758 new wxGridCellBoolRenderer,
2759 new wxGridCellBoolEditor);
3a8c693a
VZ
2760 } else
2761#endif // wxUSE_CHECKBOX
2762#if wxUSE_TEXTCTRL
2763 if ( typeName == wxGRID_VALUE_NUMBER )
c4608a8a
VZ
2764 {
2765 RegisterDataType(wxGRID_VALUE_NUMBER,
2766 new wxGridCellNumberRenderer,
2767 new wxGridCellNumberEditor);
2768 }
2769 else if ( typeName == wxGRID_VALUE_FLOAT )
2770 {
2771 RegisterDataType(wxGRID_VALUE_FLOAT,
2772 new wxGridCellFloatRenderer,
2773 new wxGridCellFloatEditor);
3a8c693a
VZ
2774 } else
2775#endif // wxUSE_TEXTCTRL
2776#if wxUSE_COMBOBOX
2777 if ( typeName == wxGRID_VALUE_CHOICE )
c4608a8a
VZ
2778 {
2779 RegisterDataType(wxGRID_VALUE_CHOICE,
2780 new wxGridCellStringRenderer,
2781 new wxGridCellChoiceEditor);
3a8c693a
VZ
2782 } else
2783#endif // wxUSE_COMBOBOX
c4608a8a
VZ
2784 {
2785 return wxNOT_FOUND;
2786 }
f2d76237 2787
c4608a8a
VZ
2788 // we get here only if just added the entry for this type, so return
2789 // the last index
2790 index = m_typeinfo.GetCount() - 1;
2791 }
2792
2793 return index;
2794}
2795
2796int wxGridTypeRegistry::FindOrCloneDataType(const wxString& typeName)
2797{
2798 int index = FindDataType(typeName);
2799 if ( index == wxNOT_FOUND )
2800 {
2801 // the first part of the typename is the "real" type, anything after ':'
2802 // are the parameters for the renderer
2803 index = FindDataType(typeName.BeforeFirst(_T(':')));
2804 if ( index == wxNOT_FOUND )
2805 {
2806 return wxNOT_FOUND;
f2d76237 2807 }
c4608a8a
VZ
2808
2809 wxGridCellRenderer *renderer = GetRenderer(index);
2810 wxGridCellRenderer *rendererOld = renderer;
2811 renderer = renderer->Clone();
2812 rendererOld->DecRef();
2813
2814 wxGridCellEditor *editor = GetEditor(index);
2815 wxGridCellEditor *editorOld = editor;
2816 editor = editor->Clone();
2817 editorOld->DecRef();
2818
2819 // do it even if there are no parameters to reset them to defaults
2820 wxString params = typeName.AfterFirst(_T(':'));
2821 renderer->SetParameters(params);
2822 editor->SetParameters(params);
2823
2824 // register the new typename
c4608a8a
VZ
2825 RegisterDataType(typeName, renderer, editor);
2826
2827 // we just registered it, it's the last one
2828 index = m_typeinfo.GetCount() - 1;
f2d76237
RD
2829 }
2830
c4608a8a 2831 return index;
f2d76237
RD
2832}
2833
2834wxGridCellRenderer* wxGridTypeRegistry::GetRenderer(int index)
2835{
2836 wxGridCellRenderer* renderer = m_typeinfo[index]->m_renderer;
faec5a43
SN
2837 if (renderer)
2838 renderer->IncRef();
f2d76237
RD
2839 return renderer;
2840}
2841
0b190b0f 2842wxGridCellEditor* wxGridTypeRegistry::GetEditor(int index)
f2d76237
RD
2843{
2844 wxGridCellEditor* editor = m_typeinfo[index]->m_editor;
faec5a43
SN
2845 if (editor)
2846 editor->IncRef();
f2d76237
RD
2847 return editor;
2848}
2849
758cbedf
VZ
2850// ----------------------------------------------------------------------------
2851// wxGridTableBase
2852// ----------------------------------------------------------------------------
2853
f85afd4e
MB
2854IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase, wxObject )
2855
2856
2857wxGridTableBase::wxGridTableBase()
f85afd4e
MB
2858{
2859 m_view = (wxGrid *) NULL;
b99be8fb 2860 m_attrProvider = (wxGridCellAttrProvider *) NULL;
f85afd4e
MB
2861}
2862
2863wxGridTableBase::~wxGridTableBase()
2864{
b99be8fb
VZ
2865 delete m_attrProvider;
2866}
2867
2868void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider *attrProvider)
2869{
2870 delete m_attrProvider;
2871 m_attrProvider = attrProvider;
f85afd4e
MB
2872}
2873
f2d76237
RD
2874bool wxGridTableBase::CanHaveAttributes()
2875{
2876 if ( ! GetAttrProvider() )
2877 {
2878 // use the default attr provider by default
2879 SetAttrProvider(new wxGridCellAttrProvider);
2880 }
ca65c044 2881 return true;
f2d76237
RD
2882}
2883
19d7140e 2884wxGridCellAttr *wxGridTableBase::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind)
b99be8fb
VZ
2885{
2886 if ( m_attrProvider )
19d7140e 2887 return m_attrProvider->GetAttr(row, col, kind);
b99be8fb
VZ
2888 else
2889 return (wxGridCellAttr *)NULL;
2890}
2891
758cbedf 2892void wxGridTableBase::SetAttr(wxGridCellAttr* attr, int row, int col)
b99be8fb
VZ
2893{
2894 if ( m_attrProvider )
2895 {
19d7140e 2896 attr->SetKind(wxGridCellAttr::Cell);
b99be8fb
VZ
2897 m_attrProvider->SetAttr(attr, row, col);
2898 }
2899 else
2900 {
2901 // as we take ownership of the pointer and don't store it, we must
2902 // free it now
39bcce60 2903 wxSafeDecRef(attr);
b99be8fb
VZ
2904 }
2905}
2906
758cbedf
VZ
2907void wxGridTableBase::SetRowAttr(wxGridCellAttr *attr, int row)
2908{
2909 if ( m_attrProvider )
2910 {
19d7140e 2911 attr->SetKind(wxGridCellAttr::Row);
758cbedf
VZ
2912 m_attrProvider->SetRowAttr(attr, row);
2913 }
2914 else
2915 {
2916 // as we take ownership of the pointer and don't store it, we must
2917 // free it now
39bcce60 2918 wxSafeDecRef(attr);
758cbedf
VZ
2919 }
2920}
2921
2922void wxGridTableBase::SetColAttr(wxGridCellAttr *attr, int col)
2923{
2924 if ( m_attrProvider )
2925 {
19d7140e 2926 attr->SetKind(wxGridCellAttr::Col);
758cbedf
VZ
2927 m_attrProvider->SetColAttr(attr, col);
2928 }
2929 else
2930 {
2931 // as we take ownership of the pointer and don't store it, we must
2932 // free it now
39bcce60 2933 wxSafeDecRef(attr);
758cbedf
VZ
2934 }
2935}
2936
aa5e1f75
SN
2937bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos),
2938 size_t WXUNUSED(numRows) )
f85afd4e 2939{
f6bcfd97 2940 wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") );
8f177c8e 2941
ca65c044 2942 return false;
f85afd4e
MB
2943}
2944
aa5e1f75 2945bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows) )
f85afd4e 2946{
f6bcfd97 2947 wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function"));
8f177c8e 2948
ca65c044 2949 return false;
f85afd4e
MB
2950}
2951
aa5e1f75
SN
2952bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos),
2953 size_t WXUNUSED(numRows) )
f85afd4e 2954{
f6bcfd97 2955 wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function"));
8f177c8e 2956
ca65c044 2957 return false;
f85afd4e
MB
2958}
2959
aa5e1f75
SN
2960bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos),
2961 size_t WXUNUSED(numCols) )
f85afd4e 2962{
f6bcfd97 2963 wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function"));
8f177c8e 2964
ca65c044 2965 return false;
f85afd4e
MB
2966}
2967
aa5e1f75 2968bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols) )
f85afd4e 2969{
f6bcfd97 2970 wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function"));
8f177c8e 2971
ca65c044 2972 return false;
f85afd4e
MB
2973}
2974
aa5e1f75
SN
2975bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos),
2976 size_t WXUNUSED(numCols) )
f85afd4e 2977{
f6bcfd97 2978 wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function"));
8f177c8e 2979
ca65c044 2980 return false;
f85afd4e
MB
2981}
2982
2983
2984wxString wxGridTableBase::GetRowLabelValue( int row )
2985{
2986 wxString s;
f2d76237
RD
2987 s << row + 1; // RD: Starting the rows at zero confuses users, no matter
2988 // how much it makes sense to us geeks.
f85afd4e
MB
2989 return s;
2990}
2991
2992wxString wxGridTableBase::GetColLabelValue( int col )
2993{
2994 // default col labels are:
2995 // cols 0 to 25 : A-Z
2996 // cols 26 to 675 : AA-ZZ
2997 // etc.
2998
2999 wxString s;
3000 unsigned int i, n;
3001 for ( n = 1; ; n++ )
3002 {
fef5c556 3003 s += (wxChar) (_T('A') + (wxChar)( col%26 ));
f85afd4e
MB
3004 col = col/26 - 1;
3005 if ( col < 0 ) break;
3006 }
3007
3008 // reverse the string...
3009 wxString s2;
3010 for ( i = 0; i < n; i++ )
3011 {
3012 s2 += s[n-i-1];
3013 }
3014
3015 return s2;
3016}
3017
3018
f2d76237
RD
3019wxString wxGridTableBase::GetTypeName( int WXUNUSED(row), int WXUNUSED(col) )
3020{
816be743 3021 return wxGRID_VALUE_STRING;
f2d76237
RD
3022}
3023
3024bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row), int WXUNUSED(col),
3025 const wxString& typeName )
3026{
816be743 3027 return typeName == wxGRID_VALUE_STRING;
f2d76237
RD
3028}
3029
3030bool wxGridTableBase::CanSetValueAs( int row, int col, const wxString& typeName )
3031{
3032 return CanGetValueAs(row, col, typeName);
3033}
3034
3035long wxGridTableBase::GetValueAsLong( int WXUNUSED(row), int WXUNUSED(col) )
3036{
3037 return 0;
3038}
3039
3040double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row), int WXUNUSED(col) )
3041{
3042 return 0.0;
3043}
3044
3045bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row), int WXUNUSED(col) )
3046{
ca65c044 3047 return false;
f2d76237
RD
3048}
3049
3050void wxGridTableBase::SetValueAsLong( int WXUNUSED(row), int WXUNUSED(col),
3051 long WXUNUSED(value) )
3052{
3053}
3054
3055void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row), int WXUNUSED(col),
3056 double WXUNUSED(value) )
3057{
3058}
3059
3060void wxGridTableBase::SetValueAsBool( int WXUNUSED(row), int WXUNUSED(col),
3061 bool WXUNUSED(value) )
3062{
3063}
3064
3065
3066void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row), int WXUNUSED(col),
3067 const wxString& WXUNUSED(typeName) )
3068{
3069 return NULL;
3070}
3071
3072void wxGridTableBase::SetValueAsCustom( int WXUNUSED(row), int WXUNUSED(col),
3073 const wxString& WXUNUSED(typeName),
3074 void* WXUNUSED(value) )
3075{
3076}
3077
f85afd4e
MB
3078//////////////////////////////////////////////////////////////////////
3079//
3080// Message class for the grid table to send requests and notifications
3081// to the grid view
3082//
3083
3084wxGridTableMessage::wxGridTableMessage()
3085{
3086 m_table = (wxGridTableBase *) NULL;
3087 m_id = -1;
3088 m_comInt1 = -1;
3089 m_comInt2 = -1;
3090}
3091
3092wxGridTableMessage::wxGridTableMessage( wxGridTableBase *table, int id,
3093 int commandInt1, int commandInt2 )
3094{
3095 m_table = table;
3096 m_id = id;
3097 m_comInt1 = commandInt1;
3098 m_comInt2 = commandInt2;
3099}
3100
3101
3102
3103//////////////////////////////////////////////////////////////////////
3104//
3105// A basic grid table for string data. An object of this class will
3106// created by wxGrid if you don't specify an alternative table class.
3107//
3108
223d09f6 3109WX_DEFINE_OBJARRAY(wxGridStringArray)
f85afd4e
MB
3110
3111IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable, wxGridTableBase )
3112
3113wxGridStringTable::wxGridStringTable()
3114 : wxGridTableBase()
3115{
3116}
3117
3118wxGridStringTable::wxGridStringTable( int numRows, int numCols )
3119 : wxGridTableBase()
3120{
f85afd4e
MB
3121 m_data.Alloc( numRows );
3122
3123 wxArrayString sa;
3124 sa.Alloc( numCols );
27f35b66 3125 sa.Add( wxEmptyString, numCols );
8f177c8e 3126
27f35b66 3127 m_data.Add( sa, numRows );
f85afd4e
MB
3128}
3129
3130wxGridStringTable::~wxGridStringTable()
3131{
3132}
3133
e32352cf 3134int wxGridStringTable::GetNumberRows()
f85afd4e
MB
3135{
3136 return m_data.GetCount();
3137}
3138
e32352cf 3139int wxGridStringTable::GetNumberCols()
f85afd4e
MB
3140{
3141 if ( m_data.GetCount() > 0 )
3142 return m_data[0].GetCount();
3143 else
3144 return 0;
3145}
3146
3147wxString wxGridStringTable::GetValue( int row, int col )
3148{
3e13956a
RD
3149 wxCHECK_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
3150 wxEmptyString,
3151 _T("invalid row or column index in wxGridStringTable") );
af547d51 3152
f85afd4e
MB
3153 return m_data[row][col];
3154}
3155
f2d76237 3156void wxGridStringTable::SetValue( int row, int col, const wxString& value )
f85afd4e 3157{
3e13956a
RD
3158 wxCHECK_RET( (row < GetNumberRows()) && (col < GetNumberCols()),
3159 _T("invalid row or column index in wxGridStringTable") );
af547d51 3160
f2d76237 3161 m_data[row][col] = value;
f85afd4e
MB
3162}
3163
3164bool wxGridStringTable::IsEmptyCell( int row, int col )
3165{
3e13956a
RD
3166 wxCHECK_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
3167 true,
af547d51
VZ
3168 _T("invalid row or column index in wxGridStringTable") );
3169
f85afd4e
MB
3170 return (m_data[row][col] == wxEmptyString);
3171}
3172
f85afd4e
MB
3173void wxGridStringTable::Clear()
3174{
3175 int row, col;
3176 int numRows, numCols;
8f177c8e 3177
f85afd4e
MB
3178 numRows = m_data.GetCount();
3179 if ( numRows > 0 )
3180 {
3181 numCols = m_data[0].GetCount();
3182
3183 for ( row = 0; row < numRows; row++ )
3184 {
3185 for ( col = 0; col < numCols; col++ )
3186 {
3187 m_data[row][col] = wxEmptyString;
3188 }
3189 }
3190 }
3191}
3192
3193
3194bool wxGridStringTable::InsertRows( size_t pos, size_t numRows )
3195{
f85afd4e 3196 size_t curNumRows = m_data.GetCount();
f6bcfd97
BP
3197 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
3198 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
8f177c8e 3199
f85afd4e
MB
3200 if ( pos >= curNumRows )
3201 {
3202 return AppendRows( numRows );
3203 }
8f177c8e 3204
f85afd4e
MB
3205 wxArrayString sa;
3206 sa.Alloc( curNumCols );
27f35b66
SN
3207 sa.Add( wxEmptyString, curNumCols );
3208 m_data.Insert( sa, pos, numRows );
f85afd4e
MB
3209 if ( GetView() )
3210 {
3211 wxGridTableMessage msg( this,
3212 wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
3213 pos,
3214 numRows );
8f177c8e 3215
f85afd4e
MB
3216 GetView()->ProcessTableMessage( msg );
3217 }
3218
ca65c044 3219 return true;
f85afd4e
MB
3220}
3221
3222bool wxGridStringTable::AppendRows( size_t numRows )
3223{
f85afd4e 3224 size_t curNumRows = m_data.GetCount();
f6bcfd97
BP
3225 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
3226 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
8f177c8e 3227
f85afd4e
MB
3228 wxArrayString sa;
3229 if ( curNumCols > 0 )
3230 {
3231 sa.Alloc( curNumCols );
27f35b66 3232 sa.Add( wxEmptyString, curNumCols );
f85afd4e 3233 }
8f177c8e 3234
27f35b66 3235 m_data.Add( sa, numRows );
f85afd4e
MB
3236
3237 if ( GetView() )
3238 {
3239 wxGridTableMessage msg( this,
3240 wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
3241 numRows );
8f177c8e 3242
f85afd4e
MB
3243 GetView()->ProcessTableMessage( msg );
3244 }
3245
ca65c044 3246 return true;
f85afd4e
MB
3247}
3248
3249bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows )
3250{
f85afd4e 3251 size_t curNumRows = m_data.GetCount();
8f177c8e 3252
f85afd4e
MB
3253 if ( pos >= curNumRows )
3254 {
e91d2033
VZ
3255 wxFAIL_MSG( wxString::Format
3256 (
3257 wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"),
3258 (unsigned long)pos,
3259 (unsigned long)numRows,
3260 (unsigned long)curNumRows
3261 ) );
3262
ca65c044 3263 return false;
f85afd4e
MB
3264 }
3265
3266 if ( numRows > curNumRows - pos )
3267 {
3268 numRows = curNumRows - pos;
3269 }
8f177c8e 3270
f85afd4e
MB
3271 if ( numRows >= curNumRows )
3272 {
d57ad377 3273 m_data.Clear();
f85afd4e
MB
3274 }
3275 else
3276 {
27f35b66 3277 m_data.RemoveAt( pos, numRows );
f85afd4e 3278 }
f85afd4e
MB
3279 if ( GetView() )
3280 {
3281 wxGridTableMessage msg( this,
3282 wxGRIDTABLE_NOTIFY_ROWS_DELETED,
3283 pos,
3284 numRows );
8f177c8e 3285
f85afd4e
MB
3286 GetView()->ProcessTableMessage( msg );
3287 }
3288
ca65c044 3289 return true;
f85afd4e
MB
3290}
3291
3292bool wxGridStringTable::InsertCols( size_t pos, size_t numCols )
3293{
3294 size_t row, col;
3295
3296 size_t curNumRows = m_data.GetCount();
f6bcfd97
BP
3297 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
3298 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
8f177c8e 3299
f85afd4e
MB
3300 if ( pos >= curNumCols )
3301 {
3302 return AppendCols( numCols );
3303 }
3304
3305 for ( row = 0; row < curNumRows; row++ )
3306 {
3307 for ( col = pos; col < pos + numCols; col++ )
3308 {
3309 m_data[row].Insert( wxEmptyString, col );
3310 }
3311 }
f85afd4e
MB
3312 if ( GetView() )
3313 {
3314 wxGridTableMessage msg( this,
3315 wxGRIDTABLE_NOTIFY_COLS_INSERTED,
3316 pos,
3317 numCols );
8f177c8e 3318
f85afd4e
MB
3319 GetView()->ProcessTableMessage( msg );
3320 }
3321
ca65c044 3322 return true;
f85afd4e
MB
3323}
3324
3325bool wxGridStringTable::AppendCols( size_t numCols )
3326{
27f35b66 3327 size_t row;
f85afd4e
MB
3328
3329 size_t curNumRows = m_data.GetCount();
f6bcfd97 3330#if 0
f85afd4e
MB
3331 if ( !curNumRows )
3332 {
3333 // TODO: something better than this ?
3334 //
f6bcfd97 3335 wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") );
ca65c044 3336 return false;
f85afd4e 3337 }
f6bcfd97 3338#endif
8f177c8e 3339
f85afd4e
MB
3340 for ( row = 0; row < curNumRows; row++ )
3341 {
27f35b66 3342 m_data[row].Add( wxEmptyString, numCols );
f85afd4e
MB
3343 }
3344
3345 if ( GetView() )
3346 {
3347 wxGridTableMessage msg( this,
3348 wxGRIDTABLE_NOTIFY_COLS_APPENDED,
3349 numCols );
8f177c8e 3350
f85afd4e
MB
3351 GetView()->ProcessTableMessage( msg );
3352 }
3353
ca65c044 3354 return true;
f85afd4e
MB
3355}
3356
3357bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
3358{
27f35b66 3359 size_t row;
f85afd4e
MB
3360
3361 size_t curNumRows = m_data.GetCount();
f6bcfd97
BP
3362 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
3363 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
8f177c8e 3364
f85afd4e
MB
3365 if ( pos >= curNumCols )
3366 {
e91d2033
VZ
3367 wxFAIL_MSG( wxString::Format
3368 (
3369 wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"),
3370 (unsigned long)pos,
3371 (unsigned long)numCols,
3372 (unsigned long)curNumCols
3373 ) );
ca65c044 3374 return false;
f85afd4e
MB
3375 }
3376
3377 if ( numCols > curNumCols - pos )
3378 {
8f177c8e 3379 numCols = curNumCols - pos;
f85afd4e
MB
3380 }
3381
3382 for ( row = 0; row < curNumRows; row++ )
3383 {
3384 if ( numCols >= curNumCols )
3385 {
dcdce64e 3386 m_data[row].Clear();
f85afd4e
MB
3387 }
3388 else
3389 {
27f35b66 3390 m_data[row].RemoveAt( pos, numCols );
f85afd4e
MB
3391 }
3392 }
f85afd4e
MB
3393 if ( GetView() )
3394 {
3395 wxGridTableMessage msg( this,
3396 wxGRIDTABLE_NOTIFY_COLS_DELETED,
3397 pos,
3398 numCols );
8f177c8e 3399
f85afd4e
MB
3400 GetView()->ProcessTableMessage( msg );
3401 }
3402
ca65c044 3403 return true;
f85afd4e
MB
3404}
3405
3406wxString wxGridStringTable::GetRowLabelValue( int row )
3407{
3408 if ( row > (int)(m_rowLabels.GetCount()) - 1 )
3409 {
3410 // using default label
3411 //
3412 return wxGridTableBase::GetRowLabelValue( row );
3413 }
3414 else
3415 {
3416 return m_rowLabels[ row ];
3417 }
3418}
3419
3420wxString wxGridStringTable::GetColLabelValue( int col )
3421{
3422 if ( col > (int)(m_colLabels.GetCount()) - 1 )
3423 {
3424 // using default label
3425 //
3426 return wxGridTableBase::GetColLabelValue( col );
3427 }
3428 else
3429 {
3430 return m_colLabels[ col ];
3431 }
3432}
3433
3434void wxGridStringTable::SetRowLabelValue( int row, const wxString& value )
3435{
3436 if ( row > (int)(m_rowLabels.GetCount()) - 1 )
3437 {
3438 int n = m_rowLabels.GetCount();
3439 int i;
3440 for ( i = n; i <= row; i++ )
3441 {
3442 m_rowLabels.Add( wxGridTableBase::GetRowLabelValue(i) );
3443 }
3444 }
3445
3446 m_rowLabels[row] = value;
3447}
3448
3449void wxGridStringTable::SetColLabelValue( int col, const wxString& value )
3450{
3451 if ( col > (int)(m_colLabels.GetCount()) - 1 )
3452 {
3453 int n = m_colLabels.GetCount();
3454 int i;
3455 for ( i = n; i <= col; i++ )
3456 {
3457 m_colLabels.Add( wxGridTableBase::GetColLabelValue(i) );
3458 }
3459 }
3460
3461 m_colLabels[col] = value;
3462}
3463
3464
3465
f85afd4e 3466//////////////////////////////////////////////////////////////////////
2d66e025
MB
3467//////////////////////////////////////////////////////////////////////
3468
3469IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow, wxWindow )
3470
3471BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxWindow )
3472 EVT_PAINT( wxGridRowLabelWindow::OnPaint )
b51c3f27 3473 EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel)
2d66e025
MB
3474 EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent )
3475 EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown )
f6bcfd97 3476 EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp )
2d66e025
MB
3477END_EVENT_TABLE()
3478
60ff3b99
VZ
3479wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid *parent,
3480 wxWindowID id,
2d66e025 3481 const wxPoint &pos, const wxSize &size )
73bb6776 3482 : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE|wxFULL_REPAINT_ON_RESIZE )
2d66e025
MB
3483{
3484 m_owner = parent;
3485}
3486
aa5e1f75 3487void wxGridRowLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
2d66e025
MB
3488{
3489 wxPaintDC dc(this);
3490
3491 // NO - don't do this because it will set both the x and y origin
3492 // coords to match the parent scrolled window and we just want to
3493 // set the y coord - MB
3494 //
3495 // m_owner->PrepareDC( dc );
60ff3b99 3496
790ad94f 3497 int x, y;
2d66e025
MB
3498 m_owner->CalcUnscrolledPosition( 0, 0, &x, &y );
3499 dc.SetDeviceOrigin( 0, -y );
60ff3b99 3500
d10f4bf9
VZ
3501 wxArrayInt rows = m_owner->CalcRowLabelsExposed( GetUpdateRegion() );
3502 m_owner->DrawRowLabels( dc , rows );
2d66e025
MB
3503}
3504
3505
3506void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent& event )
3507{
3508 m_owner->ProcessRowLabelMouseEvent( event );
3509}
3510
3511
b51c3f27
RD
3512void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent& event )
3513{
3514 m_owner->GetEventHandler()->ProcessEvent(event);
3515}
3516
3517
2d66e025
MB
3518// This seems to be required for wxMotif otherwise the mouse
3519// cursor must be in the cell edit control to get key events
3520//
3521void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent& event )
3522{
ffdd3c98 3523 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
2d66e025
MB
3524}
3525
f6bcfd97
BP
3526void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent& event )
3527{
ffdd3c98 3528 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
f6bcfd97
BP
3529}
3530
2d66e025
MB
3531
3532
3533//////////////////////////////////////////////////////////////////////
3534
3535IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow, wxWindow )
3536
3537BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxWindow )
3538 EVT_PAINT( wxGridColLabelWindow::OnPaint )
b51c3f27 3539 EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel)
2d66e025
MB
3540 EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent )
3541 EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown )
f6bcfd97 3542 EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp )
2d66e025
MB
3543END_EVENT_TABLE()
3544
60ff3b99
VZ
3545wxGridColLabelWindow::wxGridColLabelWindow( wxGrid *parent,
3546 wxWindowID id,
2d66e025 3547 const wxPoint &pos, const wxSize &size )
73bb6776 3548 : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE|wxFULL_REPAINT_ON_RESIZE )
2d66e025
MB
3549{
3550 m_owner = parent;
3551}
3552
aa5e1f75 3553void wxGridColLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
2d66e025
MB
3554{
3555 wxPaintDC dc(this);
3556
3557 // NO - don't do this because it will set both the x and y origin
3558 // coords to match the parent scrolled window and we just want to
3559 // set the x coord - MB
3560 //
3561 // m_owner->PrepareDC( dc );
60ff3b99 3562
790ad94f 3563 int x, y;
2d66e025
MB
3564 m_owner->CalcUnscrolledPosition( 0, 0, &x, &y );
3565 dc.SetDeviceOrigin( -x, 0 );
3566
d10f4bf9
VZ
3567 wxArrayInt cols = m_owner->CalcColLabelsExposed( GetUpdateRegion() );
3568 m_owner->DrawColLabels( dc , cols );
2d66e025
MB
3569}
3570
3571
3572void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent& event )
3573{
3574 m_owner->ProcessColLabelMouseEvent( event );
3575}
3576
b51c3f27
RD
3577void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent& event )
3578{
3579 m_owner->GetEventHandler()->ProcessEvent(event);
3580}
3581
2d66e025
MB
3582
3583// This seems to be required for wxMotif otherwise the mouse
3584// cursor must be in the cell edit control to get key events
3585//
3586void wxGridColLabelWindow::OnKeyDown( wxKeyEvent& event )
3587{
ffdd3c98 3588 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
2d66e025
MB
3589}
3590
f6bcfd97
BP
3591void wxGridColLabelWindow::OnKeyUp( wxKeyEvent& event )
3592{
ffdd3c98 3593 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
f6bcfd97
BP
3594}
3595
2d66e025
MB
3596
3597
3598//////////////////////////////////////////////////////////////////////
3599
3600IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow, wxWindow )
3601
3602BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxWindow )
b51c3f27 3603 EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel)
2d66e025 3604 EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent )
d2fdd8d2 3605 EVT_PAINT( wxGridCornerLabelWindow::OnPaint)
2d66e025 3606 EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown )
f6bcfd97 3607 EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp )
2d66e025
MB
3608END_EVENT_TABLE()
3609
60ff3b99
VZ
3610wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent,
3611 wxWindowID id,
2d66e025 3612 const wxPoint &pos, const wxSize &size )
73bb6776 3613 : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE|wxFULL_REPAINT_ON_RESIZE )
2d66e025
MB
3614{
3615 m_owner = parent;
3616}
3617
d2fdd8d2
RR
3618void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
3619{
3620 wxPaintDC dc(this);
b99be8fb 3621
d2fdd8d2
RR
3622 int client_height = 0;
3623 int client_width = 0;
3624 GetClientSize( &client_width, &client_height );
b99be8fb 3625
73145b0e 3626 dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) );
d2fdd8d2
RR
3627 dc.DrawLine( client_width-1, client_height-1, client_width-1, 0 );
3628 dc.DrawLine( client_width-1, client_height-1, 0, client_height-1 );
d2fdd8d2
RR
3629 dc.DrawLine( 0, 0, client_width, 0 );
3630 dc.DrawLine( 0, 0, 0, client_height );
73145b0e
JS
3631
3632 dc.SetPen( *wxWHITE_PEN );
3633 dc.DrawLine( 1, 1, client_width-1, 1 );
3634 dc.DrawLine( 1, 1, 1, client_height-1 );
d2fdd8d2
RR
3635}
3636
2d66e025
MB
3637
3638void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent& event )
3639{
3640 m_owner->ProcessCornerLabelMouseEvent( event );
3641}
3642
3643
b51c3f27
RD
3644void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent& event )
3645{
3646 m_owner->GetEventHandler()->ProcessEvent(event);
3647}
3648
2d66e025
MB
3649// This seems to be required for wxMotif otherwise the mouse
3650// cursor must be in the cell edit control to get key events
3651//
3652void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent& event )
3653{
ffdd3c98 3654 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
2d66e025
MB
3655}
3656
f6bcfd97
BP
3657void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent& event )
3658{
ffdd3c98 3659 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
f6bcfd97
BP
3660}
3661
2d66e025
MB
3662
3663
f85afd4e
MB
3664//////////////////////////////////////////////////////////////////////
3665
59ddac01 3666IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxWindow )
2d66e025 3667
59ddac01 3668BEGIN_EVENT_TABLE( wxGridWindow, wxWindow )
2d66e025 3669 EVT_PAINT( wxGridWindow::OnPaint )
b51c3f27 3670 EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel)
2d66e025
MB
3671 EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent )
3672 EVT_KEY_DOWN( wxGridWindow::OnKeyDown )
f6bcfd97 3673 EVT_KEY_UP( wxGridWindow::OnKeyUp )
80acaf25
JS
3674 EVT_SET_FOCUS( wxGridWindow::OnFocus )
3675 EVT_KILL_FOCUS( wxGridWindow::OnFocus )
2796cce3 3676 EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground )
2d66e025
MB
3677END_EVENT_TABLE()
3678
60ff3b99
VZ
3679wxGridWindow::wxGridWindow( wxGrid *parent,
3680 wxGridRowLabelWindow *rowLblWin,
2d66e025 3681 wxGridColLabelWindow *colLblWin,
04418332
VZ
3682 wxWindowID id,
3683 const wxPoint &pos,
3684 const wxSize &size )
73bb6776 3685 : wxWindow( parent, id, pos, size, wxWANTS_CHARS | wxBORDER_NONE | wxCLIP_CHILDREN|wxFULL_REPAINT_ON_RESIZE,
04418332 3686 wxT("grid window") )
73145b0e 3687
2d66e025
MB
3688{
3689 m_owner = parent;
3690 m_rowLabelWin = rowLblWin;
3691 m_colLabelWin = colLblWin;
2d66e025
MB
3692}
3693
3694
3695wxGridWindow::~wxGridWindow()
3696{
3697}
3698
3699
3700void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
3701{
3702 wxPaintDC dc( this );
3703 m_owner->PrepareDC( dc );
796df70a 3704 wxRegion reg = GetUpdateRegion();
d10f4bf9
VZ
3705 wxGridCellCoordsArray DirtyCells = m_owner->CalcCellsExposed( reg );
3706 m_owner->DrawGridCellArea( dc , DirtyCells);
9496deb5 3707#if WXGRID_DRAW_LINES
796df70a
SN
3708 m_owner->DrawAllGridLines( dc, reg );
3709#endif
a5777624 3710 m_owner->DrawGridSpace( dc );
d10f4bf9 3711 m_owner->DrawHighlight( dc , DirtyCells );
2d66e025
MB
3712}
3713
3714
3715void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect )
3716{
59ddac01 3717 wxWindow::ScrollWindow( dx, dy, rect );
2d66e025
MB
3718 m_rowLabelWin->ScrollWindow( 0, dy, rect );
3719 m_colLabelWin->ScrollWindow( dx, 0, rect );
3720}
3721
3722
3723void wxGridWindow::OnMouseEvent( wxMouseEvent& event )
3724{
3725 m_owner->ProcessGridCellMouseEvent( event );
3726}
3727
b51c3f27
RD
3728void wxGridWindow::OnMouseWheel( wxMouseEvent& event )
3729{
3730 m_owner->GetEventHandler()->ProcessEvent(event);
3731}
2d66e025 3732
f6bcfd97 3733// This seems to be required for wxMotif/wxGTK otherwise the mouse
2d66e025
MB
3734// cursor must be in the cell edit control to get key events
3735//
3736void wxGridWindow::OnKeyDown( wxKeyEvent& event )
3737{
ffdd3c98 3738 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
2d66e025 3739}
f85afd4e 3740
f6bcfd97
BP
3741void wxGridWindow::OnKeyUp( wxKeyEvent& event )
3742{
ffdd3c98 3743 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) ) event.Skip();
f6bcfd97 3744}
7c8a8ad5 3745
aa5e1f75 3746void wxGridWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(event) )
8dd4f536 3747{
8dd4f536 3748}
025562fe 3749
80acaf25
JS
3750void wxGridWindow::OnFocus(wxFocusEvent& event)
3751{
3752 if ( !m_owner->GetEventHandler()->ProcessEvent( event ) )
3753 event.Skip();
3754}
2d66e025
MB
3755
3756//////////////////////////////////////////////////////////////////////
3757
33188aa4
SN
3758// Internal Helper function for computing row or column from some
3759// (unscrolled) coordinate value, using either
70e8d961 3760// m_defaultRowHeight/m_defaultColWidth or binary search on array
33188aa4
SN
3761// of m_rowBottoms/m_ColRights to speed up the search!
3762
3763// Internal helper macros for simpler use of that function
3764
3765static int CoordToRowOrCol(int coord, int defaultDist, int minDist,
64e15340 3766 const wxArrayInt& BorderArray, int nMax,
a967f048 3767 bool clipToMinMax);
33188aa4
SN
3768
3769#define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \
b8d24d4e 3770 m_minAcceptableColWidth, \
ca65c044 3771 m_colRights, m_numCols, true)
33188aa4 3772#define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \
b8d24d4e 3773 m_minAcceptableRowHeight, \
ca65c044 3774 m_rowBottoms, m_numRows, true)
33188aa4 3775/////////////////////////////////////////////////////////////////////
07296f0b 3776
b0a877ec 3777#if wxUSE_EXTENDED_RTTI
73c36334
JS
3778WX_DEFINE_FLAGS( wxGridStyle )
3779
3ff066a4 3780wxBEGIN_FLAGS( wxGridStyle )
73c36334
JS
3781 // new style border flags, we put them first to
3782 // use them for streaming out
3ff066a4
SC
3783 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
3784 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
3785 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
3786 wxFLAGS_MEMBER(wxBORDER_RAISED)
3787 wxFLAGS_MEMBER(wxBORDER_STATIC)
3788 wxFLAGS_MEMBER(wxBORDER_NONE)
ca65c044 3789
73c36334 3790 // old style border flags
3ff066a4
SC
3791 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
3792 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
3793 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
3794 wxFLAGS_MEMBER(wxRAISED_BORDER)
3795 wxFLAGS_MEMBER(wxSTATIC_BORDER)
cb0afb26 3796 wxFLAGS_MEMBER(wxBORDER)
73c36334
JS
3797
3798 // standard window styles
3ff066a4
SC
3799 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
3800 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
3801 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
3802 wxFLAGS_MEMBER(wxWANTS_CHARS)
cb0afb26 3803 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
3ff066a4
SC
3804 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
3805 wxFLAGS_MEMBER(wxVSCROLL)
3806 wxFLAGS_MEMBER(wxHSCROLL)
73c36334 3807
3ff066a4 3808wxEND_FLAGS( wxGridStyle )
73c36334 3809
b0a877ec
SC
3810IMPLEMENT_DYNAMIC_CLASS_XTI(wxGrid, wxScrolledWindow,"wx/grid.h")
3811
3ff066a4
SC
3812wxBEGIN_PROPERTIES_TABLE(wxGrid)
3813 wxHIDE_PROPERTY( Children )
af498247 3814 wxPROPERTY_FLAGS( WindowStyle , wxGridStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
3ff066a4 3815wxEND_PROPERTIES_TABLE()
b0a877ec 3816
3ff066a4
SC
3817wxBEGIN_HANDLERS_TABLE(wxGrid)
3818wxEND_HANDLERS_TABLE()
b0a877ec 3819
ca65c044 3820wxCONSTRUCTOR_5( wxGrid , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
b0a877ec
SC
3821
3822/*
3823