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