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