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