]>
Commit | Line | Data |
---|---|---|
5612a518 | 1 | ///////////////////////////////////////////////////////////////////////////// |
f85afd4e MB |
2 | // Name: grid.cpp |
3 | // Purpose: wxGrid and related classes | |
4 | // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) | |
5 | // Modified by: | |
6 | // Created: 1/08/1999 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Michael Bedward (mbedward@ozemail.com.au) | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
f85afd4e MB |
12 | #ifdef __GNUG__ |
13 | #pragma implementation "grid.h" | |
14 | #endif | |
15 | ||
4d85bcd1 JS |
16 | // For compilers that support precompilation, includes "wx/wx.h". |
17 | #include "wx/wxprec.h" | |
18 | ||
19 | #include "wx/defs.h" | |
f85afd4e MB |
20 | |
21 | #ifdef __BORLANDC__ | |
22 | #pragma hdrstop | |
23 | #endif | |
24 | ||
8f177c8e | 25 | #if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID) |
4d85bcd1 JS |
26 | #include "gridg.cpp" |
27 | #else | |
28 | ||
f85afd4e MB |
29 | #ifndef WX_PRECOMP |
30 | #include "wx/utils.h" | |
31 | #include "wx/dcclient.h" | |
32 | #include "wx/settings.h" | |
33 | #include "wx/log.h" | |
2433bb2e | 34 | #include "wx/textfile.h" |
f85afd4e MB |
35 | #endif |
36 | ||
37 | #include "wx/generic/grid.h" | |
38 | ||
b99be8fb VZ |
39 | // ---------------------------------------------------------------------------- |
40 | // array classes instantiation | |
41 | // ---------------------------------------------------------------------------- | |
42 | ||
43 | struct wxGridCellWithAttr | |
44 | { | |
45 | wxGridCellWithAttr(int row, int col, const wxGridCellAttr *pAttr) | |
46 | : coords(row, col), attr(*pAttr) | |
47 | { | |
48 | } | |
49 | ||
50 | wxGridCellCoords coords; | |
51 | wxGridCellAttr attr; | |
52 | }; | |
53 | ||
54 | WX_DECLARE_OBJARRAY(wxGridCellWithAttr, wxGridCellWithAttrArray); | |
55 | ||
56 | #include "wx/arrimpl.cpp" | |
57 | ||
58 | WX_DEFINE_OBJARRAY(wxGridCellCoordsArray) | |
59 | WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray) | |
60 | ||
61 | // ---------------------------------------------------------------------------- | |
62 | // private classes | |
63 | // ---------------------------------------------------------------------------- | |
64 | ||
65 | class WXDLLEXPORT wxGridRowLabelWindow : public wxWindow | |
66 | { | |
67 | public: | |
68 | wxGridRowLabelWindow() { m_owner = (wxGrid *)NULL; } | |
69 | wxGridRowLabelWindow( wxGrid *parent, wxWindowID id, | |
70 | const wxPoint &pos, const wxSize &size ); | |
71 | ||
72 | private: | |
73 | wxGrid *m_owner; | |
74 | ||
75 | void OnPaint( wxPaintEvent& event ); | |
76 | void OnMouseEvent( wxMouseEvent& event ); | |
77 | void OnKeyDown( wxKeyEvent& event ); | |
78 | ||
79 | DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow) | |
80 | DECLARE_EVENT_TABLE() | |
81 | }; | |
82 | ||
83 | ||
84 | class WXDLLEXPORT wxGridColLabelWindow : public wxWindow | |
85 | { | |
86 | public: | |
87 | wxGridColLabelWindow() { m_owner = (wxGrid *)NULL; } | |
88 | wxGridColLabelWindow( wxGrid *parent, wxWindowID id, | |
89 | const wxPoint &pos, const wxSize &size ); | |
90 | ||
91 | private: | |
92 | wxGrid *m_owner; | |
93 | ||
94 | void OnPaint( wxPaintEvent &event ); | |
95 | void OnMouseEvent( wxMouseEvent& event ); | |
96 | void OnKeyDown( wxKeyEvent& event ); | |
97 | ||
98 | DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow) | |
99 | DECLARE_EVENT_TABLE() | |
100 | }; | |
101 | ||
102 | ||
103 | class WXDLLEXPORT wxGridCornerLabelWindow : public wxWindow | |
104 | { | |
105 | public: | |
106 | wxGridCornerLabelWindow() { m_owner = (wxGrid *)NULL; } | |
107 | wxGridCornerLabelWindow( wxGrid *parent, wxWindowID id, | |
108 | const wxPoint &pos, const wxSize &size ); | |
109 | ||
110 | private: | |
111 | wxGrid *m_owner; | |
112 | ||
113 | void OnMouseEvent( wxMouseEvent& event ); | |
114 | void OnKeyDown( wxKeyEvent& event ); | |
115 | void OnPaint( wxPaintEvent& event ); | |
116 | ||
117 | DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow) | |
118 | DECLARE_EVENT_TABLE() | |
119 | }; | |
120 | ||
121 | class WXDLLEXPORT wxGridWindow : public wxPanel | |
122 | { | |
123 | public: | |
124 | wxGridWindow() | |
125 | { | |
126 | m_owner = (wxGrid *)NULL; | |
127 | m_rowLabelWin = (wxGridRowLabelWindow *)NULL; | |
128 | m_colLabelWin = (wxGridColLabelWindow *)NULL; | |
129 | } | |
130 | ||
131 | wxGridWindow( wxGrid *parent, | |
132 | wxGridRowLabelWindow *rowLblWin, | |
133 | wxGridColLabelWindow *colLblWin, | |
134 | wxWindowID id, const wxPoint &pos, const wxSize &size ); | |
135 | ~wxGridWindow(); | |
136 | ||
137 | void ScrollWindow( int dx, int dy, const wxRect *rect ); | |
138 | ||
139 | private: | |
140 | wxGrid *m_owner; | |
141 | wxGridRowLabelWindow *m_rowLabelWin; | |
142 | wxGridColLabelWindow *m_colLabelWin; | |
143 | ||
144 | void OnPaint( wxPaintEvent &event ); | |
145 | void OnMouseEvent( wxMouseEvent& event ); | |
146 | void OnKeyDown( wxKeyEvent& ); | |
147 | ||
148 | DECLARE_DYNAMIC_CLASS(wxGridWindow) | |
149 | DECLARE_EVENT_TABLE() | |
150 | }; | |
151 | ||
152 | // the internal data representation used by wxGridCellAttrProvider | |
153 | // | |
154 | // TODO make it more efficient | |
155 | class WXDLLEXPORT wxGridCellAttrProviderData | |
156 | { | |
157 | public: | |
158 | void SetAttr(const wxGridCellAttr *attr, int row, int col); | |
159 | wxGridCellAttr *GetAttr(int row, int col) const; | |
160 | ||
161 | private: | |
162 | // searches for the attr for given cell, returns wxNOT_FOUND if not found | |
163 | int FindIndex(int row, int col) const; | |
164 | ||
165 | wxGridCellWithAttrArray m_attrs; | |
166 | }; | |
167 | ||
168 | // ---------------------------------------------------------------------------- | |
169 | // conditional compilation | |
170 | // ---------------------------------------------------------------------------- | |
171 | ||
9496deb5 MB |
172 | #ifndef WXGRID_DRAW_LINES |
173 | #define WXGRID_DRAW_LINES 1 | |
796df70a SN |
174 | #endif |
175 | ||
f85afd4e MB |
176 | ////////////////////////////////////////////////////////////////////// |
177 | ||
178 | wxGridCellCoords wxGridNoCellCoords( -1, -1 ); | |
179 | wxRect wxGridNoCellRect( -1, -1, -1, -1 ); | |
180 | ||
f0102d2a VZ |
181 | // scroll line size |
182 | // TODO: fixed so far - make configurable later (and also different for x/y) | |
183 | static const size_t GRID_SCROLL_LINE = 10; | |
f85afd4e | 184 | |
b99be8fb VZ |
185 | // ---------------------------------------------------------------------------- |
186 | // wxGridCellAttrProviderData | |
187 | // ---------------------------------------------------------------------------- | |
188 | ||
189 | void wxGridCellAttrProviderData::SetAttr(const wxGridCellAttr *attr, | |
190 | int row, int col) | |
191 | { | |
192 | int n = FindIndex(row, col); | |
193 | if ( n == wxNOT_FOUND ) | |
194 | { | |
195 | // add the attribute | |
196 | m_attrs.Add(new wxGridCellWithAttr(row, col, attr)); | |
197 | } | |
198 | else | |
199 | { | |
200 | if ( attr ) | |
201 | { | |
202 | // change the attribute | |
203 | m_attrs[(size_t)n].attr = *attr; | |
204 | } | |
205 | else | |
206 | { | |
207 | // remove this attribute | |
208 | m_attrs.RemoveAt((size_t)n); | |
209 | } | |
210 | } | |
211 | ||
212 | delete attr; | |
213 | } | |
214 | ||
215 | wxGridCellAttr *wxGridCellAttrProviderData::GetAttr(int row, int col) const | |
216 | { | |
217 | wxGridCellAttr *attr = (wxGridCellAttr *)NULL; | |
218 | ||
219 | int n = FindIndex(row, col); | |
220 | if ( n != wxNOT_FOUND ) | |
221 | { | |
222 | attr = new wxGridCellAttr(m_attrs[(size_t)n].attr); | |
223 | } | |
224 | ||
225 | return attr; | |
226 | } | |
227 | ||
228 | int wxGridCellAttrProviderData::FindIndex(int row, int col) const | |
229 | { | |
230 | size_t count = m_attrs.GetCount(); | |
231 | for ( size_t n = 0; n < count; n++ ) | |
232 | { | |
233 | const wxGridCellCoords& coords = m_attrs[n].coords; | |
234 | if ( (coords.GetRow() == row) && (coords.GetCol() == col) ) | |
235 | { | |
236 | return n; | |
237 | } | |
238 | } | |
239 | ||
240 | return wxNOT_FOUND; | |
241 | } | |
242 | ||
243 | // ---------------------------------------------------------------------------- | |
244 | // wxGridCellAttrProvider | |
245 | // ---------------------------------------------------------------------------- | |
246 | ||
247 | wxGridCellAttrProvider::wxGridCellAttrProvider() | |
248 | { | |
249 | m_data = (wxGridCellAttrProviderData *)NULL; | |
250 | } | |
251 | ||
252 | wxGridCellAttrProvider::~wxGridCellAttrProvider() | |
253 | { | |
254 | delete m_data; | |
255 | } | |
256 | ||
257 | void wxGridCellAttrProvider::InitData() | |
258 | { | |
259 | m_data = new wxGridCellAttrProviderData; | |
260 | } | |
261 | ||
262 | wxGridCellAttr *wxGridCellAttrProvider::GetAttr(int row, int col) const | |
263 | { | |
264 | return m_data ? m_data->GetAttr(row, col) : (wxGridCellAttr *)NULL; | |
265 | } | |
266 | ||
267 | void wxGridCellAttrProvider::SetAttr(const wxGridCellAttr *attr, | |
268 | int row, int col) | |
269 | { | |
270 | if ( !m_data ) | |
271 | InitData(); | |
272 | ||
273 | m_data->SetAttr(attr, row, col); | |
274 | } | |
275 | ||
f85afd4e MB |
276 | ////////////////////////////////////////////////////////////////////// |
277 | // | |
278 | // Abstract base class for grid data (the model) | |
279 | // | |
280 | IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase, wxObject ) | |
281 | ||
282 | ||
283 | wxGridTableBase::wxGridTableBase() | |
f85afd4e MB |
284 | { |
285 | m_view = (wxGrid *) NULL; | |
b99be8fb | 286 | m_attrProvider = (wxGridCellAttrProvider *) NULL; |
f85afd4e MB |
287 | } |
288 | ||
289 | wxGridTableBase::~wxGridTableBase() | |
290 | { | |
b99be8fb VZ |
291 | delete m_attrProvider; |
292 | } | |
293 | ||
294 | void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider *attrProvider) | |
295 | { | |
296 | delete m_attrProvider; | |
297 | m_attrProvider = attrProvider; | |
f85afd4e MB |
298 | } |
299 | ||
b99be8fb VZ |
300 | wxGridCellAttr *wxGridTableBase::GetAttr(int row, int col) |
301 | { | |
302 | if ( m_attrProvider ) | |
303 | return m_attrProvider->GetAttr(row, col); | |
304 | else | |
305 | return (wxGridCellAttr *)NULL; | |
306 | } | |
307 | ||
308 | void wxGridTableBase::SetAttr(const wxGridCellAttr *attr, int row, int col ) | |
309 | { | |
310 | if ( m_attrProvider ) | |
311 | { | |
312 | m_attrProvider->SetAttr(attr, row, col); | |
313 | } | |
314 | else | |
315 | { | |
316 | // as we take ownership of the pointer and don't store it, we must | |
317 | // free it now | |
318 | delete attr; | |
319 | } | |
320 | } | |
321 | ||
f85afd4e MB |
322 | bool wxGridTableBase::InsertRows( size_t pos, size_t numRows ) |
323 | { | |
bd3c6758 MB |
324 | wxFAIL_MSG( wxT("Called grid table class function InsertRows\n" |
325 | "but your derived table class does not override this function") ); | |
8f177c8e | 326 | |
f85afd4e MB |
327 | return FALSE; |
328 | } | |
329 | ||
330 | bool wxGridTableBase::AppendRows( size_t numRows ) | |
331 | { | |
bd3c6758 MB |
332 | wxFAIL_MSG( wxT("Called grid table class function AppendRows\n" |
333 | "but your derived table class does not override this function")); | |
8f177c8e | 334 | |
f85afd4e MB |
335 | return FALSE; |
336 | } | |
337 | ||
338 | bool wxGridTableBase::DeleteRows( size_t pos, size_t numRows ) | |
339 | { | |
bd3c6758 MB |
340 | wxFAIL_MSG( wxT("Called grid table class function DeleteRows\n" |
341 | "but your derived table class does not override this function")); | |
8f177c8e | 342 | |
f85afd4e MB |
343 | return FALSE; |
344 | } | |
345 | ||
346 | bool wxGridTableBase::InsertCols( size_t pos, size_t numCols ) | |
347 | { | |
bd3c6758 MB |
348 | wxFAIL_MSG( wxT("Called grid table class function InsertCols\n" |
349 | "but your derived table class does not override this function")); | |
8f177c8e | 350 | |
f85afd4e MB |
351 | return FALSE; |
352 | } | |
353 | ||
354 | bool wxGridTableBase::AppendCols( size_t numCols ) | |
355 | { | |
bd3c6758 MB |
356 | wxFAIL_MSG(wxT("Called grid table class function AppendCols\n" |
357 | "but your derived table class does not override this function")); | |
8f177c8e | 358 | |
f85afd4e MB |
359 | return FALSE; |
360 | } | |
361 | ||
362 | bool wxGridTableBase::DeleteCols( size_t pos, size_t numCols ) | |
363 | { | |
bd3c6758 MB |
364 | wxFAIL_MSG( wxT("Called grid table class function DeleteCols\n" |
365 | "but your derived table class does not override this function")); | |
8f177c8e | 366 | |
f85afd4e MB |
367 | return FALSE; |
368 | } | |
369 | ||
370 | ||
371 | wxString wxGridTableBase::GetRowLabelValue( int row ) | |
372 | { | |
373 | wxString s; | |
374 | s << row; | |
375 | return s; | |
376 | } | |
377 | ||
378 | wxString wxGridTableBase::GetColLabelValue( int col ) | |
379 | { | |
380 | // default col labels are: | |
381 | // cols 0 to 25 : A-Z | |
382 | // cols 26 to 675 : AA-ZZ | |
383 | // etc. | |
384 | ||
385 | wxString s; | |
386 | unsigned int i, n; | |
387 | for ( n = 1; ; n++ ) | |
388 | { | |
f0102d2a | 389 | s += (_T('A') + (wxChar)( col%26 )); |
f85afd4e MB |
390 | col = col/26 - 1; |
391 | if ( col < 0 ) break; | |
392 | } | |
393 | ||
394 | // reverse the string... | |
395 | wxString s2; | |
396 | for ( i = 0; i < n; i++ ) | |
397 | { | |
398 | s2 += s[n-i-1]; | |
399 | } | |
400 | ||
401 | return s2; | |
402 | } | |
403 | ||
404 | ||
405 | ||
406 | ////////////////////////////////////////////////////////////////////// | |
407 | // | |
408 | // Message class for the grid table to send requests and notifications | |
409 | // to the grid view | |
410 | // | |
411 | ||
412 | wxGridTableMessage::wxGridTableMessage() | |
413 | { | |
414 | m_table = (wxGridTableBase *) NULL; | |
415 | m_id = -1; | |
416 | m_comInt1 = -1; | |
417 | m_comInt2 = -1; | |
418 | } | |
419 | ||
420 | wxGridTableMessage::wxGridTableMessage( wxGridTableBase *table, int id, | |
421 | int commandInt1, int commandInt2 ) | |
422 | { | |
423 | m_table = table; | |
424 | m_id = id; | |
425 | m_comInt1 = commandInt1; | |
426 | m_comInt2 = commandInt2; | |
427 | } | |
428 | ||
429 | ||
430 | ||
431 | ////////////////////////////////////////////////////////////////////// | |
432 | // | |
433 | // A basic grid table for string data. An object of this class will | |
434 | // created by wxGrid if you don't specify an alternative table class. | |
435 | // | |
436 | ||
223d09f6 | 437 | WX_DEFINE_OBJARRAY(wxGridStringArray) |
f85afd4e MB |
438 | |
439 | IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable, wxGridTableBase ) | |
440 | ||
441 | wxGridStringTable::wxGridStringTable() | |
442 | : wxGridTableBase() | |
443 | { | |
444 | } | |
445 | ||
446 | wxGridStringTable::wxGridStringTable( int numRows, int numCols ) | |
447 | : wxGridTableBase() | |
448 | { | |
449 | int row, col; | |
8f177c8e | 450 | |
f85afd4e MB |
451 | m_data.Alloc( numRows ); |
452 | ||
453 | wxArrayString sa; | |
454 | sa.Alloc( numCols ); | |
455 | for ( col = 0; col < numCols; col++ ) | |
456 | { | |
457 | sa.Add( wxEmptyString ); | |
458 | } | |
8f177c8e | 459 | |
f85afd4e MB |
460 | for ( row = 0; row < numRows; row++ ) |
461 | { | |
462 | m_data.Add( sa ); | |
463 | } | |
464 | } | |
465 | ||
466 | wxGridStringTable::~wxGridStringTable() | |
467 | { | |
468 | } | |
469 | ||
470 | long wxGridStringTable::GetNumberRows() | |
471 | { | |
472 | return m_data.GetCount(); | |
473 | } | |
474 | ||
475 | long wxGridStringTable::GetNumberCols() | |
476 | { | |
477 | if ( m_data.GetCount() > 0 ) | |
478 | return m_data[0].GetCount(); | |
479 | else | |
480 | return 0; | |
481 | } | |
482 | ||
483 | wxString wxGridStringTable::GetValue( int row, int col ) | |
484 | { | |
485 | // TODO: bounds checking | |
486 | // | |
487 | return m_data[row][col]; | |
488 | } | |
489 | ||
490 | void wxGridStringTable::SetValue( int row, int col, const wxString& s ) | |
491 | { | |
492 | // TODO: bounds checking | |
493 | // | |
494 | m_data[row][col] = s; | |
495 | } | |
496 | ||
497 | bool wxGridStringTable::IsEmptyCell( int row, int col ) | |
498 | { | |
499 | // TODO: bounds checking | |
500 | // | |
501 | return (m_data[row][col] == wxEmptyString); | |
502 | } | |
503 | ||
504 | ||
505 | void wxGridStringTable::Clear() | |
506 | { | |
507 | int row, col; | |
508 | int numRows, numCols; | |
8f177c8e | 509 | |
f85afd4e MB |
510 | numRows = m_data.GetCount(); |
511 | if ( numRows > 0 ) | |
512 | { | |
513 | numCols = m_data[0].GetCount(); | |
514 | ||
515 | for ( row = 0; row < numRows; row++ ) | |
516 | { | |
517 | for ( col = 0; col < numCols; col++ ) | |
518 | { | |
519 | m_data[row][col] = wxEmptyString; | |
520 | } | |
521 | } | |
522 | } | |
523 | } | |
524 | ||
525 | ||
526 | bool wxGridStringTable::InsertRows( size_t pos, size_t numRows ) | |
527 | { | |
528 | size_t row, col; | |
529 | ||
530 | size_t curNumRows = m_data.GetCount(); | |
531 | size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() : 0 ); | |
8f177c8e | 532 | |
f85afd4e MB |
533 | if ( pos >= curNumRows ) |
534 | { | |
535 | return AppendRows( numRows ); | |
536 | } | |
8f177c8e | 537 | |
f85afd4e MB |
538 | wxArrayString sa; |
539 | sa.Alloc( curNumCols ); | |
540 | for ( col = 0; col < curNumCols; col++ ) | |
541 | { | |
542 | sa.Add( wxEmptyString ); | |
543 | } | |
544 | ||
545 | for ( row = pos; row < pos + numRows; row++ ) | |
546 | { | |
547 | m_data.Insert( sa, row ); | |
548 | } | |
549 | ||
550 | if ( GetView() ) | |
551 | { | |
552 | wxGridTableMessage msg( this, | |
553 | wxGRIDTABLE_NOTIFY_ROWS_INSERTED, | |
554 | pos, | |
555 | numRows ); | |
8f177c8e | 556 | |
f85afd4e MB |
557 | GetView()->ProcessTableMessage( msg ); |
558 | } | |
559 | ||
560 | return TRUE; | |
561 | } | |
562 | ||
563 | bool wxGridStringTable::AppendRows( size_t numRows ) | |
564 | { | |
565 | size_t row, col; | |
566 | ||
567 | size_t curNumRows = m_data.GetCount(); | |
568 | size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() : 0 ); | |
8f177c8e | 569 | |
f85afd4e MB |
570 | wxArrayString sa; |
571 | if ( curNumCols > 0 ) | |
572 | { | |
573 | sa.Alloc( curNumCols ); | |
574 | for ( col = 0; col < curNumCols; col++ ) | |
575 | { | |
576 | sa.Add( wxEmptyString ); | |
577 | } | |
578 | } | |
8f177c8e | 579 | |
f85afd4e MB |
580 | for ( row = 0; row < numRows; row++ ) |
581 | { | |
582 | m_data.Add( sa ); | |
583 | } | |
584 | ||
585 | if ( GetView() ) | |
586 | { | |
587 | wxGridTableMessage msg( this, | |
588 | wxGRIDTABLE_NOTIFY_ROWS_APPENDED, | |
589 | numRows ); | |
8f177c8e | 590 | |
f85afd4e MB |
591 | GetView()->ProcessTableMessage( msg ); |
592 | } | |
593 | ||
8f177c8e | 594 | return TRUE; |
f85afd4e MB |
595 | } |
596 | ||
597 | bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows ) | |
598 | { | |
599 | size_t n; | |
600 | ||
601 | size_t curNumRows = m_data.GetCount(); | |
8f177c8e | 602 | |
f85afd4e MB |
603 | if ( pos >= curNumRows ) |
604 | { | |
bd3c6758 MB |
605 | wxString errmsg; |
606 | errmsg.Printf("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\n" | |
607 | "Pos value is invalid for present table with %d rows", | |
608 | pos, numRows, curNumRows ); | |
609 | wxFAIL_MSG( wxT(errmsg) ); | |
f85afd4e MB |
610 | return FALSE; |
611 | } | |
612 | ||
613 | if ( numRows > curNumRows - pos ) | |
614 | { | |
615 | numRows = curNumRows - pos; | |
616 | } | |
8f177c8e | 617 | |
f85afd4e MB |
618 | if ( numRows >= curNumRows ) |
619 | { | |
620 | m_data.Empty(); // don't release memory just yet | |
621 | } | |
622 | else | |
623 | { | |
624 | for ( n = 0; n < numRows; n++ ) | |
625 | { | |
626 | m_data.Remove( pos ); | |
627 | } | |
628 | } | |
629 | ||
630 | if ( GetView() ) | |
631 | { | |
632 | wxGridTableMessage msg( this, | |
633 | wxGRIDTABLE_NOTIFY_ROWS_DELETED, | |
634 | pos, | |
635 | numRows ); | |
8f177c8e | 636 | |
f85afd4e MB |
637 | GetView()->ProcessTableMessage( msg ); |
638 | } | |
639 | ||
8f177c8e | 640 | return TRUE; |
f85afd4e MB |
641 | } |
642 | ||
643 | bool wxGridStringTable::InsertCols( size_t pos, size_t numCols ) | |
644 | { | |
645 | size_t row, col; | |
646 | ||
647 | size_t curNumRows = m_data.GetCount(); | |
648 | size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() : 0 ); | |
8f177c8e | 649 | |
f85afd4e MB |
650 | if ( pos >= curNumCols ) |
651 | { | |
652 | return AppendCols( numCols ); | |
653 | } | |
654 | ||
655 | for ( row = 0; row < curNumRows; row++ ) | |
656 | { | |
657 | for ( col = pos; col < pos + numCols; col++ ) | |
658 | { | |
659 | m_data[row].Insert( wxEmptyString, col ); | |
660 | } | |
661 | } | |
662 | ||
663 | if ( GetView() ) | |
664 | { | |
665 | wxGridTableMessage msg( this, | |
666 | wxGRIDTABLE_NOTIFY_COLS_INSERTED, | |
667 | pos, | |
668 | numCols ); | |
8f177c8e | 669 | |
f85afd4e MB |
670 | GetView()->ProcessTableMessage( msg ); |
671 | } | |
672 | ||
673 | return TRUE; | |
674 | } | |
675 | ||
676 | bool wxGridStringTable::AppendCols( size_t numCols ) | |
677 | { | |
678 | size_t row, n; | |
679 | ||
680 | size_t curNumRows = m_data.GetCount(); | |
681 | if ( !curNumRows ) | |
682 | { | |
683 | // TODO: something better than this ? | |
684 | // | |
bd3c6758 MB |
685 | wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\n" |
686 | "Call AppendRows() first") ); | |
f85afd4e MB |
687 | return FALSE; |
688 | } | |
8f177c8e | 689 | |
f85afd4e MB |
690 | for ( row = 0; row < curNumRows; row++ ) |
691 | { | |
692 | for ( n = 0; n < numCols; n++ ) | |
693 | { | |
694 | m_data[row].Add( wxEmptyString ); | |
695 | } | |
696 | } | |
697 | ||
698 | if ( GetView() ) | |
699 | { | |
700 | wxGridTableMessage msg( this, | |
701 | wxGRIDTABLE_NOTIFY_COLS_APPENDED, | |
702 | numCols ); | |
8f177c8e | 703 | |
f85afd4e MB |
704 | GetView()->ProcessTableMessage( msg ); |
705 | } | |
706 | ||
707 | return TRUE; | |
708 | } | |
709 | ||
710 | bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols ) | |
711 | { | |
712 | size_t row, n; | |
713 | ||
714 | size_t curNumRows = m_data.GetCount(); | |
715 | size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() : 0 ); | |
8f177c8e | 716 | |
f85afd4e MB |
717 | if ( pos >= curNumCols ) |
718 | { | |
bd3c6758 MB |
719 | wxString errmsg; |
720 | errmsg.Printf( "Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\n" | |
721 | "Pos value is invalid for present table with %d cols", | |
722 | pos, numCols, curNumCols ); | |
723 | wxFAIL_MSG( wxT( errmsg ) ); | |
8f177c8e | 724 | return FALSE; |
f85afd4e MB |
725 | } |
726 | ||
727 | if ( numCols > curNumCols - pos ) | |
728 | { | |
8f177c8e | 729 | numCols = curNumCols - pos; |
f85afd4e MB |
730 | } |
731 | ||
732 | for ( row = 0; row < curNumRows; row++ ) | |
733 | { | |
734 | if ( numCols >= curNumCols ) | |
735 | { | |
736 | m_data[row].Clear(); | |
737 | } | |
738 | else | |
739 | { | |
740 | for ( n = 0; n < numCols; n++ ) | |
741 | { | |
742 | m_data[row].Remove( pos ); | |
743 | } | |
744 | } | |
745 | } | |
746 | ||
747 | if ( GetView() ) | |
748 | { | |
749 | wxGridTableMessage msg( this, | |
750 | wxGRIDTABLE_NOTIFY_COLS_DELETED, | |
751 | pos, | |
752 | numCols ); | |
8f177c8e | 753 | |
f85afd4e MB |
754 | GetView()->ProcessTableMessage( msg ); |
755 | } | |
756 | ||
8f177c8e | 757 | return TRUE; |
f85afd4e MB |
758 | } |
759 | ||
760 | wxString wxGridStringTable::GetRowLabelValue( int row ) | |
761 | { | |
762 | if ( row > (int)(m_rowLabels.GetCount()) - 1 ) | |
763 | { | |
764 | // using default label | |
765 | // | |
766 | return wxGridTableBase::GetRowLabelValue( row ); | |
767 | } | |
768 | else | |
769 | { | |
770 | return m_rowLabels[ row ]; | |
771 | } | |
772 | } | |
773 | ||
774 | wxString wxGridStringTable::GetColLabelValue( int col ) | |
775 | { | |
776 | if ( col > (int)(m_colLabels.GetCount()) - 1 ) | |
777 | { | |
778 | // using default label | |
779 | // | |
780 | return wxGridTableBase::GetColLabelValue( col ); | |
781 | } | |
782 | else | |
783 | { | |
784 | return m_colLabels[ col ]; | |
785 | } | |
786 | } | |
787 | ||
788 | void wxGridStringTable::SetRowLabelValue( int row, const wxString& value ) | |
789 | { | |
790 | if ( row > (int)(m_rowLabels.GetCount()) - 1 ) | |
791 | { | |
792 | int n = m_rowLabels.GetCount(); | |
793 | int i; | |
794 | for ( i = n; i <= row; i++ ) | |
795 | { | |
796 | m_rowLabels.Add( wxGridTableBase::GetRowLabelValue(i) ); | |
797 | } | |
798 | } | |
799 | ||
800 | m_rowLabels[row] = value; | |
801 | } | |
802 | ||
803 | void wxGridStringTable::SetColLabelValue( int col, const wxString& value ) | |
804 | { | |
805 | if ( col > (int)(m_colLabels.GetCount()) - 1 ) | |
806 | { | |
807 | int n = m_colLabels.GetCount(); | |
808 | int i; | |
809 | for ( i = n; i <= col; i++ ) | |
810 | { | |
811 | m_colLabels.Add( wxGridTableBase::GetColLabelValue(i) ); | |
812 | } | |
813 | } | |
814 | ||
815 | m_colLabels[col] = value; | |
816 | } | |
817 | ||
818 | ||
819 | ||
820 | ||
821 | ////////////////////////////////////////////////////////////////////// | |
822 | ||
823 | IMPLEMENT_DYNAMIC_CLASS( wxGridTextCtrl, wxTextCtrl ) | |
8f177c8e | 824 | |
f85afd4e MB |
825 | BEGIN_EVENT_TABLE( wxGridTextCtrl, wxTextCtrl ) |
826 | EVT_KEY_DOWN( wxGridTextCtrl::OnKeyDown ) | |
827 | END_EVENT_TABLE() | |
828 | ||
829 | ||
830 | wxGridTextCtrl::wxGridTextCtrl( wxWindow *par, | |
2d66e025 | 831 | wxGrid *grid, |
f85afd4e MB |
832 | bool isCellControl, |
833 | wxWindowID id, | |
834 | const wxString& value, | |
835 | const wxPoint& pos, | |
836 | const wxSize& size, | |
837 | long style ) | |
838 | : wxTextCtrl( par, id, value, pos, size, style ) | |
839 | { | |
2d66e025 | 840 | m_grid = grid; |
f85afd4e MB |
841 | m_isCellControl = isCellControl; |
842 | } | |
843 | ||
844 | ||
2d66e025 | 845 | void wxGridTextCtrl::OnKeyDown( wxKeyEvent& event ) |
f85afd4e | 846 | { |
2d66e025 | 847 | switch ( event.KeyCode() ) |
f85afd4e MB |
848 | { |
849 | case WXK_ESCAPE: | |
2d66e025 | 850 | m_grid->SetEditControlValue( startValue ); |
f85afd4e MB |
851 | SetInsertionPointEnd(); |
852 | break; | |
853 | ||
854 | case WXK_UP: | |
855 | case WXK_DOWN: | |
856 | case WXK_LEFT: | |
857 | case WXK_RIGHT: | |
edc2c290 MB |
858 | case WXK_PRIOR: |
859 | case WXK_NEXT: | |
f603012f | 860 | case WXK_SPACE: |
f85afd4e MB |
861 | if ( m_isCellControl ) |
862 | { | |
863 | // send the event to the parent grid, skipping the | |
864 | // event if nothing happens | |
865 | // | |
2d66e025 | 866 | event.Skip( m_grid->ProcessEvent( event ) ); |
f85afd4e MB |
867 | } |
868 | else | |
869 | { | |
870 | // default text control response within the top edit | |
871 | // control | |
872 | // | |
2d66e025 | 873 | event.Skip(); |
f85afd4e MB |
874 | } |
875 | break; | |
876 | ||
58dd5b3b MB |
877 | case WXK_RETURN: |
878 | if ( m_isCellControl ) | |
879 | { | |
880 | if ( !m_grid->ProcessEvent( event ) ) | |
881 | { | |
8a9a9d58 | 882 | #if defined(__WXMOTIF__) || defined(__WXGTK__) |
58dd5b3b MB |
883 | // wxMotif needs a little extra help... |
884 | // | |
885 | int pos = GetInsertionPoint(); | |
886 | wxString s( GetValue() ); | |
887 | s = s.Left(pos) + "\n" + s.Mid(pos); | |
888 | SetValue(s); | |
889 | SetInsertionPoint( pos ); | |
890 | #else | |
891 | // the other ports can handle a Return key press | |
892 | // | |
893 | event.Skip(); | |
f0102d2a | 894 | #endif |
58dd5b3b MB |
895 | } |
896 | } | |
897 | break; | |
898 | ||
f85afd4e MB |
899 | case WXK_HOME: |
900 | case WXK_END: | |
901 | if ( m_isCellControl ) | |
902 | { | |
903 | // send the event to the parent grid, skipping the | |
904 | // event if nothing happens | |
905 | // | |
2d66e025 | 906 | event.Skip( m_grid->ProcessEvent( event ) ); |
f85afd4e MB |
907 | } |
908 | else | |
909 | { | |
910 | // default text control response within the top edit | |
911 | // control | |
912 | // | |
2d66e025 | 913 | event.Skip(); |
f85afd4e MB |
914 | } |
915 | break; | |
8f177c8e | 916 | |
f85afd4e | 917 | default: |
2d66e025 | 918 | event.Skip(); |
f85afd4e MB |
919 | } |
920 | } | |
921 | ||
922 | void wxGridTextCtrl::SetStartValue( const wxString& s ) | |
923 | { | |
924 | startValue = s; | |
f0102d2a | 925 | wxTextCtrl::SetValue(s); |
f85afd4e MB |
926 | } |
927 | ||
928 | ||
2d66e025 MB |
929 | |
930 | ////////////////////////////////////////////////////////////////////// | |
931 | ||
932 | IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow, wxWindow ) | |
933 | ||
934 | BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxWindow ) | |
935 | EVT_PAINT( wxGridRowLabelWindow::OnPaint ) | |
936 | EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent ) | |
937 | EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown ) | |
938 | END_EVENT_TABLE() | |
939 | ||
60ff3b99 VZ |
940 | wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid *parent, |
941 | wxWindowID id, | |
2d66e025 MB |
942 | const wxPoint &pos, const wxSize &size ) |
943 | : wxWindow( parent, id, pos, size ) | |
944 | { | |
945 | m_owner = parent; | |
946 | } | |
947 | ||
948 | void wxGridRowLabelWindow::OnPaint( wxPaintEvent &event ) | |
949 | { | |
950 | wxPaintDC dc(this); | |
951 | ||
952 | // NO - don't do this because it will set both the x and y origin | |
953 | // coords to match the parent scrolled window and we just want to | |
954 | // set the y coord - MB | |
955 | // | |
956 | // m_owner->PrepareDC( dc ); | |
60ff3b99 | 957 | |
790ad94f | 958 | int x, y; |
2d66e025 MB |
959 | m_owner->CalcUnscrolledPosition( 0, 0, &x, &y ); |
960 | dc.SetDeviceOrigin( 0, -y ); | |
60ff3b99 | 961 | |
2d66e025 MB |
962 | m_owner->CalcRowLabelsExposed( GetUpdateRegion() ); |
963 | m_owner->DrawRowLabels( dc ); | |
964 | } | |
965 | ||
966 | ||
967 | void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent& event ) | |
968 | { | |
969 | m_owner->ProcessRowLabelMouseEvent( event ); | |
970 | } | |
971 | ||
972 | ||
973 | // This seems to be required for wxMotif otherwise the mouse | |
974 | // cursor must be in the cell edit control to get key events | |
975 | // | |
976 | void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent& event ) | |
977 | { | |
978 | if ( !m_owner->ProcessEvent( event ) ) event.Skip(); | |
979 | } | |
980 | ||
981 | ||
982 | ||
983 | ////////////////////////////////////////////////////////////////////// | |
984 | ||
985 | IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow, wxWindow ) | |
986 | ||
987 | BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxWindow ) | |
988 | EVT_PAINT( wxGridColLabelWindow::OnPaint ) | |
989 | EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent ) | |
990 | EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown ) | |
991 | END_EVENT_TABLE() | |
992 | ||
60ff3b99 VZ |
993 | wxGridColLabelWindow::wxGridColLabelWindow( wxGrid *parent, |
994 | wxWindowID id, | |
2d66e025 MB |
995 | const wxPoint &pos, const wxSize &size ) |
996 | : wxWindow( parent, id, pos, size ) | |
997 | { | |
998 | m_owner = parent; | |
999 | } | |
1000 | ||
1001 | void wxGridColLabelWindow::OnPaint( wxPaintEvent &event ) | |
1002 | { | |
1003 | wxPaintDC dc(this); | |
1004 | ||
1005 | // NO - don't do this because it will set both the x and y origin | |
1006 | // coords to match the parent scrolled window and we just want to | |
1007 | // set the x coord - MB | |
1008 | // | |
1009 | // m_owner->PrepareDC( dc ); | |
60ff3b99 | 1010 | |
790ad94f | 1011 | int x, y; |
2d66e025 MB |
1012 | m_owner->CalcUnscrolledPosition( 0, 0, &x, &y ); |
1013 | dc.SetDeviceOrigin( -x, 0 ); | |
1014 | ||
60ff3b99 VZ |
1015 | m_owner->CalcColLabelsExposed( GetUpdateRegion() ); |
1016 | m_owner->DrawColLabels( dc ); | |
2d66e025 MB |
1017 | } |
1018 | ||
1019 | ||
1020 | void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent& event ) | |
1021 | { | |
1022 | m_owner->ProcessColLabelMouseEvent( event ); | |
1023 | } | |
1024 | ||
1025 | ||
1026 | // This seems to be required for wxMotif otherwise the mouse | |
1027 | // cursor must be in the cell edit control to get key events | |
1028 | // | |
1029 | void wxGridColLabelWindow::OnKeyDown( wxKeyEvent& event ) | |
1030 | { | |
1031 | if ( !m_owner->ProcessEvent( event ) ) event.Skip(); | |
1032 | } | |
1033 | ||
1034 | ||
1035 | ||
1036 | ////////////////////////////////////////////////////////////////////// | |
1037 | ||
1038 | IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow, wxWindow ) | |
1039 | ||
1040 | BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxWindow ) | |
1041 | EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent ) | |
d2fdd8d2 | 1042 | EVT_PAINT( wxGridCornerLabelWindow::OnPaint) |
2d66e025 MB |
1043 | EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown ) |
1044 | END_EVENT_TABLE() | |
1045 | ||
60ff3b99 VZ |
1046 | wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent, |
1047 | wxWindowID id, | |
2d66e025 | 1048 | const wxPoint &pos, const wxSize &size ) |
d2fdd8d2 | 1049 | : wxWindow( parent, id, pos, size ) |
2d66e025 MB |
1050 | { |
1051 | m_owner = parent; | |
1052 | } | |
1053 | ||
d2fdd8d2 RR |
1054 | void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) ) |
1055 | { | |
1056 | wxPaintDC dc(this); | |
b99be8fb | 1057 | |
d2fdd8d2 RR |
1058 | int client_height = 0; |
1059 | int client_width = 0; | |
1060 | GetClientSize( &client_width, &client_height ); | |
b99be8fb | 1061 | |
d2fdd8d2 RR |
1062 | dc.SetPen( *wxBLACK_PEN ); |
1063 | dc.DrawLine( client_width-1, client_height-1, client_width-1, 0 ); | |
1064 | dc.DrawLine( client_width-1, client_height-1, 0, client_height-1 ); | |
b99be8fb | 1065 | |
d2fdd8d2 RR |
1066 | dc.SetPen( *wxWHITE_PEN ); |
1067 | dc.DrawLine( 0, 0, client_width, 0 ); | |
1068 | dc.DrawLine( 0, 0, 0, client_height ); | |
1069 | } | |
1070 | ||
2d66e025 MB |
1071 | |
1072 | void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent& event ) | |
1073 | { | |
1074 | m_owner->ProcessCornerLabelMouseEvent( event ); | |
1075 | } | |
1076 | ||
1077 | ||
1078 | // This seems to be required for wxMotif otherwise the mouse | |
1079 | // cursor must be in the cell edit control to get key events | |
1080 | // | |
1081 | void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent& event ) | |
1082 | { | |
1083 | if ( !m_owner->ProcessEvent( event ) ) event.Skip(); | |
1084 | } | |
1085 | ||
1086 | ||
1087 | ||
f85afd4e MB |
1088 | ////////////////////////////////////////////////////////////////////// |
1089 | ||
2d66e025 MB |
1090 | IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxPanel ) |
1091 | ||
1092 | BEGIN_EVENT_TABLE( wxGridWindow, wxPanel ) | |
1093 | EVT_PAINT( wxGridWindow::OnPaint ) | |
2d66e025 MB |
1094 | EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent ) |
1095 | EVT_KEY_DOWN( wxGridWindow::OnKeyDown ) | |
1096 | END_EVENT_TABLE() | |
1097 | ||
60ff3b99 VZ |
1098 | wxGridWindow::wxGridWindow( wxGrid *parent, |
1099 | wxGridRowLabelWindow *rowLblWin, | |
2d66e025 MB |
1100 | wxGridColLabelWindow *colLblWin, |
1101 | wxWindowID id, const wxPoint &pos, const wxSize &size ) | |
b0d6ff2f | 1102 | : wxPanel( parent, id, pos, size, 0, "grid window" ) |
2d66e025 MB |
1103 | { |
1104 | m_owner = parent; | |
1105 | m_rowLabelWin = rowLblWin; | |
1106 | m_colLabelWin = colLblWin; | |
60ff3b99 | 1107 | |
2d66e025 MB |
1108 | SetBackgroundColour( "WHITE" ); |
1109 | } | |
1110 | ||
1111 | ||
1112 | wxGridWindow::~wxGridWindow() | |
1113 | { | |
1114 | } | |
1115 | ||
1116 | ||
1117 | void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) | |
1118 | { | |
1119 | wxPaintDC dc( this ); | |
1120 | m_owner->PrepareDC( dc ); | |
796df70a SN |
1121 | wxRegion reg = GetUpdateRegion(); |
1122 | m_owner->CalcCellsExposed( reg ); | |
2d66e025 | 1123 | m_owner->DrawGridCellArea( dc ); |
9496deb5 | 1124 | #if WXGRID_DRAW_LINES |
796df70a SN |
1125 | m_owner->DrawAllGridLines( dc, reg ); |
1126 | #endif | |
2d66e025 MB |
1127 | } |
1128 | ||
1129 | ||
1130 | void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect ) | |
1131 | { | |
1132 | wxPanel::ScrollWindow( dx, dy, rect ); | |
1133 | m_rowLabelWin->ScrollWindow( 0, dy, rect ); | |
1134 | m_colLabelWin->ScrollWindow( dx, 0, rect ); | |
1135 | } | |
1136 | ||
1137 | ||
1138 | void wxGridWindow::OnMouseEvent( wxMouseEvent& event ) | |
1139 | { | |
1140 | m_owner->ProcessGridCellMouseEvent( event ); | |
1141 | } | |
1142 | ||
1143 | ||
1144 | // This seems to be required for wxMotif otherwise the mouse | |
1145 | // cursor must be in the cell edit control to get key events | |
1146 | // | |
1147 | void wxGridWindow::OnKeyDown( wxKeyEvent& event ) | |
1148 | { | |
1149 | if ( !m_owner->ProcessEvent( event ) ) event.Skip(); | |
1150 | } | |
f85afd4e | 1151 | |
8f177c8e | 1152 | |
2d66e025 MB |
1153 | |
1154 | ////////////////////////////////////////////////////////////////////// | |
1155 | ||
1156 | IMPLEMENT_DYNAMIC_CLASS( wxGrid, wxScrolledWindow ) | |
1157 | ||
1158 | BEGIN_EVENT_TABLE( wxGrid, wxScrolledWindow ) | |
f85afd4e MB |
1159 | EVT_PAINT( wxGrid::OnPaint ) |
1160 | EVT_SIZE( wxGrid::OnSize ) | |
f85afd4e | 1161 | EVT_KEY_DOWN( wxGrid::OnKeyDown ) |
f85afd4e | 1162 | END_EVENT_TABLE() |
8f177c8e | 1163 | |
2d66e025 MB |
1164 | wxGrid::wxGrid( wxWindow *parent, |
1165 | wxWindowID id, | |
1166 | const wxPoint& pos, | |
1167 | const wxSize& size, | |
1168 | long style, | |
1169 | const wxString& name ) | |
1170 | : wxScrolledWindow( parent, id, pos, size, style, name ) | |
1171 | { | |
1172 | Create(); | |
58dd5b3b MB |
1173 | } |
1174 | ||
1175 | ||
1176 | wxGrid::~wxGrid() | |
1177 | { | |
1178 | delete m_table; | |
1179 | } | |
1180 | ||
2d66e025 | 1181 | |
58dd5b3b MB |
1182 | // |
1183 | // ----- internal init and update functions | |
1184 | // | |
1185 | ||
1186 | void wxGrid::Create() | |
f0102d2a | 1187 | { |
4634a5d6 MB |
1188 | m_created = FALSE; // set to TRUE by CreateGrid |
1189 | m_displayed = FALSE; // set to TRUE by OnPaint | |
1190 | ||
1191 | m_table = (wxGridTableBase *) NULL; | |
1192 | m_cellEditCtrl = (wxWindow *) NULL; | |
1193 | ||
1194 | m_numRows = 0; | |
1195 | m_numCols = 0; | |
1196 | m_currentCellCoords = wxGridNoCellCoords; | |
b99be8fb | 1197 | |
18f9565d MB |
1198 | m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH; |
1199 | m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT; | |
2d66e025 | 1200 | |
7807d81c MB |
1201 | m_cornerLabelWin = new wxGridCornerLabelWindow( this, |
1202 | -1, | |
18f9565d MB |
1203 | wxDefaultPosition, |
1204 | wxDefaultSize ); | |
7807d81c | 1205 | |
60ff3b99 VZ |
1206 | m_rowLabelWin = new wxGridRowLabelWindow( this, |
1207 | -1, | |
18f9565d MB |
1208 | wxDefaultPosition, |
1209 | wxDefaultSize ); | |
2d66e025 MB |
1210 | |
1211 | m_colLabelWin = new wxGridColLabelWindow( this, | |
1212 | -1, | |
18f9565d MB |
1213 | wxDefaultPosition, |
1214 | wxDefaultSize ); | |
60ff3b99 | 1215 | |
60ff3b99 VZ |
1216 | m_gridWin = new wxGridWindow( this, |
1217 | m_rowLabelWin, | |
1218 | m_colLabelWin, | |
1219 | -1, | |
18f9565d | 1220 | wxDefaultPosition, |
2d66e025 MB |
1221 | wxDefaultSize ); |
1222 | ||
1223 | SetTargetWindow( m_gridWin ); | |
2d66e025 | 1224 | } |
f85afd4e | 1225 | |
2d66e025 MB |
1226 | |
1227 | bool wxGrid::CreateGrid( int numRows, int numCols ) | |
1228 | { | |
1229 | if ( m_created ) | |
1230 | { | |
bd3c6758 | 1231 | wxFAIL_MSG( wxT("wxGrid::CreateGrid called more than once") ); |
2d66e025 MB |
1232 | return FALSE; |
1233 | } | |
1234 | else | |
1235 | { | |
1236 | m_numRows = numRows; | |
1237 | m_numCols = numCols; | |
1238 | ||
1239 | m_table = new wxGridStringTable( m_numRows, m_numCols ); | |
1240 | m_table->SetView( this ); | |
1241 | Init(); | |
1242 | m_created = TRUE; | |
1243 | } | |
f85afd4e | 1244 | |
2d66e025 | 1245 | return m_created; |
f85afd4e MB |
1246 | } |
1247 | ||
2d66e025 | 1248 | |
f85afd4e MB |
1249 | void wxGrid::Init() |
1250 | { | |
1251 | int i; | |
1252 | ||
f85afd4e MB |
1253 | if ( m_numRows <= 0 ) |
1254 | m_numRows = WXGRID_DEFAULT_NUMBER_ROWS; | |
1255 | ||
1256 | if ( m_numCols <= 0 ) | |
1257 | m_numCols = WXGRID_DEFAULT_NUMBER_COLS; | |
1258 | ||
1259 | m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH; | |
1260 | m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT; | |
1261 | ||
60ff3b99 VZ |
1262 | if ( m_rowLabelWin ) |
1263 | { | |
1264 | m_labelBackgroundColour = m_rowLabelWin->GetBackgroundColour(); | |
1265 | } | |
1266 | else | |
1267 | { | |
1268 | m_labelBackgroundColour = wxColour( _T("WHITE") ); | |
1269 | } | |
1270 | ||
1271 | m_labelTextColour = wxColour( _T("BLACK") ); | |
f85afd4e MB |
1272 | |
1273 | // TODO: something better than this ? | |
1274 | // | |
1275 | m_labelFont = this->GetFont(); | |
1276 | m_labelFont.SetWeight( m_labelFont.GetWeight() + 2 ); | |
8f177c8e | 1277 | |
f85afd4e MB |
1278 | m_rowLabelHorizAlign = wxLEFT; |
1279 | m_rowLabelVertAlign = wxCENTRE; | |
1280 | ||
1281 | m_colLabelHorizAlign = wxCENTRE; | |
1282 | m_colLabelVertAlign = wxTOP; | |
1283 | ||
f85afd4e | 1284 | m_defaultColWidth = WXGRID_DEFAULT_COL_WIDTH; |
1f1ce288 MB |
1285 | m_defaultRowHeight = m_gridWin->GetCharHeight(); |
1286 | ||
d2fdd8d2 | 1287 | #if defined(__WXMOTIF__) || defined(__WXGTK__) // see also text ctrl sizing in ShowCellEditControl() |
1f1ce288 MB |
1288 | m_defaultRowHeight += 8; |
1289 | #else | |
1290 | m_defaultRowHeight += 4; | |
1291 | #endif | |
1292 | ||
f85afd4e MB |
1293 | m_rowHeights.Alloc( m_numRows ); |
1294 | m_rowBottoms.Alloc( m_numRows ); | |
2d66e025 | 1295 | int rowBottom = 0; |
f85afd4e MB |
1296 | for ( i = 0; i < m_numRows; i++ ) |
1297 | { | |
1298 | m_rowHeights.Add( m_defaultRowHeight ); | |
2d66e025 MB |
1299 | rowBottom += m_defaultRowHeight; |
1300 | m_rowBottoms.Add( rowBottom ); | |
f85afd4e | 1301 | } |
8f177c8e | 1302 | |
f85afd4e | 1303 | m_colWidths.Alloc( m_numCols ); |
2d66e025 MB |
1304 | m_colRights.Alloc( m_numCols ); |
1305 | int colRight = 0; | |
f85afd4e MB |
1306 | for ( i = 0; i < m_numCols; i++ ) |
1307 | { | |
1308 | m_colWidths.Add( m_defaultColWidth ); | |
2d66e025 MB |
1309 | colRight += m_defaultColWidth; |
1310 | m_colRights.Add( colRight ); | |
f85afd4e | 1311 | } |
8f177c8e | 1312 | |
b99be8fb | 1313 | // TODO: improve this by using wxSystemSettings? |
f85afd4e | 1314 | // |
b99be8fb VZ |
1315 | m_defaultCellFont = GetFont(); |
1316 | ||
1317 | m_defaultCellHAlign = wxLEFT; | |
1318 | m_defaultCellVAlign = wxTOP; | |
8f177c8e | 1319 | |
2d66e025 | 1320 | m_gridLineColour = wxColour( 128, 128, 255 ); |
f85afd4e | 1321 | m_gridLinesEnabled = TRUE; |
8f177c8e | 1322 | |
58dd5b3b | 1323 | m_cursorMode = WXGRID_CURSOR_SELECT_CELL; |
f85afd4e MB |
1324 | m_dragLastPos = -1; |
1325 | m_dragRowOrCol = -1; | |
1326 | m_isDragging = FALSE; | |
1327 | ||
1328 | m_rowResizeCursor = wxCursor( wxCURSOR_SIZENS ); | |
1329 | m_colResizeCursor = wxCursor( wxCURSOR_SIZEWE ); | |
1330 | ||
1331 | m_currentCellCoords = wxGridNoCellCoords; | |
f85afd4e MB |
1332 | |
1333 | m_selectedTopLeft = wxGridNoCellCoords; | |
1334 | m_selectedBottomRight = wxGridNoCellCoords; | |
8f177c8e | 1335 | |
f85afd4e MB |
1336 | m_editable = TRUE; // default for whole grid |
1337 | ||
2d66e025 MB |
1338 | m_inOnKeyDown = FALSE; |
1339 | m_batchCount = 0; | |
1340 | ||
f85afd4e MB |
1341 | // TODO: extend this to other types of controls |
1342 | // | |
2d66e025 MB |
1343 | m_cellEditCtrl = new wxGridTextCtrl( m_gridWin, |
1344 | this, | |
f85afd4e MB |
1345 | TRUE, |
1346 | wxGRID_CELLCTRL, | |
1347 | "", | |
1348 | wxPoint(1,1), | |
edc2c290 | 1349 | wxSize(1,1) |
d2fdd8d2 | 1350 | #if defined(__WXMSW__) |
edc2c290 | 1351 | , wxTE_MULTILINE | wxTE_NO_VSCROLL |
f85afd4e MB |
1352 | #endif |
1353 | ); | |
8f177c8e VZ |
1354 | |
1355 | m_cellEditCtrl->Show( FALSE ); | |
f85afd4e | 1356 | m_cellEditCtrlEnabled = TRUE; |
8f177c8e | 1357 | m_editCtrlType = wxGRID_TEXTCTRL; |
f85afd4e MB |
1358 | } |
1359 | ||
1360 | ||
1361 | void wxGrid::CalcDimensions() | |
1362 | { | |
f85afd4e | 1363 | int cw, ch; |
2d66e025 | 1364 | GetClientSize( &cw, &ch ); |
f85afd4e | 1365 | |
2d66e025 | 1366 | if ( m_numRows > 0 && m_numCols > 0 ) |
f85afd4e | 1367 | { |
b0d6ff2f MB |
1368 | int right = m_colRights[ m_numCols-1 ] + 50; |
1369 | int bottom = m_rowBottoms[ m_numRows-1 ] + 50; | |
60ff3b99 | 1370 | |
2d66e025 MB |
1371 | // TODO: restore the scroll position that we had before sizing |
1372 | // | |
1373 | int x, y; | |
1374 | GetViewStart( &x, &y ); | |
f0102d2a VZ |
1375 | SetScrollbars( GRID_SCROLL_LINE, GRID_SCROLL_LINE, |
1376 | right/GRID_SCROLL_LINE, bottom/GRID_SCROLL_LINE, | |
be46e4a6 | 1377 | x, y ); |
f85afd4e | 1378 | } |
f85afd4e MB |
1379 | } |
1380 | ||
1381 | ||
7807d81c MB |
1382 | void wxGrid::CalcWindowSizes() |
1383 | { | |
1384 | int cw, ch; | |
1385 | GetClientSize( &cw, &ch ); | |
b99be8fb | 1386 | |
7807d81c MB |
1387 | if ( m_cornerLabelWin->IsShown() ) |
1388 | m_cornerLabelWin->SetSize( 0, 0, m_rowLabelWidth, m_colLabelHeight ); | |
1389 | ||
1390 | if ( m_colLabelWin->IsShown() ) | |
1391 | m_colLabelWin->SetSize( m_rowLabelWidth, 0, cw-m_rowLabelWidth, m_colLabelHeight); | |
1392 | ||
1393 | if ( m_rowLabelWin->IsShown() ) | |
1394 | m_rowLabelWin->SetSize( 0, m_colLabelHeight, m_rowLabelWidth, ch-m_colLabelHeight); | |
1395 | ||
1396 | if ( m_gridWin->IsShown() ) | |
1397 | m_gridWin->SetSize( m_rowLabelWidth, m_colLabelHeight, cw-m_rowLabelWidth, ch-m_colLabelHeight); | |
1398 | } | |
1399 | ||
1400 | ||
f85afd4e MB |
1401 | // this is called when the grid table sends a message to say that it |
1402 | // has been redimensioned | |
1403 | // | |
1404 | bool wxGrid::Redimension( wxGridTableMessage& msg ) | |
1405 | { | |
1406 | int i; | |
8f177c8e | 1407 | |
f85afd4e MB |
1408 | switch ( msg.GetId() ) |
1409 | { | |
1410 | case wxGRIDTABLE_NOTIFY_ROWS_INSERTED: | |
1411 | { | |
1412 | size_t pos = msg.GetCommandInt(); | |
1413 | int numRows = msg.GetCommandInt2(); | |
1414 | for ( i = 0; i < numRows; i++ ) | |
1415 | { | |
1416 | m_rowHeights.Insert( m_defaultRowHeight, pos ); | |
1417 | m_rowBottoms.Insert( 0, pos ); | |
1418 | } | |
1419 | m_numRows += numRows; | |
2d66e025 MB |
1420 | |
1421 | int bottom = 0; | |
1422 | if ( pos > 0 ) bottom = m_rowBottoms[pos-1]; | |
60ff3b99 | 1423 | |
2d66e025 MB |
1424 | for ( i = pos; i < m_numRows; i++ ) |
1425 | { | |
1426 | bottom += m_rowHeights[i]; | |
1427 | m_rowBottoms[i] = bottom; | |
1428 | } | |
f85afd4e MB |
1429 | CalcDimensions(); |
1430 | } | |
1431 | return TRUE; | |
1432 | ||
1433 | case wxGRIDTABLE_NOTIFY_ROWS_APPENDED: | |
1434 | { | |
1435 | int numRows = msg.GetCommandInt(); | |
1436 | for ( i = 0; i < numRows; i++ ) | |
1437 | { | |
1438 | m_rowHeights.Add( m_defaultRowHeight ); | |
1439 | m_rowBottoms.Add( 0 ); | |
1440 | } | |
2d66e025 MB |
1441 | |
1442 | int oldNumRows = m_numRows; | |
f85afd4e | 1443 | m_numRows += numRows; |
2d66e025 MB |
1444 | |
1445 | int bottom = 0; | |
1446 | if ( oldNumRows > 0 ) bottom = m_rowBottoms[oldNumRows-1]; | |
60ff3b99 | 1447 | |
2d66e025 MB |
1448 | for ( i = oldNumRows; i < m_numRows; i++ ) |
1449 | { | |
1450 | bottom += m_rowHeights[i]; | |
1451 | m_rowBottoms[i] = bottom; | |
1452 | } | |
f85afd4e MB |
1453 | CalcDimensions(); |
1454 | } | |
1455 | return TRUE; | |
1456 | ||
1457 | case wxGRIDTABLE_NOTIFY_ROWS_DELETED: | |
1458 | { | |
1459 | size_t pos = msg.GetCommandInt(); | |
1460 | int numRows = msg.GetCommandInt2(); | |
1461 | for ( i = 0; i < numRows; i++ ) | |
1462 | { | |
1463 | m_rowHeights.Remove( pos ); | |
1464 | m_rowBottoms.Remove( pos ); | |
1465 | } | |
1466 | m_numRows -= numRows; | |
1467 | ||
f85afd4e MB |
1468 | if ( !m_numRows ) |
1469 | { | |
1470 | m_numCols = 0; | |
1471 | m_colWidths.Clear(); | |
1472 | m_colRights.Clear(); | |
1473 | m_currentCellCoords = wxGridNoCellCoords; | |
1474 | } | |
2d66e025 | 1475 | else |
f85afd4e | 1476 | { |
2d66e025 MB |
1477 | if ( m_currentCellCoords.GetRow() >= m_numRows ) |
1478 | m_currentCellCoords.Set( 0, 0 ); | |
1479 | ||
1480 | int h = 0; | |
1481 | for ( i = 0; i < m_numRows; i++ ) | |
1482 | { | |
1483 | h += m_rowHeights[i]; | |
1484 | m_rowBottoms[i] = h; | |
1485 | } | |
f85afd4e | 1486 | } |
60ff3b99 | 1487 | |
f85afd4e MB |
1488 | CalcDimensions(); |
1489 | } | |
1490 | return TRUE; | |
1491 | ||
1492 | case wxGRIDTABLE_NOTIFY_COLS_INSERTED: | |
1493 | { | |
1494 | size_t pos = msg.GetCommandInt(); | |
1495 | int numCols = msg.GetCommandInt2(); | |
1496 | for ( i = 0; i < numCols; i++ ) | |
1497 | { | |
1498 | m_colWidths.Insert( m_defaultColWidth, pos ); | |
1499 | m_colRights.Insert( 0, pos ); | |
1500 | } | |
1501 | m_numCols += numCols; | |
2d66e025 MB |
1502 | |
1503 | int right = 0; | |
1504 | if ( pos > 0 ) right = m_colRights[pos-1]; | |
60ff3b99 | 1505 | |
2d66e025 MB |
1506 | for ( i = pos; i < m_numCols; i++ ) |
1507 | { | |
1508 | right += m_colWidths[i]; | |
1509 | m_colRights[i] = right; | |
1510 | } | |
f85afd4e MB |
1511 | CalcDimensions(); |
1512 | } | |
1513 | return TRUE; | |
1514 | ||
1515 | case wxGRIDTABLE_NOTIFY_COLS_APPENDED: | |
1516 | { | |
1517 | int numCols = msg.GetCommandInt(); | |
1518 | for ( i = 0; i < numCols; i++ ) | |
1519 | { | |
1520 | m_colWidths.Add( m_defaultColWidth ); | |
1521 | m_colRights.Add( 0 ); | |
1522 | } | |
2d66e025 MB |
1523 | |
1524 | int oldNumCols = m_numCols; | |
f85afd4e | 1525 | m_numCols += numCols; |
2d66e025 MB |
1526 | |
1527 | int right = 0; | |
1528 | if ( oldNumCols > 0 ) right = m_colRights[oldNumCols-1]; | |
60ff3b99 | 1529 | |
2d66e025 MB |
1530 | for ( i = oldNumCols; i < m_numCols; i++ ) |
1531 | { | |
1532 | right += m_colWidths[i]; | |
1533 | m_colRights[i] = right; | |
1534 | } | |
f85afd4e MB |
1535 | CalcDimensions(); |
1536 | } | |
1537 | return TRUE; | |
1538 | ||
1539 | case wxGRIDTABLE_NOTIFY_COLS_DELETED: | |
1540 | { | |
1541 | size_t pos = msg.GetCommandInt(); | |
1542 | int numCols = msg.GetCommandInt2(); | |
1543 | for ( i = 0; i < numCols; i++ ) | |
1544 | { | |
1545 | m_colWidths.Remove( pos ); | |
1546 | m_colRights.Remove( pos ); | |
1547 | } | |
1548 | m_numCols -= numCols; | |
f85afd4e MB |
1549 | |
1550 | if ( !m_numCols ) | |
1551 | { | |
1552 | #if 0 // leave the row alone here so that AppendCols will work subsequently | |
1553 | m_numRows = 0; | |
1554 | m_rowHeights.Clear(); | |
1555 | m_rowBottoms.Clear(); | |
8f177c8e | 1556 | #endif |
f85afd4e MB |
1557 | m_currentCellCoords = wxGridNoCellCoords; |
1558 | } | |
60ff3b99 | 1559 | else |
f85afd4e | 1560 | { |
2d66e025 MB |
1561 | if ( m_currentCellCoords.GetCol() >= m_numCols ) |
1562 | m_currentCellCoords.Set( 0, 0 ); | |
1563 | ||
1564 | int w = 0; | |
1565 | for ( i = 0; i < m_numCols; i++ ) | |
1566 | { | |
1567 | w += m_colWidths[i]; | |
1568 | m_colRights[i] = w; | |
1569 | } | |
f85afd4e MB |
1570 | } |
1571 | CalcDimensions(); | |
1572 | } | |
1573 | return TRUE; | |
1574 | } | |
1575 | ||
1576 | return FALSE; | |
1577 | } | |
1578 | ||
1579 | ||
2d66e025 | 1580 | void wxGrid::CalcRowLabelsExposed( wxRegion& reg ) |
f85afd4e | 1581 | { |
2d66e025 MB |
1582 | wxRegionIterator iter( reg ); |
1583 | wxRect r; | |
f85afd4e | 1584 | |
2d66e025 | 1585 | m_rowLabelsExposed.Empty(); |
f85afd4e | 1586 | |
2d66e025 MB |
1587 | int top, bottom; |
1588 | while ( iter ) | |
f85afd4e | 1589 | { |
2d66e025 | 1590 | r = iter.GetRect(); |
f85afd4e | 1591 | |
2d66e025 MB |
1592 | // TODO: remove this when we can... |
1593 | // There is a bug in wxMotif that gives garbage update | |
1594 | // rectangles if you jump-scroll a long way by clicking the | |
1595 | // scrollbar with middle button. This is a work-around | |
1596 | // | |
1597 | #if defined(__WXMOTIF__) | |
1598 | int cw, ch; | |
1599 | m_gridWin->GetClientSize( &cw, &ch ); | |
1600 | if ( r.GetTop() > ch ) r.SetTop( 0 ); | |
1601 | r.SetBottom( wxMin( r.GetBottom(), ch ) ); | |
1602 | #endif | |
f85afd4e | 1603 | |
2d66e025 MB |
1604 | // logical bounds of update region |
1605 | // | |
1606 | int dummy; | |
1607 | CalcUnscrolledPosition( 0, r.GetTop(), &dummy, &top ); | |
1608 | CalcUnscrolledPosition( 0, r.GetBottom(), &dummy, &bottom ); | |
1609 | ||
1610 | // find the row labels within these bounds | |
1611 | // | |
1612 | int row; | |
1613 | int rowTop; | |
1614 | for ( row = 0; row < m_numRows; row++ ) | |
1615 | { | |
1616 | if ( m_rowBottoms[row] < top ) continue; | |
1617 | ||
1618 | rowTop = m_rowBottoms[row] - m_rowHeights[row]; | |
1619 | if ( rowTop > bottom ) break; | |
60ff3b99 | 1620 | |
2d66e025 MB |
1621 | m_rowLabelsExposed.Add( row ); |
1622 | } | |
60ff3b99 | 1623 | |
2d66e025 | 1624 | iter++ ; |
f85afd4e MB |
1625 | } |
1626 | } | |
1627 | ||
1628 | ||
2d66e025 | 1629 | void wxGrid::CalcColLabelsExposed( wxRegion& reg ) |
f85afd4e | 1630 | { |
2d66e025 MB |
1631 | wxRegionIterator iter( reg ); |
1632 | wxRect r; | |
f85afd4e | 1633 | |
2d66e025 | 1634 | m_colLabelsExposed.Empty(); |
f85afd4e | 1635 | |
2d66e025 MB |
1636 | int left, right; |
1637 | while ( iter ) | |
f85afd4e | 1638 | { |
2d66e025 | 1639 | r = iter.GetRect(); |
f85afd4e | 1640 | |
2d66e025 MB |
1641 | // TODO: remove this when we can... |
1642 | // There is a bug in wxMotif that gives garbage update | |
1643 | // rectangles if you jump-scroll a long way by clicking the | |
1644 | // scrollbar with middle button. This is a work-around | |
1645 | // | |
1646 | #if defined(__WXMOTIF__) | |
1647 | int cw, ch; | |
1648 | m_gridWin->GetClientSize( &cw, &ch ); | |
1649 | if ( r.GetLeft() > cw ) r.SetLeft( 0 ); | |
1650 | r.SetRight( wxMin( r.GetRight(), cw ) ); | |
1651 | #endif | |
1652 | ||
1653 | // logical bounds of update region | |
1654 | // | |
1655 | int dummy; | |
1656 | CalcUnscrolledPosition( r.GetLeft(), 0, &left, &dummy ); | |
1657 | CalcUnscrolledPosition( r.GetRight(), 0, &right, &dummy ); | |
1658 | ||
1659 | // find the cells within these bounds | |
1660 | // | |
1661 | int col; | |
1662 | int colLeft; | |
1663 | for ( col = 0; col < m_numCols; col++ ) | |
1664 | { | |
1665 | if ( m_colRights[col] < left ) continue; | |
60ff3b99 | 1666 | |
2d66e025 MB |
1667 | colLeft = m_colRights[col] - m_colWidths[col]; |
1668 | if ( colLeft > right ) break; | |
1669 | ||
1670 | m_colLabelsExposed.Add( col ); | |
1671 | } | |
60ff3b99 | 1672 | |
2d66e025 | 1673 | iter++ ; |
f85afd4e MB |
1674 | } |
1675 | } | |
1676 | ||
1677 | ||
2d66e025 | 1678 | void wxGrid::CalcCellsExposed( wxRegion& reg ) |
f85afd4e | 1679 | { |
2d66e025 MB |
1680 | wxRegionIterator iter( reg ); |
1681 | wxRect r; | |
f85afd4e | 1682 | |
2d66e025 MB |
1683 | m_cellsExposed.Empty(); |
1684 | m_rowsExposed.Empty(); | |
1685 | m_colsExposed.Empty(); | |
f85afd4e | 1686 | |
2d66e025 MB |
1687 | int left, top, right, bottom; |
1688 | while ( iter ) | |
1689 | { | |
1690 | r = iter.GetRect(); | |
f85afd4e | 1691 | |
2d66e025 MB |
1692 | // TODO: remove this when we can... |
1693 | // There is a bug in wxMotif that gives garbage update | |
1694 | // rectangles if you jump-scroll a long way by clicking the | |
1695 | // scrollbar with middle button. This is a work-around | |
1696 | // | |
1697 | #if defined(__WXMOTIF__) | |
f85afd4e | 1698 | int cw, ch; |
2d66e025 MB |
1699 | m_gridWin->GetClientSize( &cw, &ch ); |
1700 | if ( r.GetTop() > ch ) r.SetTop( 0 ); | |
1701 | if ( r.GetLeft() > cw ) r.SetLeft( 0 ); | |
1702 | r.SetRight( wxMin( r.GetRight(), cw ) ); | |
1703 | r.SetBottom( wxMin( r.GetBottom(), ch ) ); | |
1704 | #endif | |
8f177c8e | 1705 | |
2d66e025 MB |
1706 | // logical bounds of update region |
1707 | // | |
1708 | CalcUnscrolledPosition( r.GetLeft(), r.GetTop(), &left, &top ); | |
1709 | CalcUnscrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom ); | |
f85afd4e | 1710 | |
2d66e025 | 1711 | // find the cells within these bounds |
f85afd4e | 1712 | // |
2d66e025 MB |
1713 | int row, col; |
1714 | int colLeft, rowTop; | |
1715 | for ( row = 0; row < m_numRows; row++ ) | |
f85afd4e | 1716 | { |
2d66e025 | 1717 | if ( m_rowBottoms[row] < top ) continue; |
f85afd4e | 1718 | |
2d66e025 MB |
1719 | rowTop = m_rowBottoms[row] - m_rowHeights[row]; |
1720 | if ( rowTop > bottom ) break; | |
60ff3b99 | 1721 | |
2d66e025 | 1722 | m_rowsExposed.Add( row ); |
f85afd4e | 1723 | |
2d66e025 MB |
1724 | for ( col = 0; col < m_numCols; col++ ) |
1725 | { | |
1726 | if ( m_colRights[col] < left ) continue; | |
60ff3b99 | 1727 | |
2d66e025 MB |
1728 | colLeft = m_colRights[col] - m_colWidths[col]; |
1729 | if ( colLeft > right ) break; | |
60ff3b99 | 1730 | |
2d66e025 MB |
1731 | if ( m_colsExposed.Index( col ) == wxNOT_FOUND ) m_colsExposed.Add( col ); |
1732 | m_cellsExposed.Add( wxGridCellCoords( row, col ) ); | |
1733 | } | |
1734 | } | |
60ff3b99 | 1735 | |
2d66e025 | 1736 | iter++ ; |
f85afd4e MB |
1737 | } |
1738 | } | |
1739 | ||
1740 | ||
2d66e025 | 1741 | void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) |
f85afd4e | 1742 | { |
2d66e025 MB |
1743 | int x, y, row; |
1744 | wxPoint pos( event.GetPosition() ); | |
1745 | CalcUnscrolledPosition( pos.x, pos.y, &x, &y ); | |
60ff3b99 | 1746 | |
2d66e025 | 1747 | if ( event.Dragging() ) |
f85afd4e MB |
1748 | { |
1749 | m_isDragging = TRUE; | |
8f177c8e | 1750 | |
2d66e025 | 1751 | if ( event.LeftIsDown() ) |
f85afd4e MB |
1752 | { |
1753 | switch( m_cursorMode ) | |
1754 | { | |
f85afd4e MB |
1755 | case WXGRID_CURSOR_RESIZE_ROW: |
1756 | { | |
2d66e025 MB |
1757 | int cw, ch, left, dummy; |
1758 | m_gridWin->GetClientSize( &cw, &ch ); | |
1759 | CalcUnscrolledPosition( 0, 0, &left, &dummy ); | |
60ff3b99 | 1760 | |
2d66e025 MB |
1761 | wxClientDC dc( m_gridWin ); |
1762 | PrepareDC( dc ); | |
d2fdd8d2 | 1763 | dc.SetLogicalFunction(wxINVERT); |
f85afd4e MB |
1764 | if ( m_dragLastPos >= 0 ) |
1765 | { | |
2d66e025 | 1766 | dc.DrawLine( left, m_dragLastPos, left+cw, m_dragLastPos ); |
f85afd4e | 1767 | } |
2d66e025 MB |
1768 | dc.DrawLine( left, y, left+cw, y ); |
1769 | m_dragLastPos = y; | |
f85afd4e MB |
1770 | } |
1771 | break; | |
1772 | ||
1773 | case WXGRID_CURSOR_SELECT_ROW: | |
1774 | { | |
1775 | if ( (row = YToRow( y )) >= 0 && | |
1776 | !IsInSelection( row, 0 ) ) | |
1777 | { | |
1778 | SelectRow( row, TRUE ); | |
1779 | } | |
1780 | } | |
1781 | break; | |
f85afd4e MB |
1782 | } |
1783 | } | |
1784 | return; | |
1785 | } | |
1786 | ||
1787 | m_isDragging = FALSE; | |
8f177c8e | 1788 | |
60ff3b99 | 1789 | |
2d66e025 | 1790 | // ------------ Left button pressed |
f85afd4e | 1791 | // |
2d66e025 | 1792 | if ( event.LeftDown() ) |
f85afd4e | 1793 | { |
2d66e025 MB |
1794 | // don't send a label click event for a hit on the |
1795 | // edge of the row label - this is probably the user | |
1796 | // wanting to resize the row | |
1797 | // | |
1798 | if ( YToEdgeOfRow(y) < 0 ) | |
f85afd4e | 1799 | { |
2d66e025 | 1800 | row = YToRow(y); |
58dd5b3b MB |
1801 | if ( row >= 0 && |
1802 | !SendEvent( EVT_GRID_LABEL_LEFT_CLICK, row, -1, event ) ) | |
f85afd4e | 1803 | { |
2d66e025 MB |
1804 | SelectRow( row, event.ShiftDown() ); |
1805 | m_cursorMode = WXGRID_CURSOR_SELECT_ROW; | |
f85afd4e | 1806 | } |
2d66e025 MB |
1807 | } |
1808 | else | |
1809 | { | |
1810 | // starting to drag-resize a row | |
1811 | // | |
1812 | m_rowLabelWin->CaptureMouse(); | |
1813 | } | |
1814 | } | |
f85afd4e | 1815 | |
f85afd4e | 1816 | |
2d66e025 MB |
1817 | // ------------ Left double click |
1818 | // | |
1819 | else if (event.LeftDClick() ) | |
1820 | { | |
1821 | if ( YToEdgeOfRow(y) < 0 ) | |
1822 | { | |
1823 | row = YToRow(y); | |
1824 | SendEvent( EVT_GRID_LABEL_LEFT_DCLICK, row, -1, event ); | |
f85afd4e MB |
1825 | } |
1826 | } | |
60ff3b99 VZ |
1827 | |
1828 | ||
2d66e025 | 1829 | // ------------ Left button released |
f85afd4e | 1830 | // |
2d66e025 | 1831 | else if ( event.LeftUp() ) |
f85afd4e | 1832 | { |
2d66e025 | 1833 | if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW ) |
f85afd4e | 1834 | { |
2d66e025 | 1835 | m_rowLabelWin->ReleaseMouse(); |
60ff3b99 | 1836 | |
2d66e025 | 1837 | if ( m_dragLastPos >= 0 ) |
f85afd4e | 1838 | { |
2d66e025 | 1839 | // erase the last line and resize the row |
f85afd4e | 1840 | // |
2d66e025 MB |
1841 | int cw, ch, left, dummy; |
1842 | m_gridWin->GetClientSize( &cw, &ch ); | |
1843 | CalcUnscrolledPosition( 0, 0, &left, &dummy ); | |
60ff3b99 | 1844 | |
2d66e025 MB |
1845 | wxClientDC dc( m_gridWin ); |
1846 | PrepareDC( dc ); | |
1847 | dc.SetLogicalFunction( wxINVERT ); | |
1848 | dc.DrawLine( left, m_dragLastPos, left+cw, m_dragLastPos ); | |
1849 | HideCellEditControl(); | |
1850 | ||
1851 | int rowTop = m_rowBottoms[m_dragRowOrCol] - m_rowHeights[m_dragRowOrCol]; | |
60ff3b99 | 1852 | SetRowSize( m_dragRowOrCol, wxMax( y - rowTop, WXGRID_MIN_ROW_HEIGHT ) ); |
2d66e025 | 1853 | if ( !GetBatchCount() ) |
f85afd4e | 1854 | { |
70c7a608 SN |
1855 | // Only needed to get the correct rect.y: |
1856 | wxRect rect ( CellToRect( m_dragRowOrCol, 0 ) ); | |
1857 | rect.x = 0; | |
cb309039 | 1858 | CalcScrolledPosition(0, rect.y, &dummy, &rect.y); |
70c7a608 SN |
1859 | rect.width = m_rowLabelWidth; |
1860 | rect.height = ch - rect.y; | |
1861 | m_rowLabelWin->Refresh( TRUE, &rect ); | |
1862 | rect.width = cw; | |
c6a51dcd | 1863 | m_gridWin->Refresh( FALSE, &rect ); |
f85afd4e | 1864 | } |
60ff3b99 | 1865 | |
2d66e025 | 1866 | ShowCellEditControl(); |
f85afd4e | 1867 | |
2d66e025 MB |
1868 | // Note: we are ending the event *after* doing |
1869 | // default processing in this case | |
f85afd4e | 1870 | // |
2d66e025 | 1871 | SendEvent( EVT_GRID_ROW_SIZE, m_dragRowOrCol, -1, event ); |
f85afd4e | 1872 | } |
2d66e025 | 1873 | } |
f85afd4e | 1874 | |
790cc417 | 1875 | m_cursorMode = WXGRID_CURSOR_SELECT_CELL; |
2d66e025 MB |
1876 | m_dragLastPos = -1; |
1877 | } | |
f85afd4e | 1878 | |
f85afd4e | 1879 | |
2d66e025 MB |
1880 | // ------------ Right button down |
1881 | // | |
1882 | else if ( event.RightDown() ) | |
1883 | { | |
1884 | row = YToRow(y); | |
1885 | if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK, row, -1, event ) ) | |
1886 | { | |
1887 | // no default action at the moment | |
f85afd4e MB |
1888 | } |
1889 | } | |
60ff3b99 VZ |
1890 | |
1891 | ||
2d66e025 | 1892 | // ------------ Right double click |
f85afd4e | 1893 | // |
2d66e025 MB |
1894 | else if ( event.RightDClick() ) |
1895 | { | |
1896 | row = YToRow(y); | |
1897 | if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK, row, -1, event ) ) | |
1898 | { | |
1899 | // no default action at the moment | |
1900 | } | |
1901 | } | |
60ff3b99 VZ |
1902 | |
1903 | ||
2d66e025 | 1904 | // ------------ No buttons down and mouse moving |
f85afd4e | 1905 | // |
2d66e025 | 1906 | else if ( event.Moving() ) |
f85afd4e | 1907 | { |
2d66e025 MB |
1908 | m_dragRowOrCol = YToEdgeOfRow( y ); |
1909 | if ( m_dragRowOrCol >= 0 ) | |
8f177c8e | 1910 | { |
2d66e025 | 1911 | if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL ) |
8f177c8e | 1912 | { |
2d66e025 MB |
1913 | m_cursorMode = WXGRID_CURSOR_RESIZE_ROW; |
1914 | m_rowLabelWin->SetCursor( m_rowResizeCursor ); | |
8f177c8e | 1915 | } |
2d66e025 MB |
1916 | } |
1917 | else | |
1918 | { | |
b93a2fe6 MB |
1919 | m_cursorMode = WXGRID_CURSOR_SELECT_CELL; |
1920 | if ( m_rowLabelWin->GetCursor() == m_rowResizeCursor ) | |
2d66e025 | 1921 | m_rowLabelWin->SetCursor( *wxSTANDARD_CURSOR ); |
8f177c8e | 1922 | } |
f85afd4e | 1923 | } |
2d66e025 MB |
1924 | } |
1925 | ||
1926 | ||
1927 | void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) | |
1928 | { | |
1929 | int x, y, col; | |
1930 | wxPoint pos( event.GetPosition() ); | |
1931 | CalcUnscrolledPosition( pos.x, pos.y, &x, &y ); | |
60ff3b99 | 1932 | |
2d66e025 | 1933 | if ( event.Dragging() ) |
f85afd4e | 1934 | { |
2d66e025 | 1935 | m_isDragging = TRUE; |
8f177c8e | 1936 | |
2d66e025 | 1937 | if ( event.LeftIsDown() ) |
8f177c8e | 1938 | { |
2d66e025 | 1939 | switch( m_cursorMode ) |
8f177c8e | 1940 | { |
2d66e025 | 1941 | case WXGRID_CURSOR_RESIZE_COL: |
8f177c8e | 1942 | { |
2d66e025 MB |
1943 | int cw, ch, dummy, top; |
1944 | m_gridWin->GetClientSize( &cw, &ch ); | |
1945 | CalcUnscrolledPosition( 0, 0, &dummy, &top ); | |
60ff3b99 | 1946 | |
2d66e025 MB |
1947 | wxClientDC dc( m_gridWin ); |
1948 | PrepareDC( dc ); | |
d2fdd8d2 | 1949 | dc.SetLogicalFunction(wxINVERT); |
2d66e025 MB |
1950 | if ( m_dragLastPos >= 0 ) |
1951 | { | |
1952 | dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top+ch ); | |
1953 | } | |
1954 | dc.DrawLine( x, top, x, top+ch ); | |
1955 | m_dragLastPos = x; | |
f85afd4e | 1956 | } |
2d66e025 | 1957 | break; |
f85afd4e | 1958 | |
2d66e025 | 1959 | case WXGRID_CURSOR_SELECT_COL: |
f85afd4e | 1960 | { |
2d66e025 MB |
1961 | if ( (col = XToCol( x )) >= 0 && |
1962 | !IsInSelection( 0, col ) ) | |
1963 | { | |
1964 | SelectCol( col, TRUE ); | |
1965 | } | |
f85afd4e | 1966 | } |
f85afd4e | 1967 | break; |
2d66e025 | 1968 | } |
f85afd4e | 1969 | } |
2d66e025 | 1970 | return; |
f85afd4e | 1971 | } |
2d66e025 MB |
1972 | |
1973 | m_isDragging = FALSE; | |
1974 | ||
60ff3b99 | 1975 | |
2d66e025 | 1976 | // ------------ Left button pressed |
f85afd4e | 1977 | // |
2d66e025 | 1978 | if ( event.LeftDown() ) |
f85afd4e | 1979 | { |
2d66e025 MB |
1980 | // don't send a label click event for a hit on the |
1981 | // edge of the col label - this is probably the user | |
1982 | // wanting to resize the col | |
1983 | // | |
1984 | if ( XToEdgeOfCol(x) < 0 ) | |
8f177c8e | 1985 | { |
2d66e025 | 1986 | col = XToCol(x); |
58dd5b3b MB |
1987 | if ( col >= 0 && |
1988 | !SendEvent( EVT_GRID_LABEL_LEFT_CLICK, -1, col, event ) ) | |
8f177c8e | 1989 | { |
2d66e025 MB |
1990 | SelectCol( col, event.ShiftDown() ); |
1991 | m_cursorMode = WXGRID_CURSOR_SELECT_COL; | |
f85afd4e | 1992 | } |
2d66e025 MB |
1993 | } |
1994 | else | |
1995 | { | |
1996 | // starting to drag-resize a col | |
1997 | // | |
1998 | m_colLabelWin->CaptureMouse(); | |
1999 | } | |
2000 | } | |
f85afd4e | 2001 | |
f85afd4e | 2002 | |
2d66e025 MB |
2003 | // ------------ Left double click |
2004 | // | |
2005 | if ( event.LeftDClick() ) | |
2006 | { | |
2007 | if ( XToEdgeOfCol(x) < 0 ) | |
2008 | { | |
2009 | col = XToCol(x); | |
2010 | SendEvent( EVT_GRID_LABEL_LEFT_DCLICK, -1, col, event ); | |
2011 | } | |
2012 | } | |
60ff3b99 VZ |
2013 | |
2014 | ||
2d66e025 MB |
2015 | // ------------ Left button released |
2016 | // | |
2017 | else if ( event.LeftUp() ) | |
2018 | { | |
2019 | if ( m_cursorMode == WXGRID_CURSOR_RESIZE_COL ) | |
2020 | { | |
2021 | m_colLabelWin->ReleaseMouse(); | |
60ff3b99 | 2022 | |
2d66e025 | 2023 | if ( m_dragLastPos >= 0 ) |
f85afd4e | 2024 | { |
2d66e025 | 2025 | // erase the last line and resize the col |
f85afd4e | 2026 | // |
2d66e025 MB |
2027 | int cw, ch, dummy, top; |
2028 | m_gridWin->GetClientSize( &cw, &ch ); | |
2029 | CalcUnscrolledPosition( 0, 0, &dummy, &top ); | |
60ff3b99 | 2030 | |
2d66e025 MB |
2031 | wxClientDC dc( m_gridWin ); |
2032 | PrepareDC( dc ); | |
2033 | dc.SetLogicalFunction( wxINVERT ); | |
2034 | dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top+ch ); | |
2035 | HideCellEditControl(); | |
2036 | ||
2037 | int colLeft = m_colRights[m_dragRowOrCol] - m_colWidths[m_dragRowOrCol]; | |
60ff3b99 VZ |
2038 | SetColSize( m_dragRowOrCol, wxMax( x - colLeft, WXGRID_MIN_COL_WIDTH ) ); |
2039 | ||
2d66e025 MB |
2040 | if ( !GetBatchCount() ) |
2041 | { | |
70c7a608 SN |
2042 | // Only needed to get the correct rect.x: |
2043 | wxRect rect ( CellToRect( 0, m_dragRowOrCol ) ); | |
2044 | rect.y = 0; | |
cb309039 | 2045 | CalcScrolledPosition(rect.x, 0, &rect.x, &dummy); |
70c7a608 SN |
2046 | rect.width = cw - rect.x; |
2047 | rect.height = m_colLabelHeight; | |
2048 | m_colLabelWin->Refresh( TRUE, &rect ); | |
2049 | rect.height = ch; | |
c6a51dcd | 2050 | m_gridWin->Refresh( FALSE, &rect ); |
2d66e025 | 2051 | } |
60ff3b99 | 2052 | |
2d66e025 | 2053 | ShowCellEditControl(); |
f85afd4e | 2054 | |
2d66e025 MB |
2055 | // Note: we are ending the event *after* doing |
2056 | // default processing in this case | |
2057 | // | |
2058 | SendEvent( EVT_GRID_COL_SIZE, -1, m_dragRowOrCol, event ); | |
f85afd4e | 2059 | } |
2d66e025 | 2060 | } |
f85afd4e | 2061 | |
790cc417 | 2062 | m_cursorMode = WXGRID_CURSOR_SELECT_CELL; |
2d66e025 | 2063 | m_dragLastPos = -1; |
60ff3b99 VZ |
2064 | } |
2065 | ||
2066 | ||
2d66e025 MB |
2067 | // ------------ Right button down |
2068 | // | |
2069 | else if ( event.RightDown() ) | |
2070 | { | |
2071 | col = XToCol(x); | |
2072 | if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK, -1, col, event ) ) | |
2073 | { | |
2074 | // no default action at the moment | |
f85afd4e MB |
2075 | } |
2076 | } | |
60ff3b99 VZ |
2077 | |
2078 | ||
2d66e025 | 2079 | // ------------ Right double click |
f85afd4e | 2080 | // |
2d66e025 MB |
2081 | else if ( event.RightDClick() ) |
2082 | { | |
2083 | col = XToCol(x); | |
2084 | if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK, -1, col, event ) ) | |
2085 | { | |
2086 | // no default action at the moment | |
2087 | } | |
2088 | } | |
60ff3b99 VZ |
2089 | |
2090 | ||
2d66e025 | 2091 | // ------------ No buttons down and mouse moving |
f85afd4e | 2092 | // |
2d66e025 | 2093 | else if ( event.Moving() ) |
f85afd4e | 2094 | { |
2d66e025 MB |
2095 | m_dragRowOrCol = XToEdgeOfCol( x ); |
2096 | if ( m_dragRowOrCol >= 0 ) | |
f85afd4e | 2097 | { |
2d66e025 | 2098 | if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL ) |
f85afd4e | 2099 | { |
2d66e025 MB |
2100 | m_cursorMode = WXGRID_CURSOR_RESIZE_COL; |
2101 | m_colLabelWin->SetCursor( m_colResizeCursor ); | |
f85afd4e | 2102 | } |
2d66e025 MB |
2103 | } |
2104 | else | |
2105 | { | |
b93a2fe6 MB |
2106 | m_cursorMode = WXGRID_CURSOR_SELECT_CELL; |
2107 | if ( m_colLabelWin->GetCursor() == m_colResizeCursor ) | |
2d66e025 | 2108 | m_colLabelWin->SetCursor( *wxSTANDARD_CURSOR ); |
8f177c8e | 2109 | } |
f85afd4e MB |
2110 | } |
2111 | } | |
2112 | ||
2113 | ||
2d66e025 | 2114 | void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent& event ) |
f85afd4e | 2115 | { |
2d66e025 | 2116 | if ( event.LeftDown() ) |
f85afd4e | 2117 | { |
2d66e025 MB |
2118 | // indicate corner label by having both row and |
2119 | // col args == -1 | |
f85afd4e | 2120 | // |
2d66e025 MB |
2121 | if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK, -1, -1, event ) ) |
2122 | { | |
2123 | SelectAll(); | |
2124 | } | |
f85afd4e MB |
2125 | } |
2126 | ||
2d66e025 MB |
2127 | else if ( event.LeftDClick() ) |
2128 | { | |
2129 | SendEvent( EVT_GRID_LABEL_LEFT_DCLICK, -1, -1, event ); | |
2130 | } | |
8f177c8e | 2131 | |
2d66e025 | 2132 | else if ( event.RightDown() ) |
f85afd4e | 2133 | { |
2d66e025 | 2134 | if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK, -1, -1, event ) ) |
f85afd4e | 2135 | { |
2d66e025 MB |
2136 | // no default action at the moment |
2137 | } | |
2138 | } | |
f85afd4e | 2139 | |
2d66e025 MB |
2140 | else if ( event.RightDClick() ) |
2141 | { | |
2142 | if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK, -1, -1, event ) ) | |
2143 | { | |
2144 | // no default action at the moment | |
2145 | } | |
2146 | } | |
2147 | } | |
f85afd4e | 2148 | |
8f177c8e | 2149 | |
2d66e025 MB |
2150 | void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) |
2151 | { | |
2152 | int x, y; | |
2153 | wxPoint pos( event.GetPosition() ); | |
2154 | CalcUnscrolledPosition( pos.x, pos.y, &x, &y ); | |
60ff3b99 | 2155 | |
2d66e025 MB |
2156 | wxGridCellCoords coords; |
2157 | XYToCell( x, y, coords ); | |
60ff3b99 | 2158 | |
2d66e025 MB |
2159 | if ( event.Dragging() ) |
2160 | { | |
2161 | m_isDragging = TRUE; | |
2d66e025 MB |
2162 | if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL ) |
2163 | { | |
f0102d2a VZ |
2164 | // Hide the edit control, so it |
2165 | // won't interfer with drag-shrinking. | |
2166 | if ( IsCellEditControlEnabled() ) | |
2167 | HideCellEditControl(); | |
2d66e025 MB |
2168 | if ( coords != wxGridNoCellCoords ) |
2169 | { | |
2170 | if ( !IsSelection() ) | |
f85afd4e | 2171 | { |
2d66e025 | 2172 | SelectBlock( coords, coords ); |
f85afd4e MB |
2173 | } |
2174 | else | |
2175 | { | |
f0102d2a | 2176 | SelectBlock( m_currentCellCoords, coords ); |
f85afd4e | 2177 | } |
2d66e025 MB |
2178 | } |
2179 | } | |
8f177c8e | 2180 | |
2d66e025 MB |
2181 | return; |
2182 | } | |
66242c80 | 2183 | |
2d66e025 | 2184 | m_isDragging = FALSE; |
8f177c8e | 2185 | |
58dd5b3b | 2186 | if ( coords != wxGridNoCellCoords ) |
2d66e025 | 2187 | { |
58dd5b3b | 2188 | if ( event.LeftDown() ) |
2d66e025 | 2189 | { |
58dd5b3b MB |
2190 | if ( event.ShiftDown() ) |
2191 | { | |
2192 | SelectBlock( m_currentCellCoords, coords ); | |
2193 | } | |
2194 | else | |
2195 | { | |
2196 | if ( !SendEvent( EVT_GRID_CELL_LEFT_CLICK, | |
2197 | coords.GetRow(), | |
2198 | coords.GetCol(), | |
2199 | event ) ) | |
2200 | { | |
2201 | MakeCellVisible( coords ); | |
2202 | SetCurrentCell( coords ); | |
2203 | } | |
2204 | } | |
f85afd4e | 2205 | } |
f85afd4e | 2206 | |
f85afd4e | 2207 | |
58dd5b3b MB |
2208 | // ------------ Left double click |
2209 | // | |
2210 | else if ( event.LeftDClick() ) | |
2211 | { | |
2212 | SendEvent( EVT_GRID_CELL_LEFT_DCLICK, | |
2213 | coords.GetRow(), | |
2214 | coords.GetCol(), | |
2215 | event ); | |
2216 | } | |
f85afd4e | 2217 | |
8f177c8e | 2218 | |
58dd5b3b MB |
2219 | // ------------ Left button released |
2220 | // | |
2221 | else if ( event.LeftUp() ) | |
f85afd4e | 2222 | { |
58dd5b3b | 2223 | if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL ) |
52068ea5 | 2224 | { |
58dd5b3b MB |
2225 | if ( IsSelection() ) |
2226 | { | |
2227 | SendEvent( EVT_GRID_RANGE_SELECT, -1, -1, event ); | |
2228 | } | |
f85afd4e | 2229 | } |
58dd5b3b | 2230 | |
f0102d2a VZ |
2231 | // Show the edit control, if it has |
2232 | // been hidden for drag-shrinking. | |
2233 | if ( IsCellEditControlEnabled() ) | |
2234 | ShowCellEditControl(); | |
2d66e025 | 2235 | |
58dd5b3b MB |
2236 | m_dragLastPos = -1; |
2237 | } | |
f85afd4e | 2238 | |
f85afd4e | 2239 | |
58dd5b3b MB |
2240 | // ------------ Right button down |
2241 | // | |
2242 | else if ( event.RightDown() ) | |
f85afd4e | 2243 | { |
58dd5b3b MB |
2244 | if ( !SendEvent( EVT_GRID_CELL_RIGHT_CLICK, |
2245 | coords.GetRow(), | |
2246 | coords.GetCol(), | |
2247 | event ) ) | |
2248 | { | |
2249 | // no default action at the moment | |
2250 | } | |
60ff3b99 | 2251 | } |
2d66e025 | 2252 | |
60ff3b99 | 2253 | |
58dd5b3b MB |
2254 | // ------------ Right double click |
2255 | // | |
2256 | else if ( event.RightDClick() ) | |
f85afd4e | 2257 | { |
58dd5b3b MB |
2258 | if ( !SendEvent( EVT_GRID_CELL_RIGHT_DCLICK, |
2259 | coords.GetRow(), | |
2260 | coords.GetCol(), | |
2261 | event ) ) | |
2262 | { | |
2263 | // no default action at the moment | |
2264 | } | |
60ff3b99 | 2265 | } |
790cc417 MB |
2266 | |
2267 | // ------------ Moving and no button action | |
2268 | // | |
2269 | else if ( event.Moving() && !event.IsButton() ) | |
2270 | { | |
2271 | m_cursorMode = WXGRID_CURSOR_SELECT_CELL; | |
2272 | } | |
f85afd4e | 2273 | } |
f85afd4e MB |
2274 | } |
2275 | ||
2276 | ||
2d66e025 MB |
2277 | // |
2278 | // ------ interaction with data model | |
2279 | // | |
2280 | bool wxGrid::ProcessTableMessage( wxGridTableMessage& msg ) | |
f85afd4e | 2281 | { |
2d66e025 | 2282 | switch ( msg.GetId() ) |
17732cec | 2283 | { |
2d66e025 MB |
2284 | case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES: |
2285 | return GetModelValues(); | |
17732cec | 2286 | |
2d66e025 MB |
2287 | case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES: |
2288 | return SetModelValues(); | |
f85afd4e | 2289 | |
2d66e025 MB |
2290 | case wxGRIDTABLE_NOTIFY_ROWS_INSERTED: |
2291 | case wxGRIDTABLE_NOTIFY_ROWS_APPENDED: | |
2292 | case wxGRIDTABLE_NOTIFY_ROWS_DELETED: | |
2293 | case wxGRIDTABLE_NOTIFY_COLS_INSERTED: | |
2294 | case wxGRIDTABLE_NOTIFY_COLS_APPENDED: | |
2295 | case wxGRIDTABLE_NOTIFY_COLS_DELETED: | |
2296 | return Redimension( msg ); | |
2297 | ||
2298 | default: | |
2299 | return FALSE; | |
f85afd4e | 2300 | } |
2d66e025 | 2301 | } |
f85afd4e | 2302 | |
f85afd4e | 2303 | |
f85afd4e | 2304 | |
2d66e025 MB |
2305 | // The behaviour of this function depends on the grid table class |
2306 | // Clear() function. For the default wxGridStringTable class the | |
2307 | // behavious is to replace all cell contents with wxEmptyString but | |
2308 | // not to change the number of rows or cols. | |
2309 | // | |
2310 | void wxGrid::ClearGrid() | |
2311 | { | |
2312 | if ( m_table ) | |
f85afd4e | 2313 | { |
2d66e025 MB |
2314 | m_table->Clear(); |
2315 | SetEditControlValue(); | |
1f1ce288 | 2316 | if ( !GetBatchCount() ) m_gridWin->Refresh(); |
f85afd4e MB |
2317 | } |
2318 | } | |
2319 | ||
2320 | ||
2d66e025 | 2321 | bool wxGrid::InsertRows( int pos, int numRows, bool WXUNUSED(updateLabels) ) |
f85afd4e | 2322 | { |
2d66e025 | 2323 | // TODO: something with updateLabels flag |
8f177c8e | 2324 | |
2d66e025 | 2325 | if ( !m_created ) |
f85afd4e | 2326 | { |
bd3c6758 | 2327 | wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); |
2d66e025 MB |
2328 | return FALSE; |
2329 | } | |
8f177c8e | 2330 | |
2d66e025 MB |
2331 | if ( m_table ) |
2332 | { | |
2333 | bool ok = m_table->InsertRows( pos, numRows ); | |
f85afd4e | 2334 | |
2d66e025 MB |
2335 | // the table will have sent the results of the insert row |
2336 | // operation to this view object as a grid table message | |
2337 | // | |
2338 | if ( ok ) | |
2339 | { | |
2340 | if ( m_numCols == 0 ) | |
f85afd4e | 2341 | { |
2d66e025 MB |
2342 | m_table->AppendCols( WXGRID_DEFAULT_NUMBER_COLS ); |
2343 | // | |
2344 | // TODO: perhaps instead of appending the default number of cols | |
2345 | // we should remember what the last non-zero number of cols was ? | |
2346 | // | |
2347 | } | |
8f177c8e | 2348 | |
2d66e025 MB |
2349 | if ( m_currentCellCoords == wxGridNoCellCoords ) |
2350 | { | |
2351 | // if we have just inserted cols into an empty grid the current | |
2352 | // cell will be undefined... | |
2353 | // | |
2354 | SetCurrentCell( 0, 0 ); | |
f85afd4e MB |
2355 | } |
2356 | ||
2d66e025 MB |
2357 | ClearSelection(); |
2358 | if ( !GetBatchCount() ) Refresh(); | |
f85afd4e | 2359 | } |
2d66e025 MB |
2360 | |
2361 | SetEditControlValue(); | |
2362 | return ok; | |
2363 | } | |
2364 | else | |
2365 | { | |
2366 | return FALSE; | |
f85afd4e MB |
2367 | } |
2368 | } | |
2369 | ||
2370 | ||
2d66e025 | 2371 | bool wxGrid::AppendRows( int numRows, bool WXUNUSED(updateLabels) ) |
f85afd4e | 2372 | { |
2d66e025 MB |
2373 | // TODO: something with updateLabels flag |
2374 | ||
2375 | if ( !m_created ) | |
f85afd4e | 2376 | { |
bd3c6758 | 2377 | wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); |
2d66e025 MB |
2378 | return FALSE; |
2379 | } | |
2380 | ||
2381 | if ( m_table && m_table->AppendRows( numRows ) ) | |
2382 | { | |
2383 | if ( m_currentCellCoords == wxGridNoCellCoords ) | |
2384 | { | |
2385 | // if we have just inserted cols into an empty grid the current | |
2386 | // cell will be undefined... | |
2387 | // | |
2388 | SetCurrentCell( 0, 0 ); | |
2389 | } | |
2390 | ||
2391 | // the table will have sent the results of the append row | |
2392 | // operation to this view object as a grid table message | |
2393 | // | |
2394 | ClearSelection(); | |
2395 | if ( !GetBatchCount() ) Refresh(); | |
2396 | return TRUE; | |
2397 | } | |
2398 | else | |
2399 | { | |
2400 | return FALSE; | |
f85afd4e MB |
2401 | } |
2402 | } | |
2403 | ||
2d66e025 MB |
2404 | |
2405 | bool wxGrid::DeleteRows( int pos, int numRows, bool WXUNUSED(updateLabels) ) | |
f85afd4e | 2406 | { |
2d66e025 MB |
2407 | // TODO: something with updateLabels flag |
2408 | ||
2409 | if ( !m_created ) | |
f85afd4e | 2410 | { |
bd3c6758 | 2411 | wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); |
2d66e025 MB |
2412 | return FALSE; |
2413 | } | |
2414 | ||
2415 | if ( m_table && m_table->DeleteRows( pos, numRows ) ) | |
2416 | { | |
2417 | // the table will have sent the results of the delete row | |
2418 | // operation to this view object as a grid table message | |
2419 | // | |
2420 | if ( m_numRows > 0 ) | |
2421 | SetEditControlValue(); | |
2b37dc19 | 2422 | else |
2d66e025 | 2423 | HideCellEditControl(); |
f85afd4e | 2424 | |
2d66e025 MB |
2425 | ClearSelection(); |
2426 | if ( !GetBatchCount() ) Refresh(); | |
2427 | return TRUE; | |
2428 | } | |
2429 | else | |
2430 | { | |
2431 | return FALSE; | |
2432 | } | |
2433 | } | |
f85afd4e | 2434 | |
f85afd4e | 2435 | |
2d66e025 MB |
2436 | bool wxGrid::InsertCols( int pos, int numCols, bool WXUNUSED(updateLabels) ) |
2437 | { | |
2438 | // TODO: something with updateLabels flag | |
8f177c8e | 2439 | |
2d66e025 MB |
2440 | if ( !m_created ) |
2441 | { | |
bd3c6758 | 2442 | wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); |
2d66e025 MB |
2443 | return FALSE; |
2444 | } | |
f85afd4e | 2445 | |
2d66e025 MB |
2446 | if ( m_table ) |
2447 | { | |
2448 | HideCellEditControl(); | |
2449 | bool ok = m_table->InsertCols( pos, numCols ); | |
2450 | ||
2451 | // the table will have sent the results of the insert col | |
2452 | // operation to this view object as a grid table message | |
2453 | // | |
2454 | if ( ok ) | |
f85afd4e | 2455 | { |
2d66e025 | 2456 | if ( m_currentCellCoords == wxGridNoCellCoords ) |
f85afd4e | 2457 | { |
2d66e025 MB |
2458 | // if we have just inserted cols into an empty grid the current |
2459 | // cell will be undefined... | |
2460 | // | |
2461 | SetCurrentCell( 0, 0 ); | |
f85afd4e | 2462 | } |
2d66e025 MB |
2463 | |
2464 | ClearSelection(); | |
2465 | if ( !GetBatchCount() ) Refresh(); | |
f85afd4e | 2466 | } |
2d66e025 MB |
2467 | |
2468 | SetEditControlValue(); | |
2469 | return ok; | |
2470 | } | |
2471 | else | |
2472 | { | |
2473 | return FALSE; | |
f85afd4e MB |
2474 | } |
2475 | } | |
2476 | ||
2d66e025 MB |
2477 | |
2478 | bool wxGrid::AppendCols( int numCols, bool WXUNUSED(updateLabels) ) | |
f85afd4e | 2479 | { |
2d66e025 MB |
2480 | // TODO: something with updateLabels flag |
2481 | ||
2482 | if ( !m_created ) | |
f85afd4e | 2483 | { |
bd3c6758 | 2484 | wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); |
2d66e025 MB |
2485 | return FALSE; |
2486 | } | |
f85afd4e | 2487 | |
2d66e025 MB |
2488 | if ( m_table && m_table->AppendCols( numCols ) ) |
2489 | { | |
2490 | // the table will have sent the results of the append col | |
2491 | // operation to this view object as a grid table message | |
2492 | // | |
2493 | if ( m_currentCellCoords == wxGridNoCellCoords ) | |
f85afd4e | 2494 | { |
2d66e025 MB |
2495 | // if we have just inserted cols into an empty grid the current |
2496 | // cell will be undefined... | |
2497 | // | |
2498 | SetCurrentCell( 0, 0 ); | |
f85afd4e | 2499 | } |
8f177c8e | 2500 | |
2d66e025 MB |
2501 | ClearSelection(); |
2502 | if ( !GetBatchCount() ) Refresh(); | |
2503 | return TRUE; | |
f85afd4e | 2504 | } |
2d66e025 | 2505 | else |
f85afd4e | 2506 | { |
2d66e025 | 2507 | return FALSE; |
f85afd4e | 2508 | } |
f85afd4e MB |
2509 | } |
2510 | ||
2511 | ||
2d66e025 | 2512 | bool wxGrid::DeleteCols( int pos, int numCols, bool WXUNUSED(updateLabels) ) |
f85afd4e | 2513 | { |
2d66e025 | 2514 | // TODO: something with updateLabels flag |
8f177c8e | 2515 | |
2d66e025 | 2516 | if ( !m_created ) |
f85afd4e | 2517 | { |
bd3c6758 | 2518 | wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); |
2d66e025 | 2519 | return FALSE; |
f85afd4e MB |
2520 | } |
2521 | ||
2d66e025 MB |
2522 | if ( m_table && m_table->DeleteCols( pos, numCols ) ) |
2523 | { | |
2524 | // the table will have sent the results of the delete col | |
2525 | // operation to this view object as a grid table message | |
2526 | // | |
2527 | if ( m_numCols > 0 ) | |
2528 | SetEditControlValue(); | |
2529 | else | |
2530 | HideCellEditControl(); | |
8f177c8e | 2531 | |
2d66e025 MB |
2532 | ClearSelection(); |
2533 | if ( !GetBatchCount() ) Refresh(); | |
2534 | return TRUE; | |
2535 | } | |
2536 | else | |
f85afd4e | 2537 | { |
2d66e025 | 2538 | return FALSE; |
f85afd4e | 2539 | } |
f85afd4e MB |
2540 | } |
2541 | ||
2542 | ||
2d66e025 MB |
2543 | |
2544 | // | |
2545 | // ----- event handlers | |
f85afd4e | 2546 | // |
8f177c8e | 2547 | |
2d66e025 MB |
2548 | // Generate a grid event based on a mouse event and |
2549 | // return the result of ProcessEvent() | |
2550 | // | |
2551 | bool wxGrid::SendEvent( const wxEventType type, | |
2552 | int row, int col, | |
2553 | wxMouseEvent& mouseEv ) | |
2554 | { | |
2555 | if ( type == EVT_GRID_ROW_SIZE || | |
2556 | type == EVT_GRID_COL_SIZE ) | |
f85afd4e | 2557 | { |
2d66e025 MB |
2558 | int rowOrCol = (row == -1 ? col : row); |
2559 | ||
2560 | wxGridSizeEvent gridEvt( GetId(), | |
2561 | type, | |
2562 | this, | |
2563 | rowOrCol, | |
2564 | mouseEv.GetX(), mouseEv.GetY(), | |
2565 | mouseEv.ControlDown(), | |
2566 | mouseEv.ShiftDown(), | |
2567 | mouseEv.AltDown(), | |
2568 | mouseEv.MetaDown() ); | |
2569 | ||
2570 | return GetEventHandler()->ProcessEvent(gridEvt); | |
f85afd4e | 2571 | } |
2d66e025 MB |
2572 | else if ( type == EVT_GRID_RANGE_SELECT ) |
2573 | { | |
2574 | wxGridRangeSelectEvent gridEvt( GetId(), | |
2575 | type, | |
2576 | this, | |
2577 | m_selectedTopLeft, | |
2578 | m_selectedBottomRight, | |
2579 | mouseEv.ControlDown(), | |
2580 | mouseEv.ShiftDown(), | |
2581 | mouseEv.AltDown(), | |
2582 | mouseEv.MetaDown() ); | |
f85afd4e | 2583 | |
2d66e025 MB |
2584 | return GetEventHandler()->ProcessEvent(gridEvt); |
2585 | } | |
2586 | else | |
2587 | { | |
2588 | wxGridEvent gridEvt( GetId(), | |
2589 | type, | |
2590 | this, | |
2591 | row, col, | |
2592 | mouseEv.GetX(), mouseEv.GetY(), | |
2593 | mouseEv.ControlDown(), | |
2594 | mouseEv.ShiftDown(), | |
2595 | mouseEv.AltDown(), | |
2596 | mouseEv.MetaDown() ); | |
8f177c8e | 2597 | |
2d66e025 MB |
2598 | return GetEventHandler()->ProcessEvent(gridEvt); |
2599 | } | |
f85afd4e MB |
2600 | } |
2601 | ||
2602 | ||
2d66e025 MB |
2603 | // Generate a grid event of specified type and return the result |
2604 | // of ProcessEvent(). | |
f85afd4e | 2605 | // |
2d66e025 MB |
2606 | bool wxGrid::SendEvent( const wxEventType type, |
2607 | int row, int col ) | |
f85afd4e | 2608 | { |
2d66e025 MB |
2609 | if ( type == EVT_GRID_ROW_SIZE || |
2610 | type == EVT_GRID_COL_SIZE ) | |
f85afd4e | 2611 | { |
2d66e025 | 2612 | int rowOrCol = (row == -1 ? col : row); |
f85afd4e | 2613 | |
2d66e025 MB |
2614 | wxGridSizeEvent gridEvt( GetId(), |
2615 | type, | |
2616 | this, | |
2617 | rowOrCol ); | |
2618 | ||
2619 | return GetEventHandler()->ProcessEvent(gridEvt); | |
2620 | } | |
2621 | else | |
2622 | { | |
2623 | wxGridEvent gridEvt( GetId(), | |
2624 | type, | |
2625 | this, | |
2626 | row, col ); | |
8f177c8e | 2627 | |
2d66e025 MB |
2628 | return GetEventHandler()->ProcessEvent(gridEvt); |
2629 | } | |
f85afd4e MB |
2630 | } |
2631 | ||
2632 | ||
2d66e025 | 2633 | void wxGrid::OnPaint( wxPaintEvent& WXUNUSED(event) ) |
f85afd4e | 2634 | { |
2d66e025 | 2635 | wxPaintDC dc( this ); |
f85afd4e | 2636 | |
2d66e025 MB |
2637 | if ( m_currentCellCoords == wxGridNoCellCoords && |
2638 | m_numRows && m_numCols ) | |
f85afd4e | 2639 | { |
2d66e025 MB |
2640 | m_currentCellCoords.Set(0, 0); |
2641 | SetEditControlValue(); | |
2642 | ShowCellEditControl(); | |
f85afd4e | 2643 | } |
4634a5d6 MB |
2644 | |
2645 | m_displayed = TRUE; | |
8f177c8e | 2646 | } |
f85afd4e MB |
2647 | |
2648 | ||
18f9565d MB |
2649 | // This is just here to make sure that CalcDimensions gets called when |
2650 | // the grid view is resized... then the size event is skipped to allow | |
2651 | // the box sizers to handle everything | |
2652 | // | |
2d66e025 | 2653 | void wxGrid::OnSize( wxSizeEvent& event ) |
f85afd4e | 2654 | { |
7807d81c | 2655 | CalcWindowSizes(); |
2d66e025 | 2656 | CalcDimensions(); |
f85afd4e MB |
2657 | } |
2658 | ||
f85afd4e | 2659 | |
2d66e025 | 2660 | void wxGrid::OnKeyDown( wxKeyEvent& event ) |
f85afd4e | 2661 | { |
2d66e025 | 2662 | if ( m_inOnKeyDown ) |
f85afd4e | 2663 | { |
2d66e025 MB |
2664 | // shouldn't be here - we are going round in circles... |
2665 | // | |
bd3c6758 | 2666 | wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while alread active") ); |
f85afd4e MB |
2667 | } |
2668 | ||
2d66e025 | 2669 | m_inOnKeyDown = TRUE; |
f85afd4e | 2670 | |
2d66e025 MB |
2671 | // propagate the event up and see if it gets processed |
2672 | // | |
2673 | wxWindow *parent = GetParent(); | |
2674 | wxKeyEvent keyEvt( event ); | |
2675 | keyEvt.SetEventObject( parent ); | |
2676 | ||
2677 | if ( !parent->GetEventHandler()->ProcessEvent( keyEvt ) ) | |
f85afd4e | 2678 | { |
2d66e025 MB |
2679 | // try local handlers |
2680 | // | |
2681 | switch ( event.KeyCode() ) | |
2682 | { | |
2683 | case WXK_UP: | |
2684 | if ( event.ControlDown() ) | |
2685 | { | |
2686 | MoveCursorUpBlock(); | |
2687 | } | |
2688 | else | |
2689 | { | |
2690 | MoveCursorUp(); | |
2691 | } | |
2692 | break; | |
f85afd4e | 2693 | |
2d66e025 MB |
2694 | case WXK_DOWN: |
2695 | if ( event.ControlDown() ) | |
2696 | { | |
2697 | MoveCursorDownBlock(); | |
2698 | } | |
2699 | else | |
2700 | { | |
2701 | MoveCursorDown(); | |
2702 | } | |
2703 | break; | |
8f177c8e | 2704 | |
2d66e025 MB |
2705 | case WXK_LEFT: |
2706 | if ( event.ControlDown() ) | |
2707 | { | |
2708 | MoveCursorLeftBlock(); | |
2709 | } | |
2710 | else | |
2711 | { | |
2712 | MoveCursorLeft(); | |
2713 | } | |
2714 | break; | |
2715 | ||
2716 | case WXK_RIGHT: | |
2717 | if ( event.ControlDown() ) | |
2718 | { | |
2719 | MoveCursorRightBlock(); | |
2720 | } | |
2721 | else | |
2722 | { | |
2723 | MoveCursorRight(); | |
2724 | } | |
2725 | break; | |
b99be8fb | 2726 | |
f603012f MB |
2727 | case WXK_SPACE: |
2728 | if ( !IsEditable() ) | |
2729 | { | |
2730 | MoveCursorRight(); | |
2731 | } | |
2732 | else | |
2733 | { | |
8a9a9d58 | 2734 | event.Skip(); |
f603012f | 2735 | } |
8febdd39 | 2736 | break; |
2d66e025 MB |
2737 | |
2738 | case WXK_RETURN: | |
58dd5b3b MB |
2739 | if ( event.ControlDown() ) |
2740 | { | |
2741 | event.Skip(); // to let the edit control have the return | |
2742 | } | |
2743 | else | |
2744 | { | |
2745 | MoveCursorDown(); | |
2746 | } | |
2d66e025 MB |
2747 | break; |
2748 | ||
2749 | case WXK_HOME: | |
2750 | if ( event.ControlDown() ) | |
2751 | { | |
2752 | MakeCellVisible( 0, 0 ); | |
2753 | SetCurrentCell( 0, 0 ); | |
2754 | } | |
2755 | else | |
2756 | { | |
2757 | event.Skip(); | |
2758 | } | |
2759 | break; | |
2760 | ||
2761 | case WXK_END: | |
2762 | if ( event.ControlDown() ) | |
2763 | { | |
2764 | MakeCellVisible( m_numRows-1, m_numCols-1 ); | |
2765 | SetCurrentCell( m_numRows-1, m_numCols-1 ); | |
2766 | } | |
2767 | else | |
2768 | { | |
2769 | event.Skip(); | |
2770 | } | |
2771 | break; | |
2772 | ||
2773 | case WXK_PRIOR: | |
2774 | MovePageUp(); | |
2775 | break; | |
2776 | ||
2777 | case WXK_NEXT: | |
2778 | MovePageDown(); | |
2779 | break; | |
2780 | ||
2781 | default: | |
2782 | // now try the cell edit control | |
2783 | // | |
2784 | if ( IsCellEditControlEnabled() ) | |
2785 | { | |
2786 | event.SetEventObject( m_cellEditCtrl ); | |
2787 | m_cellEditCtrl->GetEventHandler()->ProcessEvent( event ); | |
2788 | } | |
2789 | break; | |
2790 | } | |
f85afd4e MB |
2791 | } |
2792 | ||
2d66e025 | 2793 | m_inOnKeyDown = FALSE; |
f85afd4e MB |
2794 | } |
2795 | ||
2d66e025 MB |
2796 | |
2797 | void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) | |
66242c80 | 2798 | { |
2d66e025 | 2799 | if ( SendEvent( EVT_GRID_SELECT_CELL, coords.GetRow(), coords.GetCol() ) ) |
66242c80 | 2800 | { |
2d66e025 MB |
2801 | // the event has been intercepted - do nothing |
2802 | return; | |
2803 | } | |
66242c80 | 2804 | |
4634a5d6 MB |
2805 | if ( m_displayed && |
2806 | m_currentCellCoords != wxGridNoCellCoords ) | |
2d66e025 | 2807 | { |
2d66e025 MB |
2808 | HideCellEditControl(); |
2809 | SaveEditControlValue(); | |
66242c80 | 2810 | } |
8f177c8e | 2811 | |
2d66e025 MB |
2812 | m_currentCellCoords = coords; |
2813 | ||
2814 | SetEditControlValue(); | |
2d66e025 | 2815 | |
4634a5d6 | 2816 | if ( m_displayed ) |
2d66e025 | 2817 | { |
4634a5d6 MB |
2818 | ShowCellEditControl(); |
2819 | ||
2820 | if ( IsSelection() ) | |
2821 | { | |
2822 | wxRect r( SelectionToDeviceRect() ); | |
2823 | ClearSelection(); | |
2824 | if ( !GetBatchCount() ) m_gridWin->Refresh( FALSE, &r ); | |
2825 | } | |
2d66e025 | 2826 | } |
66242c80 MB |
2827 | } |
2828 | ||
2d66e025 MB |
2829 | |
2830 | // | |
2831 | // ------ functions to get/send data (see also public functions) | |
2832 | // | |
2833 | ||
2834 | bool wxGrid::GetModelValues() | |
66242c80 | 2835 | { |
2d66e025 | 2836 | if ( m_table ) |
66242c80 | 2837 | { |
2d66e025 | 2838 | // all we need to do is repaint the grid |
66242c80 | 2839 | // |
2d66e025 | 2840 | m_gridWin->Refresh(); |
66242c80 MB |
2841 | return TRUE; |
2842 | } | |
8f177c8e | 2843 | |
66242c80 MB |
2844 | return FALSE; |
2845 | } | |
2846 | ||
2d66e025 MB |
2847 | |
2848 | bool wxGrid::SetModelValues() | |
f85afd4e | 2849 | { |
2d66e025 | 2850 | int row, col; |
8f177c8e | 2851 | |
2d66e025 MB |
2852 | if ( m_table ) |
2853 | { | |
2854 | for ( row = 0; row < m_numRows; row++ ) | |
f85afd4e | 2855 | { |
2d66e025 | 2856 | for ( col = 0; col < m_numCols; col++ ) |
f85afd4e | 2857 | { |
2d66e025 | 2858 | m_table->SetValue( row, col, GetCellValue(row, col) ); |
f85afd4e MB |
2859 | } |
2860 | } | |
8f177c8e | 2861 | |
f85afd4e MB |
2862 | return TRUE; |
2863 | } | |
2864 | ||
2865 | return FALSE; | |
2866 | } | |
2867 | ||
2d66e025 MB |
2868 | |
2869 | ||
2870 | // Note - this function only draws cells that are in the list of | |
2871 | // exposed cells (usually set from the update region by | |
2872 | // CalcExposedCells) | |
2873 | // | |
2874 | void wxGrid::DrawGridCellArea( wxDC& dc ) | |
f85afd4e | 2875 | { |
2d66e025 | 2876 | if ( !m_numRows || !m_numCols ) return; |
60ff3b99 | 2877 | |
2d66e025 MB |
2878 | size_t i; |
2879 | size_t numCells = m_cellsExposed.GetCount(); | |
60ff3b99 | 2880 | |
2d66e025 | 2881 | for ( i = 0; i < numCells; i++ ) |
f85afd4e | 2882 | { |
2d66e025 MB |
2883 | DrawCell( dc, m_cellsExposed[i] ); |
2884 | } | |
2885 | } | |
8f177c8e | 2886 | |
8f177c8e | 2887 | |
2d66e025 MB |
2888 | void wxGrid::DrawCell( wxDC& dc, const wxGridCellCoords& coords ) |
2889 | { | |
2890 | if ( m_colWidths[coords.GetCol()] <=0 || | |
2891 | m_rowHeights[coords.GetRow()] <= 0 ) return; | |
60ff3b99 | 2892 | |
9496deb5 | 2893 | #if !WXGRID_DRAW_LINES |
2d66e025 MB |
2894 | if ( m_gridLinesEnabled ) |
2895 | DrawCellBorder( dc, coords ); | |
796df70a | 2896 | #endif |
f85afd4e | 2897 | |
2d66e025 | 2898 | DrawCellBackground( dc, coords ); |
f85afd4e | 2899 | |
2d66e025 MB |
2900 | // TODO: separate functions here for different kinds of cells ? |
2901 | // e.g. text, image | |
2902 | // | |
2903 | DrawCellValue( dc, coords ); | |
2904 | } | |
f85afd4e | 2905 | |
2d66e025 MB |
2906 | |
2907 | void wxGrid::DrawCellBorder( wxDC& dc, const wxGridCellCoords& coords ) | |
2908 | { | |
2909 | if ( m_colWidths[coords.GetCol()] <=0 || | |
2910 | m_rowHeights[coords.GetRow()] <= 0 ) return; | |
60ff3b99 | 2911 | |
2d66e025 MB |
2912 | dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) ); |
2913 | int row = coords.GetRow(); | |
2914 | int col = coords.GetCol(); | |
60ff3b99 | 2915 | |
2d66e025 MB |
2916 | // right hand border |
2917 | // | |
bd3c6758 MB |
2918 | dc.DrawLine( m_colRights[col], m_rowBottoms[row] - m_rowHeights[row], |
2919 | m_colRights[col], m_rowBottoms[row] ); | |
2d66e025 MB |
2920 | |
2921 | // bottom border | |
2922 | // | |
bd3c6758 MB |
2923 | dc.DrawLine( m_colRights[col] - m_colWidths[col], m_rowBottoms[row], |
2924 | m_colRights[col], m_rowBottoms[row] ); | |
f85afd4e MB |
2925 | } |
2926 | ||
2d66e025 MB |
2927 | |
2928 | void wxGrid::DrawCellBackground( wxDC& dc, const wxGridCellCoords& coords ) | |
f85afd4e | 2929 | { |
2d66e025 MB |
2930 | if ( m_colWidths[coords.GetCol()] <=0 || |
2931 | m_rowHeights[coords.GetRow()] <= 0 ) return; | |
60ff3b99 | 2932 | |
2d66e025 MB |
2933 | int row = coords.GetRow(); |
2934 | int col = coords.GetCol(); | |
8f177c8e | 2935 | |
2d66e025 | 2936 | dc.SetBackgroundMode( wxSOLID ); |
f85afd4e | 2937 | |
2d66e025 MB |
2938 | if ( IsInSelection( coords ) ) |
2939 | { | |
2940 | // TODO: improve this | |
2941 | // | |
2942 | dc.SetBrush( *wxBLACK_BRUSH ); | |
f85afd4e | 2943 | } |
2d66e025 | 2944 | else |
f85afd4e | 2945 | { |
2d66e025 | 2946 | dc.SetBrush( wxBrush(GetCellBackgroundColour(row, col), wxSOLID) ); |
f85afd4e MB |
2947 | } |
2948 | ||
2d66e025 | 2949 | dc.SetPen( *wxTRANSPARENT_PEN ); |
8f177c8e | 2950 | |
2d66e025 MB |
2951 | dc.DrawRectangle( m_colRights[col] - m_colWidths[col] + 1, |
2952 | m_rowBottoms[row] - m_rowHeights[row] + 1, | |
2953 | m_colWidths[col]-1, | |
2954 | m_rowHeights[row]-1 ); | |
f85afd4e MB |
2955 | } |
2956 | ||
2957 | ||
2d66e025 | 2958 | void wxGrid::DrawCellValue( wxDC& dc, const wxGridCellCoords& coords ) |
f85afd4e | 2959 | { |
2d66e025 MB |
2960 | if ( m_colWidths[coords.GetCol()] <=0 || |
2961 | m_rowHeights[coords.GetRow()] <= 0 ) return; | |
60ff3b99 | 2962 | |
2d66e025 MB |
2963 | int row = coords.GetRow(); |
2964 | int col = coords.GetCol(); | |
f85afd4e | 2965 | |
2d66e025 | 2966 | dc.SetBackgroundMode( wxTRANSPARENT ); |
8f177c8e | 2967 | |
2d66e025 MB |
2968 | if ( IsInSelection( row, col ) ) |
2969 | { | |
2970 | // TODO: improve this | |
2971 | // | |
2972 | dc.SetTextBackground( wxColour(0, 0, 0) ); | |
2973 | dc.SetTextForeground( wxColour(255, 255, 255) ); | |
2974 | } | |
2975 | else | |
f85afd4e | 2976 | { |
2d66e025 MB |
2977 | dc.SetTextBackground( GetCellBackgroundColour(row, col) ); |
2978 | dc.SetTextForeground( GetCellTextColour(row, col) ); | |
2979 | } | |
2980 | dc.SetFont( GetCellFont(row, col) ); | |
f85afd4e | 2981 | |
2d66e025 MB |
2982 | int hAlign, vAlign; |
2983 | GetCellAlignment( row, col, &hAlign, &vAlign ); | |
8f177c8e | 2984 | |
2d66e025 MB |
2985 | wxRect rect; |
2986 | rect.SetX( m_colRights[col] - m_colWidths[col] + 2 ); | |
2987 | rect.SetY( m_rowBottoms[row] - m_rowHeights[row] + 2 ); | |
2988 | rect.SetWidth( m_colWidths[col] - 4 ); | |
2989 | rect.SetHeight( m_rowHeights[row] - 4 ); | |
60ff3b99 | 2990 | |
2d66e025 | 2991 | DrawTextRectangle( dc, GetCellValue( row, col ), rect, hAlign, vAlign ); |
f85afd4e MB |
2992 | } |
2993 | ||
2994 | ||
2d66e025 MB |
2995 | |
2996 | // TODO: remove this ??? | |
2997 | // This is used to redraw all grid lines e.g. when the grid line colour | |
2998 | // has been changed | |
2999 | // | |
796df70a | 3000 | void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & reg ) |
f85afd4e | 3001 | { |
60ff3b99 VZ |
3002 | if ( !m_gridLinesEnabled || |
3003 | !m_numRows || | |
2d66e025 | 3004 | !m_numCols ) return; |
f85afd4e | 3005 | |
2d66e025 | 3006 | int top, bottom, left, right; |
796df70a SN |
3007 | |
3008 | if (reg.IsEmpty()){ | |
3009 | int cw, ch; | |
3010 | m_gridWin->GetClientSize(&cw, &ch); | |
3011 | ||
3012 | // virtual coords of visible area | |
3013 | // | |
3014 | CalcUnscrolledPosition( 0, 0, &left, &top ); | |
3015 | CalcUnscrolledPosition( cw, ch, &right, &bottom ); | |
3016 | } | |
3017 | else{ | |
3018 | wxCoord x, y, w, h; | |
3019 | reg.GetBox(x, y, w, h); | |
3020 | CalcUnscrolledPosition( x, y, &left, &top ); | |
3021 | CalcUnscrolledPosition( x + w, y + h, &right, &bottom ); | |
3022 | } | |
f85afd4e | 3023 | |
9496deb5 MB |
3024 | // avoid drawing grid lines past the last row and col |
3025 | // | |
3026 | right = wxMin( right, m_colRights[m_numCols-1] ); | |
3027 | bottom = wxMin( bottom, m_rowBottoms[m_numRows-1] ); | |
3028 | ||
2d66e025 | 3029 | dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) ); |
f85afd4e | 3030 | |
2d66e025 | 3031 | // horizontal grid lines |
f85afd4e | 3032 | // |
60ff3b99 | 3033 | int i; |
9496deb5 | 3034 | for ( i = 0; i < m_numRows; i++ ) |
f85afd4e | 3035 | { |
bd3c6758 | 3036 | if ( m_rowBottoms[i] > bottom ) |
2d66e025 MB |
3037 | { |
3038 | break; | |
3039 | } | |
bd3c6758 | 3040 | else if ( m_rowBottoms[i] >= top ) |
2d66e025 | 3041 | { |
bd3c6758 | 3042 | dc.DrawLine( left, m_rowBottoms[i], right, m_rowBottoms[i] ); |
2d66e025 | 3043 | } |
f85afd4e MB |
3044 | } |
3045 | ||
f85afd4e | 3046 | |
2d66e025 MB |
3047 | // vertical grid lines |
3048 | // | |
9496deb5 | 3049 | for ( i = 0; i < m_numCols; i++ ) |
f85afd4e | 3050 | { |
bd3c6758 | 3051 | if ( m_colRights[i] > right ) |
2d66e025 MB |
3052 | { |
3053 | break; | |
3054 | } | |
bd3c6758 | 3055 | else if ( m_colRights[i] >= left ) |
2d66e025 | 3056 | { |
bd3c6758 | 3057 | dc.DrawLine( m_colRights[i], top, m_colRights[i], bottom ); |
2d66e025 MB |
3058 | } |
3059 | } | |
3060 | } | |
f85afd4e | 3061 | |
8f177c8e | 3062 | |
2d66e025 MB |
3063 | void wxGrid::DrawRowLabels( wxDC& dc ) |
3064 | { | |
3065 | if ( !m_numRows || !m_numCols ) return; | |
60ff3b99 | 3066 | |
2d66e025 MB |
3067 | size_t i; |
3068 | size_t numLabels = m_rowLabelsExposed.GetCount(); | |
60ff3b99 | 3069 | |
2d66e025 MB |
3070 | for ( i = 0; i < numLabels; i++ ) |
3071 | { | |
3072 | DrawRowLabel( dc, m_rowLabelsExposed[i] ); | |
60ff3b99 | 3073 | } |
f85afd4e MB |
3074 | } |
3075 | ||
3076 | ||
2d66e025 | 3077 | void wxGrid::DrawRowLabel( wxDC& dc, int row ) |
f85afd4e | 3078 | { |
2d66e025 | 3079 | if ( m_rowHeights[row] <= 0 ) return; |
60ff3b99 | 3080 | |
b0d6ff2f | 3081 | int rowTop = m_rowBottoms[row] - m_rowHeights[row]; |
b99be8fb | 3082 | |
2d66e025 | 3083 | dc.SetPen( *wxBLACK_PEN ); |
b0d6ff2f MB |
3084 | dc.DrawLine( m_rowLabelWidth-1, rowTop, |
3085 | m_rowLabelWidth-1, m_rowBottoms[row]-1 ); | |
b99be8fb | 3086 | |
b0d6ff2f MB |
3087 | dc.DrawLine( 0, m_rowBottoms[row]-1, |
3088 | m_rowLabelWidth-1, m_rowBottoms[row]-1 ); | |
b99be8fb | 3089 | |
2d66e025 | 3090 | dc.SetPen( *wxWHITE_PEN ); |
b0d6ff2f MB |
3091 | dc.DrawLine( 0, rowTop, 0, m_rowBottoms[row]-1 ); |
3092 | dc.DrawLine( 0, rowTop, m_rowLabelWidth-1, rowTop ); | |
60ff3b99 | 3093 | |
f85afd4e | 3094 | dc.SetBackgroundMode( wxTRANSPARENT ); |
f85afd4e MB |
3095 | dc.SetTextForeground( GetLabelTextColour() ); |
3096 | dc.SetFont( GetLabelFont() ); | |
8f177c8e | 3097 | |
f85afd4e | 3098 | int hAlign, vAlign; |
2d66e025 | 3099 | GetRowLabelAlignment( &hAlign, &vAlign ); |
60ff3b99 | 3100 | |
2d66e025 MB |
3101 | wxRect rect; |
3102 | rect.SetX( 2 ); | |
3103 | rect.SetY( m_rowBottoms[row] - m_rowHeights[row] + 2 ); | |
3104 | rect.SetWidth( m_rowLabelWidth - 4 ); | |
3105 | rect.SetHeight( m_rowHeights[row] - 4 ); | |
60ff3b99 | 3106 | DrawTextRectangle( dc, GetRowLabelValue( row ), rect, hAlign, vAlign ); |
f85afd4e MB |
3107 | } |
3108 | ||
3109 | ||
2d66e025 | 3110 | void wxGrid::DrawColLabels( wxDC& dc ) |
f85afd4e | 3111 | { |
2d66e025 | 3112 | if ( !m_numRows || !m_numCols ) return; |
60ff3b99 | 3113 | |
2d66e025 MB |
3114 | size_t i; |
3115 | size_t numLabels = m_colLabelsExposed.GetCount(); | |
60ff3b99 | 3116 | |
2d66e025 | 3117 | for ( i = 0; i < numLabels; i++ ) |
f85afd4e | 3118 | { |
2d66e025 | 3119 | DrawColLabel( dc, m_colLabelsExposed[i] ); |
60ff3b99 | 3120 | } |
f85afd4e MB |
3121 | } |
3122 | ||
3123 | ||
2d66e025 | 3124 | void wxGrid::DrawColLabel( wxDC& dc, int col ) |
f85afd4e | 3125 | { |
2d66e025 | 3126 | if ( m_colWidths[col] <= 0 ) return; |
60ff3b99 | 3127 | |
b0d6ff2f | 3128 | int colLeft = m_colRights[col] - m_colWidths[col]; |
b99be8fb | 3129 | |
2d66e025 | 3130 | dc.SetPen( *wxBLACK_PEN ); |
b0d6ff2f MB |
3131 | dc.DrawLine( m_colRights[col]-1, 0, |
3132 | m_colRights[col]-1, m_colLabelHeight-1 ); | |
b99be8fb | 3133 | |
b0d6ff2f MB |
3134 | dc.DrawLine( colLeft, m_colLabelHeight-1, |
3135 | m_colRights[col]-1, m_colLabelHeight-1 ); | |
b99be8fb | 3136 | |
f85afd4e | 3137 | dc.SetPen( *wxWHITE_PEN ); |
b0d6ff2f MB |
3138 | dc.DrawLine( colLeft, 0, colLeft, m_colLabelHeight-1 ); |
3139 | dc.DrawLine( colLeft, 0, m_colRights[col]-1, 0 ); | |
f85afd4e | 3140 | |
b0d6ff2f MB |
3141 | dc.SetBackgroundMode( wxTRANSPARENT ); |
3142 | dc.SetTextForeground( GetLabelTextColour() ); | |
3143 | dc.SetFont( GetLabelFont() ); | |
8f177c8e | 3144 | |
f85afd4e | 3145 | dc.SetBackgroundMode( wxTRANSPARENT ); |
f85afd4e MB |
3146 | dc.SetTextForeground( GetLabelTextColour() ); |
3147 | dc.SetFont( GetLabelFont() ); | |
8f177c8e | 3148 | |
f85afd4e | 3149 | int hAlign, vAlign; |
2d66e025 | 3150 | GetColLabelAlignment( &hAlign, &vAlign ); |
60ff3b99 | 3151 | |
2d66e025 MB |
3152 | wxRect rect; |
3153 | rect.SetX( m_colRights[col] - m_colWidths[col] + 2 ); | |
3154 | rect.SetY( 2 ); | |
3155 | rect.SetWidth( m_colWidths[col] - 4 ); | |
3156 | rect.SetHeight( m_colLabelHeight - 4 ); | |
60ff3b99 | 3157 | DrawTextRectangle( dc, GetColLabelValue( col ), rect, hAlign, vAlign ); |
f85afd4e MB |
3158 | } |
3159 | ||
3160 | ||
2d66e025 MB |
3161 | void wxGrid::DrawTextRectangle( wxDC& dc, |
3162 | const wxString& value, | |
3163 | const wxRect& rect, | |
3164 | int horizAlign, | |
3165 | int vertAlign ) | |
f85afd4e | 3166 | { |
2d66e025 MB |
3167 | long textWidth, textHeight; |
3168 | long lineWidth, lineHeight; | |
3169 | wxArrayString lines; | |
f85afd4e | 3170 | |
2d66e025 MB |
3171 | dc.SetClippingRegion( rect ); |
3172 | StringToLines( value, lines ); | |
3173 | if ( lines.GetCount() ) | |
3174 | { | |
3175 | GetTextBoxSize( dc, lines, &textWidth, &textHeight ); | |
3176 | dc.GetTextExtent( lines[0], &lineWidth, &lineHeight ); | |
f85afd4e | 3177 | |
2d66e025 MB |
3178 | float x, y; |
3179 | switch ( horizAlign ) | |
3180 | { | |
3181 | case wxRIGHT: | |
3182 | x = rect.x + (rect.width - textWidth - 1); | |
3183 | break; | |
f85afd4e | 3184 | |
2d66e025 MB |
3185 | case wxCENTRE: |
3186 | x = rect.x + ((rect.width - textWidth)/2); | |
3187 | break; | |
f85afd4e | 3188 | |
2d66e025 MB |
3189 | case wxLEFT: |
3190 | default: | |
3191 | x = rect.x + 1; | |
3192 | break; | |
3193 | } | |
f85afd4e | 3194 | |
2d66e025 MB |
3195 | switch ( vertAlign ) |
3196 | { | |
3197 | case wxBOTTOM: | |
3198 | y = rect.y + (rect.height - textHeight - 1); | |
3199 | break; | |
f85afd4e MB |
3200 | |
3201 | case wxCENTRE: | |
8f177c8e | 3202 | y = rect.y + ((rect.height - textHeight)/2); |
f85afd4e MB |
3203 | break; |
3204 | ||
3205 | case wxTOP: | |
3206 | default: | |
8f177c8e | 3207 | y = rect.y + 1; |
f85afd4e MB |
3208 | break; |
3209 | } | |
3210 | ||
b540eb2b | 3211 | for ( size_t i = 0; i < lines.GetCount(); i++ ) |
f85afd4e MB |
3212 | { |
3213 | dc.DrawText( lines[i], (long)x, (long)y ); | |
3214 | y += lineHeight; | |
3215 | } | |
3216 | } | |
8f177c8e | 3217 | |
f85afd4e | 3218 | dc.DestroyClippingRegion(); |
f85afd4e MB |
3219 | } |
3220 | ||
3221 | ||
3222 | // Split multi line text up into an array of strings. Any existing | |
3223 | // contents of the string array are preserved. | |
3224 | // | |
3225 | void wxGrid::StringToLines( const wxString& value, wxArrayString& lines ) | |
3226 | { | |
f85afd4e MB |
3227 | int startPos = 0; |
3228 | int pos; | |
2433bb2e MB |
3229 | wxString eol = wxTextFile::GetEOL( wxTextFileType_Unix ); |
3230 | wxString tVal = wxTextFile::Translate( value, wxTextFileType_Unix ); | |
3231 | ||
3232 | while ( startPos < (int)tVal.Length() ) | |
f85afd4e | 3233 | { |
2433bb2e | 3234 | pos = tVal.Mid(startPos).Find( eol ); |
f85afd4e MB |
3235 | if ( pos < 0 ) |
3236 | { | |
3237 | break; | |
3238 | } | |
3239 | else if ( pos == 0 ) | |
3240 | { | |
3241 | lines.Add( wxEmptyString ); | |
3242 | } | |
3243 | else | |
3244 | { | |
2433bb2e | 3245 | lines.Add( value.Mid(startPos, pos) ); |
f85afd4e MB |
3246 | } |
3247 | startPos += pos+1; | |
3248 | } | |
b540eb2b | 3249 | if ( startPos < (int)value.Length() ) |
f85afd4e MB |
3250 | { |
3251 | lines.Add( value.Mid( startPos ) ); | |
3252 | } | |
3253 | } | |
3254 | ||
3255 | ||
3256 | void wxGrid::GetTextBoxSize( wxDC& dc, | |
3257 | wxArrayString& lines, | |
3258 | long *width, long *height ) | |
3259 | { | |
3260 | long w = 0; | |
3261 | long h = 0; | |
3262 | long lineW, lineH; | |
3263 | ||
b540eb2b | 3264 | size_t i; |
f85afd4e MB |
3265 | for ( i = 0; i < lines.GetCount(); i++ ) |
3266 | { | |
3267 | dc.GetTextExtent( lines[i], &lineW, &lineH ); | |
3268 | w = wxMax( w, lineW ); | |
3269 | h += lineH; | |
3270 | } | |
3271 | ||
3272 | *width = w; | |
3273 | *height = h; | |
3274 | } | |
3275 | ||
3276 | ||
3277 | // | |
2d66e025 | 3278 | // ------ Edit control functions |
f85afd4e MB |
3279 | // |
3280 | ||
2d66e025 MB |
3281 | |
3282 | void wxGrid::EnableEditing( bool edit ) | |
f85afd4e | 3283 | { |
2d66e025 MB |
3284 | // TODO: improve this ? |
3285 | // | |
3286 | if ( edit != m_editable ) | |
f85afd4e | 3287 | { |
2d66e025 | 3288 | m_editable = edit; |
1f1ce288 MB |
3289 | |
3290 | // TODO: extend this for other edit control types | |
3291 | // | |
3292 | if ( m_editCtrlType == wxGRID_TEXTCTRL ) | |
3293 | { | |
3294 | ((wxTextCtrl *)m_cellEditCtrl)->SetEditable( m_editable ); | |
3295 | } | |
f85afd4e | 3296 | } |
f85afd4e MB |
3297 | } |
3298 | ||
3299 | ||
1f1ce288 | 3300 | #if 0 // disabled for the moment - the cell control is always active |
2d66e025 | 3301 | void wxGrid::EnableCellEditControl( bool enable ) |
f85afd4e | 3302 | { |
2d66e025 MB |
3303 | if ( m_cellEditCtrl && |
3304 | enable != m_cellEditCtrlEnabled ) | |
f85afd4e | 3305 | { |
2d66e025 | 3306 | m_cellEditCtrlEnabled = enable; |
60ff3b99 | 3307 | |
2d66e025 | 3308 | if ( m_cellEditCtrlEnabled ) |
f85afd4e | 3309 | { |
2d66e025 MB |
3310 | SetEditControlValue(); |
3311 | ShowCellEditControl(); | |
2d66e025 MB |
3312 | } |
3313 | else | |
3314 | { | |
2d66e025 MB |
3315 | HideCellEditControl(); |
3316 | SaveEditControlValue(); | |
f85afd4e | 3317 | } |
f85afd4e | 3318 | } |
f85afd4e | 3319 | } |
1f1ce288 | 3320 | #endif |
f85afd4e MB |
3321 | |
3322 | ||
2d66e025 | 3323 | void wxGrid::ShowCellEditControl() |
f85afd4e | 3324 | { |
2d66e025 MB |
3325 | wxRect rect; |
3326 | ||
3327 | if ( IsCellEditControlEnabled() ) | |
f85afd4e | 3328 | { |
2d66e025 MB |
3329 | if ( !IsVisible( m_currentCellCoords ) ) |
3330 | { | |
3331 | return; | |
3332 | } | |
3333 | else | |
3334 | { | |
3335 | rect = CellToRect( m_currentCellCoords ); | |
3336 | ||
3337 | // convert to scrolled coords | |
3338 | // | |
3339 | int left, top, right, bottom; | |
3340 | CalcScrolledPosition( rect.GetLeft(), rect.GetTop(), &left, &top ); | |
3341 | CalcScrolledPosition( rect.GetRight(), rect.GetBottom(), &right, &bottom ); | |
60ff3b99 | 3342 | |
2d66e025 MB |
3343 | int cw, ch; |
3344 | m_gridWin->GetClientSize( &cw, &ch ); | |
1f1ce288 MB |
3345 | |
3346 | // Make the edit control large enough to allow for internal margins | |
3347 | // TODO: remove this if the text ctrl sizing is improved esp. for unix | |
3348 | // | |
58dd5b3b | 3349 | int extra; |
d2fdd8d2 | 3350 | #if defined(__WXMOTIF__) |
58dd5b3b MB |
3351 | if ( m_currentCellCoords.GetRow() == 0 || |
3352 | m_currentCellCoords.GetCol() == 0 ) | |
3353 | { | |
3354 | extra = 2; | |
3355 | } | |
3356 | else | |
3357 | { | |
3358 | extra = 4; | |
3359 | } | |
1f1ce288 | 3360 | #else |
58dd5b3b MB |
3361 | if ( m_currentCellCoords.GetRow() == 0 || |
3362 | m_currentCellCoords.GetCol() == 0 ) | |
3363 | { | |
3364 | extra = 1; | |
3365 | } | |
3366 | else | |
3367 | { | |
3368 | extra = 2; | |
3369 | } | |
1f1ce288 | 3370 | #endif |
d2fdd8d2 RR |
3371 | |
3372 | #if defined(__WXGTK__) | |
3373 | int top_diff = 0; | |
3374 | int left_diff = 0; | |
3375 | if (left != 0) left_diff++; | |
3376 | if (top != 0) top_diff++; | |
3377 | rect.SetLeft( left + left_diff ); | |
3378 | rect.SetTop( top + top_diff ); | |
3379 | rect.SetRight( rect.GetRight() - left_diff ); | |
3380 | rect.SetBottom( rect.GetBottom() - top_diff ); | |
3381 | #else | |
58dd5b3b MB |
3382 | rect.SetLeft( wxMax(0, left - extra) ); |
3383 | rect.SetTop( wxMax(0, top - extra) ); | |
3384 | rect.SetRight( rect.GetRight() + 2*extra ); | |
3385 | rect.SetBottom( rect.GetBottom() + 2*extra ); | |
d2fdd8d2 | 3386 | #endif |
f0102d2a | 3387 | |
2d66e025 MB |
3388 | m_cellEditCtrl->SetSize( rect ); |
3389 | m_cellEditCtrl->Show( TRUE ); | |
3390 | ||
3391 | switch ( m_editCtrlType ) | |
3392 | { | |
3393 | case wxGRID_TEXTCTRL: | |
3394 | ((wxTextCtrl *) m_cellEditCtrl)->SetInsertionPointEnd(); | |
3395 | break; | |
3396 | ||
3397 | case wxGRID_CHECKBOX: | |
3398 | // TODO: anything ??? | |
3399 | // | |
3400 | break; | |
3401 | ||
3402 | case wxGRID_CHOICE: | |
3403 | // TODO: anything ??? | |
3404 | // | |
3405 | break; | |
3406 | ||
3407 | case wxGRID_COMBOBOX: | |
3408 | // TODO: anything ??? | |
3409 | // | |
3410 | break; | |
3411 | } | |
3412 | ||
3413 | m_cellEditCtrl->SetFocus(); | |
3414 | } | |
f85afd4e MB |
3415 | } |
3416 | } | |
3417 | ||
3418 | ||
2d66e025 | 3419 | void wxGrid::HideCellEditControl() |
f85afd4e | 3420 | { |
2d66e025 | 3421 | if ( IsCellEditControlEnabled() ) |
f85afd4e | 3422 | { |
2d66e025 | 3423 | m_cellEditCtrl->Show( FALSE ); |
f85afd4e | 3424 | } |
2d66e025 | 3425 | } |
8f177c8e | 3426 | |
2d66e025 MB |
3427 | |
3428 | void wxGrid::SetEditControlValue( const wxString& value ) | |
3429 | { | |
f85afd4e MB |
3430 | if ( m_table ) |
3431 | { | |
2d66e025 MB |
3432 | wxString s; |
3433 | if ( !value ) | |
3434 | s = GetCellValue(m_currentCellCoords); | |
3435 | else | |
3436 | s = value; | |
f85afd4e | 3437 | |
2d66e025 MB |
3438 | if ( IsCellEditControlEnabled() ) |
3439 | { | |
3440 | switch ( m_editCtrlType ) | |
3f296516 | 3441 | { |
2d66e025 MB |
3442 | case wxGRID_TEXTCTRL: |
3443 | ((wxGridTextCtrl *)m_cellEditCtrl)->SetStartValue(s); | |
3444 | break; | |
8f177c8e | 3445 | |
2d66e025 MB |
3446 | case wxGRID_CHECKBOX: |
3447 | // TODO: implement this | |
3448 | // | |
3449 | break; | |
3f296516 | 3450 | |
2d66e025 MB |
3451 | case wxGRID_CHOICE: |
3452 | // TODO: implement this | |
3453 | // | |
3454 | break; | |
3455 | ||
3456 | case wxGRID_COMBOBOX: | |
3457 | // TODO: implement this | |
3458 | // | |
3459 | break; | |
3460 | } | |
3461 | } | |
f85afd4e MB |
3462 | } |
3463 | } | |
3464 | ||
8f177c8e | 3465 | |
2d66e025 MB |
3466 | void wxGrid::SaveEditControlValue() |
3467 | { | |
3468 | if ( m_table ) | |
f85afd4e | 3469 | { |
2d66e025 | 3470 | wxWindow *ctrl = (wxWindow *)NULL; |
8f177c8e | 3471 | |
2d66e025 | 3472 | if ( IsCellEditControlEnabled() ) |
3f296516 | 3473 | { |
2d66e025 MB |
3474 | ctrl = m_cellEditCtrl; |
3475 | } | |
2d66e025 MB |
3476 | else |
3477 | { | |
3478 | return; | |
3f296516 | 3479 | } |
8f177c8e | 3480 | |
2d66e025 MB |
3481 | bool valueChanged = FALSE; |
3482 | ||
3483 | switch ( m_editCtrlType ) | |
3484 | { | |
3485 | case wxGRID_TEXTCTRL: | |
3486 | valueChanged = (((wxGridTextCtrl *)ctrl)->GetValue() != | |
3487 | ((wxGridTextCtrl *)ctrl)->GetStartValue()); | |
3488 | SetCellValue( m_currentCellCoords, | |
3489 | ((wxTextCtrl *) ctrl)->GetValue() ); | |
3490 | break; | |
3491 | ||
3492 | case wxGRID_CHECKBOX: | |
3493 | // TODO: implement this | |
3494 | // | |
3495 | break; | |
3496 | ||
3497 | case wxGRID_CHOICE: | |
3498 | // TODO: implement this | |
3499 | // | |
3500 | break; | |
3501 | ||
3502 | case wxGRID_COMBOBOX: | |
3503 | // TODO: implement this | |
3504 | // | |
3505 | break; | |
3506 | } | |
3507 | ||
3508 | if ( valueChanged ) | |
3509 | { | |
3510 | SendEvent( EVT_GRID_CELL_CHANGE, | |
3511 | m_currentCellCoords.GetRow(), | |
3512 | m_currentCellCoords.GetCol() ); | |
3513 | } | |
f85afd4e MB |
3514 | } |
3515 | } | |
3516 | ||
2d66e025 MB |
3517 | |
3518 | // | |
60ff3b99 VZ |
3519 | // ------ Grid location functions |
3520 | // Note that all of these functions work with the logical coordinates of | |
2d66e025 MB |
3521 | // grid cells and labels so you will need to convert from device |
3522 | // coordinates for mouse events etc. | |
3523 | // | |
3524 | ||
3525 | void wxGrid::XYToCell( int x, int y, wxGridCellCoords& coords ) | |
f85afd4e | 3526 | { |
58dd5b3b MB |
3527 | int row = YToRow(y); |
3528 | int col = XToCol(x); | |
3529 | ||
3530 | if ( row == -1 || col == -1 ) | |
3531 | { | |
3532 | coords = wxGridNoCellCoords; | |
3533 | } | |
3534 | else | |
3535 | { | |
3536 | coords.Set( row, col ); | |
3537 | } | |
2d66e025 | 3538 | } |
f85afd4e | 3539 | |
8f177c8e | 3540 | |
2d66e025 MB |
3541 | int wxGrid::YToRow( int y ) |
3542 | { | |
3543 | int i; | |
8f177c8e | 3544 | |
2d66e025 | 3545 | for ( i = 0; i < m_numRows; i++ ) |
f85afd4e | 3546 | { |
2d66e025 | 3547 | if ( y < m_rowBottoms[i] ) return i; |
f85afd4e | 3548 | } |
2d66e025 MB |
3549 | |
3550 | return -1; | |
f85afd4e MB |
3551 | } |
3552 | ||
2d66e025 MB |
3553 | |
3554 | int wxGrid::XToCol( int x ) | |
f85afd4e | 3555 | { |
2d66e025 | 3556 | int i; |
8f177c8e | 3557 | |
2d66e025 | 3558 | for ( i = 0; i < m_numCols; i++ ) |
f85afd4e | 3559 | { |
2d66e025 | 3560 | if ( x < m_colRights[i] ) return i; |
f85afd4e MB |
3561 | } |
3562 | ||
2d66e025 MB |
3563 | return -1; |
3564 | } | |
8f177c8e | 3565 | |
2d66e025 MB |
3566 | |
3567 | // return the row number that that the y coord is near the edge of, or | |
3568 | // -1 if not near an edge | |
3569 | // | |
3570 | int wxGrid::YToEdgeOfRow( int y ) | |
3571 | { | |
3572 | int i, d; | |
3573 | ||
3574 | for ( i = 0; i < m_numRows; i++ ) | |
3575 | { | |
3576 | if ( m_rowHeights[i] > WXGRID_LABEL_EDGE_ZONE ) | |
f85afd4e | 3577 | { |
2d66e025 | 3578 | d = abs( y - m_rowBottoms[i] ); |
3f296516 | 3579 | { |
2d66e025 | 3580 | if ( d < WXGRID_LABEL_EDGE_ZONE ) return i; |
3f296516 | 3581 | } |
f85afd4e | 3582 | } |
f85afd4e | 3583 | } |
2d66e025 MB |
3584 | |
3585 | return -1; | |
3586 | } | |
3587 | ||
3588 | ||
3589 | // return the col number that that the x coord is near the edge of, or | |
3590 | // -1 if not near an edge | |
3591 | // | |
3592 | int wxGrid::XToEdgeOfCol( int x ) | |
3593 | { | |
3594 | int i, d; | |
3595 | ||
3596 | for ( i = 0; i < m_numCols; i++ ) | |
f85afd4e | 3597 | { |
2d66e025 MB |
3598 | if ( m_colWidths[i] > WXGRID_LABEL_EDGE_ZONE ) |
3599 | { | |
3600 | d = abs( x - m_colRights[i] ); | |
3601 | { | |
3602 | if ( d < WXGRID_LABEL_EDGE_ZONE ) return i; | |
3603 | } | |
3604 | } | |
f85afd4e | 3605 | } |
2d66e025 MB |
3606 | |
3607 | return -1; | |
f85afd4e MB |
3608 | } |
3609 | ||
2d66e025 MB |
3610 | |
3611 | wxRect wxGrid::CellToRect( int row, int col ) | |
f85afd4e | 3612 | { |
2d66e025 | 3613 | wxRect rect( -1, -1, -1, -1 ); |
f85afd4e | 3614 | |
2d66e025 MB |
3615 | if ( row >= 0 && row < m_numRows && |
3616 | col >= 0 && col < m_numCols ) | |
f85afd4e | 3617 | { |
2d66e025 MB |
3618 | rect.x = m_colRights[col] - m_colWidths[col]; |
3619 | rect.y = m_rowBottoms[row] - m_rowHeights[row]; | |
3620 | rect.width = m_colWidths[col]; | |
3621 | rect.height = m_rowHeights[ row ]; | |
f85afd4e MB |
3622 | } |
3623 | ||
2d66e025 MB |
3624 | return rect; |
3625 | } | |
3626 | ||
3627 | ||
3628 | bool wxGrid::IsVisible( int row, int col, bool wholeCellVisible ) | |
3629 | { | |
3630 | // get the cell rectangle in logical coords | |
3631 | // | |
3632 | wxRect r( CellToRect( row, col ) ); | |
60ff3b99 | 3633 | |
2d66e025 MB |
3634 | // convert to device coords |
3635 | // | |
3636 | int left, top, right, bottom; | |
3637 | CalcScrolledPosition( r.GetLeft(), r.GetTop(), &left, &top ); | |
3638 | CalcScrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom ); | |
60ff3b99 | 3639 | |
2d66e025 MB |
3640 | // check against the client area of the grid window |
3641 | // | |
3642 | int cw, ch; | |
3643 | m_gridWin->GetClientSize( &cw, &ch ); | |
60ff3b99 | 3644 | |
2d66e025 | 3645 | if ( wholeCellVisible ) |
f85afd4e | 3646 | { |
2d66e025 | 3647 | // is the cell wholly visible ? |
8f177c8e | 3648 | // |
2d66e025 MB |
3649 | return ( left >= 0 && right <= cw && |
3650 | top >= 0 && bottom <= ch ); | |
3651 | } | |
3652 | else | |
3653 | { | |
3654 | // is the cell partly visible ? | |
3655 | // | |
3656 | return ( ((left >=0 && left < cw) || (right > 0 && right <= cw)) && | |
3657 | ((top >=0 && top < ch) || (bottom > 0 && bottom <= ch)) ); | |
3658 | } | |
3659 | } | |
3660 | ||
3661 | ||
3662 | // make the specified cell location visible by doing a minimal amount | |
3663 | // of scrolling | |
3664 | // | |
3665 | void wxGrid::MakeCellVisible( int row, int col ) | |
3666 | { | |
3667 | int i; | |
60ff3b99 | 3668 | int xpos = -1, ypos = -1; |
2d66e025 MB |
3669 | |
3670 | if ( row >= 0 && row < m_numRows && | |
3671 | col >= 0 && col < m_numCols ) | |
3672 | { | |
3673 | // get the cell rectangle in logical coords | |
3674 | // | |
3675 | wxRect r( CellToRect( row, col ) ); | |
60ff3b99 | 3676 | |
2d66e025 MB |
3677 | // convert to device coords |
3678 | // | |
3679 | int left, top, right, bottom; | |
3680 | CalcScrolledPosition( r.GetLeft(), r.GetTop(), &left, &top ); | |
3681 | CalcScrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom ); | |
60ff3b99 | 3682 | |
2d66e025 MB |
3683 | int cw, ch; |
3684 | m_gridWin->GetClientSize( &cw, &ch ); | |
60ff3b99 | 3685 | |
2d66e025 | 3686 | if ( top < 0 ) |
3f296516 | 3687 | { |
2d66e025 | 3688 | ypos = r.GetTop(); |
3f296516 | 3689 | } |
2d66e025 MB |
3690 | else if ( bottom > ch ) |
3691 | { | |
3692 | int h = r.GetHeight(); | |
3693 | ypos = r.GetTop(); | |
3694 | for ( i = row-1; i >= 0; i-- ) | |
3695 | { | |
3696 | if ( h + m_rowHeights[i] > ch ) break; | |
3697 | ||
3698 | h += m_rowHeights[i]; | |
3699 | ypos -= m_rowHeights[i]; | |
3700 | } | |
f0102d2a VZ |
3701 | |
3702 | // we divide it later by GRID_SCROLL_LINE, make sure that we don't | |
3703 | // have rounding errors (this is important, because if we do, we | |
3704 | // might not scroll at all and some cells won't be redrawn) | |
3705 | ypos += GRID_SCROLL_LINE / 2; | |
2d66e025 MB |
3706 | } |
3707 | ||
3708 | if ( left < 0 ) | |
3709 | { | |
3710 | xpos = r.GetLeft(); | |
3711 | } | |
3712 | else if ( right > cw ) | |
3713 | { | |
3714 | int w = r.GetWidth(); | |
3715 | xpos = r.GetLeft(); | |
3716 | for ( i = col-1; i >= 0; i-- ) | |
3717 | { | |
3718 | if ( w + m_colWidths[i] > cw ) break; | |
3719 | ||
3720 | w += m_colWidths[i]; | |
3721 | xpos -= m_colWidths[i]; | |
3722 | } | |
f0102d2a VZ |
3723 | |
3724 | // see comment for ypos above | |
3725 | xpos += GRID_SCROLL_LINE / 2; | |
2d66e025 MB |
3726 | } |
3727 | ||
3728 | if ( xpos != -1 || ypos != -1 ) | |
3729 | { | |
f0102d2a VZ |
3730 | if ( xpos != -1 ) xpos /= GRID_SCROLL_LINE; |
3731 | if ( ypos != -1 ) ypos /= GRID_SCROLL_LINE; | |
2d66e025 MB |
3732 | Scroll( xpos, ypos ); |
3733 | AdjustScrollbars(); | |
3734 | } | |
3735 | } | |
3736 | } | |
3737 | ||
3738 | ||
3739 | // | |
3740 | // ------ Grid cursor movement functions | |
3741 | // | |
3742 | ||
3743 | bool wxGrid::MoveCursorUp() | |
3744 | { | |
3745 | if ( m_currentCellCoords != wxGridNoCellCoords && | |
3746 | m_currentCellCoords.GetRow() > 0 ) | |
3747 | { | |
3748 | MakeCellVisible( m_currentCellCoords.GetRow() - 1, | |
3749 | m_currentCellCoords.GetCol() ); | |
60ff3b99 | 3750 | |
2d66e025 MB |
3751 | SetCurrentCell( m_currentCellCoords.GetRow() - 1, |
3752 | m_currentCellCoords.GetCol() ); | |
3753 | ||
8f177c8e | 3754 | return TRUE; |
f85afd4e | 3755 | } |
2d66e025 MB |
3756 | |
3757 | return FALSE; | |
3758 | } | |
3759 | ||
3760 | ||
3761 | bool wxGrid::MoveCursorDown() | |
3762 | { | |
3763 | // TODO: allow for scrolling | |
3764 | // | |
3765 | if ( m_currentCellCoords != wxGridNoCellCoords && | |
3766 | m_currentCellCoords.GetRow() < m_numRows-1 ) | |
f85afd4e | 3767 | { |
2d66e025 MB |
3768 | MakeCellVisible( m_currentCellCoords.GetRow() + 1, |
3769 | m_currentCellCoords.GetCol() ); | |
60ff3b99 | 3770 | |
2d66e025 MB |
3771 | SetCurrentCell( m_currentCellCoords.GetRow() + 1, |
3772 | m_currentCellCoords.GetCol() ); | |
3773 | ||
3774 | return TRUE; | |
f85afd4e | 3775 | } |
2d66e025 MB |
3776 | |
3777 | return FALSE; | |
f85afd4e MB |
3778 | } |
3779 | ||
2d66e025 MB |
3780 | |
3781 | bool wxGrid::MoveCursorLeft() | |
f85afd4e | 3782 | { |
2d66e025 MB |
3783 | if ( m_currentCellCoords != wxGridNoCellCoords && |
3784 | m_currentCellCoords.GetCol() > 0 ) | |
3785 | { | |
3786 | MakeCellVisible( m_currentCellCoords.GetRow(), | |
3787 | m_currentCellCoords.GetCol() - 1 ); | |
60ff3b99 | 3788 | |
2d66e025 MB |
3789 | SetCurrentCell( m_currentCellCoords.GetRow(), |
3790 | m_currentCellCoords.GetCol() - 1 ); | |
8f177c8e | 3791 | |
2d66e025 MB |
3792 | return TRUE; |
3793 | } | |
3794 | ||
3795 | return FALSE; | |
3796 | } | |
3797 | ||
3798 | ||
3799 | bool wxGrid::MoveCursorRight() | |
3800 | { | |
3801 | if ( m_currentCellCoords != wxGridNoCellCoords && | |
3802 | m_currentCellCoords.GetCol() < m_numCols - 1 ) | |
f85afd4e | 3803 | { |
2d66e025 MB |
3804 | MakeCellVisible( m_currentCellCoords.GetRow(), |
3805 | m_currentCellCoords.GetCol() + 1 ); | |
60ff3b99 | 3806 | |
2d66e025 MB |
3807 | SetCurrentCell( m_currentCellCoords.GetRow(), |
3808 | m_currentCellCoords.GetCol() + 1 ); | |
3809 | ||
3810 | return TRUE; | |
f85afd4e | 3811 | } |
8f177c8e | 3812 | |
2d66e025 MB |
3813 | return FALSE; |
3814 | } | |
3815 | ||
3816 | ||
3817 | bool wxGrid::MovePageUp() | |
3818 | { | |
3819 | if ( m_currentCellCoords == wxGridNoCellCoords ) return FALSE; | |
60ff3b99 | 3820 | |
2d66e025 MB |
3821 | int row = m_currentCellCoords.GetRow(); |
3822 | if ( row > 0 ) | |
f85afd4e | 3823 | { |
2d66e025 MB |
3824 | int cw, ch; |
3825 | m_gridWin->GetClientSize( &cw, &ch ); | |
60ff3b99 | 3826 | |
2d66e025 MB |
3827 | int y = m_rowBottoms[ row ] - m_rowHeights[ row ]; |
3828 | int newRow = YToRow( y - ch + 1 ); | |
3829 | if ( newRow == -1 ) | |
3830 | { | |
3831 | newRow = 0; | |
3832 | } | |
60ff3b99 | 3833 | else if ( newRow == row ) |
2d66e025 MB |
3834 | { |
3835 | newRow = row - 1; | |
3836 | } | |
8f177c8e | 3837 | |
2d66e025 MB |
3838 | MakeCellVisible( newRow, m_currentCellCoords.GetCol() ); |
3839 | SetCurrentCell( newRow, m_currentCellCoords.GetCol() ); | |
60ff3b99 | 3840 | |
f85afd4e MB |
3841 | return TRUE; |
3842 | } | |
2d66e025 MB |
3843 | |
3844 | return FALSE; | |
3845 | } | |
3846 | ||
3847 | bool wxGrid::MovePageDown() | |
3848 | { | |
3849 | if ( m_currentCellCoords == wxGridNoCellCoords ) return FALSE; | |
60ff3b99 | 3850 | |
2d66e025 MB |
3851 | int row = m_currentCellCoords.GetRow(); |
3852 | if ( row < m_numRows ) | |
f85afd4e | 3853 | { |
2d66e025 MB |
3854 | int cw, ch; |
3855 | m_gridWin->GetClientSize( &cw, &ch ); | |
60ff3b99 | 3856 | |
2d66e025 MB |
3857 | int y = m_rowBottoms[ row ] - m_rowHeights[ row ]; |
3858 | int newRow = YToRow( y + ch ); | |
3859 | if ( newRow == -1 ) | |
3860 | { | |
3861 | newRow = m_numRows - 1; | |
3862 | } | |
60ff3b99 | 3863 | else if ( newRow == row ) |
2d66e025 MB |
3864 | { |
3865 | newRow = row + 1; | |
3866 | } | |
3867 | ||
3868 | MakeCellVisible( newRow, m_currentCellCoords.GetCol() ); | |
3869 | SetCurrentCell( newRow, m_currentCellCoords.GetCol() ); | |
60ff3b99 | 3870 | |
2d66e025 | 3871 | return TRUE; |
f85afd4e | 3872 | } |
2d66e025 MB |
3873 | |
3874 | return FALSE; | |
f85afd4e | 3875 | } |
8f177c8e | 3876 | |
2d66e025 MB |
3877 | bool wxGrid::MoveCursorUpBlock() |
3878 | { | |
3879 | if ( m_table && | |
3880 | m_currentCellCoords != wxGridNoCellCoords && | |
3881 | m_currentCellCoords.GetRow() > 0 ) | |
3882 | { | |
3883 | int row = m_currentCellCoords.GetRow(); | |
3884 | int col = m_currentCellCoords.GetCol(); | |
3885 | ||
3886 | if ( m_table->IsEmptyCell(row, col) ) | |
3887 | { | |
3888 | // starting in an empty cell: find the next block of | |
3889 | // non-empty cells | |
3890 | // | |
3891 | while ( row > 0 ) | |
3892 | { | |
3893 | row-- ; | |
3894 | if ( !(m_table->IsEmptyCell(row, col)) ) break; | |
3895 | } | |
3896 | } | |
3897 | else if ( m_table->IsEmptyCell(row-1, col) ) | |
3898 | { | |
3899 | // starting at the top of a block: find the next block | |
3900 | // | |
3901 | row--; | |
3902 | while ( row > 0 ) | |
3903 | { | |
3904 | row-- ; | |
3905 | if ( !(m_table->IsEmptyCell(row, col)) ) break; | |
3906 | } | |
3907 | } | |
3908 | else | |
3909 | { | |
3910 | // starting within a block: find the top of the block | |
3911 | // | |
3912 | while ( row > 0 ) | |
3913 | { | |
3914 | row-- ; | |
3915 | if ( m_table->IsEmptyCell(row, col) ) | |
3916 | { | |
3917 | row++ ; | |
3918 | break; | |
3919 | } | |
3920 | } | |
3921 | } | |
f85afd4e | 3922 | |
2d66e025 MB |
3923 | MakeCellVisible( row, col ); |
3924 | SetCurrentCell( row, col ); | |
f85afd4e | 3925 | |
2d66e025 MB |
3926 | return TRUE; |
3927 | } | |
f85afd4e | 3928 | |
2d66e025 MB |
3929 | return FALSE; |
3930 | } | |
f85afd4e | 3931 | |
2d66e025 | 3932 | bool wxGrid::MoveCursorDownBlock() |
f85afd4e | 3933 | { |
2d66e025 MB |
3934 | if ( m_table && |
3935 | m_currentCellCoords != wxGridNoCellCoords && | |
3936 | m_currentCellCoords.GetRow() < m_numRows-1 ) | |
f85afd4e | 3937 | { |
2d66e025 MB |
3938 | int row = m_currentCellCoords.GetRow(); |
3939 | int col = m_currentCellCoords.GetCol(); | |
3940 | ||
3941 | if ( m_table->IsEmptyCell(row, col) ) | |
3942 | { | |
3943 | // starting in an empty cell: find the next block of | |
3944 | // non-empty cells | |
3945 | // | |
3946 | while ( row < m_numRows-1 ) | |
3947 | { | |
3948 | row++ ; | |
3949 | if ( !(m_table->IsEmptyCell(row, col)) ) break; | |
3950 | } | |
3951 | } | |
3952 | else if ( m_table->IsEmptyCell(row+1, col) ) | |
3953 | { | |
3954 | // starting at the bottom of a block: find the next block | |
3955 | // | |
3956 | row++; | |
3957 | while ( row < m_numRows-1 ) | |
3958 | { | |
3959 | row++ ; | |
3960 | if ( !(m_table->IsEmptyCell(row, col)) ) break; | |
3961 | } | |
3962 | } | |
3963 | else | |
3964 | { | |
3965 | // starting within a block: find the bottom of the block | |
3966 | // | |
3967 | while ( row < m_numRows-1 ) | |
3968 | { | |
3969 | row++ ; | |
3970 | if ( m_table->IsEmptyCell(row, col) ) | |
3971 | { | |
3972 | row-- ; | |
3973 | break; | |
3974 | } | |
3975 | } | |
3976 | } | |
3977 | ||
3978 | MakeCellVisible( row, col ); | |
3979 | SetCurrentCell( row, col ); | |
3980 | ||
3981 | return TRUE; | |
f85afd4e | 3982 | } |
f85afd4e | 3983 | |
2d66e025 MB |
3984 | return FALSE; |
3985 | } | |
f85afd4e | 3986 | |
2d66e025 | 3987 | bool wxGrid::MoveCursorLeftBlock() |
f85afd4e | 3988 | { |
2d66e025 MB |
3989 | if ( m_table && |
3990 | m_currentCellCoords != wxGridNoCellCoords && | |
3991 | m_currentCellCoords.GetCol() > 0 ) | |
f85afd4e | 3992 | { |
2d66e025 MB |
3993 | int row = m_currentCellCoords.GetRow(); |
3994 | int col = m_currentCellCoords.GetCol(); | |
3995 | ||
3996 | if ( m_table->IsEmptyCell(row, col) ) | |
3997 | { | |
3998 | // starting in an empty cell: find the next block of | |
3999 | // non-empty cells | |
4000 | // | |
4001 | while ( col > 0 ) | |
4002 | { | |
4003 | col-- ; | |
4004 | if ( !(m_table->IsEmptyCell(row, col)) ) break; | |
4005 | } | |
4006 | } | |
4007 | else if ( m_table->IsEmptyCell(row, col-1) ) | |
4008 | { | |
4009 | // starting at the left of a block: find the next block | |
4010 | // | |
4011 | col--; | |
4012 | while ( col > 0 ) | |
4013 | { | |
4014 | col-- ; | |
4015 | if ( !(m_table->IsEmptyCell(row, col)) ) break; | |
4016 | } | |
4017 | } | |
4018 | else | |
4019 | { | |
4020 | // starting within a block: find the left of the block | |
4021 | // | |
4022 | while ( col > 0 ) | |
4023 | { | |
4024 | col-- ; | |
4025 | if ( m_table->IsEmptyCell(row, col) ) | |
4026 | { | |
4027 | col++ ; | |
4028 | break; | |
4029 | } | |
4030 | } | |
4031 | } | |
f85afd4e | 4032 | |
2d66e025 MB |
4033 | MakeCellVisible( row, col ); |
4034 | SetCurrentCell( row, col ); | |
8f177c8e | 4035 | |
2d66e025 | 4036 | return TRUE; |
f85afd4e | 4037 | } |
2d66e025 MB |
4038 | |
4039 | return FALSE; | |
f85afd4e MB |
4040 | } |
4041 | ||
2d66e025 | 4042 | bool wxGrid::MoveCursorRightBlock() |
f85afd4e | 4043 | { |
2d66e025 MB |
4044 | if ( m_table && |
4045 | m_currentCellCoords != wxGridNoCellCoords && | |
4046 | m_currentCellCoords.GetCol() < m_numCols-1 ) | |
f85afd4e | 4047 | { |
2d66e025 MB |
4048 | int row = m_currentCellCoords.GetRow(); |
4049 | int col = m_currentCellCoords.GetCol(); | |
8f177c8e | 4050 | |
2d66e025 MB |
4051 | if ( m_table->IsEmptyCell(row, col) ) |
4052 | { | |
4053 | // starting in an empty cell: find the next block of | |
4054 | // non-empty cells | |
4055 | // | |
4056 | while ( col < m_numCols-1 ) | |
4057 | { | |
4058 | col++ ; | |
4059 | if ( !(m_table->IsEmptyCell(row, col)) ) break; | |
4060 | } | |
4061 | } | |
4062 | else if ( m_table->IsEmptyCell(row, col+1) ) | |
4063 | { | |
4064 | // starting at the right of a block: find the next block | |
4065 | // | |
4066 | col++; | |
4067 | while ( col < m_numCols-1 ) | |
4068 | { | |
4069 | col++ ; | |
4070 | if ( !(m_table->IsEmptyCell(row, col)) ) break; | |
4071 | } | |
4072 | } | |
4073 | else | |
4074 | { | |
4075 | // starting within a block: find the right of the block | |
4076 | // | |
4077 | while ( col < m_numCols-1 ) | |
4078 | { | |
4079 | col++ ; | |
4080 | if ( m_table->IsEmptyCell(row, col) ) | |
4081 | { | |
4082 | col-- ; | |
4083 | break; | |
4084 | } | |
4085 | } | |
4086 | } | |
8f177c8e | 4087 | |
2d66e025 MB |
4088 | MakeCellVisible( row, col ); |
4089 | SetCurrentCell( row, col ); | |
f85afd4e | 4090 | |
2d66e025 | 4091 | return TRUE; |
f85afd4e | 4092 | } |
2d66e025 MB |
4093 | |
4094 | return FALSE; | |
f85afd4e MB |
4095 | } |
4096 | ||
4097 | ||
2d66e025 | 4098 | |
f85afd4e | 4099 | // |
2d66e025 | 4100 | // ------ Label values and formatting |
f85afd4e MB |
4101 | // |
4102 | ||
4103 | void wxGrid::GetRowLabelAlignment( int *horiz, int *vert ) | |
4104 | { | |
4105 | *horiz = m_rowLabelHorizAlign; | |
4106 | *vert = m_rowLabelVertAlign; | |
4107 | } | |
4108 | ||
4109 | void wxGrid::GetColLabelAlignment( int *horiz, int *vert ) | |
4110 | { | |
4111 | *horiz = m_colLabelHorizAlign; | |
4112 | *vert = m_colLabelVertAlign; | |
4113 | } | |
4114 | ||
4115 | wxString wxGrid::GetRowLabelValue( int row ) | |
4116 | { | |
4117 | if ( m_table ) | |
4118 | { | |
4119 | return m_table->GetRowLabelValue( row ); | |
4120 | } | |
4121 | else | |
4122 | { | |
4123 | wxString s; | |
4124 | s << row; | |
4125 | return s; | |
4126 | } | |
4127 | } | |
4128 | ||
4129 | wxString wxGrid::GetColLabelValue( int col ) | |
4130 | { | |
4131 | if ( m_table ) | |
4132 | { | |
4133 | return m_table->GetColLabelValue( col ); | |
4134 | } | |
4135 | else | |
4136 | { | |
4137 | wxString s; | |
4138 | s << col; | |
4139 | return s; | |
4140 | } | |
4141 | } | |
4142 | ||
2e8cd977 | 4143 | |
f85afd4e MB |
4144 | void wxGrid::SetRowLabelSize( int width ) |
4145 | { | |
2e8cd977 MB |
4146 | width = wxMax( width, 0 ); |
4147 | if ( width != m_rowLabelWidth ) | |
4148 | { | |
2e8cd977 MB |
4149 | if ( width == 0 ) |
4150 | { | |
4151 | m_rowLabelWin->Show( FALSE ); | |
7807d81c | 4152 | m_cornerLabelWin->Show( FALSE ); |
2e8cd977 | 4153 | } |
7807d81c | 4154 | else if ( m_rowLabelWidth == 0 ) |
2e8cd977 | 4155 | { |
7807d81c MB |
4156 | m_rowLabelWin->Show( TRUE ); |
4157 | if ( m_colLabelHeight > 0 ) m_cornerLabelWin->Show( TRUE ); | |
2e8cd977 | 4158 | } |
b99be8fb | 4159 | |
2e8cd977 | 4160 | m_rowLabelWidth = width; |
7807d81c MB |
4161 | CalcWindowSizes(); |
4162 | Refresh( TRUE ); | |
2e8cd977 | 4163 | } |
f85afd4e MB |
4164 | } |
4165 | ||
2e8cd977 | 4166 | |
f85afd4e MB |
4167 | void wxGrid::SetColLabelSize( int height ) |
4168 | { | |
7807d81c | 4169 | height = wxMax( height, 0 ); |
2e8cd977 MB |
4170 | if ( height != m_colLabelHeight ) |
4171 | { | |
2e8cd977 MB |
4172 | if ( height == 0 ) |
4173 | { | |
2e8cd977 | 4174 | m_colLabelWin->Show( FALSE ); |
7807d81c | 4175 | m_cornerLabelWin->Show( FALSE ); |
2e8cd977 | 4176 | } |
7807d81c | 4177 | else if ( m_colLabelHeight == 0 ) |
2e8cd977 | 4178 | { |
7807d81c MB |
4179 | m_colLabelWin->Show( TRUE ); |
4180 | if ( m_rowLabelWidth > 0 ) m_cornerLabelWin->Show( TRUE ); | |
2e8cd977 | 4181 | } |
7807d81c | 4182 | |
2e8cd977 | 4183 | m_colLabelHeight = height; |
7807d81c MB |
4184 | CalcWindowSizes(); |
4185 | Refresh( TRUE ); | |
2e8cd977 | 4186 | } |
f85afd4e MB |
4187 | } |
4188 | ||
2e8cd977 | 4189 | |
f85afd4e MB |
4190 | void wxGrid::SetLabelBackgroundColour( const wxColour& colour ) |
4191 | { | |
2d66e025 MB |
4192 | if ( m_labelBackgroundColour != colour ) |
4193 | { | |
4194 | m_labelBackgroundColour = colour; | |
4195 | m_rowLabelWin->SetBackgroundColour( colour ); | |
4196 | m_colLabelWin->SetBackgroundColour( colour ); | |
4197 | m_cornerLabelWin->SetBackgroundColour( colour ); | |
4198 | ||
4199 | if ( !GetBatchCount() ) | |
4200 | { | |
4201 | m_rowLabelWin->Refresh(); | |
4202 | m_colLabelWin->Refresh(); | |
4203 | m_cornerLabelWin->Refresh(); | |
4204 | } | |
4205 | } | |
f85afd4e MB |
4206 | } |
4207 | ||
4208 | void wxGrid::SetLabelTextColour( const wxColour& colour ) | |
4209 | { | |
2d66e025 MB |
4210 | if ( m_labelTextColour != colour ) |
4211 | { | |
4212 | m_labelTextColour = colour; | |
4213 | if ( !GetBatchCount() ) | |
4214 | { | |
4215 | m_rowLabelWin->Refresh(); | |
4216 | m_colLabelWin->Refresh(); | |
4217 | } | |
4218 | } | |
f85afd4e MB |
4219 | } |
4220 | ||
4221 | void wxGrid::SetLabelFont( const wxFont& font ) | |
4222 | { | |
4223 | m_labelFont = font; | |
2d66e025 MB |
4224 | if ( !GetBatchCount() ) |
4225 | { | |
4226 | m_rowLabelWin->Refresh(); | |
4227 | m_colLabelWin->Refresh(); | |
4228 | } | |
f85afd4e MB |
4229 | } |
4230 | ||
4231 | void wxGrid::SetRowLabelAlignment( int horiz, int vert ) | |
4232 | { | |
4233 | if ( horiz == wxLEFT || horiz == wxCENTRE || horiz == wxRIGHT ) | |
4234 | { | |
4235 | m_rowLabelHorizAlign = horiz; | |
4236 | } | |
8f177c8e | 4237 | |
f85afd4e MB |
4238 | if ( vert == wxTOP || vert == wxCENTRE || vert == wxBOTTOM ) |
4239 | { | |
4240 | m_rowLabelVertAlign = vert; | |
4241 | } | |
4242 | ||
2d66e025 MB |
4243 | if ( !GetBatchCount() ) |
4244 | { | |
4245 | m_rowLabelWin->Refresh(); | |
60ff3b99 | 4246 | } |
f85afd4e MB |
4247 | } |
4248 | ||
4249 | void wxGrid::SetColLabelAlignment( int horiz, int vert ) | |
4250 | { | |
4251 | if ( horiz == wxLEFT || horiz == wxCENTRE || horiz == wxRIGHT ) | |
4252 | { | |
4253 | m_colLabelHorizAlign = horiz; | |
4254 | } | |
8f177c8e | 4255 | |
f85afd4e MB |
4256 | if ( vert == wxTOP || vert == wxCENTRE || vert == wxBOTTOM ) |
4257 | { | |
4258 | m_colLabelVertAlign = vert; | |
4259 | } | |
4260 | ||
2d66e025 MB |
4261 | if ( !GetBatchCount() ) |
4262 | { | |
2d66e025 | 4263 | m_colLabelWin->Refresh(); |
60ff3b99 | 4264 | } |
f85afd4e MB |
4265 | } |
4266 | ||
4267 | void wxGrid::SetRowLabelValue( int row, const wxString& s ) | |
4268 | { | |
4269 | if ( m_table ) | |
4270 | { | |
4271 | m_table->SetRowLabelValue( row, s ); | |
2d66e025 MB |
4272 | if ( !GetBatchCount() ) |
4273 | { | |
70c7a608 SN |
4274 | wxRect rect = CellToRect( row, 0); |
4275 | if ( rect.height > 0 ) | |
4276 | { | |
cb309039 | 4277 | CalcScrolledPosition(0, rect.y, &rect.x, &rect.y); |
70c7a608 SN |
4278 | rect.x = m_left; |
4279 | rect.width = m_rowLabelWidth; | |
4280 | m_rowLabelWin->Refresh( TRUE, &rect ); | |
4281 | } | |
2d66e025 | 4282 | } |
f85afd4e MB |
4283 | } |
4284 | } | |
4285 | ||
4286 | void wxGrid::SetColLabelValue( int col, const wxString& s ) | |
4287 | { | |
4288 | if ( m_table ) | |
4289 | { | |
4290 | m_table->SetColLabelValue( col, s ); | |
2d66e025 MB |
4291 | if ( !GetBatchCount() ) |
4292 | { | |
70c7a608 SN |
4293 | wxRect rect = CellToRect( 0, col ); |
4294 | if ( rect.width > 0 ) | |
4295 | { | |
cb309039 | 4296 | CalcScrolledPosition(rect.x, 0, &rect.x, &rect.y); |
70c7a608 SN |
4297 | rect.y = m_top; |
4298 | rect.height = m_colLabelHeight; | |
4299 | m_colLabelWin->Refresh( TRUE, &rect ); | |
4300 | } | |
2d66e025 | 4301 | } |
f85afd4e MB |
4302 | } |
4303 | } | |
4304 | ||
4305 | void wxGrid::SetGridLineColour( const wxColour& colour ) | |
4306 | { | |
2d66e025 MB |
4307 | if ( m_gridLineColour != colour ) |
4308 | { | |
4309 | m_gridLineColour = colour; | |
60ff3b99 | 4310 | |
2d66e025 MB |
4311 | wxClientDC dc( m_gridWin ); |
4312 | PrepareDC( dc ); | |
c6a51dcd | 4313 | DrawAllGridLines( dc, wxRegion() ); |
2d66e025 | 4314 | } |
f85afd4e MB |
4315 | } |
4316 | ||
4317 | void wxGrid::EnableGridLines( bool enable ) | |
4318 | { | |
4319 | if ( enable != m_gridLinesEnabled ) | |
4320 | { | |
4321 | m_gridLinesEnabled = enable; | |
2d66e025 MB |
4322 | |
4323 | if ( !GetBatchCount() ) | |
4324 | { | |
4325 | if ( enable ) | |
4326 | { | |
4327 | wxClientDC dc( m_gridWin ); | |
4328 | PrepareDC( dc ); | |
c6a51dcd | 4329 | DrawAllGridLines( dc, wxRegion() ); |
2d66e025 MB |
4330 | } |
4331 | else | |
4332 | { | |
4333 | m_gridWin->Refresh(); | |
4334 | } | |
4335 | } | |
f85afd4e MB |
4336 | } |
4337 | } | |
4338 | ||
4339 | ||
4340 | int wxGrid::GetDefaultRowSize() | |
4341 | { | |
4342 | return m_defaultRowHeight; | |
4343 | } | |
4344 | ||
4345 | int wxGrid::GetRowSize( int row ) | |
4346 | { | |
b99be8fb VZ |
4347 | wxCHECK_MSG( row >= 0 && row < m_numRows, 0, _T("invalid row index") ); |
4348 | ||
4349 | return m_rowHeights[row]; | |
f85afd4e MB |
4350 | } |
4351 | ||
4352 | int wxGrid::GetDefaultColSize() | |
4353 | { | |
4354 | return m_defaultColWidth; | |
4355 | } | |
4356 | ||
4357 | int wxGrid::GetColSize( int col ) | |
4358 | { | |
b99be8fb VZ |
4359 | wxCHECK_MSG( col >= 0 && col < m_numCols, 0, _T("invalid column index") ); |
4360 | ||
4361 | return m_colWidths[col]; | |
f85afd4e MB |
4362 | } |
4363 | ||
4364 | wxColour wxGrid::GetDefaultCellBackgroundColour() | |
4365 | { | |
2433bb2e | 4366 | return m_gridWin->GetBackgroundColour(); |
f85afd4e MB |
4367 | } |
4368 | ||
b99be8fb VZ |
4369 | // TODO VZ: this must be optimized to allow only retrieveing attr once! |
4370 | ||
4371 | wxColour wxGrid::GetCellBackgroundColour(int row, int col) | |
f85afd4e | 4372 | { |
b99be8fb VZ |
4373 | wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL; |
4374 | ||
4375 | wxColour colour; | |
4376 | if ( attr && attr->HasBackgroundColour() ) | |
4377 | colour = attr->GetBackgroundColour(); | |
4378 | else | |
4379 | colour = GetDefaultCellBackgroundColour(); | |
4380 | ||
4381 | delete attr; | |
4382 | ||
4383 | return colour; | |
f85afd4e MB |
4384 | } |
4385 | ||
4386 | wxColour wxGrid::GetDefaultCellTextColour() | |
4387 | { | |
2433bb2e | 4388 | return m_gridWin->GetForegroundColour(); |
f85afd4e MB |
4389 | } |
4390 | ||
b99be8fb | 4391 | wxColour wxGrid::GetCellTextColour( int row, int col ) |
f85afd4e | 4392 | { |
b99be8fb VZ |
4393 | wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL; |
4394 | ||
4395 | wxColour colour; | |
4396 | if ( attr && attr->HasTextColour() ) | |
4397 | colour = attr->GetTextColour(); | |
4398 | else | |
4399 | colour = GetDefaultCellTextColour(); | |
4400 | ||
4401 | delete attr; | |
4402 | ||
4403 | return colour; | |
f85afd4e MB |
4404 | } |
4405 | ||
4406 | ||
f85afd4e MB |
4407 | wxFont wxGrid::GetDefaultCellFont() |
4408 | { | |
4409 | return m_defaultCellFont; | |
4410 | } | |
4411 | ||
b99be8fb | 4412 | wxFont wxGrid::GetCellFont( int row, int col ) |
f85afd4e | 4413 | { |
b99be8fb VZ |
4414 | wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL; |
4415 | ||
4416 | wxFont font; | |
4417 | if ( attr && attr->HasFont() ) | |
4418 | font = attr->GetFont(); | |
4419 | else | |
4420 | font = GetDefaultCellFont(); | |
4421 | ||
4422 | delete attr; | |
4423 | ||
4424 | return font; | |
f85afd4e MB |
4425 | } |
4426 | ||
4427 | void wxGrid::GetDefaultCellAlignment( int *horiz, int *vert ) | |
4428 | { | |
b99be8fb VZ |
4429 | if ( horiz ) |
4430 | *horiz = m_defaultCellHAlign; | |
4431 | if ( vert ) | |
4432 | *vert = m_defaultCellVAlign; | |
f85afd4e MB |
4433 | } |
4434 | ||
b99be8fb | 4435 | void wxGrid::GetCellAlignment( int row, int col, int *horiz, int *vert ) |
f85afd4e | 4436 | { |
b99be8fb VZ |
4437 | wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL; |
4438 | ||
4439 | if ( attr && attr->HasAlignment() ) | |
4440 | attr->GetAlignment(horiz, vert); | |
4441 | else | |
4442 | GetDefaultCellAlignment(horiz, vert); | |
4443 | ||
4444 | delete attr; | |
f85afd4e MB |
4445 | } |
4446 | ||
4447 | void wxGrid::SetDefaultRowSize( int height, bool resizeExistingRows ) | |
4448 | { | |
4449 | m_defaultRowHeight = wxMax( height, WXGRID_MIN_ROW_HEIGHT ); | |
4450 | ||
4451 | if ( resizeExistingRows ) | |
4452 | { | |
f85afd4e | 4453 | int row; |
2d66e025 | 4454 | int bottom = 0; |
f85afd4e MB |
4455 | for ( row = 0; row < m_numRows; row++ ) |
4456 | { | |
4457 | m_rowHeights[row] = m_defaultRowHeight; | |
2d66e025 MB |
4458 | bottom += m_defaultRowHeight; |
4459 | m_rowBottoms[row] = bottom; | |
f85afd4e MB |
4460 | } |
4461 | CalcDimensions(); | |
f85afd4e MB |
4462 | } |
4463 | } | |
4464 | ||
4465 | void wxGrid::SetRowSize( int row, int height ) | |
4466 | { | |
b99be8fb | 4467 | wxCHECK_RET( row >= 0 && row < m_numRows, _T("invalid row index") ); |
60ff3b99 | 4468 | |
b99be8fb | 4469 | int i; |
60ff3b99 | 4470 | |
b99be8fb VZ |
4471 | int h = wxMax( 0, height ); |
4472 | int diff = h - m_rowHeights[row]; | |
60ff3b99 | 4473 | |
b99be8fb VZ |
4474 | m_rowHeights[row] = h; |
4475 | for ( i = row; i < m_numRows; i++ ) | |
f85afd4e | 4476 | { |
b99be8fb | 4477 | m_rowBottoms[i] += diff; |
f85afd4e | 4478 | } |
b99be8fb VZ |
4479 | CalcDimensions(); |
4480 | ||
4481 | // Note: we are ending the event *after* doing | |
4482 | // default processing in this case | |
4483 | // | |
4484 | SendEvent( EVT_GRID_ROW_SIZE, | |
4485 | row, -1 ); | |
f85afd4e MB |
4486 | } |
4487 | ||
4488 | void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols ) | |
4489 | { | |
4490 | m_defaultColWidth = wxMax( width, WXGRID_MIN_COL_WIDTH ); | |
4491 | ||
4492 | if ( resizeExistingCols ) | |
4493 | { | |
f85afd4e | 4494 | int col; |
2d66e025 | 4495 | int right = 0; |
f85afd4e MB |
4496 | for ( col = 0; col < m_numCols; col++ ) |
4497 | { | |
4498 | m_colWidths[col] = m_defaultColWidth; | |
2d66e025 MB |
4499 | right += m_defaultColWidth; |
4500 | m_colRights[col] = right; | |
f85afd4e MB |
4501 | } |
4502 | CalcDimensions(); | |
f85afd4e MB |
4503 | } |
4504 | } | |
4505 | ||
4506 | void wxGrid::SetColSize( int col, int width ) | |
4507 | { | |
b99be8fb | 4508 | wxCHECK_RET( col >= 0 && col < m_numCols, _T("invalid column index") ); |
60ff3b99 | 4509 | |
b99be8fb | 4510 | int i; |
f85afd4e | 4511 | |
b99be8fb VZ |
4512 | int w = wxMax( 0, width ); |
4513 | int diff = w - m_colWidths[col]; | |
4514 | m_colWidths[col] = w; | |
60ff3b99 | 4515 | |
b99be8fb | 4516 | for ( i = col; i < m_numCols; i++ ) |
f85afd4e | 4517 | { |
b99be8fb | 4518 | m_colRights[i] += diff; |
f85afd4e | 4519 | } |
b99be8fb VZ |
4520 | CalcDimensions(); |
4521 | ||
4522 | // Note: we are ending the event *after* doing | |
4523 | // default processing in this case | |
4524 | // | |
4525 | SendEvent( EVT_GRID_COL_SIZE, | |
4526 | -1, col ); | |
f85afd4e MB |
4527 | } |
4528 | ||
b99be8fb | 4529 | void wxGrid::SetDefaultCellBackgroundColour( const wxColour& col ) |
f85afd4e | 4530 | { |
2433bb2e | 4531 | m_gridWin->SetBackgroundColour(col); |
f85afd4e MB |
4532 | } |
4533 | ||
b99be8fb | 4534 | void wxGrid::SetDefaultCellTextColour( const wxColour& col ) |
f85afd4e | 4535 | { |
2433bb2e | 4536 | m_gridWin->SetForegroundColour(col); |
f85afd4e MB |
4537 | } |
4538 | ||
b99be8fb | 4539 | void wxGrid::SetDefaultCellAlignment( int horiz, int vert ) |
f85afd4e | 4540 | { |
b99be8fb VZ |
4541 | m_defaultCellHAlign = horiz; |
4542 | m_defaultCellVAlign = vert; | |
f85afd4e MB |
4543 | } |
4544 | ||
b99be8fb | 4545 | bool wxGrid::CanHaveAttributes() |
f85afd4e | 4546 | { |
b99be8fb VZ |
4547 | if ( !m_table ) |
4548 | { | |
4549 | return FALSE; | |
4550 | } | |
4551 | ||
4552 | if ( !m_table->GetAttrProvider() ) | |
4553 | { | |
4554 | // use the default attr provider by default | |
4555 | // (another choice would be to just return FALSE thus forcing the user | |
4556 | // to it himself) | |
4557 | m_table->SetAttrProvider(new wxGridCellAttrProvider); | |
4558 | } | |
4559 | ||
4560 | return TRUE; | |
f85afd4e MB |
4561 | } |
4562 | ||
b99be8fb | 4563 | void wxGrid::SetCellBackgroundColour( int row, int col, const wxColour& colour ) |
f85afd4e | 4564 | { |
b99be8fb VZ |
4565 | if ( CanHaveAttributes() ) |
4566 | { | |
4567 | wxGridCellAttr *attr = new wxGridCellAttr; | |
4568 | attr->SetBackgroundColour(colour); | |
4569 | ||
4570 | m_table->SetAttr(attr, row, col); | |
4571 | } | |
f85afd4e MB |
4572 | } |
4573 | ||
b99be8fb | 4574 | void wxGrid::SetCellTextColour( int row, int col, const wxColour& colour ) |
f85afd4e | 4575 | { |
b99be8fb VZ |
4576 | if ( CanHaveAttributes() ) |
4577 | { | |
4578 | wxGridCellAttr *attr = new wxGridCellAttr; | |
4579 | attr->SetTextColour(colour); | |
4580 | ||
4581 | m_table->SetAttr(attr, row, col); | |
4582 | } | |
f85afd4e MB |
4583 | } |
4584 | ||
b99be8fb | 4585 | void wxGrid::SetDefaultCellFont( const wxFont& font ) |
f85afd4e | 4586 | { |
b99be8fb | 4587 | m_defaultCellFont = font; |
f85afd4e MB |
4588 | } |
4589 | ||
b99be8fb | 4590 | void wxGrid::SetCellFont( int row, int col, const wxFont& font ) |
f85afd4e | 4591 | { |
b99be8fb VZ |
4592 | if ( CanHaveAttributes() ) |
4593 | { | |
4594 | wxGridCellAttr *attr = new wxGridCellAttr; | |
4595 | attr->SetFont(font); | |
4596 | ||
4597 | m_table->SetAttr(attr, row, col); | |
4598 | } | |
4599 | } | |
4600 | ||
4601 | void wxGrid::SetCellAlignment( int row, int col, int horiz, int vert ) | |
4602 | { | |
4603 | if ( CanHaveAttributes() ) | |
4604 | { | |
4605 | wxGridCellAttr *attr = new wxGridCellAttr; | |
4606 | attr->SetAlignment(horiz, vert); | |
4607 | ||
4608 | m_table->SetAttr(attr, row, col); | |
4609 | } | |
f85afd4e MB |
4610 | } |
4611 | ||
4612 | ||
2d66e025 | 4613 | |
f85afd4e MB |
4614 | // |
4615 | // ------ cell value accessor functions | |
4616 | // | |
4617 | ||
4618 | void wxGrid::SetCellValue( int row, int col, const wxString& s ) | |
4619 | { | |
4620 | if ( m_table ) | |
4621 | { | |
4622 | m_table->SetValue( row, col, s.c_str() ); | |
2d66e025 MB |
4623 | if ( !GetBatchCount() ) |
4624 | { | |
4625 | wxClientDC dc( m_gridWin ); | |
4626 | PrepareDC( dc ); | |
4627 | DrawCell( dc, wxGridCellCoords(row, col) ); | |
4628 | } | |
60ff3b99 | 4629 | |
2d66e025 | 4630 | #if 0 // TODO: edit in place |
60ff3b99 | 4631 | |
f85afd4e MB |
4632 | if ( m_currentCellCoords.GetRow() == row && |
4633 | m_currentCellCoords.GetCol() == col ) | |
4634 | { | |
4635 | SetEditControlValue( s ); | |
4636 | } | |
2d66e025 | 4637 | #endif |
f85afd4e | 4638 | |
f85afd4e MB |
4639 | } |
4640 | } | |
4641 | ||
4642 | ||
4643 | // | |
2d66e025 | 4644 | // ------ Block, row and col selection |
f85afd4e MB |
4645 | // |
4646 | ||
4647 | void wxGrid::SelectRow( int row, bool addToSelected ) | |
4648 | { | |
2d66e025 | 4649 | wxRect r; |
60ff3b99 | 4650 | |
f85afd4e MB |
4651 | if ( IsSelection() && addToSelected ) |
4652 | { | |
70c7a608 SN |
4653 | wxRect rect[4]; |
4654 | bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE }; | |
4655 | int i; | |
4656 | ||
4657 | wxCoord oldLeft = m_selectedTopLeft.GetCol(); | |
4658 | wxCoord oldTop = m_selectedTopLeft.GetRow(); | |
4659 | wxCoord oldRight = m_selectedBottomRight.GetCol(); | |
4660 | wxCoord oldBottom = m_selectedBottomRight.GetRow(); | |
4661 | ||
4662 | if ( oldTop > row ) | |
4663 | { | |
4664 | need_refresh[0] = TRUE; | |
4665 | rect[0] = BlockToDeviceRect( wxGridCellCoords ( row, 0 ), | |
4666 | wxGridCellCoords ( oldTop - 1, | |
4667 | m_numCols - 1 ) ); | |
f85afd4e | 4668 | m_selectedTopLeft.SetRow( row ); |
70c7a608 | 4669 | } |
8f177c8e | 4670 | |
70c7a608 SN |
4671 | if ( oldLeft > 0 ) |
4672 | { | |
4673 | need_refresh[1] = TRUE; | |
4674 | rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop, 0 ), | |
4675 | wxGridCellCoords ( oldBottom, | |
4676 | oldLeft - 1 ) ); | |
8f177c8e | 4677 | |
70c7a608 SN |
4678 | m_selectedTopLeft.SetCol( 0 ); |
4679 | } | |
4680 | ||
4681 | if ( oldBottom < row ) | |
4682 | { | |
4683 | need_refresh[2] = TRUE; | |
4684 | rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldBottom + 1, 0 ), | |
4685 | wxGridCellCoords ( row, | |
4686 | m_numCols - 1 ) ); | |
f85afd4e | 4687 | m_selectedBottomRight.SetRow( row ); |
70c7a608 | 4688 | } |
8f177c8e | 4689 | |
70c7a608 SN |
4690 | if ( oldRight < m_numCols - 1 ) |
4691 | { | |
4692 | need_refresh[3] = TRUE; | |
4693 | rect[3] = BlockToDeviceRect( wxGridCellCoords ( oldTop , | |
4694 | oldRight + 1 ), | |
4695 | wxGridCellCoords ( oldBottom, | |
4696 | m_numCols - 1 ) ); | |
4697 | m_selectedBottomRight.SetCol( m_numCols - 1 ); | |
4698 | } | |
2d66e025 | 4699 | |
70c7a608 SN |
4700 | for (i = 0; i < 4; i++ ) |
4701 | if ( need_refresh[i] && rect[i] != wxGridNoCellRect ) | |
c6a51dcd | 4702 | m_gridWin->Refresh( FALSE, &(rect[i]) ); |
f85afd4e MB |
4703 | } |
4704 | else | |
4705 | { | |
2d66e025 | 4706 | r = SelectionToDeviceRect(); |
f85afd4e | 4707 | ClearSelection(); |
c6a51dcd | 4708 | if ( r != wxGridNoCellRect ) m_gridWin->Refresh( FALSE, &r ); |
60ff3b99 | 4709 | |
f85afd4e MB |
4710 | m_selectedTopLeft.Set( row, 0 ); |
4711 | m_selectedBottomRight.Set( row, m_numCols-1 ); | |
2d66e025 | 4712 | r = SelectionToDeviceRect(); |
c6a51dcd | 4713 | m_gridWin->Refresh( FALSE, &r ); |
f85afd4e | 4714 | } |
8f177c8e | 4715 | |
f85afd4e | 4716 | wxGridRangeSelectEvent gridEvt( GetId(), |
b5f788a5 | 4717 | EVT_GRID_RANGE_SELECT, |
f85afd4e MB |
4718 | this, |
4719 | m_selectedTopLeft, | |
4720 | m_selectedBottomRight ); | |
4721 | ||
4722 | GetEventHandler()->ProcessEvent(gridEvt); | |
4723 | } | |
4724 | ||
4725 | ||
4726 | void wxGrid::SelectCol( int col, bool addToSelected ) | |
4727 | { | |
2d66e025 | 4728 | if ( IsSelection() && addToSelected ) |
f85afd4e | 4729 | { |
70c7a608 SN |
4730 | wxRect rect[4]; |
4731 | bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE }; | |
4732 | int i; | |
4733 | ||
4734 | wxCoord oldLeft = m_selectedTopLeft.GetCol(); | |
4735 | wxCoord oldTop = m_selectedTopLeft.GetRow(); | |
4736 | wxCoord oldRight = m_selectedBottomRight.GetCol(); | |
4737 | wxCoord oldBottom = m_selectedBottomRight.GetRow(); | |
4738 | ||
4739 | if ( oldLeft > col ) | |
4740 | { | |
4741 | need_refresh[0] = TRUE; | |
4742 | rect[0] = BlockToDeviceRect( wxGridCellCoords ( 0, col ), | |
b99be8fb | 4743 | wxGridCellCoords ( m_numRows - 1, |
70c7a608 | 4744 | oldLeft - 1 ) ); |
f85afd4e | 4745 | m_selectedTopLeft.SetCol( col ); |
70c7a608 | 4746 | } |
f85afd4e | 4747 | |
70c7a608 SN |
4748 | if ( oldTop > 0 ) |
4749 | { | |
4750 | need_refresh[1] = TRUE; | |
4751 | rect[1] = BlockToDeviceRect( wxGridCellCoords ( 0, oldLeft ), | |
b99be8fb | 4752 | wxGridCellCoords ( oldTop - 1, |
70c7a608 SN |
4753 | oldRight ) ); |
4754 | m_selectedTopLeft.SetRow( 0 ); | |
4755 | } | |
f85afd4e | 4756 | |
70c7a608 SN |
4757 | if ( oldRight < col ) |
4758 | { | |
4759 | need_refresh[2] = TRUE; | |
4760 | rect[2] = BlockToDeviceRect( wxGridCellCoords ( 0, oldRight + 1 ), | |
4761 | wxGridCellCoords ( m_numRows - 1, | |
4762 | col ) ); | |
f85afd4e | 4763 | m_selectedBottomRight.SetCol( col ); |
70c7a608 | 4764 | } |
f85afd4e | 4765 | |
70c7a608 SN |
4766 | if ( oldBottom < m_numRows - 1 ) |
4767 | { | |
4768 | need_refresh[3] = TRUE; | |
4769 | rect[3] = BlockToDeviceRect( wxGridCellCoords ( oldBottom + 1, | |
4770 | oldLeft ), | |
4771 | wxGridCellCoords ( m_numRows - 1, | |
4772 | oldRight ) ); | |
4773 | m_selectedBottomRight.SetRow( m_numRows - 1 ); | |
4774 | } | |
2d66e025 | 4775 | |
70c7a608 SN |
4776 | for (i = 0; i < 4; i++ ) |
4777 | if ( need_refresh[i] && rect[i] != wxGridNoCellRect ) | |
c6a51dcd | 4778 | m_gridWin->Refresh( FALSE, &(rect[i]) ); |
f85afd4e MB |
4779 | } |
4780 | else | |
4781 | { | |
70c7a608 | 4782 | wxRect r; |
b99be8fb | 4783 | |
2d66e025 | 4784 | r = SelectionToDeviceRect(); |
f85afd4e | 4785 | ClearSelection(); |
c6a51dcd | 4786 | if ( r != wxGridNoCellRect ) m_gridWin->Refresh( FALSE, &r ); |
60ff3b99 | 4787 | |
f85afd4e MB |
4788 | m_selectedTopLeft.Set( 0, col ); |
4789 | m_selectedBottomRight.Set( m_numRows-1, col ); | |
2d66e025 | 4790 | r = SelectionToDeviceRect(); |
c6a51dcd | 4791 | m_gridWin->Refresh( FALSE, &r ); |
f85afd4e MB |
4792 | } |
4793 | ||
4794 | wxGridRangeSelectEvent gridEvt( GetId(), | |
b5f788a5 | 4795 | EVT_GRID_RANGE_SELECT, |
f85afd4e MB |
4796 | this, |
4797 | m_selectedTopLeft, | |
4798 | m_selectedBottomRight ); | |
4799 | ||
4800 | GetEventHandler()->ProcessEvent(gridEvt); | |
4801 | } | |
4802 | ||
4803 | ||
4804 | void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol ) | |
4805 | { | |
4806 | int temp; | |
da6af900 | 4807 | wxGridCellCoords updateTopLeft, updateBottomRight; |
8f177c8e | 4808 | |
f85afd4e MB |
4809 | if ( topRow > bottomRow ) |
4810 | { | |
4811 | temp = topRow; | |
4812 | topRow = bottomRow; | |
4813 | bottomRow = temp; | |
4814 | } | |
4815 | ||
4816 | if ( leftCol > rightCol ) | |
4817 | { | |
4818 | temp = leftCol; | |
4819 | leftCol = rightCol; | |
4820 | rightCol = temp; | |
4821 | } | |
f0102d2a | 4822 | |
70c7a608 SN |
4823 | updateTopLeft = wxGridCellCoords( topRow, leftCol ); |
4824 | updateBottomRight = wxGridCellCoords( bottomRow, rightCol ); | |
da6af900 | 4825 | |
70c7a608 SN |
4826 | if ( m_selectedTopLeft != updateTopLeft || |
4827 | m_selectedBottomRight != updateBottomRight ) | |
da6af900 | 4828 | { |
70c7a608 SN |
4829 | // Compute two optimal update rectangles: |
4830 | // Either one rectangle is a real subset of the | |
4831 | // other, or they are (almost) disjoint! | |
4832 | wxRect rect[4]; | |
4833 | bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE }; | |
4834 | int i; | |
4835 | ||
4836 | // Store intermediate values | |
4837 | wxCoord oldLeft = m_selectedTopLeft.GetCol(); | |
4838 | wxCoord oldTop = m_selectedTopLeft.GetRow(); | |
4839 | wxCoord oldRight = m_selectedBottomRight.GetCol(); | |
4840 | wxCoord oldBottom = m_selectedBottomRight.GetRow(); | |
4841 | ||
4842 | // Determine the outer/inner coordinates. | |
4843 | if (oldLeft > leftCol) | |
f0102d2a | 4844 | { |
70c7a608 SN |
4845 | temp = oldLeft; |
4846 | oldLeft = leftCol; | |
4847 | leftCol = temp; | |
cb309039 | 4848 | } |
70c7a608 | 4849 | if (oldTop > topRow ) |
f0102d2a | 4850 | { |
70c7a608 SN |
4851 | temp = oldTop; |
4852 | oldTop = topRow; | |
4853 | topRow = temp; | |
cb309039 SN |
4854 | } |
4855 | if (oldRight < rightCol ) | |
70c7a608 SN |
4856 | { |
4857 | temp = oldRight; | |
4858 | oldRight = rightCol; | |
4859 | rightCol = temp; | |
cb309039 SN |
4860 | } |
4861 | if (oldBottom < bottomRow) | |
4862 | { | |
70c7a608 SN |
4863 | temp = oldBottom; |
4864 | oldBottom = bottomRow; | |
4865 | bottomRow = temp; | |
cb309039 | 4866 | } |
70c7a608 SN |
4867 | |
4868 | // Now, either the stuff marked old is the outer | |
4869 | // rectangle or we don't have a situation where one | |
4870 | // is contained in the other. | |
b99be8fb | 4871 | |
cb309039 SN |
4872 | if ( oldLeft < leftCol ) |
4873 | { | |
4874 | need_refresh[0] = TRUE; | |
4875 | rect[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop, | |
4876 | oldLeft ), | |
b99be8fb | 4877 | wxGridCellCoords ( oldBottom, |
cb309039 SN |
4878 | leftCol - 1 ) ); |
4879 | } | |
4880 | ||
4881 | if ( oldTop < topRow ) | |
4882 | { | |
4883 | need_refresh[1] = TRUE; | |
4884 | rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop, | |
4885 | leftCol ), | |
b99be8fb | 4886 | wxGridCellCoords ( topRow - 1, |
cb309039 SN |
4887 | rightCol ) ); |
4888 | } | |
4889 | ||
4890 | if ( oldRight > rightCol ) | |
4891 | { | |
4892 | need_refresh[2] = TRUE; | |
4893 | rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop, | |
4894 | rightCol + 1 ), | |
4895 | wxGridCellCoords ( oldBottom, | |
4896 | oldRight ) ); | |
4897 | } | |
4898 | ||
4899 | if ( oldBottom > bottomRow ) | |
4900 | { | |
4901 | need_refresh[3] = TRUE; | |
4902 | rect[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow + 1, | |
4903 | leftCol ), | |
4904 | wxGridCellCoords ( oldBottom, | |
4905 | rightCol ) ); | |
4906 | } | |
70c7a608 SN |
4907 | |
4908 | ||
4909 | // Change Selection | |
4910 | m_selectedTopLeft = updateTopLeft; | |
4911 | m_selectedBottomRight = updateBottomRight; | |
b99be8fb | 4912 | |
70c7a608 SN |
4913 | // various Refresh() calls |
4914 | for (i = 0; i < 4; i++ ) | |
4915 | if ( need_refresh[i] && rect[i] != wxGridNoCellRect ) | |
c6a51dcd | 4916 | m_gridWin->Refresh( FALSE, &(rect[i]) ); |
da6af900 | 4917 | } |
f85afd4e MB |
4918 | |
4919 | // only generate an event if the block is not being selected by | |
4920 | // dragging the mouse (in which case the event will be generated in | |
2d66e025 | 4921 | // the mouse event handler) |
f85afd4e MB |
4922 | if ( !m_isDragging ) |
4923 | { | |
4924 | wxGridRangeSelectEvent gridEvt( GetId(), | |
b5f788a5 | 4925 | EVT_GRID_RANGE_SELECT, |
f85afd4e MB |
4926 | this, |
4927 | m_selectedTopLeft, | |
4928 | m_selectedBottomRight ); | |
8f177c8e | 4929 | |
f85afd4e MB |
4930 | GetEventHandler()->ProcessEvent(gridEvt); |
4931 | } | |
4932 | } | |
4933 | ||
4934 | void wxGrid::SelectAll() | |
4935 | { | |
4936 | m_selectedTopLeft.Set( 0, 0 ); | |
4937 | m_selectedBottomRight.Set( m_numRows-1, m_numCols-1 ); | |
4938 | ||
2d66e025 | 4939 | m_gridWin->Refresh(); |
f85afd4e MB |
4940 | } |
4941 | ||
4942 | ||
4943 | void wxGrid::ClearSelection() | |
4944 | { | |
2d66e025 MB |
4945 | m_selectedTopLeft = wxGridNoCellCoords; |
4946 | m_selectedBottomRight = wxGridNoCellCoords; | |
8f177c8e | 4947 | } |
f85afd4e MB |
4948 | |
4949 | ||
da6af900 | 4950 | // This function returns the rectangle that encloses the given block |
2d66e025 MB |
4951 | // in device coords clipped to the client size of the grid window. |
4952 | // | |
58dd5b3b MB |
4953 | wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft, |
4954 | const wxGridCellCoords &bottomRight ) | |
f85afd4e | 4955 | { |
58dd5b3b | 4956 | wxRect rect( wxGridNoCellRect ); |
f85afd4e MB |
4957 | wxRect cellRect; |
4958 | ||
58dd5b3b MB |
4959 | cellRect = CellToRect( topLeft ); |
4960 | if ( cellRect != wxGridNoCellRect ) | |
f85afd4e | 4961 | { |
58dd5b3b MB |
4962 | rect = cellRect; |
4963 | } | |
4964 | else | |
4965 | { | |
4966 | rect = wxRect( 0, 0, 0, 0 ); | |
4967 | } | |
60ff3b99 | 4968 | |
58dd5b3b MB |
4969 | cellRect = CellToRect( bottomRight ); |
4970 | if ( cellRect != wxGridNoCellRect ) | |
4971 | { | |
4972 | rect += cellRect; | |
2d66e025 MB |
4973 | } |
4974 | else | |
4975 | { | |
4976 | return wxGridNoCellRect; | |
f85afd4e MB |
4977 | } |
4978 | ||
58dd5b3b MB |
4979 | // convert to scrolled coords |
4980 | // | |
4981 | int left, top, right, bottom; | |
4982 | CalcScrolledPosition( rect.GetLeft(), rect.GetTop(), &left, &top ); | |
4983 | CalcScrolledPosition( rect.GetRight(), rect.GetBottom(), &right, &bottom ); | |
4984 | ||
4985 | int cw, ch; | |
4986 | m_gridWin->GetClientSize( &cw, &ch ); | |
4987 | ||
4988 | rect.SetLeft( wxMax(0, left) ); | |
4989 | rect.SetTop( wxMax(0, top) ); | |
4990 | rect.SetRight( wxMin(cw, right) ); | |
4991 | rect.SetBottom( wxMin(ch, bottom) ); | |
4992 | ||
f85afd4e MB |
4993 | return rect; |
4994 | } | |
4995 | ||
4996 | ||
58dd5b3b | 4997 | |
f85afd4e MB |
4998 | // |
4999 | // ------ Grid event classes | |
5000 | // | |
5001 | ||
5002 | IMPLEMENT_DYNAMIC_CLASS( wxGridEvent, wxEvent ) | |
5003 | ||
5004 | wxGridEvent::wxGridEvent( int id, wxEventType type, wxObject* obj, | |
5005 | int row, int col, int x, int y, | |
5006 | bool control, bool shift, bool alt, bool meta ) | |
5007 | : wxNotifyEvent( type, id ) | |
5008 | { | |
5009 | m_row = row; | |
5010 | m_col = col; | |
5011 | m_x = x; | |
5012 | m_y = y; | |
5013 | m_control = control; | |
5014 | m_shift = shift; | |
5015 | m_alt = alt; | |
5016 | m_meta = meta; | |
8f177c8e | 5017 | |
f85afd4e MB |
5018 | SetEventObject(obj); |
5019 | } | |
5020 | ||
5021 | ||
5022 | IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent, wxEvent ) | |
5023 | ||
5024 | wxGridSizeEvent::wxGridSizeEvent( int id, wxEventType type, wxObject* obj, | |
5025 | int rowOrCol, int x, int y, | |
5026 | bool control, bool shift, bool alt, bool meta ) | |
5027 | : wxNotifyEvent( type, id ) | |
5028 | { | |
5029 | m_rowOrCol = rowOrCol; | |
5030 | m_x = x; | |
5031 | m_y = y; | |
5032 | m_control = control; | |
5033 | m_shift = shift; | |
5034 | m_alt = alt; | |
5035 | m_meta = meta; | |
8f177c8e | 5036 | |
f85afd4e MB |
5037 | SetEventObject(obj); |
5038 | } | |
5039 | ||
5040 | ||
5041 | IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent, wxEvent ) | |
5042 | ||
5043 | wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id, wxEventType type, wxObject* obj, | |
8f177c8e VZ |
5044 | const wxGridCellCoords& topLeft, |
5045 | const wxGridCellCoords& bottomRight, | |
5046 | bool control, bool shift, bool alt, bool meta ) | |
5047 | : wxNotifyEvent( type, id ) | |
f85afd4e MB |
5048 | { |
5049 | m_topLeft = topLeft; | |
5050 | m_bottomRight = bottomRight; | |
5051 | m_control = control; | |
5052 | m_shift = shift; | |
5053 | m_alt = alt; | |
5054 | m_meta = meta; | |
5055 | ||
5056 | SetEventObject(obj); | |
5057 | } | |
5058 | ||
5059 | ||
5060 | #endif // ifndef wxUSE_NEW_GRID | |
5061 |