added support for gcc precompiled headers
[wxWidgets.git] / src / generic / gridctrl.cpp
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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "gridctrl.h"
14 #endif
15
16 #include "wx/wxprec.h"
17
18 #ifdef __BORLANDC__
19 #pragma hdrstop
20 #endif
21
22 #if wxUSE_GRID
23
24 #ifndef WX_PRECOMP
25 #include "wx/textctrl.h"
26 #include "wx/dc.h"
27 #endif // WX_PRECOMP
28
29 #include "wx/generic/gridctrl.h"
30 #include "wx/tokenzr.h"
31
32 // ----------------------------------------------------------------------------
33 // wxGridCellDateTimeRenderer
34 // ----------------------------------------------------------------------------
35
36 #if wxUSE_DATETIME
37
38 // Enables a grid cell to display a formated date and or time
39
40 wxGridCellDateTimeRenderer::wxGridCellDateTimeRenderer(wxString outformat, wxString informat)
41 {
42 m_iformat = informat;
43 m_oformat = outformat;
44 m_tz = wxDateTime::Local;
45 m_dateDef = wxDefaultDateTime;
46 }
47
48 wxGridCellRenderer *wxGridCellDateTimeRenderer::Clone() const
49 {
50 wxGridCellDateTimeRenderer *renderer = new wxGridCellDateTimeRenderer;
51 renderer->m_iformat = m_iformat;
52 renderer->m_oformat = m_oformat;
53 renderer->m_dateDef = m_dateDef;
54 renderer->m_tz = m_tz;
55
56 return renderer;
57 }
58
59 wxString wxGridCellDateTimeRenderer::GetString(wxGrid& grid, int row, int col)
60 {
61 wxGridTableBase *table = grid.GetTable();
62
63 bool hasDatetime = FALSE;
64 wxDateTime val;
65 wxString text;
66 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_DATETIME) )
67 {
68 void * tempval = table->GetValueAsCustom(row, col,wxGRID_VALUE_DATETIME);
69
70 if (tempval){
71 val = *((wxDateTime *)tempval);
72 hasDatetime = TRUE;
73 delete (wxDateTime *)tempval;
74 }
75
76 }
77
78 if (!hasDatetime )
79 {
80 text = table->GetValue(row, col);
81 hasDatetime = (val.ParseFormat( text, m_iformat, m_dateDef ) != (wxChar *)NULL) ;
82 }
83
84 if ( hasDatetime )
85 text = val.Format(m_oformat, m_tz );
86
87 //If we faild to parse string just show what we where given?
88 return text;
89 }
90
91 void wxGridCellDateTimeRenderer::Draw(wxGrid& grid,
92 wxGridCellAttr& attr,
93 wxDC& dc,
94 const wxRect& rectCell,
95 int row, int col,
96 bool isSelected)
97 {
98 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
99
100 SetTextColoursAndFont(grid, attr, dc, isSelected);
101
102 // draw the text right aligned by default
103 int hAlign, vAlign;
104 attr.GetAlignment(&hAlign, &vAlign);
105 hAlign = wxRIGHT;
106
107 wxRect rect = rectCell;
108 rect.Inflate(-1);
109
110 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
111 }
112
113 wxSize wxGridCellDateTimeRenderer::GetBestSize(wxGrid& grid,
114 wxGridCellAttr& attr,
115 wxDC& dc,
116 int row, int col)
117 {
118 return DoGetBestSize(attr, dc, GetString(grid, row, col));
119 }
120
121 void wxGridCellDateTimeRenderer::SetParameters(const wxString& params){
122 if (!params.IsEmpty())
123 m_oformat=params;
124 }
125
126 #endif // wxUSE_DATETIME
127
128 // ----------------------------------------------------------------------------
129 // wxGridCellChoiceNumberRenderer
130 // ----------------------------------------------------------------------------
131 // Renders a number as a textual equivalent.
132 // eg data in cell is 0,1,2 ... n the cell could be rendered as "John","Fred"..."Bob"
133
134
135 wxGridCellEnumRenderer::wxGridCellEnumRenderer(const wxString& choices)
136 {
137 if (!choices.IsEmpty())
138 SetParameters(choices);
139 }
140
141 wxGridCellRenderer *wxGridCellEnumRenderer::Clone() const
142 {
143 wxGridCellEnumRenderer *renderer = new wxGridCellEnumRenderer;
144 renderer->m_choices = m_choices;
145 return renderer;
146 }
147
148 wxString wxGridCellEnumRenderer::GetString(wxGrid& grid, int row, int col)
149 {
150 wxGridTableBase *table = grid.GetTable();
151 wxString text;
152 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
153 {
154 int choiceno = table->GetValueAsLong(row, col);
155 text.Printf(_T("%s"), m_choices[ choiceno ].c_str() );
156 }
157 else
158 {
159 text = table->GetValue(row, col);
160 }
161
162
163 //If we faild to parse string just show what we where given?
164 return text;
165 }
166
167 void wxGridCellEnumRenderer::Draw(wxGrid& grid,
168 wxGridCellAttr& attr,
169 wxDC& dc,
170 const wxRect& rectCell,
171 int row, int col,
172 bool isSelected)
173 {
174 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
175
176 SetTextColoursAndFont(grid, attr, dc, isSelected);
177
178 // draw the text right aligned by default
179 int hAlign, vAlign;
180 attr.GetAlignment(&hAlign, &vAlign);
181 hAlign = wxRIGHT;
182
183 wxRect rect = rectCell;
184 rect.Inflate(-1);
185
186 grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign);
187 }
188
189 wxSize wxGridCellEnumRenderer::GetBestSize(wxGrid& grid,
190 wxGridCellAttr& attr,
191 wxDC& dc,
192 int row, int col)
193 {
194 return DoGetBestSize(attr, dc, GetString(grid, row, col));
195 }
196
197 void wxGridCellEnumRenderer::SetParameters(const wxString& params)
198 {
199 if ( !params )
200 {
201 // what can we do?
202 return;
203 }
204
205 m_choices.Empty();
206
207 wxStringTokenizer tk(params, _T(','));
208 while ( tk.HasMoreTokens() )
209 {
210 m_choices.Add(tk.GetNextToken());
211 }
212 }
213
214 #if wxUSE_COMBOBOX
215
216 // ----------------------------------------------------------------------------
217 // wxGridCellEnumEditor
218 // ----------------------------------------------------------------------------
219
220 // A cell editor which displays an enum number as a textual equivalent. eg
221 // data in cell is 0,1,2 ... n the cell could be displayed as
222 // "John","Fred"..."Bob" in the combo choice box
223
224 wxGridCellEnumEditor::wxGridCellEnumEditor(const wxString& choices)
225 : wxGridCellChoiceEditor()
226 {
227 m_startint = -1;
228
229 if (!choices.IsEmpty())
230 SetParameters(choices);
231 }
232
233 wxGridCellEditor *wxGridCellEnumEditor::Clone() const
234 {
235 wxGridCellEnumEditor *editor = new wxGridCellEnumEditor();
236 editor->m_startint = m_startint;
237 return editor;
238 }
239
240 void wxGridCellEnumEditor::BeginEdit(int row, int col, wxGrid* grid)
241 {
242 wxASSERT_MSG(m_control,
243 wxT("The wxGridCellEnumEditor must be Created first!"));
244
245 wxGridTableBase *table = grid->GetTable();
246
247 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
248 {
249 m_startint = table->GetValueAsLong(row, col);
250 }
251 else
252 {
253 wxString startValue = table->GetValue(row, col);
254 if (startValue.IsNumber() && !startValue.IsEmpty())
255 {
256 startValue.ToLong(&m_startint);
257 }
258 else
259 {
260 m_startint=-1;
261 }
262 }
263
264 Combo()->SetSelection(m_startint);
265 Combo()->SetInsertionPointEnd();
266 Combo()->SetFocus();
267
268 }
269
270 bool wxGridCellEnumEditor::EndEdit(int row, int col, wxGrid* grid)
271 {
272 int pos = Combo()->GetSelection();
273 bool changed = (pos != m_startint);
274 if (changed)
275 {
276 if (grid->GetTable()->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER))
277 grid->GetTable()->SetValueAsLong(row, col, pos);
278 else
279 grid->GetTable()->SetValue(row, col,wxString::Format(wxT("%i"),pos));
280 }
281
282 return changed;
283 }
284
285 #endif // wxUSE_COMBOBOX
286
287 // ----------------------------------------------------------------------------
288 // wxGridCellAutoWrapStringEditor
289 // ----------------------------------------------------------------------------
290
291 void
292 wxGridCellAutoWrapStringEditor::Create(wxWindow* parent,
293 wxWindowID id,
294 wxEvtHandler* evtHandler)
295 {
296 m_control = new wxTextCtrl(parent, id, wxEmptyString,
297 wxDefaultPosition, wxDefaultSize,
298 wxTE_MULTILINE | wxTE_RICH);
299
300
301 wxGridCellEditor::Create(parent, id, evtHandler);
302 }
303
304 void
305 wxGridCellAutoWrapStringRenderer::Draw(wxGrid& grid,
306 wxGridCellAttr& attr,
307 wxDC& dc,
308 const wxRect& rectCell,
309 int row, int col,
310 bool isSelected) {
311
312
313 wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
314
315 // now we only have to draw the text
316 SetTextColoursAndFont(grid, attr, dc, isSelected);
317
318 int horizAlign, vertAlign;
319 attr.GetAlignment(&horizAlign, &vertAlign);
320
321 wxRect rect = rectCell;
322 rect.Inflate(-1);
323
324 grid.DrawTextRectangle(dc, GetTextLines(grid,dc,attr,rect,row,col),
325 rect, horizAlign, vertAlign);
326 }
327
328
329 wxArrayString
330 wxGridCellAutoWrapStringRenderer::GetTextLines(wxGrid& grid,
331 wxDC& dc,
332 wxGridCellAttr& attr,
333 const wxRect& rect,
334 int row, int col)
335 {
336 wxString data = grid.GetCellValue(row, col);
337
338 wxArrayString lines;
339 dc.SetFont(attr.GetFont());
340
341 //Taken from wxGrid again!
342 wxCoord x = 0, y = 0, curr_x = 0;
343 wxCoord max_x = rect.GetWidth();
344
345 dc.SetFont(attr.GetFont());
346 wxStringTokenizer tk(data , _T(" \n\t\r"));
347 wxString thisline(wxT(""));
348
349 while ( tk.HasMoreTokens() )
350 {
351 wxString tok = tk.GetNextToken();
352 //FIXME: this causes us to print an extra unnecesary
353 // space at the end of the line. But it
354 // is invisible , simplifies the size calculation
355 // and ensures tokens are seperated in the display
356 tok += _T(" ");
357
358 dc.GetTextExtent(tok, &x, &y);
359 if ( curr_x + x > max_x) {
360 lines.Add( wxString(thisline) );
361 thisline = tok;
362 curr_x=x;
363 } else {
364 thisline+= tok;
365 curr_x += x;
366 }
367
368 }
369 //Add last line
370 lines.Add( wxString(thisline) );
371
372 return lines;
373 }
374
375
376 wxSize
377 wxGridCellAutoWrapStringRenderer::GetBestSize(wxGrid& grid,
378 wxGridCellAttr& attr,
379 wxDC& dc,
380 int row, int col)
381 {
382 wxCoord x,y, height , width = grid.GetColSize(col) -10;
383 int count = 250; //Limit iterations..
384
385 wxRect rect(0,0,width,10);
386
387 // M is a nice large character 'y' gives descender!.
388 dc.GetTextExtent(wxT("My"), &x, &y);
389
390 do
391 {
392 width+=10;
393 rect.SetWidth(width);
394 height = y *( GetTextLines(grid,dc,attr,rect,row,col).GetCount());
395 count--;
396 // Search for a shape no taller than the golden ratio.
397 } while (count && (width < (height*1.68)) );
398
399
400 return wxSize(width,height);
401 }
402
403 #endif // wxUSE_GRID
404