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