1 ///////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/gridctrl.cpp
3 // Purpose: wxGrid controls
4 // Author: Paul Gammans, Roger Gammans
7 // Copyright: (c) The Computer Surgery (paul@compsurg.co.uk)
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 #include "wx/wxprec.h"
19 #include "wx/generic/gridctrl.h"
20 #include "wx/generic/grideditors.h"
23 #include "wx/textctrl.h"
25 #include "wx/combobox.h"
26 #include "wx/settings.h"
28 #include "wx/checkbox.h"
31 #include "wx/tokenzr.h"
32 #include "wx/renderer.h"
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
39 void wxGridCellRenderer
::Draw(wxGrid
& grid
,
43 int WXUNUSED(row
), int WXUNUSED(col
),
46 dc
.SetBackgroundMode( wxBRUSHSTYLE_SOLID
);
49 if ( grid
.IsThisEnabled() )
53 if ( grid
.HasFocus() )
54 clr
= grid
.GetSelectionBackground();
56 clr
= wxSystemSettings
::GetColour(wxSYS_COLOUR_BTNSHADOW
);
60 clr
= attr
.GetBackgroundColour();
63 else // grey out fields if the grid is disabled
65 clr
= wxSystemSettings
::GetColour(wxSYS_COLOUR_BTNFACE
);
69 dc
.SetPen( *wxTRANSPARENT_PEN
);
70 dc
.DrawRectangle(rect
);
74 // ----------------------------------------------------------------------------
75 // wxGridCellDateTimeRenderer
76 // ----------------------------------------------------------------------------
80 // Enables a grid cell to display a formatted date and or time
82 wxGridCellDateTimeRenderer
::wxGridCellDateTimeRenderer(const wxString
& outformat
, const wxString
& informat
)
85 m_oformat
= outformat
;
86 m_tz
= wxDateTime
::Local
;
87 m_dateDef
= wxDefaultDateTime
;
90 wxGridCellRenderer
*wxGridCellDateTimeRenderer
::Clone() const
92 wxGridCellDateTimeRenderer
*renderer
= new wxGridCellDateTimeRenderer
;
93 renderer
->m_iformat
= m_iformat
;
94 renderer
->m_oformat
= m_oformat
;
95 renderer
->m_dateDef
= m_dateDef
;
96 renderer
->m_tz
= m_tz
;
101 wxString wxGridCellDateTimeRenderer
::GetString(const wxGrid
& grid
, int row
, int col
)
103 wxGridTableBase
*table
= grid
.GetTable();
105 bool hasDatetime
= false;
108 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_DATETIME
) )
110 void * tempval
= table
->GetValueAsCustom(row
, col
,wxGRID_VALUE_DATETIME
);
114 val
= *((wxDateTime
*)tempval
);
116 delete (wxDateTime
*)tempval
;
123 text
= table
->GetValue(row
, col
);
124 const char * const end
= val
.ParseFormat(text
, m_iformat
, m_dateDef
);
125 hasDatetime
= end
&& !*end
;
129 text
= val
.Format(m_oformat
, m_tz
);
131 // If we failed to parse string just show what we where given?
135 void wxGridCellDateTimeRenderer
::Draw(wxGrid
& grid
,
136 wxGridCellAttr
& attr
,
138 const wxRect
& rectCell
,
142 wxGridCellRenderer
::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
144 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
146 // draw the text right aligned by default
147 int hAlign
= wxALIGN_RIGHT
,
148 vAlign
= wxALIGN_INVALID
;
149 attr
.GetNonDefaultAlignment(&hAlign
, &vAlign
);
151 wxRect rect
= rectCell
;
154 grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
);
157 wxSize wxGridCellDateTimeRenderer
::GetBestSize(wxGrid
& grid
,
158 wxGridCellAttr
& attr
,
162 return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
));
165 void wxGridCellDateTimeRenderer
::SetParameters(const wxString
& params
)
171 #endif // wxUSE_DATETIME
173 // ----------------------------------------------------------------------------
174 // wxGridCellEnumRenderer
175 // ----------------------------------------------------------------------------
176 // Renders a number as a textual equivalent.
177 // eg data in cell is 0,1,2 ... n the cell could be rendered as "John","Fred"..."Bob"
180 wxGridCellEnumRenderer
::wxGridCellEnumRenderer(const wxString
& choices
)
182 if (!choices
.empty())
183 SetParameters(choices
);
186 wxGridCellRenderer
*wxGridCellEnumRenderer
::Clone() const
188 wxGridCellEnumRenderer
*renderer
= new wxGridCellEnumRenderer
;
189 renderer
->m_choices
= m_choices
;
193 wxString wxGridCellEnumRenderer
::GetString(const wxGrid
& grid
, int row
, int col
)
195 wxGridTableBase
*table
= grid
.GetTable();
197 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) )
199 int choiceno
= table
->GetValueAsLong(row
, col
);
200 text
.Printf(wxT("%s"), m_choices
[ choiceno
].c_str() );
204 text
= table
->GetValue(row
, col
);
208 //If we faild to parse string just show what we where given?
212 void wxGridCellEnumRenderer
::Draw(wxGrid
& grid
,
213 wxGridCellAttr
& attr
,
215 const wxRect
& rectCell
,
219 wxGridCellRenderer
::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
221 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
223 // draw the text right aligned by default
224 int hAlign
= wxALIGN_RIGHT
,
225 vAlign
= wxALIGN_INVALID
;
226 attr
.GetNonDefaultAlignment(&hAlign
, &vAlign
);
228 wxRect rect
= rectCell
;
231 grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
);
234 wxSize wxGridCellEnumRenderer
::GetBestSize(wxGrid
& grid
,
235 wxGridCellAttr
& attr
,
239 return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
));
242 void wxGridCellEnumRenderer
::SetParameters(const wxString
& params
)
252 wxStringTokenizer
tk(params
, wxT(','));
253 while ( tk
.HasMoreTokens() )
255 m_choices
.Add(tk
.GetNextToken());
260 // ----------------------------------------------------------------------------
261 // wxGridCellAutoWrapStringRenderer
262 // ----------------------------------------------------------------------------
266 wxGridCellAutoWrapStringRenderer
::Draw(wxGrid
& grid
,
267 wxGridCellAttr
& attr
,
269 const wxRect
& rectCell
,
274 wxGridCellRenderer
::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
276 // now we only have to draw the text
277 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
279 int horizAlign
, vertAlign
;
280 attr
.GetAlignment(&horizAlign
, &vertAlign
);
282 wxRect rect
= rectCell
;
285 grid
.DrawTextRectangle(dc
, GetTextLines(grid
,dc
,attr
,rect
,row
,col
),
286 rect
, horizAlign
, vertAlign
);
291 wxGridCellAutoWrapStringRenderer
::GetTextLines(wxGrid
& grid
,
293 const wxGridCellAttr
& attr
,
297 dc
.SetFont(attr
.GetFont());
298 const wxCoord maxWidth
= rect
.GetWidth();
300 // Transform logical lines into physical ones, wrapping the longer ones.
302 logicalLines
= wxSplit(grid
.GetCellValue(row
, col
), '\n', '\0');
304 // Trying to do anything if the column is hidden anyhow doesn't make sense
305 // and we run into problems in BreakLine() in this case.
309 wxArrayString physicalLines
;
310 for ( wxArrayString
::const_iterator it
= logicalLines
.begin();
311 it
!= logicalLines
.end();
314 const wxString
& line
= *it
;
316 if ( dc
.GetTextExtent(line
).x
> maxWidth
)
318 // Line does not fit, break it up.
319 BreakLine(dc
, line
, maxWidth
, physicalLines
);
321 else // The entire line fits as is
323 physicalLines
.push_back(line
);
327 return physicalLines
;
331 wxGridCellAutoWrapStringRenderer
::BreakLine(wxDC
& dc
,
332 const wxString
& logicalLine
,
334 wxArrayString
& lines
)
336 wxCoord lineWidth
= 0;
340 wxStringTokenizer
wordTokenizer(logicalLine
, wxS(" \t"), wxTOKEN_RET_DELIMS
);
341 while ( wordTokenizer
.HasMoreTokens() )
343 const wxString word
= wordTokenizer
.GetNextToken();
344 const wxCoord wordWidth
= dc
.GetTextExtent(word
).x
;
345 if ( lineWidth
+ wordWidth
< maxWidth
)
347 // Word fits, just add it to this line.
349 lineWidth
+= wordWidth
;
353 // Word does not fit, check whether the word is itself wider that
355 if ( wordWidth
< maxWidth
)
357 // Word can fit in a new line, put it at the beginning
359 lines
.push_back(line
);
361 lineWidth
= wordWidth
;
363 else // Word cannot fit in available width at all.
367 lines
.push_back(line
);
372 // Break it up in several lines.
373 lineWidth
= BreakWord(dc
, word
, maxWidth
, lines
, line
);
379 lines
.push_back(line
);
384 wxGridCellAutoWrapStringRenderer
::BreakWord(wxDC
& dc
,
385 const wxString
& word
,
387 wxArrayString
& lines
,
391 dc
.GetPartialTextExtents(word
, widths
);
393 // TODO: Use binary search to find the first element > maxWidth.
394 const unsigned count
= widths
.size();
396 for ( n
= 0; n
< count
; n
++ )
398 if ( widths
[n
] > maxWidth
)
404 // This is a degenerate case: the first character of the word is
405 // already wider than the available space, so we just can't show it
406 // completely and have to put the first character in this line.
410 lines
.push_back(word
.substr(0, n
));
412 // Check if the remainder of the string fits in one line.
414 // Unfortunately we can't use the existing partial text extents as the
415 // extent of the remainder may be different when it's rendered in a
416 // separate line instead of as part of the same one, so we have to
418 const wxString rest
= word
.substr(n
);
419 const wxCoord restWidth
= dc
.GetTextExtent(rest
).x
;
420 if ( restWidth
<= maxWidth
)
426 // Break the rest of the word into lines.
428 // TODO: Perhaps avoid recursion? The code is simpler like this but using a
429 // loop in this function would probably be more efficient.
430 return BreakWord(dc
, rest
, maxWidth
, lines
, line
);
434 wxGridCellAutoWrapStringRenderer
::GetBestSize(wxGrid
& grid
,
435 wxGridCellAttr
& attr
,
439 wxCoord x
,y
, height
, width
= grid
.GetColSize(col
) -20;
440 // for width, subtract 20 because ColSize includes a magin of 10 pixels
441 // that we do not want here and because we always start with an increment
442 // by 10 in the loop below.
443 int count
= 250; //Limit iterations..
445 wxRect
rect(0,0,width
,10);
447 // M is a nice large character 'y' gives descender!.
448 dc
.GetTextExtent(wxT("My"), &x
, &y
);
453 rect
.SetWidth(width
);
454 height
= y
* (wx_truncate_cast(wxCoord
, GetTextLines(grid
,dc
,attr
,rect
,row
,col
).GetCount()));
456 // Search for a shape no taller than the golden ratio.
457 } while (count
&& (width
< (height
*1.68)) );
460 return wxSize(width
,height
);
464 // ----------------------------------------------------------------------------
465 // wxGridCellStringRenderer
466 // ----------------------------------------------------------------------------
468 void wxGridCellStringRenderer
::SetTextColoursAndFont(const wxGrid
& grid
,
469 const wxGridCellAttr
& attr
,
473 dc
.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT
);
475 // TODO some special colours for attr.IsReadOnly() case?
477 // different coloured text when the grid is disabled
478 if ( grid
.IsThisEnabled() )
483 if ( grid
.HasFocus() )
484 clr
= grid
.GetSelectionBackground();
486 clr
= wxSystemSettings
::GetColour(wxSYS_COLOUR_BTNSHADOW
);
487 dc
.SetTextBackground( clr
);
488 dc
.SetTextForeground( grid
.GetSelectionForeground() );
492 dc
.SetTextBackground( attr
.GetBackgroundColour() );
493 dc
.SetTextForeground( attr
.GetTextColour() );
498 dc
.SetTextBackground(wxSystemSettings
::GetColour(wxSYS_COLOUR_BTNFACE
));
499 dc
.SetTextForeground(wxSystemSettings
::GetColour(wxSYS_COLOUR_GRAYTEXT
));
502 dc
.SetFont( attr
.GetFont() );
505 wxSize wxGridCellStringRenderer
::DoGetBestSize(const wxGridCellAttr
& attr
,
507 const wxString
& text
)
509 wxCoord x
= 0, y
= 0, max_x
= 0;
510 dc
.SetFont(attr
.GetFont());
511 wxStringTokenizer
tk(text
, wxT('\n'));
512 while ( tk
.HasMoreTokens() )
514 dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
);
515 max_x
= wxMax(max_x
, x
);
518 y
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines.
520 return wxSize(max_x
, y
);
523 wxSize wxGridCellStringRenderer
::GetBestSize(wxGrid
& grid
,
524 wxGridCellAttr
& attr
,
528 return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
));
531 void wxGridCellStringRenderer
::Draw(wxGrid
& grid
,
532 wxGridCellAttr
& attr
,
534 const wxRect
& rectCell
,
538 wxRect rect
= rectCell
;
541 // erase only this cells background, overflow cells should have been erased
542 wxGridCellRenderer
::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
545 attr
.GetAlignment(&hAlign
, &vAlign
);
547 int overflowCols
= 0;
549 if (attr
.GetOverflow())
551 int cols
= grid
.GetNumberCols();
552 int best_width
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth();
553 int cell_rows
, cell_cols
;
554 attr
.GetSize( &cell_rows
, &cell_cols
); // shouldn't get here if <= 0
555 if ((best_width
> rectCell
.width
) && (col
< cols
) && grid
.GetTable())
557 int i
, c_cols
, c_rows
;
558 for (i
= col
+cell_cols
; i
< cols
; i
++)
560 bool is_empty
= true;
561 for (int j
=row
; j
< row
+ cell_rows
; j
++)
563 // check w/ anchor cell for multicell block
564 grid
.GetCellSize(j
, i
, &c_rows
, &c_cols
);
567 if (!grid
.GetTable()->IsEmptyCell(j
+ c_rows
, i
))
576 rect
.width
+= grid
.GetColSize(i
);
584 if (rect
.width
>= best_width
)
588 overflowCols
= i
- col
- cell_cols
+ 1;
589 if (overflowCols
>= cols
)
590 overflowCols
= cols
- 1;
593 if (overflowCols
> 0) // redraw overflow cells w/ proper hilight
595 hAlign
= wxALIGN_LEFT
; // if oveflowed then it's left aligned
597 clip
.x
+= rectCell
.width
;
598 // draw each overflow cell individually
599 int col_end
= col
+ cell_cols
+ overflowCols
;
600 if (col_end
>= grid
.GetNumberCols())
601 col_end
= grid
.GetNumberCols() - 1;
602 for (int i
= col
+ cell_cols
; i
<= col_end
; i
++)
604 clip
.width
= grid
.GetColSize(i
) - 1;
605 dc
.DestroyClippingRegion();
606 dc
.SetClippingRegion(clip
);
608 SetTextColoursAndFont(grid
, attr
, dc
,
609 grid
.IsInSelection(row
,i
));
611 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
),
612 rect
, hAlign
, vAlign
);
613 clip
.x
+= grid
.GetColSize(i
) - 1;
619 dc
.DestroyClippingRegion();
623 // now we only have to draw the text
624 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
626 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
),
627 rect
, hAlign
, vAlign
);
630 // ----------------------------------------------------------------------------
631 // wxGridCellNumberRenderer
632 // ----------------------------------------------------------------------------
634 wxString wxGridCellNumberRenderer
::GetString(const wxGrid
& grid
, int row
, int col
)
636 wxGridTableBase
*table
= grid
.GetTable();
638 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) )
640 text
.Printf(wxT("%ld"), table
->GetValueAsLong(row
, col
));
644 text
= table
->GetValue(row
, col
);
650 void wxGridCellNumberRenderer
::Draw(wxGrid
& grid
,
651 wxGridCellAttr
& attr
,
653 const wxRect
& rectCell
,
657 wxGridCellRenderer
::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
659 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
661 // draw the text right aligned by default
662 int hAlign
= wxALIGN_RIGHT
,
663 vAlign
= wxALIGN_INVALID
;
664 attr
.GetNonDefaultAlignment(&hAlign
, &vAlign
);
666 wxRect rect
= rectCell
;
669 grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
);
672 wxSize wxGridCellNumberRenderer
::GetBestSize(wxGrid
& grid
,
673 wxGridCellAttr
& attr
,
677 return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
));
680 // ----------------------------------------------------------------------------
681 // wxGridCellFloatRenderer
682 // ----------------------------------------------------------------------------
684 wxGridCellFloatRenderer
::wxGridCellFloatRenderer(int width
,
689 SetPrecision(precision
);
693 wxGridCellRenderer
*wxGridCellFloatRenderer
::Clone() const
695 wxGridCellFloatRenderer
*renderer
= new wxGridCellFloatRenderer
;
696 renderer
->m_width
= m_width
;
697 renderer
->m_precision
= m_precision
;
698 renderer
->m_style
= m_style
;
699 renderer
->m_format
= m_format
;
704 wxString wxGridCellFloatRenderer
::GetString(const wxGrid
& grid
, int row
, int col
)
706 wxGridTableBase
*table
= grid
.GetTable();
711 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) )
713 val
= table
->GetValueAsDouble(row
, col
);
718 text
= table
->GetValue(row
, col
);
719 hasDouble
= text
.ToDouble(&val
);
728 if ( m_precision
== -1 )
730 // default width/precision
735 m_format
.Printf(wxT("%%.%d"), m_precision
);
738 else if ( m_precision
== -1 )
741 m_format
.Printf(wxT("%%%d."), m_width
);
745 m_format
.Printf(wxT("%%%d.%d"), m_width
, m_precision
);
748 bool isUpper
= ( ( m_style
& wxGRID_FLOAT_FORMAT_UPPER
) == wxGRID_FLOAT_FORMAT_UPPER
);
749 if ( ( m_style
& wxGRID_FLOAT_FORMAT_SCIENTIFIC
) == wxGRID_FLOAT_FORMAT_SCIENTIFIC
)
750 m_format
+= isUpper ?
wxT('E') : wxT('e');
751 else if ( ( m_style
& wxGRID_FLOAT_FORMAT_COMPACT
) == wxGRID_FLOAT_FORMAT_COMPACT
)
752 m_format
+= isUpper ?
wxT('G') : wxT('g');
754 m_format
+= wxT('f');
757 text
.Printf(m_format
, val
);
760 //else: text already contains the string
765 void wxGridCellFloatRenderer
::Draw(wxGrid
& grid
,
766 wxGridCellAttr
& attr
,
768 const wxRect
& rectCell
,
772 wxGridCellRenderer
::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
774 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
776 // draw the text right aligned by default
777 int hAlign
= wxALIGN_RIGHT
,
778 vAlign
= wxALIGN_INVALID
;
779 attr
.GetNonDefaultAlignment(&hAlign
, &vAlign
);
781 wxRect rect
= rectCell
;
784 grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
);
787 wxSize wxGridCellFloatRenderer
::GetBestSize(wxGrid
& grid
,
788 wxGridCellAttr
& attr
,
792 return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
));
795 void wxGridCellFloatRenderer
::SetParameters(const wxString
& params
)
802 SetFormat(wxGRID_FLOAT_FORMAT_DEFAULT
);
807 wxString tmp
= params
.BeforeFirst(wxT(','), &rest
);
811 if ( tmp
.ToLong(&width
) )
813 SetWidth((int)width
);
817 wxLogDebug(wxT("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str());
821 tmp
= rest
.BeforeFirst(wxT(','));
825 if ( tmp
.ToLong(&precision
) )
827 SetPrecision((int)precision
);
831 wxLogDebug(wxT("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str());
835 tmp
= rest
.AfterFirst(wxT(','));
838 if ( tmp
[0] == wxT('f') )
840 SetFormat(wxGRID_FLOAT_FORMAT_FIXED
);
842 else if ( tmp
[0] == wxT('e') )
844 SetFormat(wxGRID_FLOAT_FORMAT_SCIENTIFIC
);
846 else if ( tmp
[0] == wxT('g') )
848 SetFormat(wxGRID_FLOAT_FORMAT_COMPACT
);
850 else if ( tmp
[0] == wxT('E') )
852 SetFormat(wxGRID_FLOAT_FORMAT_SCIENTIFIC
|
853 wxGRID_FLOAT_FORMAT_UPPER
);
855 else if ( tmp
[0] == wxT('F') )
857 SetFormat(wxGRID_FLOAT_FORMAT_FIXED
|
858 wxGRID_FLOAT_FORMAT_UPPER
);
860 else if ( tmp
[0] == wxT('G') )
862 SetFormat(wxGRID_FLOAT_FORMAT_COMPACT
|
863 wxGRID_FLOAT_FORMAT_UPPER
);
867 wxLogDebug("Invalid wxGridCellFloatRenderer format "
868 "parameter string '%s ignored", params
);
874 // ----------------------------------------------------------------------------
875 // wxGridCellBoolRenderer
876 // ----------------------------------------------------------------------------
878 wxSize wxGridCellBoolRenderer
::ms_sizeCheckMark
;
880 wxSize wxGridCellBoolRenderer
::GetBestSize(wxGrid
& grid
,
881 wxGridCellAttr
& WXUNUSED(attr
),
886 // compute it only once (no locks for MT safeness in GUI thread...)
887 if ( !ms_sizeCheckMark
.x
)
889 ms_sizeCheckMark
= wxRendererNative
::Get().GetCheckBoxSize(&grid
);
892 return ms_sizeCheckMark
;
895 void wxGridCellBoolRenderer
::Draw(wxGrid
& grid
,
896 wxGridCellAttr
& attr
,
902 wxGridCellRenderer
::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
);
904 // draw a check mark in the centre (ignoring alignment - TODO)
905 wxSize size
= GetBestSize(grid
, attr
, dc
, row
, col
);
907 // don't draw outside the cell
908 wxCoord minSize
= wxMin(rect
.width
, rect
.height
);
909 if ( size
.x
>= minSize
|| size
.y
>= minSize
)
911 // and even leave (at least) 1 pixel margin
912 size
.x
= size
.y
= minSize
;
915 // draw a border around checkmark
917 attr
.GetAlignment(&hAlign
, &vAlign
);
920 if (hAlign
== wxALIGN_CENTRE
)
922 rectBorder
.x
= rect
.x
+ rect
.width
/ 2 - size
.x
/ 2;
923 rectBorder
.y
= rect
.y
+ rect
.height
/ 2 - size
.y
/ 2;
924 rectBorder
.width
= size
.x
;
925 rectBorder
.height
= size
.y
;
927 else if (hAlign
== wxALIGN_LEFT
)
929 rectBorder
.x
= rect
.x
+ 2;
930 rectBorder
.y
= rect
.y
+ rect
.height
/ 2 - size
.y
/ 2;
931 rectBorder
.width
= size
.x
;
932 rectBorder
.height
= size
.y
;
934 else if (hAlign
== wxALIGN_RIGHT
)
936 rectBorder
.x
= rect
.x
+ rect
.width
- size
.x
- 2;
937 rectBorder
.y
= rect
.y
+ rect
.height
/ 2 - size
.y
/ 2;
938 rectBorder
.width
= size
.x
;
939 rectBorder
.height
= size
.y
;
943 if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) )
945 value
= grid
.GetTable()->GetValueAsBool(row
, col
);
949 wxString
cellval( grid
.GetTable()->GetValue(row
, col
) );
950 value
= wxGridCellBoolEditor
::IsTrueValue(cellval
);
955 flags
|= wxCONTROL_CHECKED
;
957 wxRendererNative
::Get().DrawCheckBox( &grid
, dc
, rectBorder
, flags
);