]> git.saurik.com Git - wxWidgets.git/blob - src/generic/gridctrl.cpp
Make wxOwnerDrawnComboBox::DoGetBestSize() twice as fast.
[wxWidgets.git] / src / generic / gridctrl.cpp
1 ///////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/gridctrl.cpp
3 // Purpose: wxGrid controls
4 // Author: Paul Gammans, Roger Gammans
5 // Modified by:
6 // Created: 11/04/2001
7 // Copyright: (c) The Computer Surgery (paul@compsurg.co.uk)
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/wxprec.h"
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 #if wxUSE_GRID
18
19 #include "wx/generic/gridctrl.h"
20 #include "wx/generic/grideditors.h"
21
22 #ifndef WX_PRECOMP
23 #include "wx/textctrl.h"
24 #include "wx/dc.h"
25 #include "wx/combobox.h"
26 #include "wx/settings.h"
27 #include "wx/log.h"
28 #include "wx/checkbox.h"
29 #endif // WX_PRECOMP
30
31 #include "wx/tokenzr.h"
32 #include "wx/renderer.h"
33
34
35 // ----------------------------------------------------------------------------
36 // wxGridCellRenderer
37 // ----------------------------------------------------------------------------
38
39 void wxGridCellRenderer::Draw(wxGrid& grid,
40 wxGridCellAttr& attr,
41 wxDC& dc,
42 const wxRect& rect,
43 int WXUNUSED(row), int WXUNUSED(col),
44 bool isSelected)
45 {
46 dc.SetBackgroundMode( wxBRUSHSTYLE_SOLID );
47
48 wxColour clr;
49 if ( grid.IsThisEnabled() )
50 {
51 if ( isSelected )
52 {
53 if ( grid.HasFocus() )
54 clr = grid.GetSelectionBackground();
55 else
56 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
57 }
58 else
59 {
60 clr = attr.GetBackgroundColour();
61 }
62 }
63 else // grey out fields if the grid is disabled
64 {
65 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
66 }
67
68 dc.SetBrush(clr);
69 dc.SetPen( *wxTRANSPARENT_PEN );
70 dc.DrawRectangle(rect);
71 }
72
73
74 // ----------------------------------------------------------------------------
75 // wxGridCellDateTimeRenderer
76 // ----------------------------------------------------------------------------
77
78 #if wxUSE_DATETIME
79
80 // Enables a grid cell to display a formatted date and or time
81
82 wxGridCellDateTimeRenderer::wxGridCellDateTimeRenderer(const wxString& outformat, const wxString& informat)
83 {
84 m_iformat = informat;
85 m_oformat = outformat;
86 m_tz = wxDateTime::Local;
87 m_dateDef = wxDefaultDateTime;
88 }
89
90 wxGridCellRenderer *wxGridCellDateTimeRenderer::Clone() const
91 {
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;
97
98 return renderer;
99 }
100
101 wxString wxGridCellDateTimeRenderer::GetString(const wxGrid& grid, int row, int col)
102 {
103 wxGridTableBase *table = grid.GetTable();
104
105 bool hasDatetime = false;
106 wxDateTime val;
107 wxString text;
108 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_DATETIME) )
109 {
110 void * tempval = table->GetValueAsCustom(row, col,wxGRID_VALUE_DATETIME);
111
112 if (tempval)
113 {
114 val = *((wxDateTime *)tempval);
115 hasDatetime = true;
116 delete (wxDateTime *)tempval;
117 }
118
119 }
120
121 if (!hasDatetime )
122 {
123 text = table->GetValue(row, col);
124 const char * const end = val.ParseFormat(text, m_iformat, m_dateDef);
125 hasDatetime = end && !*end;
126 }
127
128 if ( hasDatetime )
129 text = val.Format(m_oformat, m_tz );
130
131 // If we failed to parse string just show what we where given?
132 return text;
133 }
134
135 void wxGridCellDateTimeRenderer::Draw(wxGrid& grid,
136 wxGridCellAttr& attr,
137 wxDC& dc,
138 const wxRect& rectCell,
139 int row, int col,
140 bool isSelected)
141 {
142 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
143
144 SetTextColoursAndFont(grid, attr, dc, isSelected);
145
146 // draw the text right aligned by default
147 int hAlign = wxALIGN_RIGHT,
148 vAlign = wxALIGN_INVALID;
149 attr.GetNonDefaultAlignment(&hAlign, &vAlign);
150
151 wxRect rect = rectCell;
152 rect.Inflate(-1);
153
154 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
155 }
156
157 wxSize wxGridCellDateTimeRenderer::GetBestSize(wxGrid& grid,
158 wxGridCellAttr& attr,
159 wxDC& dc,
160 int row, int col)
161 {
162 return DoGetBestSize(attr, dc, GetString(grid, row, col));
163 }
164
165 void wxGridCellDateTimeRenderer::SetParameters(const wxString& params)
166 {
167 if (!params.empty())
168 m_oformat=params;
169 }
170
171 #endif // wxUSE_DATETIME
172
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"
178
179
180 wxGridCellEnumRenderer::wxGridCellEnumRenderer(const wxString& choices)
181 {
182 if (!choices.empty())
183 SetParameters(choices);
184 }
185
186 wxGridCellRenderer *wxGridCellEnumRenderer::Clone() const
187 {
188 wxGridCellEnumRenderer *renderer = new wxGridCellEnumRenderer;
189 renderer->m_choices = m_choices;
190 return renderer;
191 }
192
193 wxString wxGridCellEnumRenderer::GetString(const wxGrid& grid, int row, int col)
194 {
195 wxGridTableBase *table = grid.GetTable();
196 wxString text;
197 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
198 {
199 int choiceno = table->GetValueAsLong(row, col);
200 text.Printf(wxT("%s"), m_choices[ choiceno ].c_str() );
201 }
202 else
203 {
204 text = table->GetValue(row, col);
205 }
206
207
208 //If we faild to parse string just show what we where given?
209 return text;
210 }
211
212 void wxGridCellEnumRenderer::Draw(wxGrid& grid,
213 wxGridCellAttr& attr,
214 wxDC& dc,
215 const wxRect& rectCell,
216 int row, int col,
217 bool isSelected)
218 {
219 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
220
221 SetTextColoursAndFont(grid, attr, dc, isSelected);
222
223 // draw the text right aligned by default
224 int hAlign = wxALIGN_RIGHT,
225 vAlign = wxALIGN_INVALID;
226 attr.GetNonDefaultAlignment(&hAlign, &vAlign);
227
228 wxRect rect = rectCell;
229 rect.Inflate(-1);
230
231 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
232 }
233
234 wxSize wxGridCellEnumRenderer::GetBestSize(wxGrid& grid,
235 wxGridCellAttr& attr,
236 wxDC& dc,
237 int row, int col)
238 {
239 return DoGetBestSize(attr, dc, GetString(grid, row, col));
240 }
241
242 void wxGridCellEnumRenderer::SetParameters(const wxString& params)
243 {
244 if ( !params )
245 {
246 // what can we do?
247 return;
248 }
249
250 m_choices.Empty();
251
252 wxStringTokenizer tk(params, wxT(','));
253 while ( tk.HasMoreTokens() )
254 {
255 m_choices.Add(tk.GetNextToken());
256 }
257 }
258
259
260 // ----------------------------------------------------------------------------
261 // wxGridCellAutoWrapStringRenderer
262 // ----------------------------------------------------------------------------
263
264
265 void
266 wxGridCellAutoWrapStringRenderer::Draw(wxGrid& grid,
267 wxGridCellAttr& attr,
268 wxDC& dc,
269 const wxRect& rectCell,
270 int row, int col,
271 bool isSelected) {
272
273
274 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
275
276 // now we only have to draw the text
277 SetTextColoursAndFont(grid, attr, dc, isSelected);
278
279 int horizAlign, vertAlign;
280 attr.GetAlignment(&horizAlign, &vertAlign);
281
282 wxRect rect = rectCell;
283 rect.Inflate(-1);
284
285 grid.DrawTextRectangle(dc, GetTextLines(grid,dc,attr,rect,row,col),
286 rect, horizAlign, vertAlign);
287 }
288
289
290 wxArrayString
291 wxGridCellAutoWrapStringRenderer::GetTextLines(wxGrid& grid,
292 wxDC& dc,
293 const wxGridCellAttr& attr,
294 const wxRect& rect,
295 int row, int col)
296 {
297 dc.SetFont(attr.GetFont());
298 const wxCoord maxWidth = rect.GetWidth();
299
300 // Transform logical lines into physical ones, wrapping the longer ones.
301 const wxArrayString
302 logicalLines = wxSplit(grid.GetCellValue(row, col), '\n', '\0');
303
304 wxArrayString physicalLines;
305 for ( wxArrayString::const_iterator it = logicalLines.begin();
306 it != logicalLines.end();
307 ++it )
308 {
309 const wxString& line = *it;
310
311 if ( dc.GetTextExtent(line).x > maxWidth )
312 {
313 // Line does not fit, break it up.
314 BreakLine(dc, line, maxWidth, physicalLines);
315 }
316 else // The entire line fits as is
317 {
318 physicalLines.push_back(line);
319 }
320 }
321
322 return physicalLines;
323 }
324
325 void
326 wxGridCellAutoWrapStringRenderer::BreakLine(wxDC& dc,
327 const wxString& logicalLine,
328 wxCoord maxWidth,
329 wxArrayString& lines)
330 {
331 wxCoord lineWidth = 0;
332 wxString line;
333
334 // For each word
335 wxStringTokenizer wordTokenizer(logicalLine, wxS(" \t"), wxTOKEN_RET_DELIMS);
336 while ( wordTokenizer.HasMoreTokens() )
337 {
338 const wxString word = wordTokenizer.GetNextToken();
339 const wxCoord wordWidth = dc.GetTextExtent(word).x;
340 if ( lineWidth + wordWidth < maxWidth )
341 {
342 // Word fits, just add it to this line.
343 line += word;
344 lineWidth += wordWidth;
345 }
346 else
347 {
348 // Word does not fit, check whether the word is itself wider that
349 // available width
350 if ( wordWidth < maxWidth )
351 {
352 // Word can fit in a new line, put it at the beginning
353 // of the new line.
354 lines.push_back(line);
355 line = word;
356 lineWidth = wordWidth;
357 }
358 else // Word cannot fit in available width at all.
359 {
360 if ( !line.empty() )
361 {
362 lines.push_back(line);
363 line.clear();
364 lineWidth = 0;
365 }
366
367 // Break it up in several lines.
368 lineWidth = BreakWord(dc, word, maxWidth, lines, line);
369 }
370 }
371 }
372
373 if ( !line.empty() )
374 lines.push_back(line);
375 }
376
377
378 wxCoord
379 wxGridCellAutoWrapStringRenderer::BreakWord(wxDC& dc,
380 const wxString& word,
381 wxCoord maxWidth,
382 wxArrayString& lines,
383 wxString& line)
384 {
385 wxArrayInt widths;
386 dc.GetPartialTextExtents(word, widths);
387
388 // TODO: Use binary search to find the first element > maxWidth.
389 const unsigned count = widths.size();
390 unsigned n;
391 for ( n = 0; n < count; n++ )
392 {
393 if ( widths[n] > maxWidth )
394 break;
395 }
396
397 if ( n == 0 )
398 {
399 // This is a degenerate case: the first character of the word is
400 // already wider than the available space, so we just can't show it
401 // completely and have to put the first character in this line.
402 n = 1;
403 }
404
405 lines.push_back(word.substr(0, n));
406
407 // Check if the remainder of the string fits in one line.
408 //
409 // Unfortunately we can't use the existing partial text extents as the
410 // extent of the remainder may be different when it's rendered in a
411 // separate line instead of as part of the same one, so we have to
412 // recompute it.
413 const wxString rest = word.substr(n);
414 const wxCoord restWidth = dc.GetTextExtent(rest).x;
415 if ( restWidth <= maxWidth )
416 {
417 line = rest;
418 return restWidth;
419 }
420
421 // Break the rest of the word into lines.
422 //
423 // TODO: Perhaps avoid recursion? The code is simpler like this but using a
424 // loop in this function would probably be more efficient.
425 return BreakWord(dc, rest, maxWidth, lines, line);
426 }
427
428 wxSize
429 wxGridCellAutoWrapStringRenderer::GetBestSize(wxGrid& grid,
430 wxGridCellAttr& attr,
431 wxDC& dc,
432 int row, int col)
433 {
434 wxCoord x,y, height , width = grid.GetColSize(col) -20;
435 // for width, subtract 20 because ColSize includes a magin of 10 pixels
436 // that we do not want here and because we always start with an increment
437 // by 10 in the loop below.
438 int count = 250; //Limit iterations..
439
440 wxRect rect(0,0,width,10);
441
442 // M is a nice large character 'y' gives descender!.
443 dc.GetTextExtent(wxT("My"), &x, &y);
444
445 do
446 {
447 width+=10;
448 rect.SetWidth(width);
449 height = y * (wx_truncate_cast(wxCoord, GetTextLines(grid,dc,attr,rect,row,col).GetCount()));
450 count--;
451 // Search for a shape no taller than the golden ratio.
452 } while (count && (width < (height*1.68)) );
453
454
455 return wxSize(width,height);
456 }
457
458
459 // ----------------------------------------------------------------------------
460 // wxGridCellStringRenderer
461 // ----------------------------------------------------------------------------
462
463 void wxGridCellStringRenderer::SetTextColoursAndFont(const wxGrid& grid,
464 const wxGridCellAttr& attr,
465 wxDC& dc,
466 bool isSelected)
467 {
468 dc.SetBackgroundMode( wxBRUSHSTYLE_TRANSPARENT );
469
470 // TODO some special colours for attr.IsReadOnly() case?
471
472 // different coloured text when the grid is disabled
473 if ( grid.IsThisEnabled() )
474 {
475 if ( isSelected )
476 {
477 wxColour clr;
478 if ( grid.HasFocus() )
479 clr = grid.GetSelectionBackground();
480 else
481 clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
482 dc.SetTextBackground( clr );
483 dc.SetTextForeground( grid.GetSelectionForeground() );
484 }
485 else
486 {
487 dc.SetTextBackground( attr.GetBackgroundColour() );
488 dc.SetTextForeground( attr.GetTextColour() );
489 }
490 }
491 else
492 {
493 dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
494 dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
495 }
496
497 dc.SetFont( attr.GetFont() );
498 }
499
500 wxSize wxGridCellStringRenderer::DoGetBestSize(const wxGridCellAttr& attr,
501 wxDC& dc,
502 const wxString& text)
503 {
504 wxCoord x = 0, y = 0, max_x = 0;
505 dc.SetFont(attr.GetFont());
506 wxStringTokenizer tk(text, wxT('\n'));
507 while ( tk.HasMoreTokens() )
508 {
509 dc.GetTextExtent(tk.GetNextToken(), &x, &y);
510 max_x = wxMax(max_x, x);
511 }
512
513 y *= 1 + text.Freq(wxT('\n')); // multiply by the number of lines.
514
515 return wxSize(max_x, y);
516 }
517
518 wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid,
519 wxGridCellAttr& attr,
520 wxDC& dc,
521 int row, int col)
522 {
523 return DoGetBestSize(attr, dc, grid.GetCellValue(row, col));
524 }
525
526 void wxGridCellStringRenderer::Draw(wxGrid& grid,
527 wxGridCellAttr& attr,
528 wxDC& dc,
529 const wxRect& rectCell,
530 int row, int col,
531 bool isSelected)
532 {
533 wxRect rect = rectCell;
534 rect.Inflate(-1);
535
536 // erase only this cells background, overflow cells should have been erased
537 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
538
539 int hAlign, vAlign;
540 attr.GetAlignment(&hAlign, &vAlign);
541
542 int overflowCols = 0;
543
544 if (attr.GetOverflow())
545 {
546 int cols = grid.GetNumberCols();
547 int best_width = GetBestSize(grid,attr,dc,row,col).GetWidth();
548 int cell_rows, cell_cols;
549 attr.GetSize( &cell_rows, &cell_cols ); // shouldn't get here if <= 0
550 if ((best_width > rectCell.width) && (col < cols) && grid.GetTable())
551 {
552 int i, c_cols, c_rows;
553 for (i = col+cell_cols; i < cols; i++)
554 {
555 bool is_empty = true;
556 for (int j=row; j < row + cell_rows; j++)
557 {
558 // check w/ anchor cell for multicell block
559 grid.GetCellSize(j, i, &c_rows, &c_cols);
560 if (c_rows > 0)
561 c_rows = 0;
562 if (!grid.GetTable()->IsEmptyCell(j + c_rows, i))
563 {
564 is_empty = false;
565 break;
566 }
567 }
568
569 if (is_empty)
570 {
571 rect.width += grid.GetColSize(i);
572 }
573 else
574 {
575 i--;
576 break;
577 }
578
579 if (rect.width >= best_width)
580 break;
581 }
582
583 overflowCols = i - col - cell_cols + 1;
584 if (overflowCols >= cols)
585 overflowCols = cols - 1;
586 }
587
588 if (overflowCols > 0) // redraw overflow cells w/ proper hilight
589 {
590 hAlign = wxALIGN_LEFT; // if oveflowed then it's left aligned
591 wxRect clip = rect;
592 clip.x += rectCell.width;
593 // draw each overflow cell individually
594 int col_end = col + cell_cols + overflowCols;
595 if (col_end >= grid.GetNumberCols())
596 col_end = grid.GetNumberCols() - 1;
597 for (int i = col + cell_cols; i <= col_end; i++)
598 {
599 clip.width = grid.GetColSize(i) - 1;
600 dc.DestroyClippingRegion();
601 dc.SetClippingRegion(clip);
602
603 SetTextColoursAndFont(grid, attr, dc,
604 grid.IsInSelection(row,i));
605
606 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
607 rect, hAlign, vAlign);
608 clip.x += grid.GetColSize(i) - 1;
609 }
610
611 rect = rectCell;
612 rect.Inflate(-1);
613 rect.width++;
614 dc.DestroyClippingRegion();
615 }
616 }
617
618 // now we only have to draw the text
619 SetTextColoursAndFont(grid, attr, dc, isSelected);
620
621 grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
622 rect, hAlign, vAlign);
623 }
624
625 // ----------------------------------------------------------------------------
626 // wxGridCellNumberRenderer
627 // ----------------------------------------------------------------------------
628
629 wxString wxGridCellNumberRenderer::GetString(const wxGrid& grid, int row, int col)
630 {
631 wxGridTableBase *table = grid.GetTable();
632 wxString text;
633 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
634 {
635 text.Printf(wxT("%ld"), table->GetValueAsLong(row, col));
636 }
637 else
638 {
639 text = table->GetValue(row, col);
640 }
641
642 return text;
643 }
644
645 void wxGridCellNumberRenderer::Draw(wxGrid& grid,
646 wxGridCellAttr& attr,
647 wxDC& dc,
648 const wxRect& rectCell,
649 int row, int col,
650 bool isSelected)
651 {
652 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
653
654 SetTextColoursAndFont(grid, attr, dc, isSelected);
655
656 // draw the text right aligned by default
657 int hAlign = wxALIGN_RIGHT,
658 vAlign = wxALIGN_INVALID;
659 attr.GetNonDefaultAlignment(&hAlign, &vAlign);
660
661 wxRect rect = rectCell;
662 rect.Inflate(-1);
663
664 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
665 }
666
667 wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
668 wxGridCellAttr& attr,
669 wxDC& dc,
670 int row, int col)
671 {
672 return DoGetBestSize(attr, dc, GetString(grid, row, col));
673 }
674
675 // ----------------------------------------------------------------------------
676 // wxGridCellFloatRenderer
677 // ----------------------------------------------------------------------------
678
679 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width,
680 int precision,
681 int format)
682 {
683 SetWidth(width);
684 SetPrecision(precision);
685 SetFormat(format);
686 }
687
688 wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const
689 {
690 wxGridCellFloatRenderer *renderer = new wxGridCellFloatRenderer;
691 renderer->m_width = m_width;
692 renderer->m_precision = m_precision;
693 renderer->m_style = m_style;
694 renderer->m_format = m_format;
695
696 return renderer;
697 }
698
699 wxString wxGridCellFloatRenderer::GetString(const wxGrid& grid, int row, int col)
700 {
701 wxGridTableBase *table = grid.GetTable();
702
703 bool hasDouble;
704 double val;
705 wxString text;
706 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
707 {
708 val = table->GetValueAsDouble(row, col);
709 hasDouble = true;
710 }
711 else
712 {
713 text = table->GetValue(row, col);
714 hasDouble = text.ToDouble(&val);
715 }
716
717 if ( hasDouble )
718 {
719 if ( !m_format )
720 {
721 if ( m_width == -1 )
722 {
723 if ( m_precision == -1 )
724 {
725 // default width/precision
726 m_format = wxT("%");
727 }
728 else
729 {
730 m_format.Printf(wxT("%%.%d"), m_precision);
731 }
732 }
733 else if ( m_precision == -1 )
734 {
735 // default precision
736 m_format.Printf(wxT("%%%d."), m_width);
737 }
738 else
739 {
740 m_format.Printf(wxT("%%%d.%d"), m_width, m_precision);
741 }
742
743 bool isUpper = ( ( m_style & wxGRID_FLOAT_FORMAT_UPPER ) == wxGRID_FLOAT_FORMAT_UPPER);
744 if ( ( m_style & wxGRID_FLOAT_FORMAT_SCIENTIFIC ) == wxGRID_FLOAT_FORMAT_SCIENTIFIC)
745 m_format += isUpper ? wxT('E') : wxT('e');
746 else if ( ( m_style & wxGRID_FLOAT_FORMAT_COMPACT ) == wxGRID_FLOAT_FORMAT_COMPACT)
747 m_format += isUpper ? wxT('G') : wxT('g');
748 else
749 m_format += wxT('f');
750 }
751
752 text.Printf(m_format, val);
753
754 }
755 //else: text already contains the string
756
757 return text;
758 }
759
760 void wxGridCellFloatRenderer::Draw(wxGrid& grid,
761 wxGridCellAttr& attr,
762 wxDC& dc,
763 const wxRect& rectCell,
764 int row, int col,
765 bool isSelected)
766 {
767 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
768
769 SetTextColoursAndFont(grid, attr, dc, isSelected);
770
771 // draw the text right aligned by default
772 int hAlign = wxALIGN_RIGHT,
773 vAlign = wxALIGN_INVALID;
774 attr.GetNonDefaultAlignment(&hAlign, &vAlign);
775
776 wxRect rect = rectCell;
777 rect.Inflate(-1);
778
779 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
780 }
781
782 wxSize wxGridCellFloatRenderer::GetBestSize(wxGrid& grid,
783 wxGridCellAttr& attr,
784 wxDC& dc,
785 int row, int col)
786 {
787 return DoGetBestSize(attr, dc, GetString(grid, row, col));
788 }
789
790 void wxGridCellFloatRenderer::SetParameters(const wxString& params)
791 {
792 if ( !params )
793 {
794 // reset to defaults
795 SetWidth(-1);
796 SetPrecision(-1);
797 SetFormat(wxGRID_FLOAT_FORMAT_DEFAULT);
798 }
799 else
800 {
801 wxString rest;
802 wxString tmp = params.BeforeFirst(wxT(','), &rest);
803 if ( !tmp.empty() )
804 {
805 long width;
806 if ( tmp.ToLong(&width) )
807 {
808 SetWidth((int)width);
809 }
810 else
811 {
812 wxLogDebug(wxT("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params.c_str());
813 }
814 }
815
816 tmp = rest.BeforeFirst(wxT(','));
817 if ( !tmp.empty() )
818 {
819 long precision;
820 if ( tmp.ToLong(&precision) )
821 {
822 SetPrecision((int)precision);
823 }
824 else
825 {
826 wxLogDebug(wxT("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params.c_str());
827 }
828 }
829
830 tmp = rest.AfterFirst(wxT(','));
831 if ( !tmp.empty() )
832 {
833 if ( tmp[0] == wxT('f') )
834 {
835 SetFormat(wxGRID_FLOAT_FORMAT_FIXED);
836 }
837 else if ( tmp[0] == wxT('e') )
838 {
839 SetFormat(wxGRID_FLOAT_FORMAT_SCIENTIFIC);
840 }
841 else if ( tmp[0] == wxT('g') )
842 {
843 SetFormat(wxGRID_FLOAT_FORMAT_COMPACT);
844 }
845 else if ( tmp[0] == wxT('E') )
846 {
847 SetFormat(wxGRID_FLOAT_FORMAT_SCIENTIFIC |
848 wxGRID_FLOAT_FORMAT_UPPER);
849 }
850 else if ( tmp[0] == wxT('F') )
851 {
852 SetFormat(wxGRID_FLOAT_FORMAT_FIXED |
853 wxGRID_FLOAT_FORMAT_UPPER);
854 }
855 else if ( tmp[0] == wxT('G') )
856 {
857 SetFormat(wxGRID_FLOAT_FORMAT_COMPACT |
858 wxGRID_FLOAT_FORMAT_UPPER);
859 }
860 else
861 {
862 wxLogDebug("Invalid wxGridCellFloatRenderer format "
863 "parameter string '%s ignored", params);
864 }
865 }
866 }
867 }
868
869 // ----------------------------------------------------------------------------
870 // wxGridCellBoolRenderer
871 // ----------------------------------------------------------------------------
872
873 wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
874
875 wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
876 wxGridCellAttr& WXUNUSED(attr),
877 wxDC& WXUNUSED(dc),
878 int WXUNUSED(row),
879 int WXUNUSED(col))
880 {
881 // compute it only once (no locks for MT safeness in GUI thread...)
882 if ( !ms_sizeCheckMark.x )
883 {
884 ms_sizeCheckMark = wxRendererNative::Get().GetCheckBoxSize(&grid);
885 }
886
887 return ms_sizeCheckMark;
888 }
889
890 void wxGridCellBoolRenderer::Draw(wxGrid& grid,
891 wxGridCellAttr& attr,
892 wxDC& dc,
893 const wxRect& rect,
894 int row, int col,
895 bool isSelected)
896 {
897 wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
898
899 // draw a check mark in the centre (ignoring alignment - TODO)
900 wxSize size = GetBestSize(grid, attr, dc, row, col);
901
902 // don't draw outside the cell
903 wxCoord minSize = wxMin(rect.width, rect.height);
904 if ( size.x >= minSize || size.y >= minSize )
905 {
906 // and even leave (at least) 1 pixel margin
907 size.x = size.y = minSize;
908 }
909
910 // draw a border around checkmark
911 int vAlign, hAlign;
912 attr.GetAlignment(&hAlign, &vAlign);
913
914 wxRect rectBorder;
915 if (hAlign == wxALIGN_CENTRE)
916 {
917 rectBorder.x = rect.x + rect.width / 2 - size.x / 2;
918 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
919 rectBorder.width = size.x;
920 rectBorder.height = size.y;
921 }
922 else if (hAlign == wxALIGN_LEFT)
923 {
924 rectBorder.x = rect.x + 2;
925 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
926 rectBorder.width = size.x;
927 rectBorder.height = size.y;
928 }
929 else if (hAlign == wxALIGN_RIGHT)
930 {
931 rectBorder.x = rect.x + rect.width - size.x - 2;
932 rectBorder.y = rect.y + rect.height / 2 - size.y / 2;
933 rectBorder.width = size.x;
934 rectBorder.height = size.y;
935 }
936
937 bool value;
938 if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
939 {
940 value = grid.GetTable()->GetValueAsBool(row, col);
941 }
942 else
943 {
944 wxString cellval( grid.GetTable()->GetValue(row, col) );
945 value = wxGridCellBoolEditor::IsTrueValue(cellval);
946 }
947
948 int flags = 0;
949 if (value)
950 flags |= wxCONTROL_CHECKED;
951
952 wxRendererNative::Get().DrawCheckBox( &grid, dc, rectBorder, flags );
953 }
954
955 #endif // wxUSE_GRID
956