]>
Commit | Line | Data |
---|---|---|
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 |