]>
Commit | Line | Data |
---|---|---|
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 | 43 | wxGridCellDateTimeRenderer::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 | ||
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 | ||
fbfb8bcc | 62 | wxString 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 | ||
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 | ||
7448de8d WS |
126 | void 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 | ||
141 | wxGridCellEnumRenderer::wxGridCellEnumRenderer(const wxString& choices) | |
142 | { | |
7448de8d | 143 | if (!choices.empty()) |
d10f4bf9 VZ |
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 | ||
fbfb8bcc | 154 | wxString 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 | ||
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 | ||
3a8c693a | 220 | |
d10f4bf9 | 221 | // ---------------------------------------------------------------------------- |
29efc6e4 | 222 | // wxGridCellAutoWrapStringRenderer |
d10f4bf9 | 223 | // ---------------------------------------------------------------------------- |
3a8c693a | 224 | |
d10f4bf9 VZ |
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, | |
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 | ||
310 | wxSize | |
311 | wxGridCellAutoWrapStringRenderer::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 | ||
345 | void 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 | ||
383 | void 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 | ||
420 | wxSize 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 | ||
438 | wxSize 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 | ||
446 | void 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 | ||
549 | wxString 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 | ||
565 | void 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 | ||
587 | wxSize 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 | ||
599 | wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision) | |
600 | { | |
601 | SetWidth(width); | |
602 | SetPrecision(precision); | |
603 | } | |
604 | ||
605 | wxGridCellRenderer *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 | ||
615 | wxString 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 | ||
668 | void 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 | ||
690 | wxSize 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 | ||
698 | void 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 | ||
742 | wxSize wxGridCellBoolRenderer::ms_sizeCheckMark; | |
743 | ||
744 | // FIXME these checkbox size calculations are really ugly... | |
745 | ||
746 | // between checkmark and box | |
747 | static const wxCoord wxGRID_CHECKMARK_MARGIN = 2; | |
748 | ||
749 | wxSize 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 | ||
775 | void 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 |