]> git.saurik.com Git - wxWidgets.git/blame - src/generic/gridctrl.cpp
refactor wxDocChildFrame and wxDocMDIChildFrame to use wxDocChildFrameAny intead...
[wxWidgets.git] / src / generic / gridctrl.cpp
CommitLineData
d10f4bf9
VZ
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)
65571936 9// Licence: wxWindows licence
d10f4bf9
VZ
10/////////////////////////////////////////////////////////////////////////////
11
d10f4bf9
VZ
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
f7556ff0 18#if wxUSE_GRID
b53dc7d6 19
df9fac6d 20#include "wx/generic/gridctrl.h"
29efc6e4 21#include "wx/generic/grideditors.h"
df9fac6d 22
7ac05a91
VZ
23#ifndef WX_PRECOMP
24 #include "wx/textctrl.h"
25 #include "wx/dc.h"
df9fac6d 26 #include "wx/combobox.h"
85fe9f6f
FM
27 #include "wx/settings.h"
28 #include "wx/log.h"
29 #include "wx/checkbox.h"
7ac05a91
VZ
30#endif // WX_PRECOMP
31
d10f4bf9 32#include "wx/tokenzr.h"
29efc6e4 33#include "wx/renderer.h"
d10f4bf9
VZ
34
35// ----------------------------------------------------------------------------
36// wxGridCellDateTimeRenderer
37// ----------------------------------------------------------------------------
38
e2b87f38
VZ
39#if wxUSE_DATETIME
40
90e572f1 41// Enables a grid cell to display a formatted date and or time
d10f4bf9 42
fbfb8bcc 43wxGridCellDateTimeRenderer::wxGridCellDateTimeRenderer(const wxString& outformat, const wxString& informat)
d10f4bf9
VZ
44{
45 m_iformat = informat;
46 m_oformat = outformat;
47 m_tz = wxDateTime::Local;
48 m_dateDef = wxDefaultDateTime;
49}
50
51wxGridCellRenderer *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
fbfb8bcc 62wxString wxGridCellDateTimeRenderer::GetString(const wxGrid& grid, int row, int col)
d10f4bf9
VZ
63{
64 wxGridTableBase *table = grid.GetTable();
65
ca65c044 66 bool hasDatetime = false;
d10f4bf9
VZ
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
6a147dfe
VZ
73 if (tempval)
74 {
d10f4bf9 75 val = *((wxDateTime *)tempval);
ca65c044 76 hasDatetime = true;
d10f4bf9
VZ
77 delete (wxDateTime *)tempval;
78 }
79
80 }
81
82 if (!hasDatetime )
83 {
84 text = table->GetValue(row, col);
6a147dfe
VZ
85 const char * const end = val.ParseFormat(text, m_iformat, m_dateDef);
86 hasDatetime = end && !*end;
d10f4bf9
VZ
87 }
88
89 if ( hasDatetime )
90 text = val.Format(m_oformat, m_tz );
91
6a147dfe 92 // If we failed to parse string just show what we where given?
d10f4bf9
VZ
93 return text;
94}
95
96void 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
118wxSize 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
7448de8d
WS
126void wxGridCellDateTimeRenderer::SetParameters(const wxString& params)
127{
128 if (!params.empty())
d10f4bf9
VZ
129 m_oformat=params;
130}
131
e2b87f38
VZ
132#endif // wxUSE_DATETIME
133
d10f4bf9
VZ
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
141wxGridCellEnumRenderer::wxGridCellEnumRenderer(const wxString& choices)
142{
7448de8d 143 if (!choices.empty())
d10f4bf9
VZ
144 SetParameters(choices);
145}
146
147wxGridCellRenderer *wxGridCellEnumRenderer::Clone() const
148{
149 wxGridCellEnumRenderer *renderer = new wxGridCellEnumRenderer;
150 renderer->m_choices = m_choices;
151 return renderer;
152}
153
fbfb8bcc 154wxString wxGridCellEnumRenderer::GetString(const wxGrid& grid, int row, int col)
d10f4bf9
VZ
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
173void 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
195wxSize 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
203void 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
3a8c693a 220
d10f4bf9 221// ----------------------------------------------------------------------------
29efc6e4 222// wxGridCellAutoWrapStringRenderer
d10f4bf9 223// ----------------------------------------------------------------------------
3a8c693a 224
d10f4bf9
VZ
225
226void
227wxGridCellAutoWrapStringRenderer::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
251wxArrayString
252wxGridCellAutoWrapStringRenderer::GetTextLines(wxGrid& grid,
253 wxDC& dc,
fbfb8bcc 254 const wxGridCellAttr& attr,
d10f4bf9
VZ
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"));
ca65c044 269 wxString thisline = wxEmptyString;
d10f4bf9
VZ
270
271 while ( tk.HasMoreTokens() )
272 {
273 wxString tok = tk.GetNextToken();
7448de8d
WS
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(" ");
d10f4bf9
VZ
279
280 dc.GetTextExtent(tok, &x, &y);
7448de8d
WS
281 if ( curr_x + x > max_x)
282 {
5c3a7f71
VZ
283 if ( curr_x == 0 )
284 {
285 // this means that a single token is wider than the maximal
286 // width -- still use it as is as we need to show at least the
287 // part of it which fits
288 lines.Add(tok);
289 }
290 else
291 {
292 lines.Add(thisline);
293 thisline = tok;
294 curr_x = x;
295 }
7448de8d
WS
296 }
297 else
298 {
d10f4bf9 299 thisline+= tok;
7448de8d
WS
300 curr_x += x;
301 }
d10f4bf9
VZ
302 }
303 //Add last line
304 lines.Add( wxString(thisline) );
305
306 return lines;
307}
308
309
310wxSize
311wxGridCellAutoWrapStringRenderer::GetBestSize(wxGrid& grid,
312 wxGridCellAttr& attr,
313 wxDC& dc,
314 int row, int col)
315{
86647b53
SN
316 wxCoord x,y, height , width = grid.GetColSize(col) -20;
317 // for width, subtract 20 because ColSize includes a magin of 10 pixels
318 // that we do not want here and because we always start with an increment
319 // by 10 in the loop below.
d10f4bf9
VZ
320 int count = 250; //Limit iterations..
321
322 wxRect rect(0,0,width,10);
323
324 // M is a nice large character 'y' gives descender!.
8dd8f875 325 dc.GetTextExtent(wxT("My"), &x, &y);
d10f4bf9
VZ
326
327 do
328 {
329 width+=10;
330 rect.SetWidth(width);
4a10ea8b 331 height = y * (wx_truncate_cast(wxCoord, GetTextLines(grid,dc,attr,rect,row,col).GetCount()));
d10f4bf9
VZ
332 count--;
333 // Search for a shape no taller than the golden ratio.
334 } while (count && (width < (height*1.68)) );
335
336
337 return wxSize(width,height);
338}
339
29efc6e4
FM
340
341// ----------------------------------------------------------------------------
342// wxGridCellRenderer
343// ----------------------------------------------------------------------------
344
345void wxGridCellRenderer::Draw(wxGrid& grid,
346 wxGridCellAttr& attr,
347 wxDC& dc,
348 const wxRect& rect,
349 int WXUNUSED(row), int WXUNUSED(col),
350 bool isSelected)
351{
352 dc.SetBackgroundMode( wxBRUSHSTYLE_SOLID );
353
354 wxColour clr;
355 if ( grid.IsEnabled() )
356 {
357 if ( isSelected )
358 {
359 if ( grid.HasFocus() )
360 clr = grid.GetSelectionBackground();
361 else
362 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
363 }
364 else
365 {
366 clr = attr.GetBackgroundColour();
367 }
368 }
369 else // grey out fields if the grid is disabled
370 {
371 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
372 }
373
374 dc.SetBrush(clr);
375 dc.SetPen( *wxTRANSPARENT_PEN );
376 dc.DrawRectangle(rect);
377}
378
379// ----------------------------------------------------------------------------
380// wxGridCellStringRenderer
381// ----------------------------------------------------------------------------
382
383void wxGridCellStringRenderer::SetTextColoursAndFont(const wxGrid& grid,
384 const wxGridCellAttr& attr,
385 wxDC& dc,
386 bool isSelected)
387{
388 dc.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT );
389
390 // TODO some special colours for attr.IsReadOnly() case?
391
392 // different coloured text when the grid is disabled
393 if ( grid.IsEnabled() )
394 {
395 if ( isSelected )
396 {
397 wxColour clr;
398 if ( grid.HasFocus() )
399 clr = grid.GetSelectionBackground();
400 else
401 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
402 dc.SetTextBackground( clr );
403 dc.SetTextForeground( grid.GetSelectionForeground() );
404 }
405 else
406 {
407 dc.SetTextBackground( attr.GetBackgroundColour() );
408 dc.SetTextForeground( attr.GetTextColour() );
409 }
410 }
411 else
412 {
413 dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
414 dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
415 }
416
417 dc.SetFont( attr.GetFont() );
418}
419
420wxSize wxGridCellStringRenderer::DoGetBestSize(const wxGridCellAttr& attr,
421 wxDC& dc,
422 const wxString& text)
423{
424 wxCoord x = 0, y = 0, max_x = 0;
425 dc.SetFont(attr.GetFont());
426 wxStringTokenizer tk(text, _T('\n'));
427 while ( tk.HasMoreTokens() )
428 {
429 dc.GetTextExtent(tk.GetNextToken(), &x, &y);
430 max_x = wxMax(max_x, x);
431 }
432
433 y *= 1 + text.Freq(wxT('\n')); // multiply by the number of lines.
434
435 return wxSize(max_x, y);
436}
437
438wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid,
439 wxGridCellAttr& attr,
440 wxDC& dc,
441 int row, int col)
442{
443 return DoGetBestSize(attr, dc, grid.GetCellValue(row, col));
444}
445
446void wxGridCellStringRenderer::Draw(wxGrid& grid,
447 wxGridCellAttr& attr,
448 wxDC& dc,
449 const wxRect& rectCell,
450 int row, int col,
451 bool isSelected)
452{
453 wxRect rect = rectCell;
454 rect.Inflate(-1);
455
456 // erase only this cells background, overflow cells should have been erased
457 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
458
459 int hAlign, vAlign;
460 attr.GetAlignment(&hAlign, &vAlign);
461
462 int overflowCols = 0;
463
464 if (attr.GetOverflow())
465 {
466 int cols = grid.GetNumberCols();
467 int best_width = GetBestSize(grid,attr,dc,row,col).GetWidth();
468 int cell_rows, cell_cols;
469 attr.GetSize( &cell_rows, &cell_cols ); // shouldn't get here if <= 0
470 if ((best_width > rectCell.width) && (col < cols) && grid.GetTable())
471 {
472 int i, c_cols, c_rows;
473 for (i = col+cell_cols; i < cols; i++)
474 {
475 bool is_empty = true;
476 for (int j=row; j < row + cell_rows; j++)
477 {
478 // check w/ anchor cell for multicell block
479 grid.GetCellSize(j, i, &c_rows, &c_cols);
480 if (c_rows > 0)
481 c_rows = 0;
482 if (!grid.GetTable()->IsEmptyCell(j + c_rows, i))
483 {
484 is_empty = false;
485 break;
486 }
487 }
488
489 if (is_empty)
490 {
491 rect.width += grid.GetColSize(i);
492 }
493 else
494 {
495 i--;
496 break;
497 }
498
499 if (rect.width >= best_width)
500 break;
501 }
502
503 overflowCols = i - col - cell_cols + 1;
504 if (overflowCols >= cols)
505 overflowCols = cols - 1;
506 }
507
508 if (overflowCols > 0) // redraw overflow cells w/ proper hilight
509 {
510 hAlign = wxALIGN_LEFT; // if oveflowed then it's left aligned
511 wxRect clip = rect;
512 clip.x += rectCell.width;
513 // draw each overflow cell individually
514 int col_end = col + cell_cols + overflowCols;
515 if (col_end >= grid.GetNumberCols())
516 col_end = grid.GetNumberCols() - 1;
517 for (int i = col + cell_cols; i <= col_end; i++)
518 {
519 clip.width = grid.GetColSize(i) - 1;
520 dc.DestroyClippingRegion();
521 dc.SetClippingRegion(clip);
522
523 SetTextColoursAndFont(grid, attr, dc,
524 grid.IsInSelection(row,i));
525
526 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
527 rect, hAlign, vAlign);
528 clip.x += grid.GetColSize(i) - 1;
529 }
530
531 rect = rectCell;
532 rect.Inflate(-1);
533 rect.width++;
534 dc.DestroyClippingRegion();
535 }
536 }
537
538 // now we only have to draw the text
539 SetTextColoursAndFont(grid, attr, dc, isSelected);
540
541 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
542 rect, hAlign, vAlign);
543}
544
545// ----------------------------------------------------------------------------
546// wxGridCellNumberRenderer
547// ----------------------------------------------------------------------------
548
549wxString wxGridCellNumberRenderer::GetString(const wxGrid& grid, int row, int col)
550{
551 wxGridTableBase *table = grid.GetTable();
552 wxString text;
553 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
554 {
555 text.Printf(_T("%ld"), table->GetValueAsLong(row, col));
556 }
557 else
558 {
559 text = table->GetValue(row, col);
560 }
561
562 return text;
563}
564
565void wxGridCellNumberRenderer::Draw(wxGrid& grid,
566 wxGridCellAttr& attr,
567 wxDC& dc,
568 const wxRect& rectCell,
569 int row, int col,
570 bool isSelected)
571{
572 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
573
574 SetTextColoursAndFont(grid, attr, dc, isSelected);
575
576 // draw the text right aligned by default
577 int hAlign, vAlign;
578 attr.GetAlignment(&hAlign, &vAlign);
579 hAlign = wxALIGN_RIGHT;
580
581 wxRect rect = rectCell;
582 rect.Inflate(-1);
583
584 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
585}
586
587wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
588 wxGridCellAttr& attr,
589 wxDC& dc,
590 int row, int col)
591{
592 return DoGetBestSize(attr, dc, GetString(grid, row, col));
593}
594
595// ----------------------------------------------------------------------------
596// wxGridCellFloatRenderer
597// ----------------------------------------------------------------------------
598
599wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision)
600{
601 SetWidth(width);
602 SetPrecision(precision);
603}
604
605wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const
606{
607 wxGridCellFloatRenderer *renderer = new wxGridCellFloatRenderer;
608 renderer->m_width = m_width;
609 renderer->m_precision = m_precision;
610 renderer->m_format = m_format;
611
612 return renderer;
613}
614
615wxString wxGridCellFloatRenderer::GetString(const wxGrid& grid, int row, int col)
616{
617 wxGridTableBase *table = grid.GetTable();
618
619 bool hasDouble;
620 double val;
621 wxString text;
622 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
623 {
624 val = table->GetValueAsDouble(row, col);
625 hasDouble = true;
626 }
627 else
628 {
629 text = table->GetValue(row, col);
630 hasDouble = text.ToDouble(&val);
631 }
632
633 if ( hasDouble )
634 {
635 if ( !m_format )
636 {
637 if ( m_width == -1 )
638 {
639 if ( m_precision == -1 )
640 {
641 // default width/precision
642 m_format = _T("%f");
643 }
644 else
645 {
646 m_format.Printf(_T("%%.%df"), m_precision);
647 }
648 }
649 else if ( m_precision == -1 )
650 {
651 // default precision
652 m_format.Printf(_T("%%%d.f"), m_width);
653 }
654 else
655 {
656 m_format.Printf(_T("%%%d.%df"), m_width, m_precision);
657 }
658 }
659
660 text.Printf(m_format, val);
661
662 }
663 //else: text already contains the string
664
665 return text;
666}
667
668void wxGridCellFloatRenderer::Draw(wxGrid& grid,
669 wxGridCellAttr& attr,
670 wxDC& dc,
671 const wxRect& rectCell,
672 int row, int col,
673 bool isSelected)
674{
675 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
676
677 SetTextColoursAndFont(grid, attr, dc, isSelected);
678
679 // draw the text right aligned by default
680 int hAlign, vAlign;
681 attr.GetAlignment(&hAlign, &vAlign);
682 hAlign = wxALIGN_RIGHT;
683
684 wxRect rect = rectCell;
685 rect.Inflate(-1);
686
687 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
688}
689
690wxSize wxGridCellFloatRenderer::GetBestSize(wxGrid& grid,
691 wxGridCellAttr& attr,
692 wxDC& dc,
693 int row, int col)
694{
695 return DoGetBestSize(attr, dc, GetString(grid, row, col));
696}
697
698void wxGridCellFloatRenderer::SetParameters(const wxString& params)
699{
700 if ( !params )
701 {
702 // reset to defaults
703 SetWidth(-1);
704 SetPrecision(-1);
705 }
706 else
707 {
708 wxString tmp = params.BeforeFirst(_T(','));
709 if ( !tmp.empty() )
710 {
711 long width;
712 if ( tmp.ToLong(&width) )
713 {
714 SetWidth((int)width);
715 }
716 else
717 {
718 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params.c_str());
719 }
720 }
721
722 tmp = params.AfterFirst(_T(','));
723 if ( !tmp.empty() )
724 {
725 long precision;
726 if ( tmp.ToLong(&precision) )
727 {
728 SetPrecision((int)precision);
729 }
730 else
731 {
732 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params.c_str());
733 }
734 }
735 }
736}
737
738// ----------------------------------------------------------------------------
739// wxGridCellBoolRenderer
740// ----------------------------------------------------------------------------
741
742wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
743
744// FIXME these checkbox size calculations are really ugly...
745
746// between checkmark and box
747static const wxCoord wxGRID_CHECKMARK_MARGIN = 2;
748
749wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
750 wxGridCellAttr& WXUNUSED(attr),
751 wxDC& WXUNUSED(dc),
752 int WXUNUSED(row),
753 int WXUNUSED(col))
754{
755 // compute it only once (no locks for MT safeness in GUI thread...)
756 if ( !ms_sizeCheckMark.x )
757 {
758 // get checkbox size
759 wxCheckBox *checkbox = new wxCheckBox(&grid, wxID_ANY, wxEmptyString);
760 wxSize size = checkbox->GetBestSize();
761 wxCoord checkSize = size.y + 2 * wxGRID_CHECKMARK_MARGIN;
762
763#if defined(__WXMOTIF__)
764 checkSize -= size.y / 2;
765#endif
766
767 delete checkbox;
768
769 ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize;
770 }
771
772 return ms_sizeCheckMark;
773}
774
775void wxGridCellBoolRenderer::Draw(wxGrid& grid,
776 wxGridCellAttr& attr,
777 wxDC& dc,
778 const wxRect& rect,
779 int row, int col,
780 bool isSelected)
781{
782 wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
783
784 // draw a check mark in the centre (ignoring alignment - TODO)
785 wxSize size = GetBestSize(grid, attr, dc, row, col);
786
787 // don't draw outside the cell
788 wxCoord minSize = wxMin(rect.width, rect.height);
789 if ( size.x >= minSize || size.y >= minSize )
790 {
791 // and even leave (at least) 1 pixel margin
792 size.x = size.y = minSize;
793 }
794
795 // draw a border around checkmark
796 int vAlign, hAlign;
797 attr.GetAlignment(&hAlign, &vAlign);
798
799 wxRect rectBorder;
800 if (hAlign == wxALIGN_CENTRE)
801 {
802 rectBorder.x = rect.x + rect.width / 2 - size.x / 2;
803 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
804 rectBorder.width = size.x;
805 rectBorder.height = size.y;
806 }
807 else if (hAlign == wxALIGN_LEFT)
808 {
809 rectBorder.x = rect.x + 2;
810 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
811 rectBorder.width = size.x;
812 rectBorder.height = size.y;
813 }
814 else if (hAlign == wxALIGN_RIGHT)
815 {
816 rectBorder.x = rect.x + rect.width - size.x - 2;
817 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
818 rectBorder.width = size.x;
819 rectBorder.height = size.y;
820 }
821
822 bool value;
823 if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
824 {
825 value = grid.GetTable()->GetValueAsBool(row, col);
826 }
827 else
828 {
829 wxString cellval( grid.GetTable()->GetValue(row, col) );
830 value = wxGridCellBoolEditor::IsTrueValue(cellval);
831 }
832
833 int flags = 0;
834 if (value)
835 flags |= wxCONTROL_CHECKED;
836
837 wxRendererNative::Get().DrawCheckBox( &grid, dc, rectBorder, flags );
838}
839
3a8c693a
VZ
840#endif // wxUSE_GRID
841