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