split wxGrid implementation in grideditors.cpp (for wxGridCellEditor-derived classes...
[wxWidgets.git] / src / generic / gridctrl.cpp
1 ///////////////////////////////////////////////////////////////////////////
2 // Name: generic/gridctrl.cpp
3 // Purpose: wxGrid controls
4 // Author: Paul Gammans, Roger Gammans
5 // Modified by:
6 // Created: 11/04/2001
7 // RCS-ID: $Id$
8 // Copyright: (c) The Computer Surgery (paul@compsurg.co.uk)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #if wxUSE_GRID
19
20 #include "wx/generic/gridctrl.h"
21 #include "wx/generic/grideditors.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/textctrl.h"
25 #include "wx/dc.h"
26 #include "wx/combobox.h"
27 #endif // WX_PRECOMP
28
29 #include "wx/tokenzr.h"
30 #include "wx/renderer.h"
31
32 // ----------------------------------------------------------------------------
33 // wxGridCellDateTimeRenderer
34 // ----------------------------------------------------------------------------
35
36 #if wxUSE_DATETIME
37
38 // Enables a grid cell to display a formatted date and or time
39
40 wxGridCellDateTimeRenderer::wxGridCellDateTimeRenderer(const wxString& outformat, const wxString& informat)
41 {
42 m_iformat = informat;
43 m_oformat = outformat;
44 m_tz = wxDateTime::Local;
45 m_dateDef = wxDefaultDateTime;
46 }
47
48 wxGridCellRenderer *wxGridCellDateTimeRenderer::Clone() const
49 {
50 wxGridCellDateTimeRenderer *renderer = new wxGridCellDateTimeRenderer;
51 renderer->m_iformat = m_iformat;
52 renderer->m_oformat = m_oformat;
53 renderer->m_dateDef = m_dateDef;
54 renderer->m_tz = m_tz;
55
56 return renderer;
57 }
58
59 wxString wxGridCellDateTimeRenderer::GetString(const wxGrid& grid, int row, int col)
60 {
61 wxGridTableBase *table = grid.GetTable();
62
63 bool hasDatetime = false;
64 wxDateTime val;
65 wxString text;
66 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_DATETIME) )
67 {
68 void * tempval = table->GetValueAsCustom(row, col,wxGRID_VALUE_DATETIME);
69
70 if (tempval)
71 {
72 val = *((wxDateTime *)tempval);
73 hasDatetime = true;
74 delete (wxDateTime *)tempval;
75 }
76
77 }
78
79 if (!hasDatetime )
80 {
81 text = table->GetValue(row, col);
82 const char * const end = val.ParseFormat(text, m_iformat, m_dateDef);
83 hasDatetime = end && !*end;
84 }
85
86 if ( hasDatetime )
87 text = val.Format(m_oformat, m_tz );
88
89 // If we failed to parse string just show what we where given?
90 return text;
91 }
92
93 void wxGridCellDateTimeRenderer::Draw(wxGrid& grid,
94 wxGridCellAttr& attr,
95 wxDC& dc,
96 const wxRect& rectCell,
97 int row, int col,
98 bool isSelected)
99 {
100 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
101
102 SetTextColoursAndFont(grid, attr, dc, isSelected);
103
104 // draw the text right aligned by default
105 int hAlign, vAlign;
106 attr.GetAlignment(&hAlign, &vAlign);
107 hAlign = wxRIGHT;
108
109 wxRect rect = rectCell;
110 rect.Inflate(-1);
111
112 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
113 }
114
115 wxSize wxGridCellDateTimeRenderer::GetBestSize(wxGrid& grid,
116 wxGridCellAttr& attr,
117 wxDC& dc,
118 int row, int col)
119 {
120 return DoGetBestSize(attr, dc, GetString(grid, row, col));
121 }
122
123 void wxGridCellDateTimeRenderer::SetParameters(const wxString& params)
124 {
125 if (!params.empty())
126 m_oformat=params;
127 }
128
129 #endif // wxUSE_DATETIME
130
131 // ----------------------------------------------------------------------------
132 // wxGridCellChoiceNumberRenderer
133 // ----------------------------------------------------------------------------
134 // Renders a number as a textual equivalent.
135 // eg data in cell is 0,1,2 ... n the cell could be rendered as "John","Fred"..."Bob"
136
137
138 wxGridCellEnumRenderer::wxGridCellEnumRenderer(const wxString& choices)
139 {
140 if (!choices.empty())
141 SetParameters(choices);
142 }
143
144 wxGridCellRenderer *wxGridCellEnumRenderer::Clone() const
145 {
146 wxGridCellEnumRenderer *renderer = new wxGridCellEnumRenderer;
147 renderer->m_choices = m_choices;
148 return renderer;
149 }
150
151 wxString wxGridCellEnumRenderer::GetString(const wxGrid& grid, int row, int col)
152 {
153 wxGridTableBase *table = grid.GetTable();
154 wxString text;
155 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
156 {
157 int choiceno = table->GetValueAsLong(row, col);
158 text.Printf(_T("%s"), m_choices[ choiceno ].c_str() );
159 }
160 else
161 {
162 text = table->GetValue(row, col);
163 }
164
165
166 //If we faild to parse string just show what we where given?
167 return text;
168 }
169
170 void wxGridCellEnumRenderer::Draw(wxGrid& grid,
171 wxGridCellAttr& attr,
172 wxDC& dc,
173 const wxRect& rectCell,
174 int row, int col,
175 bool isSelected)
176 {
177 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
178
179 SetTextColoursAndFont(grid, attr, dc, isSelected);
180
181 // draw the text right aligned by default
182 int hAlign, vAlign;
183 attr.GetAlignment(&hAlign, &vAlign);
184 hAlign = wxRIGHT;
185
186 wxRect rect = rectCell;
187 rect.Inflate(-1);
188
189 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
190 }
191
192 wxSize wxGridCellEnumRenderer::GetBestSize(wxGrid& grid,
193 wxGridCellAttr& attr,
194 wxDC& dc,
195 int row, int col)
196 {
197 return DoGetBestSize(attr, dc, GetString(grid, row, col));
198 }
199
200 void wxGridCellEnumRenderer::SetParameters(const wxString& params)
201 {
202 if ( !params )
203 {
204 // what can we do?
205 return;
206 }
207
208 m_choices.Empty();
209
210 wxStringTokenizer tk(params, _T(','));
211 while ( tk.HasMoreTokens() )
212 {
213 m_choices.Add(tk.GetNextToken());
214 }
215 }
216
217
218 // ----------------------------------------------------------------------------
219 // wxGridCellAutoWrapStringRenderer
220 // ----------------------------------------------------------------------------
221
222
223 void
224 wxGridCellAutoWrapStringRenderer::Draw(wxGrid& grid,
225 wxGridCellAttr& attr,
226 wxDC& dc,
227 const wxRect& rectCell,
228 int row, int col,
229 bool isSelected) {
230
231
232 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
233
234 // now we only have to draw the text
235 SetTextColoursAndFont(grid, attr, dc, isSelected);
236
237 int horizAlign, vertAlign;
238 attr.GetAlignment(&horizAlign, &vertAlign);
239
240 wxRect rect = rectCell;
241 rect.Inflate(-1);
242
243 grid.DrawTextRectangle(dc, GetTextLines(grid,dc,attr,rect,row,col),
244 rect, horizAlign, vertAlign);
245 }
246
247
248 wxArrayString
249 wxGridCellAutoWrapStringRenderer::GetTextLines(wxGrid& grid,
250 wxDC& dc,
251 const wxGridCellAttr& attr,
252 const wxRect& rect,
253 int row, int col)
254 {
255 wxString data = grid.GetCellValue(row, col);
256
257 wxArrayString lines;
258 dc.SetFont(attr.GetFont());
259
260 //Taken from wxGrid again!
261 wxCoord x = 0, y = 0, curr_x = 0;
262 wxCoord max_x = rect.GetWidth();
263
264 dc.SetFont(attr.GetFont());
265 wxStringTokenizer tk(data , _T(" \n\t\r"));
266 wxString thisline = wxEmptyString;
267
268 while ( tk.HasMoreTokens() )
269 {
270 wxString tok = tk.GetNextToken();
271 //FIXME: this causes us to print an extra unnecesary
272 // space at the end of the line. But it
273 // is invisible , simplifies the size calculation
274 // and ensures tokens are separated in the display
275 tok += _T(" ");
276
277 dc.GetTextExtent(tok, &x, &y);
278 if ( curr_x + x > max_x)
279 {
280 lines.Add( wxString(thisline) );
281 thisline = tok;
282 curr_x=x;
283 }
284 else
285 {
286 thisline+= tok;
287 curr_x += x;
288 }
289 }
290 //Add last line
291 lines.Add( wxString(thisline) );
292
293 return lines;
294 }
295
296
297 wxSize
298 wxGridCellAutoWrapStringRenderer::GetBestSize(wxGrid& grid,
299 wxGridCellAttr& attr,
300 wxDC& dc,
301 int row, int col)
302 {
303 wxCoord x,y, height , width = grid.GetColSize(col) -20;
304 // for width, subtract 20 because ColSize includes a magin of 10 pixels
305 // that we do not want here and because we always start with an increment
306 // by 10 in the loop below.
307 int count = 250; //Limit iterations..
308
309 wxRect rect(0,0,width,10);
310
311 // M is a nice large character 'y' gives descender!.
312 dc.GetTextExtent(wxT("My"), &x, &y);
313
314 do
315 {
316 width+=10;
317 rect.SetWidth(width);
318 height = y * (wx_truncate_cast(wxCoord, GetTextLines(grid,dc,attr,rect,row,col).GetCount()));
319 count--;
320 // Search for a shape no taller than the golden ratio.
321 } while (count && (width < (height*1.68)) );
322
323
324 return wxSize(width,height);
325 }
326
327
328 // ----------------------------------------------------------------------------
329 // wxGridCellRenderer
330 // ----------------------------------------------------------------------------
331
332 void wxGridCellRenderer::Draw(wxGrid& grid,
333 wxGridCellAttr& attr,
334 wxDC& dc,
335 const wxRect& rect,
336 int WXUNUSED(row), int WXUNUSED(col),
337 bool isSelected)
338 {
339 dc.SetBackgroundMode( wxBRUSHSTYLE_SOLID );
340
341 wxColour clr;
342 if ( grid.IsEnabled() )
343 {
344 if ( isSelected )
345 {
346 if ( grid.HasFocus() )
347 clr = grid.GetSelectionBackground();
348 else
349 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
350 }
351 else
352 {
353 clr = attr.GetBackgroundColour();
354 }
355 }
356 else // grey out fields if the grid is disabled
357 {
358 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
359 }
360
361 dc.SetBrush(clr);
362 dc.SetPen( *wxTRANSPARENT_PEN );
363 dc.DrawRectangle(rect);
364 }
365
366 // ----------------------------------------------------------------------------
367 // wxGridCellStringRenderer
368 // ----------------------------------------------------------------------------
369
370 void wxGridCellStringRenderer::SetTextColoursAndFont(const wxGrid& grid,
371 const wxGridCellAttr& attr,
372 wxDC& dc,
373 bool isSelected)
374 {
375 dc.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT );
376
377 // TODO some special colours for attr.IsReadOnly() case?
378
379 // different coloured text when the grid is disabled
380 if ( grid.IsEnabled() )
381 {
382 if ( isSelected )
383 {
384 wxColour clr;
385 if ( grid.HasFocus() )
386 clr = grid.GetSelectionBackground();
387 else
388 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
389 dc.SetTextBackground( clr );
390 dc.SetTextForeground( grid.GetSelectionForeground() );
391 }
392 else
393 {
394 dc.SetTextBackground( attr.GetBackgroundColour() );
395 dc.SetTextForeground( attr.GetTextColour() );
396 }
397 }
398 else
399 {
400 dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
401 dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
402 }
403
404 dc.SetFont( attr.GetFont() );
405 }
406
407 wxSize wxGridCellStringRenderer::DoGetBestSize(const wxGridCellAttr& attr,
408 wxDC& dc,
409 const wxString& text)
410 {
411 wxCoord x = 0, y = 0, max_x = 0;
412 dc.SetFont(attr.GetFont());
413 wxStringTokenizer tk(text, _T('\n'));
414 while ( tk.HasMoreTokens() )
415 {
416 dc.GetTextExtent(tk.GetNextToken(), &x, &y);
417 max_x = wxMax(max_x, x);
418 }
419
420 y *= 1 + text.Freq(wxT('\n')); // multiply by the number of lines.
421
422 return wxSize(max_x, y);
423 }
424
425 wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid,
426 wxGridCellAttr& attr,
427 wxDC& dc,
428 int row, int col)
429 {
430 return DoGetBestSize(attr, dc, grid.GetCellValue(row, col));
431 }
432
433 void wxGridCellStringRenderer::Draw(wxGrid& grid,
434 wxGridCellAttr& attr,
435 wxDC& dc,
436 const wxRect& rectCell,
437 int row, int col,
438 bool isSelected)
439 {
440 wxRect rect = rectCell;
441 rect.Inflate(-1);
442
443 // erase only this cells background, overflow cells should have been erased
444 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
445
446 int hAlign, vAlign;
447 attr.GetAlignment(&hAlign, &vAlign);
448
449 int overflowCols = 0;
450
451 if (attr.GetOverflow())
452 {
453 int cols = grid.GetNumberCols();
454 int best_width = GetBestSize(grid,attr,dc,row,col).GetWidth();
455 int cell_rows, cell_cols;
456 attr.GetSize( &cell_rows, &cell_cols ); // shouldn't get here if <= 0
457 if ((best_width > rectCell.width) && (col < cols) && grid.GetTable())
458 {
459 int i, c_cols, c_rows;
460 for (i = col+cell_cols; i < cols; i++)
461 {
462 bool is_empty = true;
463 for (int j=row; j < row + cell_rows; j++)
464 {
465 // check w/ anchor cell for multicell block
466 grid.GetCellSize(j, i, &c_rows, &c_cols);
467 if (c_rows > 0)
468 c_rows = 0;
469 if (!grid.GetTable()->IsEmptyCell(j + c_rows, i))
470 {
471 is_empty = false;
472 break;
473 }
474 }
475
476 if (is_empty)
477 {
478 rect.width += grid.GetColSize(i);
479 }
480 else
481 {
482 i--;
483 break;
484 }
485
486 if (rect.width >= best_width)
487 break;
488 }
489
490 overflowCols = i - col - cell_cols + 1;
491 if (overflowCols >= cols)
492 overflowCols = cols - 1;
493 }
494
495 if (overflowCols > 0) // redraw overflow cells w/ proper hilight
496 {
497 hAlign = wxALIGN_LEFT; // if oveflowed then it's left aligned
498 wxRect clip = rect;
499 clip.x += rectCell.width;
500 // draw each overflow cell individually
501 int col_end = col + cell_cols + overflowCols;
502 if (col_end >= grid.GetNumberCols())
503 col_end = grid.GetNumberCols() - 1;
504 for (int i = col + cell_cols; i <= col_end; i++)
505 {
506 clip.width = grid.GetColSize(i) - 1;
507 dc.DestroyClippingRegion();
508 dc.SetClippingRegion(clip);
509
510 SetTextColoursAndFont(grid, attr, dc,
511 grid.IsInSelection(row,i));
512
513 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
514 rect, hAlign, vAlign);
515 clip.x += grid.GetColSize(i) - 1;
516 }
517
518 rect = rectCell;
519 rect.Inflate(-1);
520 rect.width++;
521 dc.DestroyClippingRegion();
522 }
523 }
524
525 // now we only have to draw the text
526 SetTextColoursAndFont(grid, attr, dc, isSelected);
527
528 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
529 rect, hAlign, vAlign);
530 }
531
532 // ----------------------------------------------------------------------------
533 // wxGridCellNumberRenderer
534 // ----------------------------------------------------------------------------
535
536 wxString wxGridCellNumberRenderer::GetString(const wxGrid& grid, int row, int col)
537 {
538 wxGridTableBase *table = grid.GetTable();
539 wxString text;
540 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
541 {
542 text.Printf(_T("%ld"), table->GetValueAsLong(row, col));
543 }
544 else
545 {
546 text = table->GetValue(row, col);
547 }
548
549 return text;
550 }
551
552 void wxGridCellNumberRenderer::Draw(wxGrid& grid,
553 wxGridCellAttr& attr,
554 wxDC& dc,
555 const wxRect& rectCell,
556 int row, int col,
557 bool isSelected)
558 {
559 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
560
561 SetTextColoursAndFont(grid, attr, dc, isSelected);
562
563 // draw the text right aligned by default
564 int hAlign, vAlign;
565 attr.GetAlignment(&hAlign, &vAlign);
566 hAlign = wxALIGN_RIGHT;
567
568 wxRect rect = rectCell;
569 rect.Inflate(-1);
570
571 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
572 }
573
574 wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
575 wxGridCellAttr& attr,
576 wxDC& dc,
577 int row, int col)
578 {
579 return DoGetBestSize(attr, dc, GetString(grid, row, col));
580 }
581
582 // ----------------------------------------------------------------------------
583 // wxGridCellFloatRenderer
584 // ----------------------------------------------------------------------------
585
586 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision)
587 {
588 SetWidth(width);
589 SetPrecision(precision);
590 }
591
592 wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const
593 {
594 wxGridCellFloatRenderer *renderer = new wxGridCellFloatRenderer;
595 renderer->m_width = m_width;
596 renderer->m_precision = m_precision;
597 renderer->m_format = m_format;
598
599 return renderer;
600 }
601
602 wxString wxGridCellFloatRenderer::GetString(const wxGrid& grid, int row, int col)
603 {
604 wxGridTableBase *table = grid.GetTable();
605
606 bool hasDouble;
607 double val;
608 wxString text;
609 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
610 {
611 val = table->GetValueAsDouble(row, col);
612 hasDouble = true;
613 }
614 else
615 {
616 text = table->GetValue(row, col);
617 hasDouble = text.ToDouble(&val);
618 }
619
620 if ( hasDouble )
621 {
622 if ( !m_format )
623 {
624 if ( m_width == -1 )
625 {
626 if ( m_precision == -1 )
627 {
628 // default width/precision
629 m_format = _T("%f");
630 }
631 else
632 {
633 m_format.Printf(_T("%%.%df"), m_precision);
634 }
635 }
636 else if ( m_precision == -1 )
637 {
638 // default precision
639 m_format.Printf(_T("%%%d.f"), m_width);
640 }
641 else
642 {
643 m_format.Printf(_T("%%%d.%df"), m_width, m_precision);
644 }
645 }
646
647 text.Printf(m_format, val);
648
649 }
650 //else: text already contains the string
651
652 return text;
653 }
654
655 void wxGridCellFloatRenderer::Draw(wxGrid& grid,
656 wxGridCellAttr& attr,
657 wxDC& dc,
658 const wxRect& rectCell,
659 int row, int col,
660 bool isSelected)
661 {
662 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
663
664 SetTextColoursAndFont(grid, attr, dc, isSelected);
665
666 // draw the text right aligned by default
667 int hAlign, vAlign;
668 attr.GetAlignment(&hAlign, &vAlign);
669 hAlign = wxALIGN_RIGHT;
670
671 wxRect rect = rectCell;
672 rect.Inflate(-1);
673
674 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
675 }
676
677 wxSize wxGridCellFloatRenderer::GetBestSize(wxGrid& grid,
678 wxGridCellAttr& attr,
679 wxDC& dc,
680 int row, int col)
681 {
682 return DoGetBestSize(attr, dc, GetString(grid, row, col));
683 }
684
685 void wxGridCellFloatRenderer::SetParameters(const wxString& params)
686 {
687 if ( !params )
688 {
689 // reset to defaults
690 SetWidth(-1);
691 SetPrecision(-1);
692 }
693 else
694 {
695 wxString tmp = params.BeforeFirst(_T(','));
696 if ( !tmp.empty() )
697 {
698 long width;
699 if ( tmp.ToLong(&width) )
700 {
701 SetWidth((int)width);
702 }
703 else
704 {
705 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params.c_str());
706 }
707 }
708
709 tmp = params.AfterFirst(_T(','));
710 if ( !tmp.empty() )
711 {
712 long precision;
713 if ( tmp.ToLong(&precision) )
714 {
715 SetPrecision((int)precision);
716 }
717 else
718 {
719 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params.c_str());
720 }
721 }
722 }
723 }
724
725 // ----------------------------------------------------------------------------
726 // wxGridCellBoolRenderer
727 // ----------------------------------------------------------------------------
728
729 wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
730
731 // FIXME these checkbox size calculations are really ugly...
732
733 // between checkmark and box
734 static const wxCoord wxGRID_CHECKMARK_MARGIN = 2;
735
736 wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
737 wxGridCellAttr& WXUNUSED(attr),
738 wxDC& WXUNUSED(dc),
739 int WXUNUSED(row),
740 int WXUNUSED(col))
741 {
742 // compute it only once (no locks for MT safeness in GUI thread...)
743 if ( !ms_sizeCheckMark.x )
744 {
745 // get checkbox size
746 wxCheckBox *checkbox = new wxCheckBox(&grid, wxID_ANY, wxEmptyString);
747 wxSize size = checkbox->GetBestSize();
748 wxCoord checkSize = size.y + 2 * wxGRID_CHECKMARK_MARGIN;
749
750 #if defined(__WXMOTIF__)
751 checkSize -= size.y / 2;
752 #endif
753
754 delete checkbox;
755
756 ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize;
757 }
758
759 return ms_sizeCheckMark;
760 }
761
762 void wxGridCellBoolRenderer::Draw(wxGrid& grid,
763 wxGridCellAttr& attr,
764 wxDC& dc,
765 const wxRect& rect,
766 int row, int col,
767 bool isSelected)
768 {
769 wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
770
771 // draw a check mark in the centre (ignoring alignment - TODO)
772 wxSize size = GetBestSize(grid, attr, dc, row, col);
773
774 // don't draw outside the cell
775 wxCoord minSize = wxMin(rect.width, rect.height);
776 if ( size.x >= minSize || size.y >= minSize )
777 {
778 // and even leave (at least) 1 pixel margin
779 size.x = size.y = minSize;
780 }
781
782 // draw a border around checkmark
783 int vAlign, hAlign;
784 attr.GetAlignment(&hAlign, &vAlign);
785
786 wxRect rectBorder;
787 if (hAlign == wxALIGN_CENTRE)
788 {
789 rectBorder.x = rect.x + rect.width / 2 - size.x / 2;
790 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
791 rectBorder.width = size.x;
792 rectBorder.height = size.y;
793 }
794 else if (hAlign == wxALIGN_LEFT)
795 {
796 rectBorder.x = rect.x + 2;
797 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
798 rectBorder.width = size.x;
799 rectBorder.height = size.y;
800 }
801 else if (hAlign == wxALIGN_RIGHT)
802 {
803 rectBorder.x = rect.x + rect.width - size.x - 2;
804 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
805 rectBorder.width = size.x;
806 rectBorder.height = size.y;
807 }
808
809 bool value;
810 if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
811 {
812 value = grid.GetTable()->GetValueAsBool(row, col);
813 }
814 else
815 {
816 wxString cellval( grid.GetTable()->GetValue(row, col) );
817 value = wxGridCellBoolEditor::IsTrueValue(cellval);
818 }
819
820 int flags = 0;
821 if (value)
822 flags |= wxCONTROL_CHECKED;
823
824 wxRendererNative::Get().DrawCheckBox( &grid, dc, rectBorder, flags );
825 }
826
827 #endif // wxUSE_GRID
828