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