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