]> git.saurik.com Git - wxWidgets.git/blob - src/generic/listctrl.cpp
wxTextFile::Type changed to ::wxTextFileType (portability)
[wxWidgets.git] / src / generic / listctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: listctrl.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "listctrl.h"
12 #endif
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #include "wx/dcscreen.h"
22 #include "wx/app.h"
23 #include "wx/listctrl.h"
24
25 //-----------------------------------------------------------------------------
26 // wxListItemData
27 //-----------------------------------------------------------------------------
28
29 IMPLEMENT_DYNAMIC_CLASS(wxListItemData,wxObject);
30
31 wxListItemData::wxListItemData(void)
32 {
33 m_image = -1;
34 m_data = 0;
35 m_xpos = 0;
36 m_ypos = 0;
37 m_width = 0;
38 m_height = 0;
39 m_colour = wxBLACK;
40 }
41
42 wxListItemData::wxListItemData( const wxListItem &info )
43 {
44 m_image = -1;
45 m_data = 0;
46 m_colour = info.m_colour;
47 SetItem( info );
48 }
49
50 void wxListItemData::SetItem( const wxListItem &info )
51 {
52 if (info.m_mask & wxLIST_MASK_TEXT) m_text = info.m_text;
53 if (info.m_mask & wxLIST_MASK_IMAGE) m_image = info.m_image;
54 if (info.m_mask & wxLIST_MASK_DATA) m_data = info.m_data;
55 m_colour = info.m_colour;
56 m_xpos = 0;
57 m_ypos = 0;
58 m_width = info.m_width;
59 m_height = 0;
60 }
61
62 void wxListItemData::SetText( const wxString &s )
63 {
64 m_text = s;
65 }
66
67 void wxListItemData::SetImage( int image )
68 {
69 m_image = image;
70 }
71
72 void wxListItemData::SetData( long data )
73 {
74 m_data = data;
75 }
76
77 void wxListItemData::SetPosition( int x, int y )
78 {
79 m_xpos = x;
80 m_ypos = y;
81 }
82
83 void wxListItemData::SetSize( int width, int height )
84 {
85 if (width != -1) m_width = width;
86 if (height != -1) m_height = height;
87 }
88
89 void wxListItemData::SetColour( wxColour *col )
90 {
91 m_colour = col;
92 }
93
94 bool wxListItemData::HasImage(void) const
95 {
96 return (m_image >= 0);
97 }
98
99 bool wxListItemData::HasText(void) const
100 {
101 return (!m_text.IsNull());
102 }
103
104 bool wxListItemData::IsHit( int x, int y ) const
105 {
106 return ((x >= m_xpos) && (x <= m_xpos+m_width) && (y >= m_ypos) && (y <= m_ypos+m_height));
107 }
108
109 void wxListItemData::GetText( wxString &s )
110 {
111 s = m_text;
112 }
113
114 int wxListItemData::GetX( void ) const
115 {
116 return m_xpos;
117 }
118
119 int wxListItemData::GetY( void ) const
120 {
121 return m_ypos;
122 }
123
124 int wxListItemData::GetWidth(void) const
125 {
126 return m_width;
127 }
128
129 int wxListItemData::GetHeight(void) const
130 {
131 return m_height;
132 }
133
134 int wxListItemData::GetImage(void) const
135 {
136 return m_image;
137 }
138
139 void wxListItemData::GetItem( wxListItem &info )
140 {
141 info.m_text = m_text;
142 info.m_image = m_image;
143 info.m_data = m_data;
144 }
145
146 wxColour *wxListItemData::GetColour(void)
147 {
148 return m_colour;
149 }
150
151 //-----------------------------------------------------------------------------
152 // wxListHeaderData
153 //-----------------------------------------------------------------------------
154
155 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData,wxObject);
156
157 wxListHeaderData::wxListHeaderData(void)
158 {
159 m_mask = 0;
160 m_image = 0;
161 m_format = 0;
162 m_width = 0;
163 m_xpos = 0;
164 m_ypos = 0;
165 m_height = 0;
166 }
167
168 wxListHeaderData::wxListHeaderData( const wxListItem &item )
169 {
170 SetItem( item );
171 m_xpos = 0;
172 m_ypos = 0;
173 m_height = 0;
174 }
175
176 void wxListHeaderData::SetItem( const wxListItem &item )
177 {
178 m_mask = item.m_mask;
179 m_text = item.m_text;
180 m_image = item.m_image;
181 m_format = item.m_format;
182 m_width = item.m_width;
183 if (m_width < 0) m_width = 80;
184 if (m_width < 6) m_width = 6;
185 }
186
187 void wxListHeaderData::SetPosition( int x, int y )
188 {
189 m_xpos = x;
190 m_ypos = y;
191 }
192
193 void wxListHeaderData::SetHeight( int h )
194 {
195 m_height = h;
196 }
197
198 void wxListHeaderData::SetWidth( int w )
199 {
200 m_width = w;
201 if (m_width < 0) m_width = 80;
202 if (m_width < 6) m_width = 6;
203 }
204
205 void wxListHeaderData::SetFormat( int format )
206 {
207 m_format = format;
208 }
209
210 bool wxListHeaderData::HasImage(void) const
211 {
212 return (m_image != 0);
213 }
214
215 bool wxListHeaderData::HasText(void) const
216 {
217 return (m_text.Length() > 0);
218 }
219
220 bool wxListHeaderData::IsHit( int x, int y ) const
221 {
222 return ((x >= m_xpos) && (x <= m_xpos+m_width) && (y >= m_ypos) && (y <= m_ypos+m_height));
223 }
224
225 void wxListHeaderData::GetItem( wxListItem &item )
226 {
227 item.m_mask = m_mask;
228 item.m_text = m_text;
229 item.m_image = m_image;
230 item.m_format = m_format;
231 item.m_width = m_width;
232 }
233
234 void wxListHeaderData::GetText( wxString &s )
235 {
236 s = m_text;
237 }
238
239 int wxListHeaderData::GetImage(void) const
240 {
241 return m_image;
242 }
243
244 int wxListHeaderData::GetWidth(void) const
245 {
246 return m_width;
247 }
248
249 int wxListHeaderData::GetFormat(void) const
250 {
251 return m_format;
252 }
253
254 //-----------------------------------------------------------------------------
255 // wxListLineData
256 //-----------------------------------------------------------------------------
257
258 IMPLEMENT_DYNAMIC_CLASS(wxListLineData,wxObject);
259
260 wxListLineData::wxListLineData( wxListMainWindow *owner, int mode, wxBrush *hilightBrush )
261 {
262 m_mode = mode;
263 m_hilighted = FALSE;
264 m_owner = owner;
265 m_hilightBrush = hilightBrush;
266 m_items.DeleteContents( TRUE );
267 m_spacing = 0;
268 }
269
270 void wxListLineData::CalculateSize( wxDC *dc, int spacing )
271 {
272 m_spacing = spacing;
273 switch (m_mode)
274 {
275 case wxLC_ICON:
276 {
277 m_bound_all.width = m_spacing;
278 m_bound_all.height = m_spacing+13;
279 wxNode *node = m_items.First();
280 if (node)
281 {
282 wxListItemData *item = (wxListItemData*)node->Data();
283 wxString s;
284 item->GetText( s );
285 long lw,lh;
286 dc->GetTextExtent( s, &lw, &lh );
287 if (lw > m_spacing) m_bound_all.width = lw;
288 }
289 break;
290 }
291 case wxLC_LIST:
292 {
293 wxNode *node = m_items.First();
294 if (node)
295 {
296 wxListItemData *item = (wxListItemData*)node->Data();
297 wxString s;
298 item->GetText( s );
299 long lw,lh;
300 dc->GetTextExtent( s, &lw, &lh );
301 m_bound_all.width = lw;
302 m_bound_all.height = lh;
303 }
304 break;
305 }
306 case wxLC_REPORT:
307 {
308 m_bound_all.width = 0;
309 m_bound_all.height = 0;
310 wxNode *node = m_items.First();
311 while (node)
312 {
313 wxListItemData *item = (wxListItemData*)node->Data();
314 wxString s;
315 item->GetText( s );
316 if (s.IsNull()) s = "H";
317 long lw,lh;
318 dc->GetTextExtent( s, &lw, &lh );
319 item->SetSize( item->GetWidth(), lh );
320 m_bound_all.width += lw;
321 m_bound_all.height = lh;
322 node = node->Next();
323 }
324 break;
325 }
326 }
327 }
328
329 void wxListLineData::SetPosition( wxDC *dc, int x, int y, int window_width )
330 {
331 m_bound_all.x = x;
332 m_bound_all.y = y;
333 switch (m_mode)
334 {
335 case wxLC_ICON:
336 {
337 AssignRect( m_bound_icon, 0, 0, 0, 0 );
338 AssignRect( m_bound_label, 0, 0, 0, 0 );
339 AssignRect( m_bound_hilight, m_bound_all );
340 wxNode *node = m_items.First();
341 if (node)
342 {
343 wxListItemData *item = (wxListItemData*)node->Data();
344 if (item->HasImage())
345 {
346 wxListItemData *item = (wxListItemData*)node->Data();
347 int w = 0;
348 int h = 0;
349 m_owner->GetImageSize( item->GetImage(), w, h );
350 m_bound_icon.x = m_bound_all.x + (m_spacing/2) - (w/2);
351 m_bound_icon.y = m_bound_all.y + m_spacing - h - 5;
352 m_bound_icon.width = w;
353 m_bound_icon.height = h;
354 if (!item->HasText())
355 {
356 AssignRect( m_bound_hilight, m_bound_icon );
357 m_bound_hilight.x -= 5;
358 m_bound_hilight.y -= 5;
359 m_bound_hilight.width += 9;
360 m_bound_hilight.height += 9;
361 }
362 }
363 if (item->HasText())
364 {
365 wxString s;
366 item->GetText( s );
367 long lw,lh;
368 dc->GetTextExtent( s, &lw, &lh );
369 if (m_bound_all.width > m_spacing)
370 m_bound_label.x = m_bound_all.x;
371 else
372 m_bound_label.x = m_bound_all.x + (m_spacing/2) - lw/2;
373 m_bound_label.y = m_bound_all.y + m_bound_all.height - lh;
374 m_bound_label.width = lw;
375 m_bound_label.height = lh;
376 AssignRect( m_bound_hilight, m_bound_label );
377 m_bound_hilight.x -= 2;
378 m_bound_hilight.y -= 2;
379 m_bound_hilight.width += 4;
380 m_bound_hilight.height += 4;
381 }
382 }
383 break;
384 }
385 case wxLC_LIST:
386 {
387 AssignRect( m_bound_label, m_bound_all );
388 m_bound_all.x -= 2;
389 m_bound_all.y -= 2;
390 m_bound_all.width += 4;
391 m_bound_all.height += 3;
392 AssignRect( m_bound_hilight, m_bound_all );
393 AssignRect( m_bound_icon, 0, 0, 0, 0 );
394 break;
395 }
396 case wxLC_REPORT:
397 {
398 long lw,lh;
399 dc->GetTextExtent( "H", &lw, &lh );
400 m_bound_all.x = 0;
401 m_bound_all.y -= 0;
402 m_bound_all.height = lh+3;
403 m_bound_all.width = window_width;
404 AssignRect( m_bound_hilight, m_bound_all );
405 AssignRect( m_bound_label, 0, 0, 0 ,0 );
406 AssignRect( m_bound_icon, 0, 0, 0, 0 );
407 break;
408 }
409 }
410 }
411
412 void wxListLineData::SetColumnPosition( int index, int x )
413 {
414 int i = index;
415 wxNode *node = m_items.Nth( i );
416 if (node)
417 {
418 wxListItemData *item = (wxListItemData*)node->Data();
419 item->SetPosition( x, m_bound_all.y+1 );
420 }
421 }
422
423 void wxListLineData::GetSize( int &width, int &height )
424 {
425 width = m_bound_all.width;
426 height = m_bound_all.height;
427 }
428
429 void wxListLineData::GetExtent( int &x, int &y, int &width, int &height )
430 {
431 x = m_bound_all.x;
432 y = m_bound_all.y;
433 width = m_bound_all.width;
434 height = m_bound_all.height;
435 }
436
437 void wxListLineData::GetLabelExtent( int &x, int &y, int &width, int &height )
438 {
439 x = m_bound_label.x;
440 y = m_bound_label.y;
441 width = m_bound_label.width;
442 height = m_bound_label.height;
443 }
444
445 void wxListLineData::GetRect( wxRectangle &rect )
446 {
447 AssignRect( rect, m_bound_all );
448 }
449
450 long wxListLineData::IsHit( int x, int y )
451 {
452 wxNode *node = m_items.First();
453 if (node)
454 {
455 wxListItemData *item = (wxListItemData*)node->Data();
456 if (item->HasImage() && IsInRect( x, y, m_bound_icon )) return wxLIST_HITTEST_ONITEMICON;
457 if (item->HasText() && IsInRect( x, y, m_bound_label )) return wxLIST_HITTEST_ONITEMLABEL;
458 // if (!(item->HasImage() || item->HasText())) return 0;
459 }
460 // if there is no icon or text = empty
461 if (IsInRect( x, y, m_bound_all )) return wxLIST_HITTEST_ONITEMICON;
462 return 0;
463 }
464
465 void wxListLineData::InitItems( int num )
466 {
467 for (int i = 0; i < num; i++) m_items.Append( new wxListItemData() );
468 }
469
470 void wxListLineData::SetItem( int index, const wxListItem &info )
471 {
472 wxNode *node = m_items.Nth( index );
473 if (node)
474 {
475 wxListItemData *item = (wxListItemData*)node->Data();
476 item->SetItem( info );
477 }
478 }
479
480 void wxListLineData::GetItem( int index, wxListItem &info )
481 {
482 int i = index;
483 wxNode *node = m_items.Nth( i );
484 if (node)
485 {
486 wxListItemData *item = (wxListItemData*)node->Data();
487 item->GetItem( info );
488 }
489 }
490
491 void wxListLineData::GetText( int index, wxString &s )
492 {
493 int i = index;
494 wxNode *node = m_items.Nth( i );
495 s = "";
496 if (node)
497 {
498 wxListItemData *item = (wxListItemData*)node->Data();
499 item->GetText( s );
500 }
501 }
502
503 void wxListLineData::SetText( int index, const wxString s )
504 {
505 int i = index;
506 wxNode *node = m_items.Nth( i );
507 if (node)
508 {
509 wxListItemData *item = (wxListItemData*)node->Data();
510 item->SetText( s );
511 }
512 }
513
514 int wxListLineData::GetImage( int index )
515 {
516 int i = index;
517 wxNode *node = m_items.Nth( i );
518 if (node)
519 {
520 wxListItemData *item = (wxListItemData*)node->Data();
521 return item->GetImage();
522 }
523 return -1;
524 }
525
526 void wxListLineData::DoDraw( wxDC *dc, bool hilight, bool paintBG )
527 {
528 long dev_x = dc->LogicalToDeviceX( m_bound_all.x-2 );
529 long dev_y = dc->LogicalToDeviceY( m_bound_all.y-2 );
530 long dev_w = dc->LogicalToDeviceXRel( m_bound_all.width+4 );
531 long dev_h = dc->LogicalToDeviceYRel( m_bound_all.height+4 );
532
533 if (!m_owner->IsExposed( dev_x, dev_y, dev_w, dev_h ))
534 {
535 return;
536 }
537
538 if (paintBG)
539 {
540 if (hilight)
541 {
542 dc->SetBrush( * m_hilightBrush );
543 dc->SetPen( * wxTRANSPARENT_PEN );
544 }
545 else
546 {
547 dc->SetBrush( * wxWHITE_BRUSH );
548 dc->SetPen( * wxTRANSPARENT_PEN );
549 }
550 dc->DrawRectangle( m_bound_hilight.x, m_bound_hilight.y,
551 m_bound_hilight.width, m_bound_hilight.height );
552 }
553
554 if (m_mode == wxLC_REPORT)
555 {
556 wxString s;
557 wxNode *node = m_items.First();
558 while (node)
559 {
560 wxListItemData *item = (wxListItemData*)node->Data();
561 dc->SetClippingRegion( item->GetX(), item->GetY(), item->GetWidth()-3, item->GetHeight() );
562 int x = item->GetX();
563 if (item->HasImage())
564 {
565 int y = 0;
566 m_owner->DrawImage( item->GetImage(), dc, x, item->GetY() );
567 m_owner->GetImageSize( item->GetImage(), x, y );
568 x += item->GetX() + 5;
569 }
570 if (item->HasText())
571 {
572 item->GetText( s );
573 if (hilight)
574 dc->SetTextForeground( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
575 else
576 dc->SetTextForeground( *item->GetColour() );
577 dc->DrawText( s, x, item->GetY() );
578 }
579 dc->DestroyClippingRegion();
580 node = node->Next();
581 }
582 }
583 else
584 {
585 wxNode *node = m_items.First();
586 if (node)
587 {
588 wxListItemData *item = (wxListItemData*)node->Data();
589 if (item->HasImage())
590 {
591 m_owner->DrawImage( item->GetImage(), dc, m_bound_icon.x, m_bound_icon.y );
592 }
593 if (item->HasText())
594 {
595 wxString s;
596 item->GetText( s );
597 if (hilight)
598 dc->SetTextForeground( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
599 else
600 dc->SetTextForeground( * item->GetColour() );
601 dc->DrawText( s, m_bound_label.x, m_bound_label.y );
602 }
603 }
604 }
605 }
606
607 void wxListLineData::Hilight( bool on )
608 {
609 if (on == m_hilighted) return;
610 if (on)
611 m_owner->SelectLine( this );
612 else
613 m_owner->DeselectLine( this );
614 m_hilighted = on;
615 }
616
617 void wxListLineData::ReverseHilight( void )
618 {
619 m_hilighted = !m_hilighted;
620 if (m_hilighted)
621 m_owner->SelectLine( this );
622 else
623 m_owner->DeselectLine( this );
624 }
625
626 void wxListLineData::DrawRubberBand( wxDC *dc, bool on )
627 {
628 if (on)
629 {
630 dc->SetPen( * wxBLACK_PEN );
631 dc->SetBrush( * wxTRANSPARENT_BRUSH );
632 dc->DrawRectangle( m_bound_hilight.x, m_bound_hilight.y,
633 m_bound_hilight.width, m_bound_hilight.height );
634 }
635 }
636
637 void wxListLineData::Draw( wxDC *dc )
638 {
639 DoDraw( dc, m_hilighted, m_hilighted );
640 }
641
642 bool wxListLineData::IsInRect( int x, int y, const wxRectangle &rect )
643 {
644 return ((x >= rect.x) && (x <= rect.x+rect.width) &&
645 (y >= rect.y) && (y <= rect.y+rect.height));
646 }
647
648 bool wxListLineData::IsHilighted( void )
649 {
650 return m_hilighted;
651 }
652
653 void wxListLineData::AssignRect( wxRectangle &dest, int x, int y, int width, int height )
654 {
655 dest.x = x;
656 dest.y = y;
657 dest.width = width;
658 dest.height = height;
659 }
660
661 void wxListLineData::AssignRect( wxRectangle &dest, const wxRectangle &source )
662 {
663 dest.x = source.x;
664 dest.y = source.y;
665 dest.width = source.width;
666 dest.height = source.height;
667 }
668
669 //-----------------------------------------------------------------------------
670 // wxListHeaderWindow
671 //-----------------------------------------------------------------------------
672
673 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow,wxWindow);
674
675 BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow)
676 EVT_PAINT (wxListHeaderWindow::OnPaint)
677 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse)
678 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus)
679 END_EVENT_TABLE()
680
681 wxListHeaderWindow::wxListHeaderWindow( void )
682 {
683 m_owner = (wxListMainWindow *) NULL;
684 m_currentCursor = (wxCursor *) NULL;
685 m_resizeCursor = (wxCursor *) NULL;
686 m_isDraging = FALSE;
687 }
688
689 wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, wxWindowID id, wxListMainWindow *owner,
690 const wxPoint &pos, const wxSize &size,
691 long style, const wxString &name ) :
692 wxWindow( win, id, pos, size, style, name )
693 {
694 m_owner = owner;
695 // m_currentCursor = wxSTANDARD_CURSOR;
696 m_currentCursor = (wxCursor *) NULL;
697 m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
698 m_isDraging = FALSE;
699 }
700
701 wxListHeaderWindow::~wxListHeaderWindow( void )
702 {
703 delete m_resizeCursor;
704 }
705
706 void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h )
707 {
708 const int m_corner = 1;
709
710 dc->SetBrush( *wxTRANSPARENT_BRUSH );
711
712 dc->SetPen( *wxBLACK_PEN );
713 dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer)
714 dc->DrawRectangle( x, y+h, w, 1 ); // bottom (outer)
715
716 wxPen pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID );
717
718 dc->SetPen( pen );
719 dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner)
720 dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner)
721
722 dc->SetPen( *wxWHITE_PEN );
723 dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer)
724 dc->DrawRectangle( x, y, 1, h ); // left (outer)
725 dc->DrawLine( x, y+h-1, x+1, y+h-1 );
726 dc->DrawLine( x+w-1, y, x+w-1, y+1 );
727 }
728
729 void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
730 {
731 wxPaintDC dc( this );
732 PrepareDC( dc );
733
734 dc.BeginDrawing();
735
736 dc.SetFont( GetFont() );
737
738 int w = 0;
739 int h = 0;
740 int x = 0;
741 int y = 0;
742 GetClientSize( &w, &h );
743
744 dc.SetTextForeground( *wxBLACK );
745 if (m_foregroundColour.Ok()) dc.SetTextForeground( m_foregroundColour );
746
747 x = 1;
748 y = 1;
749 int numColumns = m_owner->GetColumnCount();
750 wxListItem item;
751 for (int i = 0; i < numColumns; i++)
752 {
753 m_owner->GetColumn( i, item );
754 int cw = item.m_width-2;
755 if ((i+1 == numColumns) || (x+item.m_width > w-5)) cw = w-x-1;
756 dc.SetPen( *wxWHITE_PEN );
757
758 DoDrawRect( &dc, x, y, cw, h-2 );
759 dc.SetClippingRegion( x, y, cw-5, h-4 );
760 dc.DrawText( item.m_text, x+4, y+3 );
761 dc.DestroyClippingRegion();
762 x += item.m_width;
763 if (x > w+5) break;
764 }
765 dc.EndDrawing();
766 }
767
768 void wxListHeaderWindow::DrawCurrent()
769 {
770 int x1 = m_currentX;
771 int y1 = 0;
772 int x2 = m_currentX-1;
773 int y2 = 0;
774 int dummy;
775 m_owner->GetClientSize( &dummy, &y2 );
776 ClientToScreen( &x1, &y1 );
777 m_owner->ClientToScreen( &x2, &y2 );
778
779 wxScreenDC dc;
780 dc.SetLogicalFunction( wxXOR );
781 dc.SetPen( wxPen( *wxBLACK, 2, wxSOLID ) );
782 dc.SetBrush( *wxTRANSPARENT_BRUSH );
783
784 dc.DrawLine( x1, y1, x2, y2 );
785
786 dc.SetLogicalFunction( wxCOPY );
787
788 dc.SetPen( wxNullPen );
789 dc.SetBrush( wxNullBrush );
790 }
791
792 void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
793 {
794 int x = event.GetX();
795 int y = event.GetY();
796 if (m_isDraging)
797 {
798 DrawCurrent();
799 if (event.ButtonUp())
800 {
801 ReleaseMouse();
802 m_isDraging = FALSE;
803 m_owner->SetColumnWidth( m_column, m_currentX-m_minX );
804 }
805 else
806 {
807 int size_x = 0;
808 int dummy;
809 GetClientSize( &size_x, & dummy );
810 if (x > m_minX+7)
811 m_currentX = x;
812 else
813 m_currentX = m_minX+7;
814 if (m_currentX > size_x-7) m_currentX = size_x-7;
815 DrawCurrent();
816 }
817 return;
818 }
819
820 m_minX = 0;
821 bool hit_border = FALSE;
822 int xpos = 0;
823 for (int j = 0; j < m_owner->GetColumnCount(); j++)
824 {
825 xpos += m_owner->GetColumnWidth( j );
826 if ((abs(x-xpos) < 3) && (y < 22))
827 {
828 hit_border = TRUE;
829 m_column = j;
830 break;
831 }
832 m_minX = xpos;
833 }
834
835 if (event.LeftDown() && hit_border)
836 {
837 m_isDraging = TRUE;
838 m_currentX = x;
839 DrawCurrent();
840 CaptureMouse();
841 return;
842 }
843
844 if (event.Moving())
845 {
846 if (hit_border)
847 {
848 if (m_currentCursor == wxSTANDARD_CURSOR) SetCursor( * m_resizeCursor );
849 m_currentCursor = m_resizeCursor;
850 }
851 else
852 {
853 if (m_currentCursor != wxSTANDARD_CURSOR) SetCursor( * wxSTANDARD_CURSOR );
854 m_currentCursor = wxSTANDARD_CURSOR;
855 }
856 }
857 }
858
859 void wxListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
860 {
861 m_owner->SetFocus();
862 }
863
864 //-----------------------------------------------------------------------------
865 // wxListRenameTimer (internal)
866 //-----------------------------------------------------------------------------
867
868 wxListRenameTimer::wxListRenameTimer( wxListMainWindow *owner )
869 {
870 m_owner = owner;
871 }
872
873 void wxListRenameTimer::Notify()
874 {
875 m_owner->OnRenameTimer();
876 }
877
878 //-----------------------------------------------------------------------------
879 // wxListTextCtrl (internal)
880 //-----------------------------------------------------------------------------
881
882 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl,wxTextCtrl);
883
884 BEGIN_EVENT_TABLE(wxListTextCtrl,wxTextCtrl)
885 EVT_CHAR (wxListTextCtrl::OnChar)
886 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus)
887 END_EVENT_TABLE()
888
889 wxListTextCtrl::wxListTextCtrl( wxWindow *parent, const wxWindowID id,
890 bool *accept, wxString *res, wxListMainWindow *owner,
891 const wxString &value, const wxPoint &pos, const wxSize &size,
892 int style, const wxValidator& validator, const wxString &name ) :
893 wxTextCtrl( parent, id, value, pos, size, style, validator, name )
894 {
895 m_res = res;
896 m_accept = accept;
897 m_owner = owner;
898 }
899
900 void wxListTextCtrl::OnChar( wxKeyEvent &event )
901 {
902 if (event.m_keyCode == WXK_RETURN)
903 {
904 (*m_accept) = TRUE;
905 (*m_res) = GetValue();
906 m_owner->OnRenameAccept();
907 // Show( FALSE );
908 Destroy();
909 return;
910 }
911 if (event.m_keyCode == WXK_ESCAPE)
912 {
913 (*m_accept) = FALSE;
914 (*m_res) = "";
915 // Show( FALSE );
916 Destroy();
917 return;
918 }
919 event.Skip();
920 }
921
922 void wxListTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
923 {
924 (*m_accept) = FALSE;
925 (*m_res) = "";
926 // Show( FALSE );
927 Destroy();
928 return;
929 }
930
931 //-----------------------------------------------------------------------------
932 // wxListMainWindow
933 //-----------------------------------------------------------------------------
934
935 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow,wxScrolledWindow);
936
937 BEGIN_EVENT_TABLE(wxListMainWindow,wxScrolledWindow)
938 EVT_PAINT (wxListMainWindow::OnPaint)
939 EVT_SIZE (wxListMainWindow::OnSize)
940 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse)
941 EVT_CHAR (wxListMainWindow::OnChar)
942 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus)
943 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus)
944 END_EVENT_TABLE()
945
946 wxListMainWindow::wxListMainWindow( void )
947 {
948 m_mode = 0;
949 m_lines.DeleteContents( TRUE );
950 m_columns.DeleteContents( TRUE );
951 m_current = (wxListLineData *) NULL;
952 m_visibleLines = 0;
953 m_hilightBrush = (wxBrush *) NULL;
954 m_xScroll = 0;
955 m_yScroll = 0;
956 m_dirty = TRUE;
957 m_small_image_list = (wxImageList *) NULL;
958 m_normal_image_list = (wxImageList *) NULL;
959 m_small_spacing = 30;
960 m_normal_spacing = 40;
961 m_hasFocus = FALSE;
962 m_usedKeys = TRUE;
963 m_lastOnSame = FALSE;
964 m_renameTimer = new wxListRenameTimer( this );
965 m_isCreated = FALSE;
966 m_dragCount = 0;
967 }
968
969 wxListMainWindow::wxListMainWindow( wxWindow *parent, wxWindowID id,
970 const wxPoint &pos, const wxSize &size,
971 long style, const wxString &name ) :
972 wxScrolledWindow( parent, id, pos, size, style|wxHSCROLL|wxVSCROLL, name )
973 {
974 m_mode = style;
975 m_lines.DeleteContents( TRUE );
976 m_columns.DeleteContents( TRUE );
977 m_current = (wxListLineData *) NULL;
978 m_dirty = TRUE;
979 m_visibleLines = 0;
980 m_hilightBrush = new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), wxSOLID );
981 m_small_image_list = (wxImageList *) NULL;
982 m_normal_image_list = (wxImageList *) NULL;
983 m_small_spacing = 30;
984 m_normal_spacing = 40;
985 m_hasFocus = FALSE;
986 m_dragCount = 0;
987 m_isCreated = FALSE;
988 wxSize sz = size;
989 sz.y = 25;
990
991 if (m_mode & wxLC_REPORT)
992 {
993 m_xScroll = 0;
994 m_yScroll = 15;
995 }
996 else
997 {
998 m_xScroll = 15;
999 m_yScroll = 0;
1000 }
1001 SetScrollbars( m_xScroll, m_yScroll, 0, 0, 0, 0 );
1002
1003 m_usedKeys = TRUE;
1004 m_lastOnSame = FALSE;
1005 m_renameTimer = new wxListRenameTimer( this );
1006 m_renameAccept = FALSE;
1007
1008 SetBackgroundColour( *wxWHITE );
1009 }
1010
1011 wxListMainWindow::~wxListMainWindow( void )
1012 {
1013 if (m_hilightBrush) delete m_hilightBrush;
1014
1015 delete m_renameTimer;
1016 }
1017
1018 void wxListMainWindow::RefreshLine( wxListLineData *line )
1019 {
1020 int x = 0;
1021 int y = 0;
1022 int w = 0;
1023 int h = 0;
1024 if (line)
1025 {
1026 wxClientDC dc(this);
1027 PrepareDC( dc );
1028 line->GetExtent( x, y, w, h );
1029 wxRectangle rect(
1030 dc.LogicalToDeviceX(x-3),
1031 dc.LogicalToDeviceY(y-3),
1032 dc.LogicalToDeviceXRel(w+6),
1033 dc.LogicalToDeviceXRel(h+6) );
1034 Refresh( TRUE, &rect );
1035 }
1036 }
1037
1038 void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
1039 {
1040 if (m_dirty) return;
1041
1042 if (m_lines.GetCount() == 0) return;
1043
1044 wxPaintDC dc( this );
1045 PrepareDC( dc );
1046
1047 dc.BeginDrawing();
1048
1049 dc.SetFont( GetFont() );
1050
1051 if (m_mode & wxLC_REPORT)
1052 {
1053 int lineSpacing = 0;
1054 wxListLineData *line = (wxListLineData*)m_lines.First()->Data();
1055 int dummy = 0;
1056 line->GetSize( dummy, lineSpacing );
1057 lineSpacing += 1;
1058
1059 int y_s = m_yScroll*GetScrollPos( wxVERTICAL );
1060
1061 wxNode *node = m_lines.Nth( y_s / lineSpacing );
1062 for (int i = 0; i < m_visibleLines+2; i++)
1063 {
1064 if (!node) break;
1065
1066 line = (wxListLineData*)node->Data();
1067 line->Draw( &dc );
1068 node = node->Next();
1069 }
1070 }
1071 else
1072 {
1073 wxNode *node = m_lines.First();
1074 while (node)
1075 {
1076 wxListLineData *line = (wxListLineData*)node->Data();
1077 line->Draw( &dc );
1078 node = node->Next();
1079 }
1080 }
1081
1082 if (m_current) m_current->DrawRubberBand( &dc, m_hasFocus );
1083
1084 dc.EndDrawing();
1085 }
1086
1087 void wxListMainWindow::HilightAll( bool on )
1088 {
1089 wxNode *node = m_lines.First();
1090 while (node)
1091 {
1092 wxListLineData *line = (wxListLineData *)node->Data();
1093 if (line->IsHilighted() != on)
1094 {
1095 line->Hilight( on );
1096 RefreshLine( line );
1097 }
1098 node = node->Next();
1099 }
1100 }
1101
1102 void wxListMainWindow::SendNotify( wxListLineData *line, wxEventType command )
1103 {
1104 wxListEvent le( command, GetParent()->GetId() );
1105 le.SetEventObject( GetParent() );
1106 le.m_itemIndex = GetIndexOfLine( line );
1107 line->GetItem( 0, le.m_item );
1108 GetParent()->GetEventHandler()->ProcessEvent( le );
1109 }
1110
1111 void wxListMainWindow::FocusLine( wxListLineData *WXUNUSED(line) )
1112 {
1113 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
1114 }
1115
1116 void wxListMainWindow::UnfocusLine( wxListLineData *WXUNUSED(line) )
1117 {
1118 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
1119 }
1120
1121 void wxListMainWindow::SelectLine( wxListLineData *line )
1122 {
1123 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_SELECTED );
1124 }
1125
1126 void wxListMainWindow::DeselectLine( wxListLineData *line )
1127 {
1128 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_DESELECTED );
1129 }
1130
1131 void wxListMainWindow::DeleteLine( wxListLineData *line )
1132 {
1133 SendNotify( line, wxEVT_COMMAND_LIST_DELETE_ITEM );
1134 }
1135
1136 void wxListMainWindow::StartLabelEdit( wxListLineData *line )
1137 {
1138 SendNotify( line, wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT );
1139 }
1140
1141 void wxListMainWindow::RenameLine( wxListLineData *line, const wxString &newName )
1142 {
1143 wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
1144 le.SetEventObject( GetParent() );
1145 le.m_itemIndex = GetIndexOfLine( line );
1146 line->GetItem( 0, le.m_item );
1147 le.m_item.m_text = newName;
1148 GetParent()->GetEventHandler()->ProcessEvent( le );
1149 }
1150
1151 void wxListMainWindow::OnRenameTimer()
1152 {
1153 StartLabelEdit( m_current );
1154 wxString s;
1155 m_current->GetText( 0, s );
1156 int x = 0;
1157 int y = 0;
1158 int w = 0;
1159 int h = 0;
1160 m_current->GetLabelExtent( x, y, w, h );
1161
1162 wxClientDC dc(this);
1163 PrepareDC( dc );
1164 x = dc.LogicalToDeviceX( x );
1165 y = dc.LogicalToDeviceY( y );
1166
1167 wxListTextCtrl *text = new wxListTextCtrl(
1168 this, -1, &m_renameAccept, &m_renameRes, this, s, wxPoint(x-4,y-4), wxSize(w+11,h+8) );
1169 text->SetFocus();
1170 }
1171
1172 void wxListMainWindow::OnRenameAccept()
1173 {
1174 RenameLine( m_current, m_renameRes );
1175 }
1176
1177 void wxListMainWindow::OnMouse( wxMouseEvent &event )
1178 {
1179 if (GetParent()->GetEventHandler()->ProcessEvent( event)) return;
1180
1181 if (!m_current) return;
1182 if (m_dirty) return;
1183
1184 wxClientDC dc(this);
1185 PrepareDC(dc);
1186 long x = dc.DeviceToLogicalX( (long)event.GetX() );
1187 long y = dc.DeviceToLogicalY( (long)event.GetY() );
1188
1189 // Did we actually hit an item ?
1190 long hitResult = 0;
1191 wxNode *node = m_lines.First();
1192 wxListLineData *line = (wxListLineData *) NULL;
1193 while (node)
1194 {
1195 line = (wxListLineData*)node->Data();
1196 hitResult = line->IsHit( x, y );
1197 if (hitResult) break;
1198 line = (wxListLineData *) NULL;
1199 node = node->Next();
1200 }
1201
1202 if (!event.Dragging())
1203 m_dragCount = 0;
1204 else
1205 m_dragCount++;
1206
1207 if (event.Dragging() && (m_dragCount > 3))
1208 {
1209 m_dragCount = 0;
1210
1211 wxListEvent le( wxEVT_COMMAND_LIST_BEGIN_DRAG, GetParent()->GetId() );
1212 le.SetEventObject( GetParent() );
1213 le.m_pointDrag.x = x;
1214 le.m_pointDrag.y = y;
1215 GetParent()->GetEventHandler()->ProcessEvent( le );
1216
1217 return;
1218 }
1219
1220 if (!line) return;
1221
1222 if (event.ButtonDClick())
1223 {
1224 m_usedKeys = FALSE;
1225 m_lastOnSame = FALSE;
1226 m_renameTimer->Stop();
1227
1228 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
1229
1230 return;
1231 }
1232
1233 if (event.LeftUp() && m_lastOnSame)
1234 {
1235 m_usedKeys = FALSE;
1236 if ((line == m_current) &&
1237 (hitResult == wxLIST_HITTEST_ONITEMLABEL) &&
1238 (m_mode & wxLC_EDIT_LABELS) )
1239 {
1240 m_renameTimer->Start( 100, TRUE );
1241 }
1242 m_lastOnSame = FALSE;
1243 return;
1244 }
1245
1246 if (event.RightDown())
1247 {
1248 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK );
1249 return;
1250 }
1251
1252 if (event.MiddleDown())
1253 {
1254 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK );
1255 return;
1256 }
1257
1258 if (event.LeftDown())
1259 {
1260 m_usedKeys = FALSE;
1261 wxListLineData *oldCurrent = m_current;
1262 if (m_mode & wxLC_SINGLE_SEL)
1263 {
1264 m_current = line;
1265 HilightAll( FALSE );
1266 m_current->ReverseHilight();
1267 RefreshLine( m_current );
1268 }
1269 else
1270 {
1271 if (event.ShiftDown())
1272 {
1273 m_current = line;
1274 m_current->ReverseHilight();
1275 RefreshLine( m_current );
1276 }
1277 else if (event.ControlDown())
1278 {
1279 m_current = line;
1280
1281 int numOfCurrent = -1;
1282 node = m_lines.First();
1283 while (node)
1284 {
1285 wxListLineData *test_line = (wxListLineData*)node->Data();
1286 numOfCurrent++;
1287 if (test_line == oldCurrent) break;
1288 node = node->Next();
1289 }
1290
1291 int numOfLine = -1;
1292 node = m_lines.First();
1293 while (node)
1294 {
1295 wxListLineData *test_line = (wxListLineData*)node->Data();
1296 numOfLine++;
1297 if (test_line == line) break;
1298 node = node->Next();
1299 }
1300
1301 if (numOfLine < numOfCurrent)
1302 {
1303 int i = numOfLine;
1304 numOfLine = numOfCurrent;
1305 numOfCurrent = i;
1306 }
1307
1308 wxNode *node = m_lines.Nth( numOfCurrent );
1309 for (int i = 0; i <= numOfLine-numOfCurrent; i++)
1310 {
1311 wxListLineData *test_line= (wxListLineData*)node->Data();
1312 test_line->Hilight(TRUE);
1313 RefreshLine( test_line );
1314 node = node->Next();
1315 }
1316 }
1317 else
1318 {
1319 m_current = line;
1320 HilightAll( FALSE );
1321 m_current->ReverseHilight();
1322 RefreshLine( m_current );
1323 }
1324 }
1325 if (m_current != oldCurrent)
1326 {
1327 RefreshLine( oldCurrent );
1328 UnfocusLine( oldCurrent );
1329 FocusLine( m_current );
1330 }
1331 m_lastOnSame = (m_current == oldCurrent);
1332 return;
1333 }
1334 }
1335
1336 void wxListMainWindow::MoveToFocus( void )
1337 {
1338 if (!m_current) return;
1339
1340 int x = 0;
1341 int y = 0;
1342 int w = 0;
1343 int h = 0;
1344 m_current->GetExtent( x, y, w, h );
1345
1346 int w_p = 0;
1347 int h_p = 0;
1348 GetClientSize( &w_p, &h_p );
1349
1350 if (m_mode & wxLC_REPORT)
1351 {
1352 int y_s = m_yScroll*GetScrollPos( wxVERTICAL );
1353 if ((y > y_s) && (y+h < y_s+h_p)) return;
1354 if (y-y_s < 5) Scroll( -1, (y-5-h_p/2)/m_yScroll );
1355 if (y+h+5 > y_s+h_p) Scroll( -1, (y+h-h_p/2+h+15)/m_yScroll );
1356 }
1357 else
1358 {
1359 int x_s = m_xScroll*GetScrollPos( wxHORIZONTAL );
1360 if ((x > x_s) && (x+w < x_s+w_p)) return;
1361 if (x-x_s < 5) Scroll( (x-5)/m_xScroll, -1 );
1362 if (x+w-5 > x_s+w_p) Scroll( (x+w-w_p+15)/m_xScroll, -1 );
1363 }
1364 }
1365
1366 void wxListMainWindow::OnArrowChar( wxListLineData *newCurrent, bool shiftDown )
1367 {
1368 if ((m_mode & wxLC_SINGLE_SEL) || (m_usedKeys == FALSE)) m_current->Hilight( FALSE );
1369 wxListLineData *oldCurrent = m_current;
1370 m_current = newCurrent;
1371 MoveToFocus();
1372 if (shiftDown || (m_mode & wxLC_SINGLE_SEL)) m_current->Hilight( TRUE );
1373 RefreshLine( m_current );
1374 RefreshLine( oldCurrent );
1375 FocusLine( m_current );
1376 UnfocusLine( oldCurrent );
1377 }
1378
1379 void wxListMainWindow::OnChar( wxKeyEvent &event )
1380 {
1381 wxListEvent le( wxEVT_COMMAND_LIST_KEY_DOWN, GetParent()->GetId() );
1382 le.m_code = event.KeyCode();
1383 le.SetEventObject( GetParent() );
1384 GetParent()->GetEventHandler()->ProcessEvent( le );
1385
1386 /*
1387 if (event.KeyCode() == WXK_TAB)
1388 {
1389 if (event.ShiftDown())
1390 TravPrev( &event );
1391 else
1392 TravNext( &event );
1393 return;
1394 }
1395 */
1396 if ( !m_current )
1397 {
1398 event.Skip();
1399 return;
1400 }
1401
1402 switch (event.KeyCode())
1403 {
1404 case WXK_UP:
1405 {
1406 wxNode *node = m_lines.Member( m_current )->Previous();
1407 if (node) OnArrowChar( (wxListLineData*)node->Data(), event.ShiftDown() );
1408 break;
1409 }
1410 case WXK_DOWN:
1411 {
1412 wxNode *node = m_lines.Member( m_current )->Next();
1413 if (node) OnArrowChar( (wxListLineData*)node->Data(), event.ShiftDown() );
1414 break;
1415 }
1416 case WXK_END:
1417 {
1418 wxNode *node = m_lines.Last();
1419 OnArrowChar( (wxListLineData*)node->Data(), event.ShiftDown() );
1420 break;
1421 }
1422 case WXK_HOME:
1423 {
1424 wxNode *node = m_lines.First();
1425 OnArrowChar( (wxListLineData*)node->Data(), event.ShiftDown() );
1426 break;
1427 }
1428 case WXK_PRIOR:
1429 {
1430 int steps = 0;
1431 if (m_mode & wxLC_REPORT) { steps = m_visibleLines-1; }
1432 else
1433 {
1434 int pos = 0;
1435 wxNode *node = m_lines.First();
1436 for (;;) { if (m_current == (wxListLineData*)node->Data()) break; pos++; node = node->Next(); }
1437 steps = pos % m_visibleLines;
1438 }
1439 wxNode *node = m_lines.Member( m_current );
1440 for (int i = 0; i < steps; i++) if (node->Previous()) node = node->Previous();
1441 if (node) OnArrowChar( (wxListLineData*)node->Data(), event.ShiftDown() );
1442 break;
1443 }
1444 case WXK_NEXT:
1445 {
1446 int steps = 0;
1447 if (m_mode & wxLC_REPORT) { steps = m_visibleLines-1; }
1448 else
1449 {
1450 int pos = 0; wxNode *node = m_lines.First();
1451 for (;;) { if (m_current == (wxListLineData*)node->Data()) break; pos++; node = node->Next(); }
1452 steps = m_visibleLines-(pos % m_visibleLines)-1;
1453 }
1454 wxNode *node = m_lines.Member( m_current );
1455 for (int i = 0; i < steps; i++) if (node->Next()) node = node->Next();
1456 if (node) OnArrowChar( (wxListLineData*)node->Data(), event.ShiftDown() );
1457 break;
1458 }
1459 case WXK_LEFT:
1460 {
1461 if (!(m_mode & wxLC_REPORT))
1462 {
1463 wxNode *node = m_lines.Member( m_current );
1464 for (int i = 0; i <m_visibleLines; i++) if (node->Previous()) node = node->Previous();
1465 if (node) OnArrowChar( (wxListLineData*)node->Data(), event.ShiftDown() );
1466 }
1467 break;
1468 }
1469 case WXK_RIGHT:
1470 {
1471 if (!(m_mode & wxLC_REPORT))
1472 {
1473 wxNode *node = m_lines.Member( m_current );
1474 for (int i = 0; i <m_visibleLines; i++) if (node->Next()) node = node->Next();
1475 if (node) OnArrowChar( (wxListLineData*)node->Data(), event.ShiftDown() );
1476 }
1477 break;
1478 }
1479 case WXK_SPACE:
1480 {
1481 m_current->ReverseHilight();
1482 RefreshLine( m_current );
1483 }
1484 break;
1485 case WXK_INSERT:
1486 {
1487 if (!(m_mode & wxLC_SINGLE_SEL))
1488 {
1489 wxListLineData *oldCurrent = m_current;
1490 m_current->ReverseHilight();
1491 wxNode *node = m_lines.Member( m_current )->Next();
1492 if (node) m_current = (wxListLineData*)node->Data();
1493 MoveToFocus();
1494 RefreshLine( oldCurrent );
1495 RefreshLine( m_current );
1496 UnfocusLine( oldCurrent );
1497 FocusLine( m_current );
1498 }
1499 }
1500 break;
1501 case WXK_RETURN:
1502 case WXK_EXECUTE:
1503 {
1504 wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, GetParent()->GetId() );
1505 le.SetEventObject( GetParent() );
1506 le.m_itemIndex = GetIndexOfLine( m_current );
1507 m_current->GetItem( 0, le.m_item );
1508 GetParent()->GetEventHandler()->ProcessEvent( le );
1509 }
1510 break;
1511 default:
1512 {
1513 event.Skip();
1514 return;
1515 }
1516 }
1517 m_usedKeys = TRUE;
1518 }
1519
1520 void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
1521 {
1522 m_hasFocus = TRUE;
1523 RefreshLine( m_current );
1524
1525 if (!GetParent()) return;
1526
1527 wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
1528 event.SetEventObject( GetParent() );
1529 GetParent()->GetEventHandler()->ProcessEvent( event );
1530 }
1531
1532 void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
1533 {
1534 m_hasFocus = FALSE;
1535 RefreshLine( m_current );
1536 }
1537
1538 void wxListMainWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1539 {
1540 /*
1541 We don't even allow the wxScrolledWindow::AdjustScrollbars() call
1542
1543 */
1544 }
1545
1546 void wxListMainWindow::DrawImage( int index, wxDC *dc, int x, int y )
1547 {
1548 if ((m_mode & wxLC_ICON) && (m_normal_image_list))
1549 {
1550 m_normal_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
1551 return;
1552 }
1553 if ((m_mode & wxLC_SMALL_ICON) && (m_small_image_list))
1554 {
1555 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
1556 }
1557 if ((m_mode & wxLC_REPORT) && (m_small_image_list))
1558 {
1559 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
1560 return;
1561 }
1562 }
1563
1564 void wxListMainWindow::GetImageSize( int index, int &width, int &height )
1565 {
1566 if ((m_mode & wxLC_ICON) && (m_normal_image_list))
1567 {
1568 m_normal_image_list->GetSize( index, width, height );
1569 return;
1570 }
1571 if ((m_mode & wxLC_SMALL_ICON) && (m_small_image_list))
1572 {
1573 m_small_image_list->GetSize( index, width, height );
1574 return;
1575 }
1576 if ((m_mode & wxLC_REPORT) && (m_small_image_list))
1577 {
1578 m_small_image_list->GetSize( index, width, height );
1579 return;
1580 }
1581 width = 0;
1582 height = 0;
1583 }
1584
1585 int wxListMainWindow::GetTextLength( wxString &s )
1586 {
1587 wxClientDC dc( this );
1588 long lw = 0;
1589 long lh = 0;
1590 dc.GetTextExtent( s, &lw, &lh );
1591 return lw + 6;
1592 }
1593
1594 int wxListMainWindow::GetIndexOfLine( const wxListLineData *line )
1595 {
1596 int i = 0;
1597 wxNode *node = m_lines.First();
1598 while (node)
1599 {
1600 if (line == (wxListLineData*)node->Data()) return i;
1601 i++;
1602 node = node->Next();
1603 }
1604 return -1;
1605 }
1606
1607 void wxListMainWindow::SetImageList( wxImageList *imageList, int which )
1608 {
1609 m_dirty = TRUE;
1610 if (which == wxIMAGE_LIST_NORMAL) m_normal_image_list = imageList;
1611 if (which == wxIMAGE_LIST_SMALL) m_small_image_list = imageList;
1612 }
1613
1614 void wxListMainWindow::SetItemSpacing( int spacing, bool isSmall )
1615 {
1616 m_dirty = TRUE;
1617 if (isSmall)
1618 {
1619 m_small_spacing = spacing;
1620 }
1621 else
1622 {
1623 m_normal_spacing = spacing;
1624 }
1625 }
1626
1627 int wxListMainWindow::GetItemSpacing( bool isSmall )
1628 {
1629 if (isSmall) return m_small_spacing; else return m_normal_spacing;
1630 }
1631
1632 void wxListMainWindow::SetColumn( int col, wxListItem &item )
1633 {
1634 m_dirty = TRUE;
1635 wxNode *node = m_columns.Nth( col );
1636 if (node)
1637 {
1638 if (item.m_width == wxLIST_AUTOSIZE_USEHEADER) item.m_width = GetTextLength( item.m_text )+7;
1639 wxListHeaderData *column = (wxListHeaderData*)node->Data();
1640 column->SetItem( item );
1641 }
1642 wxListCtrl *lc = (wxListCtrl*) GetParent();
1643 if (lc->m_headerWin) lc->m_headerWin->Refresh();
1644 }
1645
1646 void wxListMainWindow::SetColumnWidth( int col, int width )
1647 {
1648 if (!(m_mode & wxLC_REPORT)) return;
1649
1650 m_dirty = TRUE;
1651
1652 wxNode *node = m_columns.Nth( col );
1653 if (node)
1654 {
1655 wxListHeaderData *column = (wxListHeaderData*)node->Data();
1656 column->SetWidth( width );
1657 }
1658
1659 node = m_lines.First();
1660 while (node)
1661 {
1662 wxListLineData *line = (wxListLineData*)node->Data();
1663 wxNode *n = line->m_items.Nth( col );
1664 if (n)
1665 {
1666 wxListItemData *item = (wxListItemData*)n->Data();
1667 item->SetSize( width, -1 );
1668 }
1669 node = node->Next();
1670 }
1671
1672 wxListCtrl *lc = (wxListCtrl*) GetParent();
1673 if (lc->m_headerWin) lc->m_headerWin->Refresh();
1674 }
1675
1676 void wxListMainWindow::GetColumn( int col, wxListItem &item )
1677 {
1678 wxNode *node = m_columns.Nth( col );
1679 if (node)
1680 {
1681 wxListHeaderData *column = (wxListHeaderData*)node->Data();
1682 column->GetItem( item );
1683 }
1684 else
1685 {
1686 item.m_format = 0;
1687 item.m_width = 0;
1688 item.m_text = "";
1689 item.m_image = 0;
1690 item.m_data = 0;
1691 }
1692 }
1693
1694 int wxListMainWindow::GetColumnWidth( int col )
1695 {
1696 wxNode *node = m_columns.Nth( col );
1697 if (node)
1698 {
1699 wxListHeaderData *column = (wxListHeaderData*)node->Data();
1700 return column->GetWidth();
1701 }
1702 else
1703 {
1704 return 0;
1705 }
1706 }
1707
1708 int wxListMainWindow::GetColumnCount( void )
1709 {
1710 return m_columns.Number();
1711 }
1712
1713 int wxListMainWindow::GetCountPerPage( void )
1714 {
1715 return m_visibleLines;
1716 }
1717
1718 void wxListMainWindow::SetItem( wxListItem &item )
1719 {
1720 m_dirty = TRUE;
1721 wxNode *node = m_lines.Nth( item.m_itemId );
1722 if (node)
1723 {
1724 wxListLineData *line = (wxListLineData*)node->Data();
1725 if (m_mode & wxLC_REPORT) item.m_width = GetColumnWidth( item.m_col )-3;
1726 line->SetItem( item.m_col, item );
1727 }
1728 }
1729
1730 void wxListMainWindow::SetItemState( long item, long state, long stateMask )
1731 {
1732 // m_dirty = TRUE; no recalcs needed
1733
1734 wxListLineData *oldCurrent = m_current;
1735
1736 if (stateMask & wxLIST_STATE_FOCUSED)
1737 {
1738 wxNode *node = m_lines.Nth( item );
1739 if (node)
1740 {
1741 wxListLineData *line = (wxListLineData*)node->Data();
1742 UnfocusLine( m_current );
1743 m_current = line;
1744 FocusLine( m_current );
1745 RefreshLine( m_current );
1746 RefreshLine( oldCurrent );
1747 }
1748 }
1749
1750 if (stateMask & wxLIST_STATE_SELECTED)
1751 {
1752 bool on = state & wxLIST_STATE_SELECTED;
1753 if (!on && (m_mode & wxLC_SINGLE_SEL)) return;
1754
1755 wxNode *node = m_lines.Nth( item );
1756 if (node)
1757 {
1758 wxListLineData *line = (wxListLineData*)node->Data();
1759 if (m_mode & wxLC_SINGLE_SEL)
1760 {
1761 UnfocusLine( m_current );
1762 m_current = line;
1763 FocusLine( m_current );
1764 oldCurrent->Hilight( FALSE );
1765 RefreshLine( m_current );
1766 RefreshLine( oldCurrent );
1767 }
1768 bool on = state & wxLIST_STATE_SELECTED;
1769 if (on != line->IsHilighted())
1770 {
1771 line->Hilight( on );
1772 RefreshLine( line );
1773 }
1774 }
1775 }
1776 }
1777
1778 int wxListMainWindow::GetItemState( long item, long stateMask )
1779 {
1780 int ret = wxLIST_STATE_DONTCARE;
1781 if (stateMask & wxLIST_STATE_FOCUSED)
1782 {
1783 wxNode *node = m_lines.Nth( item );
1784 if (node)
1785 {
1786 wxListLineData *line = (wxListLineData*)node->Data();
1787 if (line == m_current) ret |= wxLIST_STATE_FOCUSED;
1788 }
1789 }
1790 if (stateMask & wxLIST_STATE_SELECTED)
1791 {
1792 wxNode *node = m_lines.Nth( item );
1793 if (node)
1794 {
1795 wxListLineData *line = (wxListLineData*)node->Data();
1796 if (line->IsHilighted()) ret |= wxLIST_STATE_FOCUSED;
1797 }
1798 }
1799 return ret;
1800 }
1801
1802 void wxListMainWindow::GetItem( wxListItem &item )
1803 {
1804 wxNode *node = m_lines.Nth( item.m_itemId );
1805 if (node)
1806 {
1807 wxListLineData *line = (wxListLineData*)node->Data();
1808 line->GetItem( item.m_col, item );
1809 }
1810 else
1811 {
1812 item.m_mask = 0;
1813 item.m_text = "";
1814 item.m_image = 0;
1815 item.m_data = 0;
1816 }
1817 }
1818
1819 int wxListMainWindow::GetItemCount( void )
1820 {
1821 return m_lines.Number();
1822 }
1823
1824 void wxListMainWindow::GetItemRect( long index, wxRectangle &rect )
1825 {
1826 wxNode *node = m_lines.Nth( index );
1827 if (node)
1828 {
1829 wxListLineData *line = (wxListLineData*)node->Data();
1830 line->GetRect( rect );
1831 }
1832 else
1833 {
1834 rect.x = 0;
1835 rect.y = 0;
1836 rect.width = 0;
1837 rect.height = 0;
1838 }
1839 }
1840
1841 bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos)
1842 {
1843 wxNode *node = m_lines.Nth( item );
1844 if (node)
1845 {
1846 wxRectangle rect;
1847 wxListLineData *line = (wxListLineData*)node->Data();
1848 line->GetRect( rect );
1849 pos.x = rect.x;
1850 pos.y = rect.y;
1851 }
1852 else
1853 {
1854 pos.x = 0;
1855 pos.y = 0;
1856 }
1857 return TRUE;
1858 }
1859
1860 int wxListMainWindow::GetSelectedItemCount( void )
1861 {
1862 int ret = 0;
1863 wxNode *node = m_lines.First();
1864 while (node)
1865 {
1866 wxListLineData *line = (wxListLineData*)node->Data();
1867 if (line->IsHilighted()) ret++;
1868 node = node->Next();
1869 }
1870 return ret;
1871 }
1872
1873 void wxListMainWindow::SetMode( long mode )
1874 {
1875 m_dirty = TRUE;
1876 m_mode = mode;
1877
1878 DeleteEverything();
1879
1880 if (m_mode & wxLC_REPORT)
1881 {
1882 m_xScroll = 0;
1883 m_yScroll = 15;
1884 }
1885 else
1886 {
1887 m_xScroll = 15;
1888 m_yScroll = 0;
1889 }
1890 }
1891
1892 long wxListMainWindow::GetMode( void ) const
1893 {
1894 return m_mode;
1895 }
1896
1897 void wxListMainWindow::CalculatePositions( void )
1898 {
1899 if (!m_lines.First()) return;
1900
1901 wxClientDC dc( this );
1902 dc.SetFont( GetFont() );
1903
1904 int iconSpacing = 0;
1905 if (m_mode & wxLC_ICON) iconSpacing = m_normal_spacing;
1906 if (m_mode & wxLC_SMALL_ICON) iconSpacing = m_small_spacing;
1907
1908 // we take the first line (which also can be an icon or
1909 // an a text item in wxLC_ICON and wxLC_LIST modes) to
1910 // measure the size of the line
1911
1912 int lineWidth = 0;
1913 int lineHeight = 0;
1914 int lineSpacing = 0;
1915
1916 wxListLineData *line = (wxListLineData*)m_lines.First()->Data();
1917 line->CalculateSize( &dc, iconSpacing );
1918 int dummy = 0;
1919 line->GetSize( dummy, lineSpacing );
1920 lineSpacing += 4;
1921
1922 int clientWidth = 0;
1923 int clientHeight = 0;
1924
1925 if (m_mode & wxLC_REPORT)
1926 {
1927 int x = 4;
1928 int y = 1;
1929 int entireHeight = m_lines.Number() * lineSpacing + 2;
1930 int scroll_pos = GetScrollPos( wxVERTICAL );
1931 SetScrollbars( m_xScroll, m_yScroll, 0, (entireHeight+15) / m_yScroll, 0, scroll_pos, TRUE );
1932 GetClientSize( &clientWidth, &clientHeight );
1933
1934 wxNode* node = m_lines.First();
1935 while (node)
1936 {
1937 wxListLineData *line = (wxListLineData*)node->Data();
1938 line->CalculateSize( &dc, iconSpacing );
1939 line->SetPosition( &dc, x, y, clientWidth );
1940 int col_x = 2;
1941 for (int i = 0; i < GetColumnCount(); i++)
1942 {
1943 line->SetColumnPosition( i, col_x );
1944 col_x += GetColumnWidth( i );
1945 }
1946 y += lineSpacing; // one pixel blank line between items
1947 node = node->Next();
1948 }
1949 m_visibleLines = clientHeight / lineSpacing;
1950 }
1951 else
1952 {
1953 // at first we try without any scrollbar. if the items don't
1954 // fit into the window, we recalculate after subtracting an
1955 // approximated 15 pt for the horizontal scrollbar
1956
1957 GetSize( &clientWidth, &clientHeight );
1958 clientHeight -= 4; // sunken frame
1959
1960 int entireWidth = 0;
1961
1962 for (int tries = 0; tries < 2; tries++)
1963 {
1964 entireWidth = 0;
1965 int x = 5; // painting is done at x-2
1966 int y = 5; // painting is done at y-2
1967 int maxWidth = 0;
1968 wxNode *node = m_lines.First();
1969 while (node)
1970 {
1971 wxListLineData *line = (wxListLineData*)node->Data();
1972 line->CalculateSize( &dc, iconSpacing );
1973 line->SetPosition( &dc, x, y, clientWidth );
1974 line->GetSize( lineWidth, lineHeight );
1975 if (lineWidth > maxWidth) maxWidth = lineWidth;
1976 y += lineSpacing;
1977 if (y+lineSpacing-6 >= clientHeight) // -6 for earlier "line breaking"
1978 {
1979 y = 5;
1980 x += maxWidth+6;
1981 entireWidth += maxWidth+6;
1982 maxWidth = 0;
1983 }
1984 node = node->Next();
1985 if (!node) entireWidth += maxWidth;
1986 if ((tries == 0) && (entireWidth > clientWidth))
1987 {
1988 clientHeight -= 15; // scrollbar height
1989 break;
1990 }
1991 if (!node) tries = 1; // everything fits, no second try required
1992 }
1993 }
1994 m_visibleLines = (clientHeight+6) / (lineSpacing); // +6 for earlier "line breaking"
1995
1996 int scroll_pos = GetScrollPos( wxHORIZONTAL );
1997 SetScrollbars( m_xScroll, m_yScroll, (entireWidth+15) / m_xScroll, 0, scroll_pos, 0, TRUE );
1998 }
1999 }
2000
2001 void wxListMainWindow::RealizeChanges( void )
2002 {
2003 if (!m_current)
2004 {
2005 wxNode *node = m_lines.First();
2006 if (node) m_current = (wxListLineData*)node->Data();
2007 }
2008 if (m_current)
2009 {
2010 FocusLine( m_current );
2011 if (m_mode & wxLC_SINGLE_SEL) m_current->Hilight( TRUE );
2012 }
2013 }
2014
2015 long wxListMainWindow::GetNextItem( long item, int WXUNUSED(geometry), int state )
2016 {
2017 long ret = 0;
2018 if (item > 0) ret = item;
2019 wxNode *node = m_lines.Nth( ret );
2020 while (node)
2021 {
2022 wxListLineData *line = (wxListLineData*)node->Data();
2023 if ((state & wxLIST_STATE_FOCUSED) && (line == m_current)) return ret;
2024 if ((state & wxLIST_STATE_SELECTED) && (line->IsHilighted())) return ret;
2025 if (!state) return ret;
2026 ret++;
2027 node = node->Next();
2028 }
2029 return -1;
2030 }
2031
2032 void wxListMainWindow::DeleteItem( long index )
2033 {
2034 m_dirty = TRUE;
2035 wxNode *node = m_lines.Nth( index );
2036 if (node)
2037 {
2038 wxListLineData *line = (wxListLineData*)node->Data();
2039 if (m_current == line) m_current = (wxListLineData *) NULL;
2040 DeleteLine( line );
2041 m_lines.DeleteNode( node );
2042 }
2043 }
2044
2045 void wxListMainWindow::DeleteColumn( int col )
2046 {
2047 wxCHECK_RET( col < (int)m_columns.GetCount(),
2048 "attempting to delete inexistent column in wxListView" );
2049
2050 m_dirty = TRUE;
2051 wxNode *node = m_columns.Nth( col );
2052 if (node) m_columns.DeleteNode( node );
2053 }
2054
2055 void wxListMainWindow::DeleteAllItems( void )
2056 {
2057 m_dirty = TRUE;
2058 m_current = (wxListLineData *) NULL;
2059 wxNode *node = m_lines.First();
2060 while (node)
2061 {
2062 wxListLineData *line = (wxListLineData*)node->Data();
2063 DeleteLine( line );
2064 node = node->Next();
2065 }
2066 m_lines.Clear();
2067 }
2068
2069 void wxListMainWindow::DeleteEverything( void )
2070 {
2071 m_dirty = TRUE;
2072 m_current = (wxListLineData *) NULL;
2073 wxNode *node = m_lines.First();
2074 while (node)
2075 {
2076 wxListLineData *line = (wxListLineData*)node->Data();
2077 DeleteLine( line );
2078 node = node->Next();
2079 }
2080 m_lines.Clear();
2081 m_current = (wxListLineData *) NULL;
2082 m_columns.Clear();
2083 }
2084
2085 void wxListMainWindow::EnsureVisible( long index )
2086 {
2087 wxListLineData *oldCurrent = m_current;
2088 m_current = (wxListLineData *) NULL;
2089 int i = index;
2090 wxNode *node = m_lines.Nth( i );
2091 if (node) m_current = (wxListLineData*)node->Data();
2092 if (m_current) MoveToFocus();
2093 m_current = oldCurrent;
2094 }
2095
2096 long wxListMainWindow::FindItem(long start, const wxString& str, bool WXUNUSED(partial) )
2097 {
2098 long pos = start;
2099 wxString tmp = str;
2100 if (pos < 0) pos = 0;
2101 wxNode *node = m_lines.Nth( pos );
2102 while (node)
2103 {
2104 wxListLineData *line = (wxListLineData*)node->Data();
2105 wxString s = "";
2106 line->GetText( 0, s );
2107 if (s == tmp) return pos;
2108 node = node->Next();
2109 pos++;
2110 }
2111 return -1;
2112 }
2113
2114 long wxListMainWindow::FindItem(long start, long data)
2115 {
2116 long pos = start;
2117 if (pos < 0) pos = 0;
2118 wxNode *node = m_lines.Nth( pos );
2119 while (node)
2120 {
2121 wxListLineData *line = (wxListLineData*)node->Data();
2122 wxListItem item;
2123 line->GetItem( 0, item );
2124 if (item.m_data == data) return pos;
2125 node = node->Next();
2126 pos++;
2127 }
2128 return -1;
2129 }
2130
2131 long wxListMainWindow::HitTest( int x, int y, int &flags )
2132 {
2133 wxNode *node = m_lines.First();
2134 int count = 0;
2135 while (node)
2136 {
2137 wxListLineData *line = (wxListLineData*)node->Data();
2138 long ret = line->IsHit( x, y );
2139 if (ret & flags)
2140 {
2141 flags = ret;
2142 return count;
2143 }
2144 node = node->Next();
2145 count++;
2146 }
2147 return -1;
2148 }
2149
2150 void wxListMainWindow::InsertItem( wxListItem &item )
2151 {
2152 m_dirty = TRUE;
2153 int mode = 0;
2154 if (m_mode & wxLC_REPORT) mode = wxLC_REPORT;
2155 else if (m_mode & wxLC_LIST) mode = wxLC_LIST;
2156 else if (m_mode & wxLC_ICON) mode = wxLC_ICON;
2157 else if (m_mode & wxLC_SMALL_ICON) mode = wxLC_ICON; // no typo
2158 wxListLineData *line = new wxListLineData( this, mode, m_hilightBrush );
2159 if (m_mode & wxLC_REPORT)
2160 {
2161 line->InitItems( GetColumnCount() );
2162 item.m_width = GetColumnWidth( 0 )-3;
2163 }
2164 else
2165 line->InitItems( 1 );
2166 line->SetItem( 0, item );
2167 if ((item.m_itemId >= 0) && (item.m_itemId < (int)m_lines.GetCount()))
2168 {
2169 wxNode *node = m_lines.Nth( item.m_itemId );
2170 if (node) m_lines.Insert( node, line );
2171 }
2172 else
2173 {
2174 m_lines.Append( line );
2175 }
2176 }
2177
2178 void wxListMainWindow::InsertColumn( long col, wxListItem &item )
2179 {
2180 m_dirty = TRUE;
2181 if (m_mode & wxLC_REPORT)
2182 {
2183 if (item.m_width == wxLIST_AUTOSIZE_USEHEADER) item.m_width = GetTextLength( item.m_text );
2184 wxListHeaderData *column = new wxListHeaderData( item );
2185 if ((col >= 0) && (col < (int)m_columns.GetCount()))
2186 {
2187 wxNode *node = m_columns.Nth( col );
2188 if (node)
2189 m_columns.Insert( node, column );
2190 }
2191 else
2192 {
2193 m_columns.Append( column );
2194 }
2195 }
2196 }
2197
2198 wxListCtrlCompare list_ctrl_compare_func_2;
2199 long list_ctrl_compare_data;
2200
2201 int list_ctrl_compare_func_1( const void *arg1, const void *arg2 )
2202 {
2203 wxListLineData *line1 = *((wxListLineData**)arg1);
2204 wxListLineData *line2 = *((wxListLineData**)arg2);
2205 wxListItem item;
2206 line1->GetItem( 0, item );
2207 long data1 = item.m_data;
2208 line2->GetItem( 0, item );
2209 long data2 = item.m_data;
2210 return list_ctrl_compare_func_2( data1, data2, list_ctrl_compare_data );
2211 }
2212
2213 void wxListMainWindow::SortItems( wxListCtrlCompare fn, long data )
2214 {
2215 list_ctrl_compare_func_2 = fn;
2216 list_ctrl_compare_data = data;
2217 m_lines.Sort( list_ctrl_compare_func_1 );
2218 }
2219
2220 // -------------------------------------------------------------------------------------
2221 // wxListItem
2222 // -------------------------------------------------------------------------------------
2223
2224 IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
2225
2226 wxListItem::wxListItem(void)
2227 {
2228 m_mask = 0;
2229 m_itemId = 0;
2230 m_col = 0;
2231 m_state = 0;
2232 m_stateMask = 0;
2233 m_image = 0;
2234 m_data = 0;
2235 m_format = wxLIST_FORMAT_CENTRE;
2236 m_width = 0;
2237 m_colour = wxBLACK;
2238 }
2239
2240 // -------------------------------------------------------------------------------------
2241 // wxListEvent
2242 // -------------------------------------------------------------------------------------
2243
2244 IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
2245
2246 wxListEvent::wxListEvent( wxEventType commandType, int id ):
2247 wxNotifyEvent( commandType, id )
2248 {
2249 m_code = 0;
2250 m_itemIndex = 0;
2251 m_oldItemIndex = 0;
2252 m_col = 0;
2253 m_cancelled = FALSE;
2254 m_pointDrag.x = 0;
2255 m_pointDrag.y = 0;
2256 }
2257
2258 // -------------------------------------------------------------------------------------
2259 // wxListCtrl
2260 // -------------------------------------------------------------------------------------
2261
2262 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
2263
2264 BEGIN_EVENT_TABLE(wxListCtrl,wxControl)
2265 EVT_SIZE (wxListCtrl::OnSize)
2266 EVT_IDLE (wxListCtrl::OnIdle)
2267 END_EVENT_TABLE()
2268
2269 wxListCtrl::wxListCtrl(void)
2270 {
2271 m_imageListNormal = (wxImageList *) NULL;
2272 m_imageListSmall = (wxImageList *) NULL;
2273 m_imageListState = (wxImageList *) NULL;
2274 m_mainWin = (wxListMainWindow*) NULL;
2275 m_headerWin = (wxListHeaderWindow*) NULL;
2276 }
2277
2278 wxListCtrl::~wxListCtrl(void)
2279 {
2280 }
2281
2282 bool wxListCtrl::Create( wxWindow *parent, wxWindowID id,
2283 const wxPoint &pos, const wxSize &size,
2284 long style, const wxValidator &validator,
2285 const wxString &name )
2286 {
2287 m_imageListNormal = (wxImageList *) NULL;
2288 m_imageListSmall = (wxImageList *) NULL;
2289 m_imageListState = (wxImageList *) NULL;
2290 m_mainWin = (wxListMainWindow*) NULL;
2291 m_headerWin = (wxListHeaderWindow*) NULL;
2292
2293 long s = style;
2294
2295 if ((s & wxLC_REPORT == 0) &&
2296 (s & wxLC_LIST == 0) &&
2297 (s & wxLC_ICON == 0))
2298 s = s | wxLC_LIST;
2299
2300 bool ret = wxControl::Create( parent, id, pos, size, s, name );
2301
2302 SetValidator( validator );
2303
2304 if (s & wxSUNKEN_BORDER) s -= wxSUNKEN_BORDER;
2305
2306 m_mainWin = new wxListMainWindow( this, -1, wxPoint(0,0), size, s );
2307
2308 if (GetWindowStyleFlag() & wxLC_REPORT)
2309 m_headerWin = new wxListHeaderWindow( this, -1, m_mainWin, wxPoint(0,0), wxSize(size.x,23), wxTAB_TRAVERSAL );
2310 else
2311 m_headerWin = (wxListHeaderWindow *) NULL;
2312
2313 return ret;
2314 }
2315
2316 void wxListCtrl::OnSize( wxSizeEvent &WXUNUSED(event) )
2317 {
2318 // handled in OnIdle
2319
2320 if (m_mainWin) m_mainWin->m_dirty = TRUE;
2321 }
2322
2323 void wxListCtrl::SetSingleStyle( long style, bool add )
2324 {
2325 long flag = GetWindowStyleFlag();
2326
2327 if (add)
2328 {
2329 if (style & wxLC_MASK_TYPE) flag = flag & ~wxLC_MASK_TYPE;
2330 if (style & wxLC_MASK_ALIGN) flag = flag & ~wxLC_MASK_ALIGN;
2331 if (style & wxLC_MASK_SORT) flag = flag & ~wxLC_MASK_SORT;
2332 }
2333
2334 if (add)
2335 {
2336 flag |= style;
2337 }
2338 else
2339 {
2340 if (flag & style) flag -= style;
2341 }
2342
2343 SetWindowStyleFlag( flag );
2344 }
2345
2346 void wxListCtrl::SetWindowStyleFlag( long flag )
2347 {
2348 m_mainWin->DeleteEverything();
2349
2350 int width = 0;
2351 int height = 0;
2352 GetClientSize( &width, &height );
2353
2354 m_mainWin->SetMode( flag );
2355
2356 if (flag & wxLC_REPORT)
2357 {
2358 if (!(GetWindowStyleFlag() & wxLC_REPORT))
2359 {
2360 // m_mainWin->SetSize( 0, 24, width, height-24 );
2361 if (!m_headerWin)
2362 {
2363 m_headerWin = new wxListHeaderWindow( this, -1, m_mainWin, wxPoint(0,0), wxSize(width,23), wxTAB_TRAVERSAL );
2364 }
2365 else
2366 {
2367 // m_headerWin->SetSize( 0, 0, width, 23 );
2368 m_headerWin->Show( TRUE );
2369 }
2370 }
2371 }
2372 else
2373 {
2374 if (GetWindowStyleFlag() & wxLC_REPORT)
2375 {
2376 // m_mainWin->SetSize( 0, 0, width, height );
2377 m_headerWin->Show( FALSE );
2378 }
2379 }
2380
2381 wxWindow::SetWindowStyleFlag( flag );
2382 }
2383
2384 bool wxListCtrl::GetColumn(int col, wxListItem &item) const
2385 {
2386 m_mainWin->GetColumn( col, item );
2387 return TRUE;
2388 }
2389
2390 bool wxListCtrl::SetColumn( int col, wxListItem& item )
2391 {
2392 m_mainWin->SetColumn( col, item );
2393 return TRUE;
2394 }
2395
2396 int wxListCtrl::GetColumnWidth( int col ) const
2397 {
2398 return m_mainWin->GetColumnWidth( col );
2399 }
2400
2401 bool wxListCtrl::SetColumnWidth( int col, int width )
2402 {
2403 m_mainWin->SetColumnWidth( col, width );
2404 return TRUE;
2405 }
2406
2407 int wxListCtrl::GetCountPerPage(void) const
2408 {
2409 return m_mainWin->GetCountPerPage(); // different from Windows ?
2410 }
2411
2412 /*
2413 wxText& wxListCtrl::GetEditControl(void) const
2414 {
2415 }
2416 */
2417
2418 bool wxListCtrl::GetItem( wxListItem &info ) const
2419 {
2420 m_mainWin->GetItem( info );
2421 return TRUE;
2422 }
2423
2424 bool wxListCtrl::SetItem( wxListItem &info )
2425 {
2426 m_mainWin->SetItem( info );
2427 return TRUE;
2428 }
2429
2430 long wxListCtrl::SetItem( long index, int col, const wxString& label, int imageId )
2431 {
2432 wxListItem info;
2433 info.m_text = label;
2434 info.m_mask = wxLIST_MASK_TEXT;
2435 info.m_itemId = index;
2436 info.m_col = col;
2437 if ( imageId > -1 )
2438 {
2439 info.m_image = imageId;
2440 info.m_mask |= wxLIST_MASK_IMAGE;
2441 }
2442 ;
2443 m_mainWin->SetItem(info);
2444 return TRUE;
2445 }
2446
2447 int wxListCtrl::GetItemState( long item, long stateMask ) const
2448 {
2449 return m_mainWin->GetItemState( item, stateMask );
2450 }
2451
2452 bool wxListCtrl::SetItemState( long item, long state, long stateMask )
2453 {
2454 m_mainWin->SetItemState( item, state, stateMask );
2455 return TRUE;
2456 }
2457
2458 bool wxListCtrl::SetItemImage( long item, int image, int WXUNUSED(selImage) )
2459 {
2460 wxListItem info;
2461 info.m_image = image;
2462 info.m_mask = wxLIST_MASK_IMAGE;
2463 info.m_itemId = item;
2464 m_mainWin->SetItem( info );
2465 return TRUE;
2466 }
2467
2468 wxString wxListCtrl::GetItemText( long item ) const
2469 {
2470 wxListItem info;
2471 info.m_itemId = item;
2472 m_mainWin->GetItem( info );
2473 return info.m_text;
2474 }
2475
2476 void wxListCtrl::SetItemText( long item, const wxString &str )
2477 {
2478 wxListItem info;
2479 info.m_mask = wxLIST_MASK_TEXT;
2480 info.m_itemId = item;
2481 info.m_text = str;
2482 m_mainWin->SetItem( info );
2483 }
2484
2485 long wxListCtrl::GetItemData( long item ) const
2486 {
2487 wxListItem info;
2488 info.m_itemId = item;
2489 m_mainWin->GetItem( info );
2490 return info.m_data;
2491 }
2492
2493 bool wxListCtrl::SetItemData( long item, long data )
2494 {
2495 wxListItem info;
2496 info.m_mask = wxLIST_MASK_DATA;
2497 info.m_itemId = item;
2498 info.m_data = data;
2499 m_mainWin->SetItem( info );
2500 return TRUE;
2501 }
2502
2503 bool wxListCtrl::GetItemRect( long item, wxRectangle &rect, int WXUNUSED(code) ) const
2504 {
2505 m_mainWin->GetItemRect( item, rect );
2506 return TRUE;
2507 }
2508
2509 bool wxListCtrl::GetItemPosition( long item, wxPoint& pos ) const
2510 {
2511 m_mainWin->GetItemPosition( item, pos );
2512 return TRUE;
2513 }
2514
2515 bool wxListCtrl::SetItemPosition( long WXUNUSED(item), const wxPoint& WXUNUSED(pos) )
2516 {
2517 return 0;
2518 }
2519
2520 int wxListCtrl::GetItemCount(void) const
2521 {
2522 return m_mainWin->GetItemCount();
2523 }
2524
2525 int wxListCtrl::GetColumnCount(void) const
2526 {
2527 return m_mainWin->GetColumnCount();
2528 }
2529
2530 void wxListCtrl::SetItemSpacing( int spacing, bool isSmall )
2531 {
2532 m_mainWin->SetItemSpacing( spacing, isSmall );
2533 }
2534
2535 int wxListCtrl::GetItemSpacing( bool isSmall ) const
2536 {
2537 return m_mainWin->GetItemSpacing( isSmall );
2538 }
2539
2540 int wxListCtrl::GetSelectedItemCount(void) const
2541 {
2542 return m_mainWin->GetSelectedItemCount();
2543 }
2544
2545 /*
2546 wxColour wxListCtrl::GetTextColour(void) const
2547 {
2548 }
2549
2550 void wxListCtrl::SetTextColour(const wxColour& WXUNUSED(col))
2551 {
2552 }
2553 */
2554
2555 long wxListCtrl::GetTopItem(void) const
2556 {
2557 return 0;
2558 }
2559
2560 long wxListCtrl::GetNextItem( long item, int geom, int state ) const
2561 {
2562 return m_mainWin->GetNextItem( item, geom, state );
2563 }
2564
2565 wxImageList *wxListCtrl::GetImageList(int which) const
2566 {
2567 if (which == wxIMAGE_LIST_NORMAL)
2568 {
2569 return m_imageListNormal;
2570 }
2571 else if (which == wxIMAGE_LIST_SMALL)
2572 {
2573 return m_imageListSmall;
2574 }
2575 else if (which == wxIMAGE_LIST_STATE)
2576 {
2577 return m_imageListState;
2578 }
2579 return (wxImageList *) NULL;
2580 }
2581
2582 void wxListCtrl::SetImageList( wxImageList *imageList, int which )
2583 {
2584 m_mainWin->SetImageList( imageList, which );
2585 }
2586
2587 bool wxListCtrl::Arrange( int WXUNUSED(flag) )
2588 {
2589 return 0;
2590 }
2591
2592 bool wxListCtrl::DeleteItem( long item )
2593 {
2594 m_mainWin->DeleteItem( item );
2595 return TRUE;
2596 }
2597
2598 bool wxListCtrl::DeleteAllItems(void)
2599 {
2600 m_mainWin->DeleteAllItems();
2601 return TRUE;
2602 }
2603
2604 bool wxListCtrl::DeleteAllColumns()
2605 {
2606 for ( size_t n = 0; n < m_mainWin->m_columns.GetCount(); n++ )
2607 DeleteColumn(n);
2608
2609 return TRUE;
2610 }
2611
2612 void wxListCtrl::ClearAll()
2613 {
2614 m_mainWin->DeleteEverything();
2615 }
2616
2617 bool wxListCtrl::DeleteColumn( int col )
2618 {
2619 m_mainWin->DeleteColumn( col );
2620 return TRUE;
2621 }
2622
2623 /*
2624 wxText& wxListCtrl::Edit( long WXUNUSED(item ) )
2625 {
2626 }
2627 */
2628
2629 bool wxListCtrl::EnsureVisible( long item )
2630 {
2631 m_mainWin->EnsureVisible( item );
2632 return TRUE;
2633 }
2634
2635 long wxListCtrl::FindItem( long start, const wxString& str, bool partial )
2636 {
2637 return m_mainWin->FindItem( start, str, partial );
2638 }
2639
2640 long wxListCtrl::FindItem( long start, long data )
2641 {
2642 return m_mainWin->FindItem( start, data );
2643 }
2644
2645 long wxListCtrl::FindItem( long WXUNUSED(start), const wxPoint& WXUNUSED(pt),
2646 int WXUNUSED(direction))
2647 {
2648 return 0;
2649 }
2650
2651 long wxListCtrl::HitTest( const wxPoint &point, int &flags )
2652 {
2653 return m_mainWin->HitTest( (int)point.x, (int)point.y, flags );
2654 }
2655
2656 long wxListCtrl::InsertItem( wxListItem& info )
2657 {
2658 m_mainWin->InsertItem( info );
2659 return 0;
2660 }
2661
2662 long wxListCtrl::InsertItem( long index, const wxString &label )
2663 {
2664 wxListItem info;
2665 info.m_text = label;
2666 info.m_mask = wxLIST_MASK_TEXT;
2667 info.m_itemId = index;
2668 return InsertItem( info );
2669 }
2670
2671 long wxListCtrl::InsertItem( long index, int imageIndex )
2672 {
2673 wxListItem info;
2674 info.m_mask = wxLIST_MASK_IMAGE;
2675 info.m_image = imageIndex;
2676 info.m_itemId = index;
2677 return InsertItem( info );
2678 }
2679
2680 long wxListCtrl::InsertItem( long index, const wxString &label, int imageIndex )
2681 {
2682 wxListItem info;
2683 info.m_text = label;
2684 info.m_image = imageIndex;
2685 info.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE;
2686 info.m_itemId = index;
2687 return InsertItem( info );
2688 }
2689
2690 long wxListCtrl::InsertColumn( long col, wxListItem &item )
2691 {
2692 m_mainWin->InsertColumn( col, item );
2693 return 0;
2694 }
2695
2696 long wxListCtrl::InsertColumn( long col, const wxString &heading,
2697 int format, int width )
2698 {
2699 wxListItem item;
2700 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
2701 item.m_text = heading;
2702 if (width >= -2)
2703 {
2704 item.m_mask |= wxLIST_MASK_WIDTH;
2705 item.m_width = width;
2706 }
2707 ;
2708 item.m_format = format;
2709
2710 return InsertColumn( col, item );
2711 }
2712
2713 bool wxListCtrl::ScrollList( int WXUNUSED(dx), int WXUNUSED(dy) )
2714 {
2715 return 0;
2716 }
2717
2718 // Sort items.
2719 // fn is a function which takes 3 long arguments: item1, item2, data.
2720 // item1 is the long data associated with a first item (NOT the index).
2721 // item2 is the long data associated with a second item (NOT the index).
2722 // data is the same value as passed to SortItems.
2723 // The return value is a negative number if the first item should precede the second
2724 // item, a positive number of the second item should precede the first,
2725 // or zero if the two items are equivalent.
2726 // data is arbitrary data to be passed to the sort function.
2727
2728 bool wxListCtrl::SortItems( wxListCtrlCompare fn, long data )
2729 {
2730 m_mainWin->SortItems( fn, data );
2731 return TRUE;
2732 }
2733
2734 void wxListCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) )
2735 {
2736 if (!m_mainWin->m_dirty) return;
2737
2738 int cw = 0;
2739 int ch = 0;
2740 GetClientSize( &cw, &ch );
2741
2742 int x = 0;
2743 int y = 0;
2744 int w = 0;
2745 int h = 0;
2746
2747 if (GetWindowStyleFlag() & wxLC_REPORT)
2748 {
2749 m_headerWin->GetPosition( &x, &y );
2750 m_headerWin->GetSize( &w, &h );
2751 if ((x != 0) || (y != 0) || (w != cw) || (h != 23))
2752 m_headerWin->SetSize( 0, 0, cw, 23 );
2753
2754 m_mainWin->GetPosition( &x, &y );
2755 m_mainWin->GetSize( &w, &h );
2756 if ((x != 0) || (y != 24) || (w != cw) || (h != ch-24))
2757 m_mainWin->SetSize( 0, 24, cw, ch-24 );
2758 }
2759 else
2760 {
2761 m_mainWin->GetPosition( &x, &y );
2762 m_mainWin->GetSize( &w, &h );
2763 if ((x != 0) || (y != 24) || (w != cw) || (h != ch))
2764 m_mainWin->SetSize( 0, 0, cw, ch );
2765 }
2766
2767 m_mainWin->CalculatePositions();
2768 m_mainWin->RealizeChanges();
2769 m_mainWin->m_dirty = FALSE;
2770 m_mainWin->Refresh();
2771 }
2772
2773 void wxListCtrl::SetBackgroundColour( const wxColour &colour )
2774 {
2775 if (m_mainWin)
2776 {
2777 m_mainWin->SetBackgroundColour( colour );
2778 m_mainWin->m_dirty = TRUE;
2779 }
2780 if (m_headerWin)
2781 m_headerWin->SetBackgroundColour( colour );
2782 }
2783
2784 void wxListCtrl::SetForegroundColour( const wxColour &colour )
2785 {
2786 if (m_mainWin)
2787 {
2788 m_mainWin->SetForegroundColour( colour );
2789 m_mainWin->m_dirty = TRUE;
2790 }
2791 if (m_headerWin)
2792 m_headerWin->SetForegroundColour( colour );
2793 }
2794
2795 void wxListCtrl::SetFont( const wxFont &font )
2796 {
2797 if (m_mainWin)
2798 {
2799 m_mainWin->SetFont( font );
2800 m_mainWin->m_dirty = TRUE;
2801 }
2802 if (m_headerWin)
2803 m_headerWin->SetFont( font );
2804 }
2805