]> git.saurik.com Git - wxWidgets.git/blob - src/generic/listctrl.cpp
compilation fix for broken OS/2 compiler
[wxWidgets.git] / src / generic / listctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/listctrl.cpp
3 // Purpose: generic implementation of wxListCtrl
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 #ifdef __GNUG__
19 #pragma implementation "listctrl.h"
20 #pragma implementation "listctrlbase.h"
21 #endif
22
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 #if wxUSE_LISTCTRL
31
32 #include "wx/dcscreen.h"
33 #include "wx/app.h"
34 #include "wx/listctrl.h"
35 #include "wx/generic/imaglist.h"
36 #include "wx/dynarray.h"
37
38 #ifdef __WXGTK__
39 #include <gtk/gtk.h>
40 #include "wx/gtk/win_gtk.h"
41 #endif
42
43 #ifndef wxUSE_GENERIC_LIST_EXTENSIONS
44 #define wxUSE_GENERIC_LIST_EXTENSIONS 1
45 #endif
46
47 // ----------------------------------------------------------------------------
48 // events
49 // ----------------------------------------------------------------------------
50
51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG)
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
56 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
57 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
58 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
59 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
60 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
61 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
62 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
63 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
64 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
65 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
66 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
67
68 // ============================================================================
69 // private classes
70 // ============================================================================
71
72 //-----------------------------------------------------------------------------
73 // wxListItemData (internal)
74 //-----------------------------------------------------------------------------
75
76 class WXDLLEXPORT wxListItemData : public wxObject
77 {
78 public:
79 wxListItemData();
80 ~wxListItemData() { delete m_attr; }
81
82 wxListItemData( const wxListItem &info );
83 void SetItem( const wxListItem &info );
84 void SetImage( int image );
85 void SetData( long data );
86 void SetPosition( int x, int y );
87 void SetSize( int width, int height );
88 bool HasImage() const;
89
90 bool HasText() const { return !m_text.empty(); }
91 const wxString& GetText() const { return m_text; }
92 void SetText(const wxString& text) { m_text = text; }
93
94 bool IsHit( int x, int y ) const;
95
96 int GetX( void ) const;
97 int GetY( void ) const;
98 int GetWidth() const;
99 int GetHeight() const;
100 int GetImage() const;
101 void GetItem( wxListItem &info ) const;
102
103 wxListItemAttr *GetAttributes() const { return m_attr; }
104
105 public:
106 int m_image;
107 long m_data;
108 int m_xpos,
109 m_ypos;
110 int m_width,
111 m_height;
112
113 wxListItemAttr *m_attr;
114
115 protected:
116 wxString m_text;
117
118 private:
119 DECLARE_DYNAMIC_CLASS(wxListItemData);
120 };
121
122 //-----------------------------------------------------------------------------
123 // wxListHeaderData (internal)
124 //-----------------------------------------------------------------------------
125
126 class WXDLLEXPORT wxListHeaderData : public wxObject
127 {
128 protected:
129 long m_mask;
130 int m_image;
131 wxString m_text;
132 int m_format;
133 int m_width;
134 int m_xpos,
135 m_ypos;
136 int m_height;
137
138 public:
139 wxListHeaderData();
140 wxListHeaderData( const wxListItem &info );
141 void SetItem( const wxListItem &item );
142 void SetPosition( int x, int y );
143 void SetWidth( int w );
144 void SetFormat( int format );
145 void SetHeight( int h );
146 bool HasImage() const;
147
148 bool HasText() const { return !m_text.empty(); }
149 const wxString& GetText() const { return m_text; }
150 void SetText(const wxString& text) { m_text = text; }
151
152 void GetItem( wxListItem &item );
153
154 bool IsHit( int x, int y ) const;
155 int GetImage() const;
156 int GetWidth() const;
157 int GetFormat() const;
158
159 private:
160 DECLARE_DYNAMIC_CLASS(wxListHeaderData);
161 };
162
163 //-----------------------------------------------------------------------------
164 // wxListLineData (internal)
165 //-----------------------------------------------------------------------------
166
167 WX_DECLARE_LIST(wxListItemData, wxListItemDataList);
168 #include "wx/listimpl.cpp"
169 WX_DEFINE_LIST(wxListItemDataList);
170
171 class WXDLLEXPORT wxListLineData : public wxObject
172 {
173 public:
174 wxListItemDataList m_items;
175 wxRect m_bound_all;
176 wxRect m_bound_label;
177 wxRect m_bound_icon;
178 wxRect m_bound_hilight;
179 int m_mode;
180 bool m_hilighted;
181 wxBrush *m_hilightBrush;
182 int m_spacing;
183 wxListMainWindow *m_owner;
184
185 void DoDraw( wxDC *dc, bool hilight, bool paintBG );
186
187 public:
188 wxListLineData() {}
189 wxListLineData( wxListMainWindow *owner, int mode, wxBrush *hilightBrush );
190 void CalculateSize( wxDC *dc, int spacing );
191 void SetPosition( wxDC *dc, int x, int y, int window_width );
192 void SetColumnPosition( int index, int x );
193 void GetSize( int &width, int &height );
194 void GetExtent( int &x, int &y, int &width, int &height );
195 void GetLabelExtent( int &x, int &y, int &width, int &height );
196 long IsHit( int x, int y );
197 void InitItems( int num );
198 void SetItem( int index, const wxListItem &info );
199 void GetItem( int index, wxListItem &info );
200 wxString GetText(int index) const;
201 void SetText( int index, const wxString s );
202 int GetImage( int index );
203 void GetRect( wxRect &rect );
204 void Hilight( bool on );
205 void ReverseHilight();
206 void DrawRubberBand( wxDC *dc, bool on );
207 void Draw( wxDC *dc );
208 bool IsInRect( int x, int y, const wxRect &rect );
209 bool IsHilighted();
210 void AssignRect( wxRect &dest, int x, int y, int width, int height );
211 void AssignRect( wxRect &dest, const wxRect &source );
212
213 private:
214 void SetAttributes(wxDC *dc,
215 const wxListItemAttr *attr,
216 const wxColour& colText, const wxFont& font,
217 bool hilight);
218
219 DECLARE_DYNAMIC_CLASS(wxListLineData);
220 };
221
222
223 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData, wxListLineDataArray);
224 #include "wx/arrimpl.cpp"
225 WX_DEFINE_OBJARRAY(wxListLineDataArray);
226
227 //-----------------------------------------------------------------------------
228 // wxListHeaderWindow (internal)
229 //-----------------------------------------------------------------------------
230
231 class WXDLLEXPORT wxListHeaderWindow : public wxWindow
232 {
233 protected:
234 wxListMainWindow *m_owner;
235 wxCursor *m_currentCursor;
236 wxCursor *m_resizeCursor;
237 bool m_isDragging;
238
239 // column being resized
240 int m_column;
241
242 // divider line position in logical (unscrolled) coords
243 int m_currentX;
244
245 // minimal position beyond which the divider line can't be dragged in
246 // logical coords
247 int m_minX;
248
249 public:
250 wxListHeaderWindow();
251 virtual ~wxListHeaderWindow();
252
253 wxListHeaderWindow( wxWindow *win,
254 wxWindowID id,
255 wxListMainWindow *owner,
256 const wxPoint &pos = wxDefaultPosition,
257 const wxSize &size = wxDefaultSize,
258 long style = 0,
259 const wxString &name = "wxlistctrlcolumntitles" );
260
261 void DoDrawRect( wxDC *dc, int x, int y, int w, int h );
262 void DrawCurrent();
263 void AdjustDC(wxDC& dc);
264
265 void OnPaint( wxPaintEvent &event );
266 void OnMouse( wxMouseEvent &event );
267 void OnSetFocus( wxFocusEvent &event );
268
269 // needs refresh
270 bool m_dirty;
271
272 private:
273 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow)
274 DECLARE_EVENT_TABLE()
275 };
276
277 //-----------------------------------------------------------------------------
278 // wxListRenameTimer (internal)
279 //-----------------------------------------------------------------------------
280
281 class WXDLLEXPORT wxListRenameTimer: public wxTimer
282 {
283 private:
284 wxListMainWindow *m_owner;
285
286 public:
287 wxListRenameTimer( wxListMainWindow *owner );
288 void Notify();
289 };
290
291 //-----------------------------------------------------------------------------
292 // wxListTextCtrl (internal)
293 //-----------------------------------------------------------------------------
294
295 class WXDLLEXPORT wxListTextCtrl: public wxTextCtrl
296 {
297 private:
298 bool *m_accept;
299 wxString *m_res;
300 wxListMainWindow *m_owner;
301 wxString m_startValue;
302
303 public:
304 wxListTextCtrl() {}
305 wxListTextCtrl( wxWindow *parent, const wxWindowID id,
306 bool *accept, wxString *res, wxListMainWindow *owner,
307 const wxString &value = "",
308 const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize,
309 int style = 0,
310 const wxValidator& validator = wxDefaultValidator,
311 const wxString &name = "listctrltextctrl" );
312 void OnChar( wxKeyEvent &event );
313 void OnKeyUp( wxKeyEvent &event );
314 void OnKillFocus( wxFocusEvent &event );
315
316 private:
317 DECLARE_DYNAMIC_CLASS(wxListTextCtrl);
318 DECLARE_EVENT_TABLE()
319 };
320
321 //-----------------------------------------------------------------------------
322 // wxListMainWindow (internal)
323 //-----------------------------------------------------------------------------
324
325 WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList);
326 #include "wx/listimpl.cpp"
327 WX_DEFINE_LIST(wxListHeaderDataList);
328
329 class WXDLLEXPORT wxListMainWindow: public wxScrolledWindow
330 {
331 public:
332 // the style of the control (combination of wxLC_XXX)
333 long m_mode;
334
335 // the array of all line objects for a non virtual list control
336 wxListLineDataArray m_lines;
337
338 // the total count of items in a virtual list control
339 long m_countVirt;
340
341 // the list of column objects
342 wxListHeaderDataList m_columns;
343
344 // currently focused item or NULL
345 wxListLineData *m_current;
346
347 // the item currently being edited or -1
348 size_t m_currentEdit;
349
350 int m_visibleLines;
351 wxBrush *m_hilightBrush;
352 wxColour *m_hilightColour;
353 int m_xScroll,
354 m_yScroll;
355 bool m_dirty;
356 wxImageList *m_small_image_list;
357 wxImageList *m_normal_image_list;
358 int m_small_spacing;
359 int m_normal_spacing;
360 bool m_hasFocus;
361 bool m_usedKeys;
362 bool m_lastOnSame;
363 wxTimer *m_renameTimer;
364 bool m_renameAccept;
365 wxString m_renameRes;
366 bool m_isCreated;
367 int m_dragCount;
368 wxPoint m_dragStart;
369
370 // for double click logic
371 size_t m_lineLastClicked,
372 m_lineBeforeLastClicked;
373
374 public:
375 wxListMainWindow();
376 wxListMainWindow( wxWindow *parent,
377 wxWindowID id,
378 const wxPoint& pos = wxDefaultPosition,
379 const wxSize& size = wxDefaultSize,
380 long style = 0,
381 const wxString &name = _T("listctrlmainwindow") );
382
383 virtual ~wxListMainWindow();
384
385 // return true if this is a virtual list control
386 bool IsVirtual() const { return (m_mode & wxLC_VIRTUAL) != 0; }
387
388 void RefreshLine( wxListLineData *line );
389 void OnPaint( wxPaintEvent &event );
390 void HilightAll( bool on );
391 void SendNotify( wxListLineData *line,
392 wxEventType command,
393 wxPoint point = wxDefaultPosition );
394 void FocusLine( wxListLineData *line );
395 void UnfocusLine( wxListLineData *line );
396 void SelectLine( wxListLineData *line );
397 void DeselectLine( wxListLineData *line );
398 void DeleteLine( wxListLineData *line );
399
400 void EditLabel( long item );
401 void Edit( long item ) { EditLabel(item); } // deprecated
402 void OnRenameTimer();
403 void OnRenameAccept();
404
405 void OnMouse( wxMouseEvent &event );
406 void MoveToFocus();
407 void OnArrowChar( wxListLineData *newCurrent, bool shiftDown );
408 void OnChar( wxKeyEvent &event );
409 void OnKeyDown( wxKeyEvent &event );
410 void OnSetFocus( wxFocusEvent &event );
411 void OnKillFocus( wxFocusEvent &event );
412 void OnSize( wxSizeEvent &event );
413 void OnScroll(wxScrollWinEvent& event) ;
414
415 void DrawImage( int index, wxDC *dc, int x, int y );
416 void GetImageSize( int index, int &width, int &height );
417 int GetIndexOfLine( const wxListLineData *line );
418 int GetTextLength( wxString &s ); // should be const
419
420 void SetImageList( wxImageList *imageList, int which );
421 void SetItemSpacing( int spacing, bool isSmall = FALSE );
422 int GetItemSpacing( bool isSmall = FALSE );
423 void SetColumn( int col, wxListItem &item );
424 void SetColumnWidth( int col, int width );
425 void GetColumn( int col, wxListItem &item );
426 int GetColumnWidth( int vol );
427 int GetColumnCount();
428 int GetCountPerPage();
429 void SetItem( wxListItem &item );
430 void GetItem( wxListItem &item );
431 void SetItemState( long item, long state, long stateMask );
432 int GetItemState( long item, long stateMask );
433 void GetItemRect( long index, wxRect &rect );
434 bool GetItemPosition( long item, wxPoint& pos );
435 int GetSelectedItemCount();
436 void SetMode( long mode );
437 long GetMode() const;
438 void CalculatePositions();
439 void RealizeChanges();
440 long GetNextItem( long item, int geometry, int state );
441 void DeleteItem( long index );
442 void DeleteAllItems();
443 void DeleteColumn( int col );
444 void DeleteEverything();
445 void EnsureVisible( long index );
446 long FindItem( long start, const wxString& str, bool partial = FALSE );
447 long FindItem( long start, long data);
448 long HitTest( int x, int y, int &flags );
449 void InsertItem( wxListItem &item );
450 // void AddItem( wxListItem &item );
451 void InsertColumn( long col, wxListItem &item );
452 // void AddColumn( wxListItem &item );
453 void SortItems( wxListCtrlCompare fn, long data );
454
455 int GetItemCount() const;
456 bool IsEmpty() const { return GetItemCount() == 0; }
457 void SetItemCount(long count);
458
459 protected:
460 // common part of all ctors
461 void Init();
462
463 // get the line data for the given index
464 wxListLineData *GetLine(size_t n) const
465 {
466 wxASSERT_MSG( n != (size_t)-1, _T("invalid line index") );
467
468 return &m_lines[n];
469 }
470
471 private:
472 DECLARE_DYNAMIC_CLASS(wxListMainWindow);
473 DECLARE_EVENT_TABLE()
474 };
475
476 // ============================================================================
477 // implementation
478 // ============================================================================
479
480 //-----------------------------------------------------------------------------
481 // wxListItemData
482 //-----------------------------------------------------------------------------
483
484 IMPLEMENT_DYNAMIC_CLASS(wxListItemData,wxObject);
485
486 wxListItemData::wxListItemData()
487 {
488 m_image = -1;
489 m_data = 0;
490 m_xpos = 0;
491 m_ypos = 0;
492 m_width = 0;
493 m_height = 0;
494 m_attr = NULL;
495 }
496
497 wxListItemData::wxListItemData( const wxListItem &info )
498 {
499 m_image = -1;
500 m_data = 0;
501 m_attr = NULL;
502
503 SetItem( info );
504 }
505
506 void wxListItemData::SetItem( const wxListItem &info )
507 {
508 if (info.m_mask & wxLIST_MASK_TEXT)
509 SetText(info.m_text);
510 if (info.m_mask & wxLIST_MASK_IMAGE)
511 m_image = info.m_image;
512 if (info.m_mask & wxLIST_MASK_DATA)
513 m_data = info.m_data;
514
515 if ( info.HasAttributes() )
516 {
517 if ( m_attr )
518 *m_attr = *info.GetAttributes();
519 else
520 m_attr = new wxListItemAttr(*info.GetAttributes());
521 }
522
523 m_xpos = 0;
524 m_ypos = 0;
525 m_width = info.m_width;
526 m_height = 0;
527 }
528
529 void wxListItemData::SetImage( int image )
530 {
531 m_image = image;
532 }
533
534 void wxListItemData::SetData( long data )
535 {
536 m_data = data;
537 }
538
539 void wxListItemData::SetPosition( int x, int y )
540 {
541 m_xpos = x;
542 m_ypos = y;
543 }
544
545 void wxListItemData::SetSize( int width, int height )
546 {
547 if (width != -1) m_width = width;
548 if (height != -1) m_height = height;
549 }
550
551 bool wxListItemData::HasImage() const
552 {
553 return (m_image >= 0);
554 }
555
556 bool wxListItemData::IsHit( int x, int y ) const
557 {
558 return ((x >= m_xpos) && (x <= m_xpos+m_width) && (y >= m_ypos) && (y <= m_ypos+m_height));
559 }
560
561 int wxListItemData::GetX() const
562 {
563 return m_xpos;
564 }
565
566 int wxListItemData::GetY() const
567 {
568 return m_ypos;
569 }
570
571 int wxListItemData::GetWidth() const
572 {
573 return m_width;
574 }
575
576 int wxListItemData::GetHeight() const
577 {
578 return m_height;
579 }
580
581 int wxListItemData::GetImage() const
582 {
583 return m_image;
584 }
585
586 void wxListItemData::GetItem( wxListItem &info ) const
587 {
588 info.m_text = m_text;
589 info.m_image = m_image;
590 info.m_data = m_data;
591
592 if ( m_attr )
593 {
594 if ( m_attr->HasTextColour() )
595 info.SetTextColour(m_attr->GetTextColour());
596 if ( m_attr->HasBackgroundColour() )
597 info.SetBackgroundColour(m_attr->GetBackgroundColour());
598 if ( m_attr->HasFont() )
599 info.SetFont(m_attr->GetFont());
600 }
601 }
602
603 //-----------------------------------------------------------------------------
604 // wxListHeaderData
605 //-----------------------------------------------------------------------------
606
607 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData,wxObject);
608
609 wxListHeaderData::wxListHeaderData()
610 {
611 m_mask = 0;
612 m_image = 0;
613 m_format = 0;
614 m_width = 0;
615 m_xpos = 0;
616 m_ypos = 0;
617 m_height = 0;
618 }
619
620 wxListHeaderData::wxListHeaderData( const wxListItem &item )
621 {
622 SetItem( item );
623 m_xpos = 0;
624 m_ypos = 0;
625 m_height = 0;
626 }
627
628 void wxListHeaderData::SetItem( const wxListItem &item )
629 {
630 m_mask = item.m_mask;
631 m_text = item.m_text;
632 m_image = item.m_image;
633 m_format = item.m_format;
634 m_width = item.m_width;
635 if (m_width < 0) m_width = 80;
636 if (m_width < 6) m_width = 6;
637 }
638
639 void wxListHeaderData::SetPosition( int x, int y )
640 {
641 m_xpos = x;
642 m_ypos = y;
643 }
644
645 void wxListHeaderData::SetHeight( int h )
646 {
647 m_height = h;
648 }
649
650 void wxListHeaderData::SetWidth( int w )
651 {
652 m_width = w;
653 if (m_width < 0) m_width = 80;
654 if (m_width < 6) m_width = 6;
655 }
656
657 void wxListHeaderData::SetFormat( int format )
658 {
659 m_format = format;
660 }
661
662 bool wxListHeaderData::HasImage() const
663 {
664 return (m_image != 0);
665 }
666
667 bool wxListHeaderData::IsHit( int x, int y ) const
668 {
669 return ((x >= m_xpos) && (x <= m_xpos+m_width) && (y >= m_ypos) && (y <= m_ypos+m_height));
670 }
671
672 void wxListHeaderData::GetItem( wxListItem &item )
673 {
674 item.m_mask = m_mask;
675 item.m_text = m_text;
676 item.m_image = m_image;
677 item.m_format = m_format;
678 item.m_width = m_width;
679 }
680
681 int wxListHeaderData::GetImage() const
682 {
683 return m_image;
684 }
685
686 int wxListHeaderData::GetWidth() const
687 {
688 return m_width;
689 }
690
691 int wxListHeaderData::GetFormat() const
692 {
693 return m_format;
694 }
695
696 //-----------------------------------------------------------------------------
697 // wxListLineData
698 //-----------------------------------------------------------------------------
699
700 IMPLEMENT_DYNAMIC_CLASS(wxListLineData,wxObject);
701
702 wxListLineData::wxListLineData( wxListMainWindow *owner, int mode, wxBrush *hilightBrush )
703 {
704 m_mode = mode;
705 m_hilighted = FALSE;
706 m_owner = owner;
707 m_hilightBrush = hilightBrush;
708 m_items.DeleteContents( TRUE );
709 m_spacing = 0;
710 }
711
712 void wxListLineData::CalculateSize( wxDC *dc, int spacing )
713 {
714 wxListItemDataList::Node *node = m_items.GetFirst();
715
716 m_spacing = spacing;
717 switch (m_mode)
718 {
719 case wxLC_ICON:
720 {
721 m_bound_all.width = m_spacing;
722 if (node)
723 {
724 wxListItemData *item = node->GetData();
725 wxString s = item->GetText();
726 if (s.IsEmpty())
727 s = wxT("H");
728
729 wxCoord lw,lh;
730 dc->GetTextExtent( s, &lw, &lh );
731 if (lh < 15)
732 lh = 15;
733 lw += 4;
734 lh += 3;
735
736 m_bound_all.height = m_spacing+lh;
737 if (lw > m_spacing)
738 m_bound_all.width = lw;
739 m_bound_label.width = lw;
740 m_bound_label.height = lh;
741
742 if (item->HasImage())
743 {
744 int w = 0;
745 int h = 0;
746 m_owner->GetImageSize( item->GetImage(), w, h );
747 m_bound_icon.width = w + 8;
748 m_bound_icon.height = h + 8;
749
750 if ( m_bound_icon.width > m_bound_all.width )
751 m_bound_all.width = m_bound_icon.width;
752 if ( h + lh > m_bound_all.height - 4 )
753 m_bound_all.height = h + lh + 4;
754 }
755
756 if (!item->HasText())
757 {
758 m_bound_hilight.width = m_bound_icon.width;
759 m_bound_hilight.height = m_bound_icon.height;
760 }
761 else
762 {
763 m_bound_hilight.width = m_bound_label.width;
764 m_bound_hilight.height = m_bound_label.height;
765 }
766 }
767 break;
768 }
769 case wxLC_LIST:
770 {
771 if (node)
772 {
773 wxListItemData *item = node->GetData();
774
775 wxString s = item->GetText();
776 if (s.IsEmpty())
777 s = wxT("H");
778
779 wxCoord lw,lh;
780 dc->GetTextExtent( s, &lw, &lh );
781 if (lh < 15)
782 lh = 15;
783 lw += 4;
784 lh += 3;
785
786 m_bound_label.width = lw;
787 m_bound_label.height = lh;
788
789 m_bound_all.width = lw;
790 m_bound_all.height = lh;
791
792 if (item->HasImage())
793 {
794 int w = 0;
795 int h = 0;
796 m_owner->GetImageSize( item->GetImage(), w, h );
797 m_bound_icon.width = w;
798 m_bound_icon.height = h;
799
800 m_bound_all.width += 4 + w;
801 if (h > m_bound_all.height) m_bound_all.height = h;
802 }
803
804 m_bound_hilight.width = m_bound_all.width;
805 m_bound_hilight.height = m_bound_all.height;
806 }
807 break;
808 }
809 case wxLC_REPORT:
810 {
811 m_bound_all.width = 0;
812 m_bound_all.height = 0;
813 if (node)
814 {
815 wxListItemData *item = node->GetData();
816 if (item->HasImage())
817 {
818 int w = 0;
819 int h = 0;
820 m_owner->GetImageSize( item->GetImage(), w, h );
821 m_bound_icon.width = w;
822 m_bound_icon.height = h;
823 }
824 else
825 {
826 m_bound_icon.width = 0;
827 m_bound_icon.height = 0;
828 }
829 }
830
831 while (node)
832 {
833 wxListItemData *item = node->GetData();
834 wxString s = item->GetText();
835 if (s.IsEmpty())
836 s = wxT("H");
837
838 wxCoord lw,lh;
839 dc->GetTextExtent( s, &lw, &lh );
840 if (lh < 15)
841 lh = 15;
842 lw += 4;
843 lh += 3;
844
845 item->SetSize( item->GetWidth(), lh );
846 m_bound_all.width += lw;
847 m_bound_all.height = lh;
848 node = node->GetNext();
849 }
850 m_bound_label.width = m_bound_all.width;
851 m_bound_label.height = m_bound_all.height;
852 break;
853 }
854 }
855 }
856
857 void wxListLineData::SetPosition( wxDC * WXUNUSED(dc),
858 int x, int y, int window_width )
859 {
860 wxListItemDataList::Node *node = m_items.GetFirst();
861
862 m_bound_all.x = x;
863 m_bound_all.y = y;
864
865 switch (m_mode)
866 {
867 case wxLC_ICON:
868 {
869 if (node)
870 {
871 wxListItemData *item = node->GetData();
872 if (item->HasImage())
873 {
874 m_bound_icon.x = m_bound_all.x + 4
875 + (m_spacing - m_bound_icon.width)/2;
876 m_bound_icon.y = m_bound_all.y + 4;
877 }
878 if (item->HasText())
879 {
880 if (m_bound_all.width > m_spacing)
881 m_bound_label.x = m_bound_all.x + 2;
882 else
883 m_bound_label.x = m_bound_all.x + 2 + (m_spacing/2) - (m_bound_label.width/2);
884 m_bound_label.y = m_bound_all.y + m_bound_all.height + 2 - m_bound_label.height;
885 m_bound_hilight.x = m_bound_label.x - 2;
886 m_bound_hilight.y = m_bound_label.y - 2;
887 }
888 else
889 {
890 m_bound_hilight.x = m_bound_icon.x - 4;
891 m_bound_hilight.y = m_bound_icon.y - 4;
892 }
893 }
894 break;
895 }
896 case wxLC_LIST:
897 {
898 m_bound_hilight.x = m_bound_all.x;
899 m_bound_hilight.y = m_bound_all.y;
900 m_bound_label.y = m_bound_all.y + 2;
901 if (node)
902 {
903 wxListItemData *item = node->GetData();
904 if (item->HasImage())
905 {
906 m_bound_icon.x = m_bound_all.x + 2;
907 m_bound_icon.y = m_bound_all.y + 2;
908 m_bound_label.x = m_bound_all.x + 6 + m_bound_icon.width;
909 }
910 else
911 {
912 m_bound_label.x = m_bound_all.x + 2;
913 }
914 }
915 break;
916 }
917 case wxLC_REPORT:
918 {
919 m_bound_all.x = 0;
920 m_bound_all.width = window_width;
921 AssignRect( m_bound_hilight, m_bound_all );
922 m_bound_label.x = m_bound_all.x + 2;
923 m_bound_label.y = m_bound_all.y + 2;
924 if (node)
925 {
926 wxListItemData *item = node->GetData();
927 if (item->HasImage())
928 {
929 m_bound_icon.x = m_bound_all.x + 2;
930 m_bound_icon.y = m_bound_all.y + 2;
931 m_bound_label.x += 4 + m_bound_icon.width;
932 }
933 }
934 break;
935 }
936 }
937 }
938
939 void wxListLineData::SetColumnPosition( int index, int x )
940 {
941 wxListItemDataList::Node *node = m_items.Item( (size_t)index );
942 if (node)
943 {
944 wxListItemData *item = node->GetData();
945 item->SetPosition( x, m_bound_all.y+1 );
946 }
947 }
948
949 void wxListLineData::GetSize( int &width, int &height )
950 {
951 width = m_bound_all.width;
952 height = m_bound_all.height;
953 }
954
955 void wxListLineData::GetExtent( int &x, int &y, int &width, int &height )
956 {
957 x = m_bound_all.x;
958 y = m_bound_all.y;
959 width = m_bound_all.width;
960 height = m_bound_all.height;
961 }
962
963 void wxListLineData::GetLabelExtent( int &x, int &y, int &width, int &height )
964 {
965 x = m_bound_label.x;
966 y = m_bound_label.y;
967 width = m_bound_label.width;
968 height = m_bound_label.height;
969 }
970
971 void wxListLineData::GetRect( wxRect &rect )
972 {
973 AssignRect( rect, m_bound_all );
974 }
975
976 long wxListLineData::IsHit( int x, int y )
977 {
978 wxListItemDataList::Node *node = m_items.GetFirst();
979 if (node)
980 {
981 wxListItemData *item = node->GetData();
982 if (item->HasImage() && IsInRect( x, y, m_bound_icon ))
983 return wxLIST_HITTEST_ONITEMICON;
984 if (item->HasText() && IsInRect( x, y, m_bound_label ))
985 return wxLIST_HITTEST_ONITEMLABEL;
986
987 }
988
989 // if there is no icon or text = empty
990 if (IsInRect( x, y, m_bound_all ))
991 return wxLIST_HITTEST_ONITEMICON;
992
993 return 0;
994 }
995
996 void wxListLineData::InitItems( int num )
997 {
998 for (int i = 0; i < num; i++)
999 m_items.Append( new wxListItemData() );
1000 }
1001
1002 void wxListLineData::SetItem( int index, const wxListItem &info )
1003 {
1004 wxListItemDataList::Node *node = m_items.Item( index );
1005 wxCHECK_RET( node, _T("invalid column index in SetItem") );
1006
1007 wxListItemData *item = node->GetData();
1008 item->SetItem( info );
1009 }
1010
1011 void wxListLineData::GetItem( int index, wxListItem &info )
1012 {
1013 wxListItemDataList::Node *node = m_items.Item( index );
1014 if (node)
1015 {
1016 wxListItemData *item = node->GetData();
1017 item->GetItem( info );
1018 }
1019 }
1020
1021 wxString wxListLineData::GetText(int index) const
1022 {
1023 wxString s;
1024
1025 wxListItemDataList::Node *node = m_items.Item( index );
1026 if (node)
1027 {
1028 wxListItemData *item = node->GetData();
1029 s = item->GetText();
1030 }
1031
1032 return s;
1033 }
1034
1035 void wxListLineData::SetText( int index, const wxString s )
1036 {
1037 wxListItemDataList::Node *node = m_items.Item( index );
1038 if (node)
1039 {
1040 wxListItemData *item = node->GetData();
1041 item->SetText( s );
1042 }
1043 }
1044
1045 int wxListLineData::GetImage( int index )
1046 {
1047 wxListItemDataList::Node *node = m_items.Item( index );
1048 if (node)
1049 {
1050 wxListItemData *item = node->GetData();
1051 return item->GetImage();
1052 }
1053 return -1;
1054 }
1055
1056 void wxListLineData::SetAttributes(wxDC *dc,
1057 const wxListItemAttr *attr,
1058 const wxColour& colText,
1059 const wxFont& font,
1060 bool hilight)
1061 {
1062 // don't use foregroud colour for drawing highlighted items - this might
1063 // make them completely invisible (and there is no way to do bit
1064 // arithmetics on wxColour, unfortunately)
1065 if ( !hilight && attr && attr->HasTextColour() )
1066 {
1067 dc->SetTextForeground(attr->GetTextColour());
1068 }
1069 else
1070 {
1071 dc->SetTextForeground(colText);
1072 }
1073
1074 if ( attr && attr->HasFont() )
1075 {
1076 dc->SetFont(attr->GetFont());
1077 }
1078 else
1079 {
1080 dc->SetFont(font);
1081 }
1082 }
1083
1084 void wxListLineData::DoDraw( wxDC *dc, bool hilight, bool paintBG )
1085 {
1086 int dev_x = 0;
1087 int dev_y = 0;
1088 m_owner->CalcScrolledPosition( m_bound_all.x, m_bound_all.y, &dev_x, &dev_y );
1089 wxCoord dev_w = m_bound_all.width;
1090 wxCoord dev_h = m_bound_all.height;
1091
1092 if (!m_owner->IsExposed( dev_x, dev_y, dev_w, dev_h ))
1093 return;
1094
1095 wxWindow *listctrl = m_owner->GetParent();
1096
1097 // default foreground colour
1098 wxColour colText;
1099 if ( hilight )
1100 {
1101 colText = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT );
1102 }
1103 else
1104 {
1105 colText = listctrl->GetForegroundColour();
1106 }
1107
1108 // default font
1109 wxFont font = listctrl->GetFont();
1110
1111 // VZ: currently we set the colours/fonts only once, but like this (i.e.
1112 // using SetAttributes() inside the loop), it will be trivial to
1113 // customize the subitems (in report mode) too.
1114 wxListItemData *item = m_items.GetFirst()->GetData();
1115 wxListItemAttr *attr = item->GetAttributes();
1116 SetAttributes(dc, attr, colText, font, hilight);
1117
1118 bool hasBgCol = attr && attr->HasBackgroundColour();
1119 if ( paintBG || hasBgCol )
1120 {
1121 if (hilight)
1122 {
1123 dc->SetBrush( * m_hilightBrush );
1124 }
1125 else
1126 {
1127 if ( hasBgCol )
1128 dc->SetBrush(wxBrush(attr->GetBackgroundColour(), wxSOLID));
1129 else
1130 dc->SetBrush( * wxWHITE_BRUSH );
1131 }
1132
1133 dc->SetPen( * wxTRANSPARENT_PEN );
1134 dc->DrawRectangle( m_bound_hilight.x, m_bound_hilight.y,
1135 m_bound_hilight.width, m_bound_hilight.height );
1136 }
1137
1138 wxListItemDataList::Node *node = m_items.GetFirst();
1139
1140 if (m_mode == wxLC_REPORT)
1141 {
1142 while (node)
1143 {
1144 wxListItemData *item = node->GetData();
1145 int x = item->GetX();
1146 if (item->HasImage())
1147 {
1148 int y = 0;
1149 m_owner->DrawImage( item->GetImage(), dc, x, item->GetY() );
1150 m_owner->GetImageSize( item->GetImage(), x, y );
1151 x += item->GetX() + 5;
1152 }
1153 dc->SetClippingRegion( item->GetX(), item->GetY(), item->GetWidth()-3, item->GetHeight() );
1154 if (item->HasText())
1155 {
1156 dc->DrawText( item->GetText(), x, item->GetY()+1 );
1157 }
1158 dc->DestroyClippingRegion();
1159 node = node->GetNext();
1160 }
1161 }
1162 else // !report
1163 {
1164 if (node)
1165 {
1166 wxListItemData *item = node->GetData();
1167 if (item->HasImage())
1168 {
1169 m_owner->DrawImage( item->GetImage(), dc, m_bound_icon.x, m_bound_icon.y );
1170 }
1171 if (item->HasText())
1172 {
1173 dc->DrawText( item->GetText(), m_bound_label.x, m_bound_label.y );
1174 }
1175 }
1176 }
1177 }
1178
1179 void wxListLineData::Hilight( bool on )
1180 {
1181 if (on == m_hilighted) return;
1182 m_hilighted = on;
1183 if (on)
1184 m_owner->SelectLine( this );
1185 else
1186 m_owner->DeselectLine( this );
1187 }
1188
1189 void wxListLineData::ReverseHilight( void )
1190 {
1191 m_hilighted = !m_hilighted;
1192 if (m_hilighted)
1193 m_owner->SelectLine( this );
1194 else
1195 m_owner->DeselectLine( this );
1196 }
1197
1198 void wxListLineData::DrawRubberBand( wxDC *dc, bool on )
1199 {
1200 if (on)
1201 {
1202 dc->SetPen( * wxBLACK_PEN );
1203 dc->SetBrush( * wxTRANSPARENT_BRUSH );
1204 dc->DrawRectangle( m_bound_hilight.x, m_bound_hilight.y,
1205 m_bound_hilight.width, m_bound_hilight.height );
1206 }
1207 }
1208
1209 void wxListLineData::Draw( wxDC *dc )
1210 {
1211 DoDraw( dc, m_hilighted, m_hilighted );
1212 }
1213
1214 bool wxListLineData::IsInRect( int x, int y, const wxRect &rect )
1215 {
1216 return ((x >= rect.x) && (x <= rect.x+rect.width) &&
1217 (y >= rect.y) && (y <= rect.y+rect.height));
1218 }
1219
1220 bool wxListLineData::IsHilighted( void )
1221 {
1222 return m_hilighted;
1223 }
1224
1225 void wxListLineData::AssignRect( wxRect &dest, int x, int y, int width, int height )
1226 {
1227 dest.x = x;
1228 dest.y = y;
1229 dest.width = width;
1230 dest.height = height;
1231 }
1232
1233 void wxListLineData::AssignRect( wxRect &dest, const wxRect &source )
1234 {
1235 dest.x = source.x;
1236 dest.y = source.y;
1237 dest.width = source.width;
1238 dest.height = source.height;
1239 }
1240
1241 //-----------------------------------------------------------------------------
1242 // wxListHeaderWindow
1243 //-----------------------------------------------------------------------------
1244
1245 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow,wxWindow);
1246
1247 BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow)
1248 EVT_PAINT (wxListHeaderWindow::OnPaint)
1249 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse)
1250 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus)
1251 END_EVENT_TABLE()
1252
1253 wxListHeaderWindow::wxListHeaderWindow( void )
1254 {
1255 m_owner = (wxListMainWindow *) NULL;
1256 m_currentCursor = (wxCursor *) NULL;
1257 m_resizeCursor = (wxCursor *) NULL;
1258 m_isDragging = FALSE;
1259 }
1260
1261 wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, wxWindowID id, wxListMainWindow *owner,
1262 const wxPoint &pos, const wxSize &size,
1263 long style, const wxString &name ) :
1264 wxWindow( win, id, pos, size, style, name )
1265 {
1266 m_owner = owner;
1267 // m_currentCursor = wxSTANDARD_CURSOR;
1268 m_currentCursor = (wxCursor *) NULL;
1269 m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
1270 m_isDragging = FALSE;
1271 m_dirty = FALSE;
1272
1273 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ) );
1274 }
1275
1276 wxListHeaderWindow::~wxListHeaderWindow( void )
1277 {
1278 delete m_resizeCursor;
1279 }
1280
1281 void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h )
1282 {
1283 #ifdef __WXGTK__
1284 GtkStateType state = GTK_STATE_NORMAL;
1285 if (!m_parent->IsEnabled()) state = GTK_STATE_INSENSITIVE;
1286
1287 x = dc->XLOG2DEV( x );
1288
1289 gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window, state, GTK_SHADOW_OUT,
1290 (GdkRectangle*) NULL, m_wxwindow, "button", x-1, y-1, w+2, h+2);
1291 #else
1292 const int m_corner = 1;
1293
1294 dc->SetBrush( *wxTRANSPARENT_BRUSH );
1295
1296 dc->SetPen( *wxBLACK_PEN );
1297 dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer)
1298 dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer)
1299
1300 wxPen pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID );
1301
1302 dc->SetPen( pen );
1303 dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner)
1304 dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner)
1305
1306 dc->SetPen( *wxWHITE_PEN );
1307 dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer)
1308 dc->DrawRectangle( x, y, 1, h ); // left (outer)
1309 dc->DrawLine( x, y+h-1, x+1, y+h-1 );
1310 dc->DrawLine( x+w-1, y, x+w-1, y+1 );
1311 #endif
1312 }
1313
1314 // shift the DC origin to match the position of the main window horz
1315 // scrollbar: this allows us to always use logical coords
1316 void wxListHeaderWindow::AdjustDC(wxDC& dc)
1317 {
1318 #if wxUSE_GENERIC_LIST_EXTENSIONS
1319 int xpix;
1320 m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
1321
1322 int x;
1323 m_owner->GetViewStart( &x, NULL );
1324
1325 // account for the horz scrollbar offset
1326 dc.SetDeviceOrigin( -x * xpix, 0 );
1327 #endif // wxUSE_GENERIC_LIST_EXTENSIONS
1328 }
1329
1330 void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
1331 {
1332 #ifdef __WXGTK__
1333 wxClientDC dc( this );
1334 #else
1335 wxPaintDC dc( this );
1336 #endif
1337
1338 PrepareDC( dc );
1339 AdjustDC( dc );
1340
1341 dc.BeginDrawing();
1342
1343 dc.SetFont( GetFont() );
1344
1345 // width and height of the entire header window
1346 int w, h;
1347 GetClientSize( &w, &h );
1348 #if wxUSE_GENERIC_LIST_EXTENSIONS
1349 m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1350 #endif // wxUSE_GENERIC_LIST_EXTENSIONS
1351
1352 dc.SetBackgroundMode(wxTRANSPARENT);
1353
1354 // do *not* use the listctrl colour for headers - one day we will have a
1355 // function to set it separately
1356 //dc.SetTextForeground( *wxBLACK );
1357 dc.SetTextForeground(wxSystemSettings::GetSystemColour( wxSYS_COLOUR_WINDOWTEXT ));
1358
1359 int x = 1; // left of the header rect
1360 const int y = 1; // top
1361 int numColumns = m_owner->GetColumnCount();
1362 wxListItem item;
1363 for (int i = 0; i < numColumns; i++)
1364 {
1365 m_owner->GetColumn( i, item );
1366 int wCol = item.m_width;
1367 int cw = wCol - 2; // the width of the rect to draw
1368
1369 int xEnd = x + wCol;
1370
1371 // VZ: no, draw it normally - this is better now as we allow resizing
1372 // of the last column as well
1373 #if 0
1374 // let the last column occupy all available space
1375 if ( i == numColumns - 1 )
1376 cw = w-x-1;
1377 #endif // 0
1378
1379 dc.SetPen( *wxWHITE_PEN );
1380
1381 DoDrawRect( &dc, x, y, cw, h-2 );
1382 dc.SetClippingRegion( x, y, cw-5, h-4 );
1383 dc.DrawText( item.GetText(), x+4, y+3 );
1384 dc.DestroyClippingRegion();
1385 x += wCol;
1386
1387 if (xEnd > w+5)
1388 break;
1389 }
1390 dc.EndDrawing();
1391 }
1392
1393 void wxListHeaderWindow::DrawCurrent()
1394 {
1395 int x1 = m_currentX;
1396 int y1 = 0;
1397 ClientToScreen( &x1, &y1 );
1398
1399 int x2 = m_currentX-1;
1400 int y2 = 0;
1401 m_owner->GetClientSize( NULL, &y2 );
1402 m_owner->ClientToScreen( &x2, &y2 );
1403
1404 wxScreenDC dc;
1405 dc.SetLogicalFunction( wxINVERT );
1406 dc.SetPen( wxPen( *wxBLACK, 2, wxSOLID ) );
1407 dc.SetBrush( *wxTRANSPARENT_BRUSH );
1408
1409 AdjustDC(dc);
1410
1411 dc.DrawLine( x1, y1, x2, y2 );
1412
1413 dc.SetLogicalFunction( wxCOPY );
1414
1415 dc.SetPen( wxNullPen );
1416 dc.SetBrush( wxNullBrush );
1417 }
1418
1419 void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
1420 {
1421 // we want to work with logical coords
1422 #if wxUSE_GENERIC_LIST_EXTENSIONS
1423 int x;
1424 m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
1425 #else // !wxUSE_GENERIC_LIST_EXTENSIONS
1426 int x = event.GetX();
1427 #endif // wxUSE_GENERIC_LIST_EXTENSIONS
1428 int y = event.GetY();
1429
1430 if (m_isDragging)
1431 {
1432 // we don't draw the line beyond our window, but we allow dragging it
1433 // there
1434 int w = 0;
1435 GetClientSize( &w, NULL );
1436 #if wxUSE_GENERIC_LIST_EXTENSIONS
1437 m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1438 #endif // wxUSE_GENERIC_LIST_EXTENSIONS
1439 w -= 6;
1440
1441 // erase the line if it was drawn
1442 if ( m_currentX < w )
1443 DrawCurrent();
1444
1445 if (event.ButtonUp())
1446 {
1447 ReleaseMouse();
1448 m_isDragging = FALSE;
1449 m_dirty = TRUE;
1450 m_owner->SetColumnWidth( m_column, m_currentX - m_minX );
1451 }
1452 else
1453 {
1454 if (x > m_minX + 7)
1455 m_currentX = x;
1456 else
1457 m_currentX = m_minX + 7;
1458
1459 // draw in the new location
1460 if ( m_currentX < w )
1461 DrawCurrent();
1462 }
1463 }
1464 else // not dragging
1465 {
1466 m_minX = 0;
1467 bool hit_border = FALSE;
1468
1469 // end of the current column
1470 int xpos = 0;
1471
1472 // find the column where this event occured
1473 int countCol = m_owner->GetColumnCount();
1474 for (int j = 0; j < countCol; j++)
1475 {
1476 xpos += m_owner->GetColumnWidth( j );
1477 m_column = j;
1478
1479 if ( (abs(x-xpos) < 3) && (y < 22) )
1480 {
1481 // near the column border
1482 hit_border = TRUE;
1483 break;
1484 }
1485
1486 if ( x < xpos )
1487 {
1488 // inside the column
1489 break;
1490 }
1491
1492 m_minX = xpos;
1493 }
1494
1495 if (event.LeftDown())
1496 {
1497 if (hit_border)
1498 {
1499 m_isDragging = TRUE;
1500 m_currentX = x;
1501 DrawCurrent();
1502 CaptureMouse();
1503 }
1504 else
1505 {
1506 wxWindow *parent = GetParent();
1507 wxListEvent le( wxEVT_COMMAND_LIST_COL_CLICK, parent->GetId() );
1508 le.SetEventObject( parent );
1509 le.m_col = m_column;
1510 parent->GetEventHandler()->ProcessEvent( le );
1511 }
1512 }
1513 else if (event.Moving())
1514 {
1515 bool setCursor;
1516 if (hit_border)
1517 {
1518 setCursor = m_currentCursor == wxSTANDARD_CURSOR;
1519 m_currentCursor = m_resizeCursor;
1520 }
1521 else
1522 {
1523 setCursor = m_currentCursor != wxSTANDARD_CURSOR;
1524 m_currentCursor = wxSTANDARD_CURSOR;
1525 }
1526
1527 if ( setCursor )
1528 SetCursor(*m_currentCursor);
1529 }
1530 }
1531 }
1532
1533 void wxListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
1534 {
1535 m_owner->SetFocus();
1536 }
1537
1538 //-----------------------------------------------------------------------------
1539 // wxListRenameTimer (internal)
1540 //-----------------------------------------------------------------------------
1541
1542 wxListRenameTimer::wxListRenameTimer( wxListMainWindow *owner )
1543 {
1544 m_owner = owner;
1545 }
1546
1547 void wxListRenameTimer::Notify()
1548 {
1549 m_owner->OnRenameTimer();
1550 }
1551
1552 //-----------------------------------------------------------------------------
1553 // wxListTextCtrl (internal)
1554 //-----------------------------------------------------------------------------
1555
1556 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl,wxTextCtrl);
1557
1558 BEGIN_EVENT_TABLE(wxListTextCtrl,wxTextCtrl)
1559 EVT_CHAR (wxListTextCtrl::OnChar)
1560 EVT_KEY_UP (wxListTextCtrl::OnKeyUp)
1561 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus)
1562 END_EVENT_TABLE()
1563
1564 wxListTextCtrl::wxListTextCtrl( wxWindow *parent,
1565 const wxWindowID id,
1566 bool *accept,
1567 wxString *res,
1568 wxListMainWindow *owner,
1569 const wxString &value,
1570 const wxPoint &pos,
1571 const wxSize &size,
1572 int style,
1573 const wxValidator& validator,
1574 const wxString &name )
1575 : wxTextCtrl( parent, id, value, pos, size, style, validator, name )
1576 {
1577 m_res = res;
1578 m_accept = accept;
1579 m_owner = owner;
1580 (*m_accept) = FALSE;
1581 (*m_res) = "";
1582 m_startValue = value;
1583 }
1584
1585 void wxListTextCtrl::OnChar( wxKeyEvent &event )
1586 {
1587 if (event.m_keyCode == WXK_RETURN)
1588 {
1589 (*m_accept) = TRUE;
1590 (*m_res) = GetValue();
1591
1592 if (!wxPendingDelete.Member(this))
1593 wxPendingDelete.Append(this);
1594
1595 if ((*m_accept) && ((*m_res) != m_startValue))
1596 m_owner->OnRenameAccept();
1597
1598 return;
1599 }
1600 if (event.m_keyCode == WXK_ESCAPE)
1601 {
1602 (*m_accept) = FALSE;
1603 (*m_res) = "";
1604
1605 if (!wxPendingDelete.Member(this))
1606 wxPendingDelete.Append(this);
1607
1608 return;
1609 }
1610
1611 event.Skip();
1612 }
1613
1614 void wxListTextCtrl::OnKeyUp( wxKeyEvent &event )
1615 {
1616 // auto-grow the textctrl:
1617 wxSize parentSize = m_owner->GetSize();
1618 wxPoint myPos = GetPosition();
1619 wxSize mySize = GetSize();
1620 int sx, sy;
1621 GetTextExtent(GetValue() + _T("MM"), &sx, &sy);
1622 if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x;
1623 if (mySize.x > sx) sx = mySize.x;
1624 SetSize(sx, -1);
1625
1626 event.Skip();
1627 }
1628
1629 void wxListTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
1630 {
1631 if (!wxPendingDelete.Member(this))
1632 wxPendingDelete.Append(this);
1633
1634 if ((*m_accept) && ((*m_res) != m_startValue))
1635 m_owner->OnRenameAccept();
1636 }
1637
1638 //-----------------------------------------------------------------------------
1639 // wxListMainWindow
1640 //-----------------------------------------------------------------------------
1641
1642 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow,wxScrolledWindow);
1643
1644 BEGIN_EVENT_TABLE(wxListMainWindow,wxScrolledWindow)
1645 EVT_PAINT (wxListMainWindow::OnPaint)
1646 EVT_SIZE (wxListMainWindow::OnSize)
1647 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse)
1648 EVT_CHAR (wxListMainWindow::OnChar)
1649 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown)
1650 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus)
1651 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus)
1652 EVT_SCROLLWIN (wxListMainWindow::OnScroll)
1653 END_EVENT_TABLE()
1654
1655 void wxListMainWindow::Init()
1656 {
1657 m_columns.DeleteContents( TRUE );
1658 m_current = (wxListLineData *) NULL;
1659 m_dirty = TRUE;
1660 m_visibleLines = 0;
1661
1662 m_small_image_list = (wxImageList *) NULL;
1663 m_normal_image_list = (wxImageList *) NULL;
1664
1665 m_small_spacing = 30;
1666 m_normal_spacing = 40;
1667
1668 m_hasFocus = FALSE;
1669 m_dragCount = 0;
1670 m_isCreated = FALSE;
1671
1672 m_usedKeys = TRUE;
1673 m_lastOnSame = FALSE;
1674 m_renameTimer = new wxListRenameTimer( this );
1675 m_renameAccept = FALSE;
1676
1677 m_currentEdit = (size_t)-1;
1678
1679 m_lineLastClicked =
1680 m_lineBeforeLastClicked = (size_t)-1;
1681 }
1682
1683 wxListMainWindow::wxListMainWindow()
1684 {
1685 Init();
1686
1687 m_mode = 0;
1688
1689 m_hilightBrush = (wxBrush *) NULL;
1690
1691 m_xScroll =
1692 m_yScroll = 0;
1693 }
1694
1695 wxListMainWindow::wxListMainWindow( wxWindow *parent,
1696 wxWindowID id,
1697 const wxPoint& pos,
1698 const wxSize& size,
1699 long style,
1700 const wxString &name )
1701 : wxScrolledWindow( parent, id, pos, size,
1702 style | wxHSCROLL | wxVSCROLL, name )
1703 {
1704 Init();
1705
1706 m_mode = style;
1707 m_hilightBrush = new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), wxSOLID );
1708 wxSize sz = size;
1709 sz.y = 25;
1710
1711 if (m_mode & wxLC_REPORT)
1712 {
1713 #if wxUSE_GENERIC_LIST_EXTENSIONS
1714 m_xScroll = 15;
1715 #else
1716 m_xScroll = 0;
1717 #endif
1718 m_yScroll = 15;
1719 }
1720 else
1721 {
1722 m_xScroll = 15;
1723 m_yScroll = 0;
1724 }
1725 SetScrollbars( m_xScroll, m_yScroll, 0, 0, 0, 0 );
1726
1727 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) );
1728 }
1729
1730 wxListMainWindow::~wxListMainWindow()
1731 {
1732 DeleteEverything();
1733
1734 if (m_hilightBrush) delete m_hilightBrush;
1735
1736 delete m_renameTimer;
1737 }
1738
1739 void wxListMainWindow::RefreshLine( wxListLineData *line )
1740 {
1741 if (m_dirty) return;
1742
1743 if (!line) return;
1744
1745 int x = 0;
1746 int y = 0;
1747 int w = 0;
1748 int h = 0;
1749 line->GetExtent( x, y, w, h );
1750 CalcScrolledPosition( x, y, &x, &y );
1751 wxRect rect( x, y, w, h );
1752 Refresh( TRUE, &rect );
1753 }
1754
1755 void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
1756 {
1757 // Note: a wxPaintDC must be constructed even if no drawing is
1758 // done (a Windows requirement).
1759 wxPaintDC dc( this );
1760
1761 if (m_dirty)
1762 {
1763 // postpone redrawing until the next OnIdle() call to minimize flicker
1764 return;
1765 }
1766
1767 PrepareDC( dc );
1768
1769 int dev_x, dev_y;
1770 CalcScrolledPosition( 0, 0, &dev_x, &dev_y );
1771
1772 if ( GetItemCount() == 0 )
1773 {
1774 // empty control. nothing to draw
1775 return;
1776 }
1777
1778 dc.BeginDrawing();
1779
1780 dc.SetFont( GetFont() );
1781
1782 if (m_mode & wxLC_REPORT)
1783 {
1784 wxPen pen(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID);
1785 wxSize clientSize = GetClientSize();
1786
1787 int lineSpacing = 0;
1788 wxListLineData *line = &m_lines[0];
1789 int dummy = 0;
1790 line->GetSize( dummy, lineSpacing );
1791 lineSpacing += 1;
1792
1793 int y_s = m_yScroll*GetScrollPos( wxVERTICAL );
1794
1795 size_t i_to = y_s / lineSpacing + m_visibleLines+2;
1796 if (i_to >= m_lines.GetCount())
1797 i_to = m_lines.GetCount();
1798
1799 size_t i;
1800 for (i = y_s / lineSpacing; i < i_to; i++)
1801 {
1802 m_lines[i].Draw( &dc );
1803 // Draw horizontal rule if required
1804 if (m_mode & wxLC_HRULES)
1805 {
1806 dc.SetPen(pen);
1807 dc.SetBrush(* wxTRANSPARENT_BRUSH);
1808 dc.DrawLine(0 - dev_x , i*lineSpacing , clientSize.x - dev_x , i*lineSpacing );
1809 }
1810 }
1811
1812 // Draw last horizontal rule
1813 if ((i > (size_t) (y_s / lineSpacing)) && (m_mode & wxLC_HRULES))
1814 {
1815 dc.SetPen(pen);
1816 dc.SetBrush(* wxTRANSPARENT_BRUSH);
1817 dc.DrawLine(0 - dev_x , i*lineSpacing , clientSize.x - dev_x , i*lineSpacing );
1818 }
1819
1820 // Draw vertical rules if required
1821 if ((m_mode & wxLC_VRULES) && (GetItemCount() > 0))
1822 {
1823 int col = 0;
1824 wxRect firstItemRect;
1825 wxRect lastItemRect;
1826 GetItemRect(0, firstItemRect);
1827 GetItemRect(GetItemCount() - 1, lastItemRect);
1828 int x = firstItemRect.GetX();
1829 dc.SetPen(pen);
1830 dc.SetBrush(* wxTRANSPARENT_BRUSH);
1831 for (col = 0; col < GetColumnCount(); col++)
1832 {
1833 int colWidth = GetColumnWidth(col);
1834 x += colWidth ;
1835 dc.DrawLine(x - dev_x, firstItemRect.GetY() - 1 - dev_y, x - dev_x, lastItemRect.GetBottom() + 1 - dev_y);
1836 }
1837 }
1838 }
1839 else // !report mode
1840 {
1841 size_t count = GetItemCount();
1842 for (size_t i = 0; i < count; i++)
1843 m_lines[i].Draw( &dc );
1844 }
1845
1846 if (m_current)
1847 m_current->DrawRubberBand( &dc, m_hasFocus );
1848
1849 dc.EndDrawing();
1850 }
1851
1852 void wxListMainWindow::HilightAll( bool on )
1853 {
1854 size_t count = GetItemCount();
1855 for (size_t i = 0; i < count; i++)
1856 {
1857 wxListLineData *line = &m_lines[i];
1858 if (line->IsHilighted() != on)
1859 {
1860 line->Hilight( on );
1861 RefreshLine( line );
1862 }
1863 }
1864 }
1865
1866 void wxListMainWindow::SendNotify( wxListLineData *line,
1867 wxEventType command,
1868 wxPoint point )
1869 {
1870 wxListEvent le( command, GetParent()->GetId() );
1871 le.SetEventObject( GetParent() );
1872 le.m_itemIndex = GetIndexOfLine( line );
1873
1874 // set only for events which have position
1875 if ( point != wxDefaultPosition )
1876 le.m_pointDrag = point;
1877
1878 line->GetItem( 0, le.m_item );
1879 GetParent()->GetEventHandler()->ProcessEvent( le );
1880 // GetParent()->GetEventHandler()->AddPendingEvent( le );
1881 }
1882
1883 void wxListMainWindow::FocusLine( wxListLineData *WXUNUSED(line) )
1884 {
1885 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
1886 }
1887
1888 void wxListMainWindow::UnfocusLine( wxListLineData *WXUNUSED(line) )
1889 {
1890 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
1891 }
1892
1893 void wxListMainWindow::SelectLine( wxListLineData *line )
1894 {
1895 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_SELECTED );
1896 }
1897
1898 void wxListMainWindow::DeselectLine( wxListLineData *line )
1899 {
1900 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_DESELECTED );
1901 }
1902
1903 void wxListMainWindow::DeleteLine( wxListLineData *line )
1904 {
1905 SendNotify( line, wxEVT_COMMAND_LIST_DELETE_ITEM );
1906 }
1907
1908 /* *** */
1909
1910 void wxListMainWindow::EditLabel( long item )
1911 {
1912 wxCHECK_RET( (item >= 0) && (item < GetItemCount()),
1913 wxT("wrong index in wxListCtrl::Edit()") );
1914
1915 m_currentEdit = (size_t)item;
1916
1917 wxListEvent le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, GetParent()->GetId() );
1918 le.SetEventObject( GetParent() );
1919 le.m_itemIndex = item;
1920 wxListLineData *data = GetLine(m_currentEdit);
1921 wxCHECK_RET( data, _T("invalid index in EditLabel()") );
1922 data->GetItem( 0, le.m_item );
1923 GetParent()->GetEventHandler()->ProcessEvent( le );
1924
1925 if (!le.IsAllowed())
1926 return;
1927
1928 // We have to call this here because the label in
1929 // question might just have been added and no screen
1930 // update taken place.
1931 if (m_dirty) wxYield();
1932
1933 wxString s = data->GetText(0);
1934 int x = 0;
1935 int y = 0;
1936 int w = 0;
1937 int h = 0;
1938 data->GetLabelExtent( x, y, w, h );
1939
1940 wxClientDC dc(this);
1941 PrepareDC( dc );
1942 x = dc.LogicalToDeviceX( x );
1943 y = dc.LogicalToDeviceY( y );
1944
1945 wxListTextCtrl *text = new wxListTextCtrl(
1946 this, -1, &m_renameAccept, &m_renameRes, this, s, wxPoint(x-4,y-4), wxSize(w+11,h+8) );
1947 text->SetFocus();
1948 }
1949
1950 void wxListMainWindow::OnRenameTimer()
1951 {
1952 wxCHECK_RET( m_current, wxT("invalid m_current") );
1953
1954 Edit( m_lines.Index( *m_current ) );
1955 }
1956
1957 void wxListMainWindow::OnRenameAccept()
1958 {
1959 wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
1960 le.SetEventObject( GetParent() );
1961 le.m_itemIndex = m_currentEdit;
1962
1963 wxListLineData *data = GetLine(m_currentEdit);
1964 wxCHECK_RET( data, _T("invalid index in OnRenameAccept()") );
1965
1966 data->GetItem( 0, le.m_item );
1967 le.m_item.m_text = m_renameRes;
1968 GetParent()->GetEventHandler()->ProcessEvent( le );
1969
1970 if (!le.IsAllowed()) return;
1971
1972 wxListItem info;
1973 info.m_mask = wxLIST_MASK_TEXT;
1974 info.m_itemId = le.m_itemIndex;
1975 info.m_text = m_renameRes;
1976 info.SetTextColour(le.m_item.GetTextColour());
1977 SetItem( info );
1978 }
1979
1980 void wxListMainWindow::OnMouse( wxMouseEvent &event )
1981 {
1982 event.SetEventObject( GetParent() );
1983 if (GetParent()->GetEventHandler()->ProcessEvent( event)) return;
1984
1985 if (!m_current) return;
1986 if (m_dirty) return;
1987 if ( !(event.Dragging() || event.ButtonDown() || event.LeftUp() || event.ButtonDClick()) ) return;
1988
1989 int x = event.GetX();
1990 int y = event.GetY();
1991 CalcUnscrolledPosition( x, y, &x, &y );
1992
1993 /* Did we actually hit an item ? */
1994 long hitResult = 0;
1995 wxListLineData *line = (wxListLineData *) NULL;
1996
1997 size_t idx;
1998 for (idx = 0; idx < m_lines.GetCount(); idx++)
1999 {
2000 line = &m_lines[idx];
2001 hitResult = line->IsHit( x, y );
2002 if (hitResult)
2003 break;
2004 line = (wxListLineData *) NULL;
2005 }
2006
2007 if (event.Dragging())
2008 {
2009 if (m_dragCount == 0)
2010 m_dragStart = wxPoint(x,y);
2011
2012 m_dragCount++;
2013
2014 if (m_dragCount != 3) return;
2015
2016 int command = event.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2017 : wxEVT_COMMAND_LIST_BEGIN_DRAG;
2018
2019 wxListEvent le( command, GetParent()->GetId() );
2020 le.SetEventObject( GetParent() );
2021 le.m_pointDrag = m_dragStart;
2022 GetParent()->GetEventHandler()->ProcessEvent( le );
2023
2024 return;
2025 }
2026 else
2027 {
2028 m_dragCount = 0;
2029 }
2030
2031 if (!line) return;
2032
2033 bool forceClick = FALSE;
2034 if (event.ButtonDClick())
2035 {
2036 m_renameTimer->Stop();
2037 m_lastOnSame = FALSE;
2038
2039 if ( idx == m_lineBeforeLastClicked )
2040 {
2041 m_usedKeys = FALSE;
2042
2043 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
2044
2045 return;
2046 }
2047 else
2048 {
2049 // the first click was on another item, so don't interpret this as
2050 // a double click, but as a simple click instead
2051 forceClick = TRUE;
2052 }
2053 }
2054
2055 if (event.LeftUp() && m_lastOnSame)
2056 {
2057 m_usedKeys = FALSE;
2058 if ((line == m_current) &&
2059 (hitResult == wxLIST_HITTEST_ONITEMLABEL) &&
2060 (m_mode & wxLC_EDIT_LABELS) )
2061 {
2062 m_renameTimer->Start( 100, TRUE );
2063 }
2064 m_lastOnSame = FALSE;
2065 return;
2066 }
2067
2068 if (event.RightDown())
2069 {
2070 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK,
2071 event.GetPosition() );
2072 return;
2073 }
2074
2075 if (event.MiddleDown())
2076 {
2077 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK );
2078 return;
2079 }
2080
2081 if ( event.LeftDown() || forceClick )
2082 {
2083 m_lineBeforeLastClicked = m_lineLastClicked;
2084 m_lineLastClicked = idx;
2085
2086 m_usedKeys = FALSE;
2087 wxListLineData *oldCurrent = m_current;
2088 if (m_mode & wxLC_SINGLE_SEL)
2089 {
2090 m_current = line;
2091 HilightAll( FALSE );
2092 m_current->ReverseHilight();
2093 RefreshLine( m_current );
2094 }
2095 else
2096 {
2097 if (event.ControlDown())
2098 {
2099 m_current = line;
2100 m_current->ReverseHilight();
2101 RefreshLine( m_current );
2102 }
2103 else if (event.ShiftDown())
2104 {
2105 size_t j;
2106
2107 m_current = line;
2108
2109 int numOfCurrent = -1;
2110 for (j = 0; j < m_lines.GetCount(); j++)
2111 {
2112 wxListLineData *test_line = &m_lines[j];
2113 numOfCurrent++;
2114 if (test_line == oldCurrent) break;
2115 }
2116
2117 int numOfLine = -1;
2118
2119 for (j = 0; j < m_lines.GetCount(); j++)
2120 {
2121 wxListLineData *test_line = &m_lines[j];
2122 numOfLine++;
2123 if (test_line == line) break;
2124 }
2125
2126 if (numOfLine < numOfCurrent)
2127 {
2128 int i = numOfLine;
2129 numOfLine = numOfCurrent;
2130 numOfCurrent = i;
2131 }
2132
2133 for (int i = 0; i <= numOfLine-numOfCurrent; i++)
2134 {
2135 wxListLineData *test_line= &m_lines[numOfCurrent + i];
2136 test_line->Hilight(TRUE);
2137 RefreshLine( test_line );
2138 }
2139 }
2140 else
2141 {
2142 m_current = line;
2143 HilightAll( FALSE );
2144 m_current->ReverseHilight();
2145 RefreshLine( m_current );
2146 }
2147 }
2148 if (m_current != oldCurrent)
2149 {
2150 RefreshLine( oldCurrent );
2151 UnfocusLine( oldCurrent );
2152 FocusLine( m_current );
2153 }
2154
2155 // forceClick is only set if the previous click was on another item
2156 m_lastOnSame = !forceClick && (m_current == oldCurrent);
2157
2158 return;
2159 }
2160 }
2161
2162 void wxListMainWindow::MoveToFocus()
2163 {
2164 if (!m_current) return;
2165
2166 int item_x = 0;
2167 int item_y = 0;
2168 int item_w = 0;
2169 int item_h = 0;
2170 m_current->GetExtent( item_x, item_y, item_w, item_h );
2171
2172 int client_w = 0;
2173 int client_h = 0;
2174 GetClientSize( &client_w, &client_h );
2175
2176 int view_x = m_xScroll*GetScrollPos( wxHORIZONTAL );
2177 int view_y = m_yScroll*GetScrollPos( wxVERTICAL );
2178
2179 if (m_mode & wxLC_REPORT)
2180 {
2181 if (item_y < view_y )
2182 Scroll( -1, (item_y)/m_yScroll );
2183 if (item_y+item_h+5 > view_y+client_h)
2184 Scroll( -1, (item_y+item_h-client_h+15)/m_yScroll );
2185 }
2186 else
2187 {
2188 if (item_x-view_x < 5)
2189 Scroll( (item_x-5)/m_xScroll, -1 );
2190 if (item_x+item_w-5 > view_x+client_w)
2191 Scroll( (item_x+item_w-client_w+15)/m_xScroll, -1 );
2192 }
2193 }
2194
2195 void wxListMainWindow::OnArrowChar( wxListLineData *newCurrent, bool shiftDown )
2196 {
2197 if ((m_mode & wxLC_SINGLE_SEL) || (m_usedKeys == FALSE)) m_current->Hilight( FALSE );
2198 wxListLineData *oldCurrent = m_current;
2199 m_current = newCurrent;
2200 if (shiftDown || (m_mode & wxLC_SINGLE_SEL)) m_current->Hilight( TRUE );
2201 RefreshLine( m_current );
2202 RefreshLine( oldCurrent );
2203 FocusLine( m_current );
2204 UnfocusLine( oldCurrent );
2205 MoveToFocus();
2206 }
2207
2208 void wxListMainWindow::OnKeyDown( wxKeyEvent &event )
2209 {
2210 wxWindow *parent = GetParent();
2211
2212 /* we propagate the key event up */
2213 wxKeyEvent ke( wxEVT_KEY_DOWN );
2214 ke.m_shiftDown = event.m_shiftDown;
2215 ke.m_controlDown = event.m_controlDown;
2216 ke.m_altDown = event.m_altDown;
2217 ke.m_metaDown = event.m_metaDown;
2218 ke.m_keyCode = event.m_keyCode;
2219 ke.m_x = event.m_x;
2220 ke.m_y = event.m_y;
2221 ke.SetEventObject( parent );
2222 if (parent->GetEventHandler()->ProcessEvent( ke )) return;
2223
2224 event.Skip();
2225 }
2226
2227 void wxListMainWindow::OnChar( wxKeyEvent &event )
2228 {
2229 wxWindow *parent = GetParent();
2230
2231 /* we send a list_key event up */
2232 if ( m_current )
2233 {
2234 wxListEvent le( wxEVT_COMMAND_LIST_KEY_DOWN, GetParent()->GetId() );
2235 le.m_itemIndex = GetIndexOfLine( m_current );
2236 m_current->GetItem( 0, le.m_item );
2237 le.m_code = (int)event.KeyCode();
2238 le.SetEventObject( parent );
2239 parent->GetEventHandler()->ProcessEvent( le );
2240 }
2241
2242 /* we propagate the char event up */
2243 wxKeyEvent ke( wxEVT_CHAR );
2244 ke.m_shiftDown = event.m_shiftDown;
2245 ke.m_controlDown = event.m_controlDown;
2246 ke.m_altDown = event.m_altDown;
2247 ke.m_metaDown = event.m_metaDown;
2248 ke.m_keyCode = event.m_keyCode;
2249 ke.m_x = event.m_x;
2250 ke.m_y = event.m_y;
2251 ke.SetEventObject( parent );
2252 if (parent->GetEventHandler()->ProcessEvent( ke )) return;
2253
2254 if (event.KeyCode() == WXK_TAB)
2255 {
2256 wxNavigationKeyEvent nevent;
2257 nevent.SetWindowChange( event.ControlDown() );
2258 nevent.SetDirection( !event.ShiftDown() );
2259 nevent.SetEventObject( GetParent()->GetParent() );
2260 nevent.SetCurrentFocus( m_parent );
2261 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent )) return;
2262 }
2263
2264 /* no item -> nothing to do */
2265 if (!m_current)
2266 {
2267 event.Skip();
2268 return;
2269 }
2270
2271 switch (event.KeyCode())
2272 {
2273 case WXK_UP:
2274 {
2275 int index = m_lines.Index(*m_current);
2276 if (index != wxNOT_FOUND && index > 0)
2277 OnArrowChar( &m_lines[index-1], event.ShiftDown() );
2278 break;
2279 }
2280 case WXK_DOWN:
2281 {
2282 int index = m_lines.Index(*m_current);
2283 if (index != wxNOT_FOUND && (size_t)index < m_lines.GetCount()-1)
2284 OnArrowChar( &m_lines[index+1], event.ShiftDown() );
2285 break;
2286 }
2287 case WXK_END:
2288 {
2289 if (!IsEmpty())
2290 OnArrowChar( &m_lines.Last(), event.ShiftDown() );
2291 break;
2292 }
2293 case WXK_HOME:
2294 {
2295 if (!IsEmpty())
2296 OnArrowChar( &m_lines[0], event.ShiftDown() );
2297 break;
2298 }
2299 case WXK_PRIOR:
2300 {
2301 int steps = 0;
2302 int index = m_lines.Index(*m_current);
2303 if (m_mode & wxLC_REPORT)
2304 {
2305 steps = m_visibleLines-1;
2306 }
2307 else
2308 {
2309 steps = index % m_visibleLines;
2310 }
2311 if (index != wxNOT_FOUND)
2312 {
2313 index -= steps;
2314 if (index < 0) index = 0;
2315 OnArrowChar( &m_lines[index], event.ShiftDown() );
2316 }
2317 break;
2318 }
2319 case WXK_NEXT:
2320 {
2321 int steps = 0;
2322 int index = m_lines.Index(*m_current);
2323 if (m_mode & wxLC_REPORT)
2324 {
2325 steps = m_visibleLines-1;
2326 }
2327 else
2328 {
2329 steps = m_visibleLines-(index % m_visibleLines)-1;
2330 }
2331
2332 if (index != wxNOT_FOUND)
2333 {
2334 index += steps;
2335 if ((size_t)index >= m_lines.GetCount())
2336 index = m_lines.GetCount()-1;
2337 OnArrowChar( &m_lines[index], event.ShiftDown() );
2338 }
2339 break;
2340 }
2341 case WXK_LEFT:
2342 {
2343 if (!(m_mode & wxLC_REPORT))
2344 {
2345 int index = m_lines.Index(*m_current);
2346 if (index != wxNOT_FOUND)
2347 {
2348 index -= m_visibleLines;
2349 if (index < 0) index = 0;
2350 OnArrowChar( &m_lines[index], event.ShiftDown() );
2351 }
2352 }
2353 break;
2354 }
2355 case WXK_RIGHT:
2356 {
2357 if (!(m_mode & wxLC_REPORT))
2358 {
2359 int index = m_lines.Index(*m_current);
2360 if (index != wxNOT_FOUND)
2361 {
2362 index += m_visibleLines;
2363 if ((size_t)index >= m_lines.GetCount())
2364 index = m_lines.GetCount()-1;
2365 OnArrowChar( &m_lines[index], event.ShiftDown() );
2366 }
2367 }
2368 break;
2369 }
2370 case WXK_SPACE:
2371 {
2372 if (m_mode & wxLC_SINGLE_SEL)
2373 {
2374 wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, GetParent()->GetId() );
2375 le.SetEventObject( GetParent() );
2376 le.m_itemIndex = GetIndexOfLine( m_current );
2377 m_current->GetItem( 0, le.m_item );
2378 GetParent()->GetEventHandler()->ProcessEvent( le );
2379 }
2380 else
2381 {
2382 m_current->ReverseHilight();
2383 RefreshLine( m_current );
2384 }
2385 break;
2386 }
2387 case WXK_INSERT:
2388 {
2389 if (!(m_mode & wxLC_SINGLE_SEL))
2390 {
2391 wxListLineData *oldCurrent = m_current;
2392 m_current->ReverseHilight();
2393 int index = m_lines.Index( *m_current ) + 1;
2394 if ( (size_t)index < m_lines.GetCount() )
2395 m_current = &m_lines[index];
2396 RefreshLine( oldCurrent );
2397 RefreshLine( m_current );
2398 UnfocusLine( oldCurrent );
2399 FocusLine( m_current );
2400 MoveToFocus();
2401 }
2402 break;
2403 }
2404 case WXK_RETURN:
2405 case WXK_EXECUTE:
2406 {
2407 wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, GetParent()->GetId() );
2408 le.SetEventObject( GetParent() );
2409 le.m_itemIndex = GetIndexOfLine( m_current );
2410 m_current->GetItem( 0, le.m_item );
2411 GetParent()->GetEventHandler()->ProcessEvent( le );
2412 break;
2413 }
2414 default:
2415 {
2416 event.Skip();
2417 return;
2418 }
2419 }
2420 m_usedKeys = TRUE;
2421 }
2422
2423 #ifdef __WXGTK__
2424 extern wxWindow *g_focusWindow;
2425 #endif
2426
2427 void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
2428 {
2429 m_hasFocus = TRUE;
2430 RefreshLine( m_current );
2431
2432 if (!GetParent()) return;
2433
2434 #ifdef __WXGTK__
2435 g_focusWindow = GetParent();
2436 #endif
2437
2438 wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
2439 event.SetEventObject( GetParent() );
2440 GetParent()->GetEventHandler()->ProcessEvent( event );
2441 }
2442
2443 void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
2444 {
2445 m_hasFocus = FALSE;
2446 RefreshLine( m_current );
2447 }
2448
2449 void wxListMainWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
2450 {
2451 /*
2452 We don't even allow the wxScrolledWindow::AdjustScrollbars() call
2453
2454 */
2455 m_dirty = TRUE;
2456 }
2457
2458 void wxListMainWindow::DrawImage( int index, wxDC *dc, int x, int y )
2459 {
2460 if ((m_mode & wxLC_ICON) && (m_normal_image_list))
2461 {
2462 m_normal_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
2463 return;
2464 }
2465 if ((m_mode & wxLC_SMALL_ICON) && (m_small_image_list))
2466 {
2467 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
2468 }
2469 if ((m_mode & wxLC_LIST) && (m_small_image_list))
2470 {
2471 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
2472 }
2473 if ((m_mode & wxLC_REPORT) && (m_small_image_list))
2474 {
2475 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
2476 return;
2477 }
2478 }
2479
2480 void wxListMainWindow::GetImageSize( int index, int &width, int &height )
2481 {
2482 if ((m_mode & wxLC_ICON) && (m_normal_image_list))
2483 {
2484 m_normal_image_list->GetSize( index, width, height );
2485 return;
2486 }
2487 if ((m_mode & wxLC_SMALL_ICON) && (m_small_image_list))
2488 {
2489 m_small_image_list->GetSize( index, width, height );
2490 return;
2491 }
2492 if ((m_mode & wxLC_LIST) && (m_small_image_list))
2493 {
2494 m_small_image_list->GetSize( index, width, height );
2495 return;
2496 }
2497 if ((m_mode & wxLC_REPORT) && (m_small_image_list))
2498 {
2499 m_small_image_list->GetSize( index, width, height );
2500 return;
2501 }
2502 width = 0;
2503 height = 0;
2504 }
2505
2506 int wxListMainWindow::GetTextLength( wxString &s )
2507 {
2508 wxClientDC dc( this );
2509 wxCoord lw = 0;
2510 wxCoord lh = 0;
2511 dc.GetTextExtent( s, &lw, &lh );
2512 return lw + 6;
2513 }
2514
2515 int wxListMainWindow::GetIndexOfLine( const wxListLineData *line )
2516 {
2517 return m_lines.Index(*line);
2518 }
2519
2520 void wxListMainWindow::SetImageList( wxImageList *imageList, int which )
2521 {
2522 m_dirty = TRUE;
2523
2524 // calc the spacing from the icon size
2525 int width = 0,
2526 height = 0;
2527 if ((imageList) && (imageList->GetImageCount()) )
2528 {
2529 imageList->GetSize(0, width, height);
2530 }
2531
2532 if (which == wxIMAGE_LIST_NORMAL)
2533 {
2534 m_normal_image_list = imageList;
2535 m_normal_spacing = width + 8;
2536 }
2537
2538 if (which == wxIMAGE_LIST_SMALL)
2539 {
2540 m_small_image_list = imageList;
2541 m_small_spacing = width + 14;
2542 }
2543 }
2544
2545 void wxListMainWindow::SetItemSpacing( int spacing, bool isSmall )
2546 {
2547 m_dirty = TRUE;
2548 if (isSmall)
2549 {
2550 m_small_spacing = spacing;
2551 }
2552 else
2553 {
2554 m_normal_spacing = spacing;
2555 }
2556 }
2557
2558 int wxListMainWindow::GetItemSpacing( bool isSmall )
2559 {
2560 return isSmall ? m_small_spacing : m_normal_spacing;
2561 }
2562
2563 void wxListMainWindow::SetColumn( int col, wxListItem &item )
2564 {
2565 m_dirty = TRUE;
2566 wxListHeaderDataList::Node *node = m_columns.Item( col );
2567 if (node)
2568 {
2569 if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
2570 item.m_width = GetTextLength( item.m_text )+7;
2571 wxListHeaderData *column = node->GetData();
2572 column->SetItem( item );
2573 }
2574
2575 wxListHeaderWindow *headerWin = ((wxListCtrl*) GetParent())->m_headerWin;
2576 if ( headerWin )
2577 headerWin->m_dirty = TRUE;
2578 }
2579
2580 void wxListMainWindow::SetColumnWidth( int col, int width )
2581 {
2582 wxCHECK_RET( m_mode & wxLC_REPORT,
2583 _T("SetColumnWidth() can only be called in report mode.") );
2584
2585 m_dirty = TRUE;
2586
2587 if (width == wxLIST_AUTOSIZE_USEHEADER)
2588 {
2589 // TODO do use the header
2590 width = 80;
2591 }
2592 else if (width == wxLIST_AUTOSIZE)
2593 {
2594 wxClientDC dc(this);
2595 dc.SetFont( GetFont() );
2596 int max = 10;
2597
2598 for (size_t i = 0; i < m_lines.GetCount(); i++)
2599 {
2600 wxListLineData *line = &m_lines[i];
2601 wxListItemDataList::Node *n = line->m_items.Item( col );
2602 if (n)
2603 {
2604 wxListItemData *item = n->GetData();
2605 int current = 0, ix = 0, iy = 0;
2606 wxCoord lx = 0, ly = 0;
2607 if (item->HasImage())
2608 {
2609 GetImageSize( item->GetImage(), ix, iy );
2610 current = ix + 5;
2611 }
2612 if (item->HasText())
2613 {
2614 wxString str = item->GetText();
2615 dc.GetTextExtent( str, &lx, &ly );
2616 current += lx;
2617 }
2618 if (current > max)
2619 max = current;
2620 }
2621 }
2622 width = max+10;
2623 }
2624
2625 wxListHeaderDataList::Node *node = m_columns.Item( col );
2626 if (node)
2627 {
2628 wxListHeaderData *column = node->GetData();
2629 column->SetWidth( width );
2630 }
2631
2632 size_t count = m_lines.GetCount();
2633 for (size_t i = 0; i < count; i++)
2634 {
2635 wxListLineData *line = &m_lines[i];
2636 wxListItemDataList::Node *n = line->m_items.Item( col );
2637 if (n)
2638 {
2639 wxListItemData *item = n->GetData();
2640 item->SetSize( width, -1 );
2641 }
2642 }
2643
2644 wxListHeaderWindow *headerWin = ((wxListCtrl*) GetParent())->m_headerWin;
2645 if ( headerWin )
2646 headerWin->m_dirty = TRUE;
2647 }
2648
2649 void wxListMainWindow::GetColumn( int col, wxListItem &item )
2650 {
2651 wxListHeaderDataList::Node *node = m_columns.Item( col );
2652 if (node)
2653 {
2654 wxListHeaderData *column = node->GetData();
2655 column->GetItem( item );
2656 }
2657 else
2658 {
2659 item.m_format = 0;
2660 item.m_width = 0;
2661 item.m_text = _T("");
2662 item.m_image = 0;
2663 item.m_data = 0;
2664 }
2665 }
2666
2667 int wxListMainWindow::GetColumnWidth( int col )
2668 {
2669 wxListHeaderDataList::Node *node = m_columns.Item( col );
2670 wxCHECK_MSG( node, 0, _T("invalid column index") );
2671
2672 wxListHeaderData *column = node->GetData();
2673 return column->GetWidth();
2674 }
2675
2676 int wxListMainWindow::GetColumnCount()
2677 {
2678 return m_columns.GetCount();
2679 }
2680
2681 int wxListMainWindow::GetCountPerPage()
2682 {
2683 return m_visibleLines;
2684 }
2685
2686 void wxListMainWindow::SetItem( wxListItem &item )
2687 {
2688 m_dirty = TRUE;
2689 if (item.m_itemId >= 0 && (size_t)item.m_itemId < m_lines.GetCount())
2690 {
2691 wxListLineData *line = &m_lines[(size_t)item.m_itemId];
2692 if (m_mode & wxLC_REPORT) item.m_width = GetColumnWidth( item.m_col )-3;
2693 line->SetItem( item.m_col, item );
2694 }
2695 }
2696
2697 void wxListMainWindow::SetItemState( long item, long state, long stateMask )
2698 {
2699 wxCHECK_RET( item >= 0 && (size_t)item < m_lines.GetCount(),
2700 _T("invalid list ctrl item index in SetItem") );
2701
2702 // m_dirty = TRUE; no recalcs needed
2703
2704 wxListLineData *oldCurrent = m_current;
2705
2706 if ( stateMask & wxLIST_STATE_FOCUSED )
2707 {
2708 wxListLineData *line = &m_lines[(size_t)item];
2709 if ( state & wxLIST_STATE_FOCUSED )
2710 {
2711 // don't do anything if this item is already focused
2712 if ( line != m_current )
2713 {
2714 UnfocusLine( m_current );
2715 m_current = line;
2716 FocusLine( m_current );
2717 if ( (m_mode & wxLC_SINGLE_SEL) && oldCurrent )
2718 oldCurrent->Hilight( FALSE );
2719
2720 RefreshLine( m_current );
2721 if ( oldCurrent )
2722 RefreshLine( oldCurrent );
2723 }
2724 }
2725 else // unfocus
2726 {
2727 // don't do anything if this item is not focused
2728 if ( line == m_current )
2729 {
2730 UnfocusLine( m_current );
2731 m_current = NULL;
2732 }
2733 }
2734 }
2735
2736 if ( stateMask & wxLIST_STATE_SELECTED )
2737 {
2738 bool on = (state & wxLIST_STATE_SELECTED) != 0;
2739 if (!on && (m_mode & wxLC_SINGLE_SEL))
2740 return;
2741
2742 wxListLineData *line = &m_lines[(size_t)item];
2743 if (m_mode & wxLC_SINGLE_SEL)
2744 {
2745 UnfocusLine( m_current );
2746 m_current = line;
2747 FocusLine( m_current );
2748 if (oldCurrent)
2749 oldCurrent->Hilight( FALSE );
2750 RefreshLine( m_current );
2751 if (oldCurrent)
2752 RefreshLine( oldCurrent );
2753 }
2754
2755 if (on != line->IsHilighted())
2756 {
2757 line->Hilight( on );
2758 RefreshLine( line );
2759 }
2760 }
2761 }
2762
2763 int wxListMainWindow::GetItemState( long item, long stateMask )
2764 {
2765 int ret = wxLIST_STATE_DONTCARE;
2766 if (stateMask & wxLIST_STATE_FOCUSED)
2767 {
2768 if (item >= 0 && (size_t)item < m_lines.GetCount())
2769 {
2770 wxListLineData *line = &m_lines[(size_t)item];
2771 if (line == m_current) ret |= wxLIST_STATE_FOCUSED;
2772 }
2773 }
2774 if (stateMask & wxLIST_STATE_SELECTED)
2775 {
2776 if (item >= 0 && (size_t)item < m_lines.GetCount())
2777 {
2778 wxListLineData *line = &m_lines[(size_t)item];
2779 if (line->IsHilighted()) ret |= wxLIST_STATE_SELECTED;
2780 }
2781 }
2782 return ret;
2783 }
2784
2785 void wxListMainWindow::GetItem( wxListItem &item )
2786 {
2787 if (item.m_itemId >= 0 && (size_t)item.m_itemId < m_lines.GetCount())
2788 {
2789 wxListLineData *line = &m_lines[(size_t)item.m_itemId];
2790 line->GetItem( item.m_col, item );
2791 }
2792 else
2793 {
2794 item.m_mask = 0;
2795 item.m_text = _T("");
2796 item.m_image = 0;
2797 item.m_data = 0;
2798 }
2799 }
2800
2801 int wxListMainWindow::GetItemCount() const
2802 {
2803 return IsVirtual() ? m_countVirt : m_lines.GetCount();
2804 }
2805
2806 void wxListMainWindow::SetItemCount(long count)
2807 {
2808 m_countVirt = count;
2809
2810 Refresh();
2811 }
2812
2813 void wxListMainWindow::GetItemRect( long index, wxRect &rect )
2814 {
2815 if (index >= 0 && (size_t)index < m_lines.GetCount())
2816 {
2817 m_lines[(size_t)index].GetRect( rect );
2818 this->CalcScrolledPosition(rect.x,rect.y,&rect.x,&rect.y);
2819 }
2820 else
2821 {
2822 rect.x = 0;
2823 rect.y = 0;
2824 rect.width = 0;
2825 rect.height = 0;
2826 }
2827 }
2828
2829 bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos)
2830 {
2831 wxRect rect;
2832 this->GetItemRect(item,rect);
2833 pos.x=rect.x; pos.y=rect.y;
2834 return TRUE;
2835 }
2836
2837 int wxListMainWindow::GetSelectedItemCount()
2838 {
2839 int ret = 0;
2840 for (size_t i = 0; i < m_lines.GetCount(); i++)
2841 {
2842 if (m_lines[i].IsHilighted()) ret++;
2843 }
2844 return ret;
2845 }
2846
2847 void wxListMainWindow::SetMode( long mode )
2848 {
2849 m_dirty = TRUE;
2850 m_mode = mode;
2851
2852 DeleteEverything();
2853
2854 if (m_mode & wxLC_REPORT)
2855 {
2856 #if wxUSE_GENERIC_LIST_EXTENSIONS
2857 m_xScroll = 15;
2858 #else
2859 m_xScroll = 0;
2860 #endif
2861 m_yScroll = 15;
2862 }
2863 else
2864 {
2865 m_xScroll = 15;
2866 m_yScroll = 0;
2867 }
2868 }
2869
2870 long wxListMainWindow::GetMode() const
2871 {
2872 return m_mode;
2873 }
2874
2875 void wxListMainWindow::CalculatePositions()
2876 {
2877 if ( IsEmpty() )
2878 return;
2879
2880 wxClientDC dc( this );
2881 dc.SetFont( GetFont() );
2882
2883 int iconSpacing = 0;
2884 if (m_mode & wxLC_ICON) iconSpacing = m_normal_spacing;
2885 if (m_mode & wxLC_SMALL_ICON) iconSpacing = m_small_spacing;
2886
2887 // we take the first line (which also can be an icon or
2888 // an a text item in wxLC_ICON and wxLC_LIST modes) to
2889 // measure the size of the line
2890
2891 int lineWidth = 0;
2892 int lineHeight = 0;
2893 int lineSpacing = 0;
2894
2895 wxListLineData *line = &m_lines[0];
2896 line->CalculateSize( &dc, iconSpacing );
2897 int dummy = 0;
2898 line->GetSize( dummy, lineSpacing );
2899 lineSpacing += 1;
2900
2901 int clientWidth = 0;
2902 int clientHeight = 0;
2903
2904 if (m_mode & wxLC_REPORT)
2905 {
2906 // scroll one line per step
2907 m_yScroll = lineSpacing;
2908
2909 int x = 4;
2910 int y = 1;
2911 int entireHeight = m_lines.GetCount() * lineSpacing + 2;
2912 int scroll_pos = GetScrollPos( wxVERTICAL );
2913 #if wxUSE_GENERIC_LIST_EXTENSIONS
2914 int x_scroll_pos = GetScrollPos( wxHORIZONTAL );
2915 #else
2916 SetScrollbars( m_xScroll, m_yScroll, 0, entireHeight/m_yScroll +1, 0, scroll_pos, TRUE );
2917 #endif
2918 GetClientSize( &clientWidth, &clientHeight );
2919
2920 int entireWidth = 0 ;
2921 for (size_t j = 0; j < m_lines.GetCount(); j++)
2922 {
2923 wxListLineData *line = &m_lines[j];
2924 line->CalculateSize( &dc, iconSpacing );
2925 line->SetPosition( &dc, x, y, clientWidth );
2926 int col_x = 2;
2927 for (int i = 0; i < GetColumnCount(); i++)
2928 {
2929 line->SetColumnPosition( i, col_x );
2930 col_x += GetColumnWidth( i );
2931 }
2932 entireWidth = wxMax( entireWidth , col_x ) ;
2933 #if wxUSE_GENERIC_LIST_EXTENSIONS
2934 line->SetPosition( &dc, x, y, col_x );
2935 #endif
2936 y += lineSpacing; // one pixel blank line between items
2937 }
2938 m_visibleLines = clientHeight / lineSpacing;
2939 #if wxUSE_GENERIC_LIST_EXTENSIONS
2940 SetScrollbars( m_xScroll, m_yScroll, entireWidth/m_xScroll +1, entireHeight/m_yScroll +1, x_scroll_pos , scroll_pos, TRUE );
2941 #endif
2942 }
2943 else
2944 {
2945 // at first we try without any scrollbar. if the items don't
2946 // fit into the window, we recalculate after subtracting an
2947 // approximated 15 pt for the horizontal scrollbar
2948
2949 GetSize( &clientWidth, &clientHeight );
2950 clientHeight -= 4; // sunken frame
2951
2952 int entireWidth = 0;
2953
2954 for (int tries = 0; tries < 2; tries++)
2955 {
2956 entireWidth = 0;
2957 int x = 2;
2958 int y = 2;
2959 int maxWidth = 0;
2960 m_visibleLines = 0;
2961 int m_currentVisibleLines = 0;
2962 for (size_t i = 0; i < m_lines.GetCount(); i++)
2963 {
2964 m_currentVisibleLines++;
2965 wxListLineData *line = &m_lines[i];
2966 line->CalculateSize( &dc, iconSpacing );
2967 line->SetPosition( &dc, x, y, clientWidth );
2968 line->GetSize( lineWidth, lineHeight );
2969 if (lineWidth > maxWidth) maxWidth = lineWidth;
2970 y += lineSpacing;
2971 if (m_currentVisibleLines > m_visibleLines)
2972 m_visibleLines = m_currentVisibleLines;
2973 if (y+lineSpacing-6 >= clientHeight) // -6 for earlier "line breaking"
2974 {
2975 m_currentVisibleLines = 0;
2976 y = 2;
2977 x += maxWidth+6;
2978 entireWidth += maxWidth+6;
2979 maxWidth = 0;
2980 }
2981 if (i == m_lines.GetCount()-1) entireWidth += maxWidth;
2982 if ((tries == 0) && (entireWidth > clientWidth))
2983 {
2984 clientHeight -= 15; // scrollbar height
2985 m_visibleLines = 0;
2986 m_currentVisibleLines = 0;
2987 break;
2988 }
2989 if (i == m_lines.GetCount()-1) tries = 1; // everything fits, no second try required
2990 }
2991 }
2992
2993 int scroll_pos = GetScrollPos( wxHORIZONTAL );
2994 SetScrollbars( m_xScroll, m_yScroll, (entireWidth+15) / m_xScroll, 0, scroll_pos, 0, TRUE );
2995 }
2996 }
2997
2998 void wxListMainWindow::RealizeChanges()
2999 {
3000 if (!m_current)
3001 {
3002 if ( !IsEmpty() )
3003 m_current = &m_lines[0];
3004 }
3005 if (m_current)
3006 {
3007 FocusLine( m_current );
3008 // TODO: MSW doesn't automatically hilight the
3009 // first item.
3010 // if (m_mode & wxLC_SINGLE_SEL) m_current->Hilight( TRUE );
3011 }
3012 }
3013
3014 long wxListMainWindow::GetNextItem( long item,
3015 int WXUNUSED(geometry),
3016 int state )
3017 {
3018 long ret = item,
3019 max = GetItemCount();
3020 wxCHECK_MSG( (ret == -1) || (ret < max), -1,
3021 _T("invalid listctrl index in GetNextItem()") );
3022
3023 // notice that we start with the next item (or the first one if item == -1)
3024 // and this is intentional to allow writing a simple loop to iterate over
3025 // all selected items
3026 ret++;
3027 if ( ret == max )
3028 {
3029 // this is not an error because the index was ok initially, just no
3030 // such item
3031 return -1;
3032 }
3033
3034 for (size_t i = (size_t)ret; i < m_lines.GetCount(); i++)
3035 {
3036 wxListLineData *line = &m_lines[i];
3037 if ((state & wxLIST_STATE_FOCUSED) && (line == m_current))
3038 return ret;
3039 if ((state & wxLIST_STATE_SELECTED) && (line->IsHilighted()))
3040 return ret;
3041 if (!state)
3042 return ret;
3043 ret++;
3044 }
3045
3046 return -1;
3047 }
3048
3049 void wxListMainWindow::DeleteItem( long index )
3050 {
3051 m_dirty = TRUE;
3052 if (index >= 0 && (size_t)index < m_lines.GetCount())
3053 {
3054 wxListLineData *line = &m_lines[(size_t)index];
3055 if (m_current == line) m_current = (wxListLineData *) NULL;
3056 DeleteLine( line );
3057 m_lines.RemoveAt( (size_t)index );
3058 }
3059 }
3060
3061 void wxListMainWindow::DeleteColumn( int col )
3062 {
3063 wxListHeaderDataList::Node *node = m_columns.Item( col );
3064
3065 wxCHECK_RET( node, wxT("invalid column index in DeleteColumn()") );
3066
3067 m_dirty = TRUE;
3068 m_columns.DeleteNode( node );
3069 }
3070
3071 void wxListMainWindow::DeleteAllItems()
3072 {
3073 m_dirty = TRUE;
3074 m_current = (wxListLineData *) NULL;
3075
3076 // to make the deletion of all items faster, we don't send the
3077 // notifications in this case: this is compatible with wxMSW and
3078 // documented in DeleteAllItems() description
3079
3080 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, GetParent()->GetId() );
3081 event.SetEventObject( GetParent() );
3082 GetParent()->GetEventHandler()->ProcessEvent( event );
3083
3084 m_lines.Clear();
3085 }
3086
3087 void wxListMainWindow::DeleteEverything()
3088 {
3089 DeleteAllItems();
3090
3091 m_columns.Clear();
3092 }
3093
3094 void wxListMainWindow::EnsureVisible( long index )
3095 {
3096 // We have to call this here because the label in
3097 // question might just have been added and no screen
3098 // update taken place.
3099 if (m_dirty) wxYield();
3100
3101 wxListLineData *oldCurrent = m_current;
3102 m_current = (wxListLineData *) NULL;
3103 if (index >= 0 && (size_t)index < m_lines.GetCount())
3104 m_current = &m_lines[(size_t)index];
3105 if (m_current) MoveToFocus();
3106 m_current = oldCurrent;
3107 }
3108
3109 long wxListMainWindow::FindItem(long start, const wxString& str, bool WXUNUSED(partial) )
3110 {
3111 long pos = start;
3112 wxString tmp = str;
3113 if (pos < 0) pos = 0;
3114 for (size_t i = (size_t)pos; i < m_lines.GetCount(); i++)
3115 {
3116 wxListLineData *line = &m_lines[i];
3117 wxString s = line->GetText(0);
3118 if (s == tmp)
3119 return pos;
3120
3121 pos++;
3122 }
3123 return -1;
3124 }
3125
3126 long wxListMainWindow::FindItem(long start, long data)
3127 {
3128 long pos = start;
3129 if (pos < 0) pos = 0;
3130 for (size_t i = (size_t)pos; i < m_lines.GetCount(); i++)
3131 {
3132 wxListLineData *line = &m_lines[i];
3133 wxListItem item;
3134 line->GetItem( 0, item );
3135 if (item.m_data == data) return pos;
3136 pos++;
3137 }
3138 return -1;
3139 }
3140
3141 long wxListMainWindow::HitTest( int x, int y, int &flags )
3142 {
3143 CalcUnscrolledPosition( x, y, &x, &y );
3144
3145 int count = 0;
3146 for (size_t i = 0; i < m_lines.GetCount(); i++)
3147 {
3148 wxListLineData *line = &m_lines[i];
3149 long ret = line->IsHit( x, y );
3150 if (ret) // & flags) // No: flags is output-only so may be garbage at this point
3151 {
3152 flags = (int)ret;
3153 return count;
3154 }
3155 count++;
3156 }
3157 return -1;
3158 }
3159
3160 void wxListMainWindow::InsertItem( wxListItem &item )
3161 {
3162 m_dirty = TRUE;
3163 int mode = 0;
3164 if (m_mode & wxLC_REPORT)
3165 mode = wxLC_REPORT;
3166 else if (m_mode & wxLC_LIST)
3167 mode = wxLC_LIST;
3168 else if (m_mode & wxLC_ICON)
3169 mode = wxLC_ICON;
3170 else if (m_mode & wxLC_SMALL_ICON)
3171 mode = wxLC_ICON; // no typo
3172 else
3173 {
3174 wxFAIL_MSG( _T("unknown mode") );
3175 }
3176
3177 wxListLineData *line = new wxListLineData( this, mode, m_hilightBrush );
3178
3179 if (m_mode & wxLC_REPORT)
3180 {
3181 line->InitItems( GetColumnCount() );
3182 item.m_width = GetColumnWidth( 0 )-3;
3183 }
3184 else
3185 {
3186 line->InitItems( 1 );
3187 }
3188
3189 line->SetItem( 0, item );
3190 if ((item.m_itemId >= 0) && ((size_t)item.m_itemId < m_lines.GetCount()))
3191 {
3192 m_lines.Insert( line, (size_t)item.m_itemId );
3193 }
3194 else
3195 {
3196 m_lines.Add( line );
3197 item.m_itemId = m_lines.GetCount()-1;
3198 }
3199 }
3200
3201 void wxListMainWindow::InsertColumn( long col, wxListItem &item )
3202 {
3203 m_dirty = TRUE;
3204 if (m_mode & wxLC_REPORT)
3205 {
3206 if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
3207 item.m_width = GetTextLength( item.m_text );
3208 wxListHeaderData *column = new wxListHeaderData( item );
3209 if ((col >= 0) && (col < (int)m_columns.GetCount()))
3210 {
3211 wxListHeaderDataList::Node *node = m_columns.Item( col );
3212 m_columns.Insert( node, column );
3213 }
3214 else
3215 {
3216 m_columns.Append( column );
3217 }
3218 }
3219 }
3220
3221 wxListCtrlCompare list_ctrl_compare_func_2;
3222 long list_ctrl_compare_data;
3223
3224 int LINKAGEMODE list_ctrl_compare_func_1( wxListLineData **arg1, wxListLineData **arg2 )
3225 {
3226 wxListLineData *line1 = *arg1;
3227 wxListLineData *line2 = *arg2;
3228 wxListItem item;
3229 line1->GetItem( 0, item );
3230 long data1 = item.m_data;
3231 line2->GetItem( 0, item );
3232 long data2 = item.m_data;
3233 return list_ctrl_compare_func_2( data1, data2, list_ctrl_compare_data );
3234 }
3235
3236 void wxListMainWindow::SortItems( wxListCtrlCompare fn, long data )
3237 {
3238 list_ctrl_compare_func_2 = fn;
3239 list_ctrl_compare_data = data;
3240 m_lines.Sort( list_ctrl_compare_func_1 );
3241 m_dirty = TRUE;
3242 }
3243
3244 void wxListMainWindow::OnScroll(wxScrollWinEvent& event)
3245 {
3246 // FIXME
3247 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
3248 wxScrolledWindow::OnScroll(event);
3249 #else
3250 HandleOnScroll( event );
3251 #endif
3252
3253 #if wxUSE_GENERIC_LIST_EXTENSIONS
3254
3255 if (event.GetOrientation() == wxHORIZONTAL && ( m_mode & wxLC_REPORT ))
3256 {
3257 wxListCtrl* lc = wxDynamicCast( GetParent() , wxListCtrl ) ;
3258 if ( lc )
3259 {
3260 lc->m_headerWin->Refresh() ;
3261 #ifdef __WXMAC__
3262 lc->m_headerWin->MacUpdateImmediately() ;
3263 #endif
3264 }
3265 }
3266 #endif
3267 }
3268
3269 // -------------------------------------------------------------------------------------
3270 // wxListItem
3271 // -------------------------------------------------------------------------------------
3272
3273 IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
3274
3275 wxListItem::wxListItem()
3276 {
3277 m_mask = 0;
3278 m_itemId = 0;
3279 m_col = 0;
3280 m_state = 0;
3281 m_stateMask = 0;
3282 m_image = 0;
3283 m_data = 0;
3284 m_format = wxLIST_FORMAT_CENTRE;
3285 m_width = 0;
3286
3287 m_attr = NULL;
3288 }
3289
3290 void wxListItem::Clear()
3291 {
3292 m_mask = 0;
3293 m_itemId = 0;
3294 m_col = 0;
3295 m_state = 0;
3296 m_stateMask = 0;
3297 m_image = 0;
3298 m_data = 0;
3299 m_format = wxLIST_FORMAT_CENTRE;
3300 m_width = 0;
3301 m_text = _T("");
3302
3303 if (m_attr) delete m_attr;
3304 m_attr = NULL;
3305 }
3306
3307 void wxListItem::ClearAttributes()
3308 {
3309 if (m_attr) delete m_attr;
3310 m_attr = NULL;
3311 }
3312
3313 // -------------------------------------------------------------------------------------
3314 // wxListEvent
3315 // -------------------------------------------------------------------------------------
3316
3317 IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
3318
3319 wxListEvent::wxListEvent( wxEventType commandType, int id ):
3320 wxNotifyEvent( commandType, id )
3321 {
3322 m_code = 0;
3323 m_itemIndex = 0;
3324 m_oldItemIndex = 0;
3325 m_col = 0;
3326 m_cancelled = FALSE;
3327 m_pointDrag.x = 0;
3328 m_pointDrag.y = 0;
3329 }
3330
3331 void wxListEvent::CopyObject(wxObject& object_dest) const
3332 {
3333 wxListEvent *obj = (wxListEvent *)&object_dest;
3334
3335 wxNotifyEvent::CopyObject(object_dest);
3336
3337 obj->m_code = m_code;
3338 obj->m_itemIndex = m_itemIndex;
3339 obj->m_oldItemIndex = m_oldItemIndex;
3340 obj->m_col = m_col;
3341 obj->m_cancelled = m_cancelled;
3342 obj->m_pointDrag = m_pointDrag;
3343 obj->m_item.m_mask = m_item.m_mask;
3344 obj->m_item.m_itemId = m_item.m_itemId;
3345 obj->m_item.m_col = m_item.m_col;
3346 obj->m_item.m_state = m_item.m_state;
3347 obj->m_item.m_stateMask = m_item.m_stateMask;
3348 obj->m_item.m_text = m_item.m_text;
3349 obj->m_item.m_image = m_item.m_image;
3350 obj->m_item.m_data = m_item.m_data;
3351 obj->m_item.m_format = m_item.m_format;
3352 obj->m_item.m_width = m_item.m_width;
3353
3354 if ( m_item.HasAttributes() )
3355 {
3356 obj->m_item.SetTextColour(m_item.GetTextColour());
3357 }
3358 }
3359
3360 // -------------------------------------------------------------------------------------
3361 // wxListCtrl
3362 // -------------------------------------------------------------------------------------
3363
3364 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
3365
3366 BEGIN_EVENT_TABLE(wxListCtrl,wxControl)
3367 EVT_SIZE (wxListCtrl::OnSize)
3368 EVT_IDLE (wxListCtrl::OnIdle)
3369 END_EVENT_TABLE()
3370
3371 wxListCtrl::wxListCtrl()
3372 {
3373 m_imageListNormal = (wxImageList *) NULL;
3374 m_imageListSmall = (wxImageList *) NULL;
3375 m_imageListState = (wxImageList *) NULL;
3376 m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE;
3377 m_mainWin = (wxListMainWindow*) NULL;
3378 m_headerWin = (wxListHeaderWindow*) NULL;
3379 }
3380
3381 wxListCtrl::~wxListCtrl()
3382 {
3383 if (m_ownsImageListNormal) delete m_imageListNormal;
3384 if (m_ownsImageListSmall) delete m_imageListSmall;
3385 if (m_ownsImageListState) delete m_imageListState;
3386 }
3387
3388 bool wxListCtrl::Create(wxWindow *parent,
3389 wxWindowID id,
3390 const wxPoint &pos,
3391 const wxSize &size,
3392 long style,
3393 const wxValidator &validator,
3394 const wxString &name)
3395 {
3396 m_imageListNormal = (wxImageList *) NULL;
3397 m_imageListSmall = (wxImageList *) NULL;
3398 m_imageListState = (wxImageList *) NULL;
3399 m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE;
3400 m_mainWin = (wxListMainWindow*) NULL;
3401 m_headerWin = (wxListHeaderWindow*) NULL;
3402
3403 if ( !(style & (wxLC_REPORT | wxLC_LIST | wxLC_ICON)) )
3404 {
3405 style = style | wxLC_LIST;
3406 }
3407
3408 bool ret = wxControl::Create( parent, id, pos, size, style, validator, name );
3409
3410
3411 if (style & wxSUNKEN_BORDER)
3412 style -= wxSUNKEN_BORDER;
3413
3414 m_mainWin = new wxListMainWindow( this, -1, wxPoint(0,0), size, style );
3415
3416 if (HasFlag(wxLC_REPORT))
3417 {
3418 m_headerWin = new wxListHeaderWindow( this, -1, m_mainWin, wxPoint(0,0), wxSize(size.x,23), wxTAB_TRAVERSAL );
3419 if (HasFlag(wxLC_NO_HEADER))
3420 m_headerWin->Show( FALSE );
3421 }
3422 else
3423 {
3424 m_headerWin = (wxListHeaderWindow *) NULL;
3425 }
3426
3427 return ret;
3428 }
3429
3430 void wxListCtrl::OnSize( wxSizeEvent &WXUNUSED(event) )
3431 {
3432 /* handled in OnIdle */
3433
3434 if (m_mainWin) m_mainWin->m_dirty = TRUE;
3435 }
3436
3437 void wxListCtrl::SetSingleStyle( long style, bool add )
3438 {
3439 long flag = GetWindowStyle();
3440
3441 if (add)
3442 {
3443 if (style & wxLC_MASK_TYPE) flag = flag & ~wxLC_MASK_TYPE;
3444 if (style & wxLC_MASK_ALIGN) flag = flag & ~wxLC_MASK_ALIGN;
3445 if (style & wxLC_MASK_SORT) flag = flag & ~wxLC_MASK_SORT;
3446 }
3447
3448 if (add)
3449 {
3450 flag |= style;
3451 }
3452 else
3453 {
3454 if (flag & style) flag -= style;
3455 }
3456
3457 SetWindowStyleFlag( flag );
3458 }
3459
3460 void wxListCtrl::SetWindowStyleFlag( long flag )
3461 {
3462 if (m_mainWin)
3463 {
3464 m_mainWin->DeleteEverything();
3465
3466 int width = 0;
3467 int height = 0;
3468 GetClientSize( &width, &height );
3469
3470 m_mainWin->SetMode( flag );
3471
3472 if (flag & wxLC_REPORT)
3473 {
3474 if (!HasFlag(wxLC_REPORT))
3475 {
3476 if (!m_headerWin)
3477 {
3478 m_headerWin = new wxListHeaderWindow( this, -1, m_mainWin,
3479 wxPoint(0,0), wxSize(width,23), wxTAB_TRAVERSAL );
3480 if (HasFlag(wxLC_NO_HEADER))
3481 m_headerWin->Show( FALSE );
3482 }
3483 else
3484 {
3485 if (flag & wxLC_NO_HEADER)
3486 m_headerWin->Show( FALSE );
3487 else
3488 m_headerWin->Show( TRUE );
3489 }
3490 }
3491 }
3492 else
3493 {
3494 if (HasFlag(wxLC_REPORT) && !(HasFlag(wxLC_NO_HEADER)))
3495 {
3496 m_headerWin->Show( FALSE );
3497 }
3498 }
3499 }
3500
3501 wxWindow::SetWindowStyleFlag( flag );
3502 }
3503
3504 bool wxListCtrl::GetColumn(int col, wxListItem &item) const
3505 {
3506 m_mainWin->GetColumn( col, item );
3507 return TRUE;
3508 }
3509
3510 bool wxListCtrl::SetColumn( int col, wxListItem& item )
3511 {
3512 m_mainWin->SetColumn( col, item );
3513 return TRUE;
3514 }
3515
3516 int wxListCtrl::GetColumnWidth( int col ) const
3517 {
3518 return m_mainWin->GetColumnWidth( col );
3519 }
3520
3521 bool wxListCtrl::SetColumnWidth( int col, int width )
3522 {
3523 m_mainWin->SetColumnWidth( col, width );
3524 return TRUE;
3525 }
3526
3527 int wxListCtrl::GetCountPerPage() const
3528 {
3529 return m_mainWin->GetCountPerPage(); // different from Windows ?
3530 }
3531
3532 bool wxListCtrl::GetItem( wxListItem &info ) const
3533 {
3534 m_mainWin->GetItem( info );
3535 return TRUE;
3536 }
3537
3538 bool wxListCtrl::SetItem( wxListItem &info )
3539 {
3540 m_mainWin->SetItem( info );
3541 return TRUE;
3542 }
3543
3544 long wxListCtrl::SetItem( long index, int col, const wxString& label, int imageId )
3545 {
3546 wxListItem info;
3547 info.m_text = label;
3548 info.m_mask = wxLIST_MASK_TEXT;
3549 info.m_itemId = index;
3550 info.m_col = col;
3551 if ( imageId > -1 )
3552 {
3553 info.m_image = imageId;
3554 info.m_mask |= wxLIST_MASK_IMAGE;
3555 };
3556 m_mainWin->SetItem(info);
3557 return TRUE;
3558 }
3559
3560 int wxListCtrl::GetItemState( long item, long stateMask ) const
3561 {
3562 return m_mainWin->GetItemState( item, stateMask );
3563 }
3564
3565 bool wxListCtrl::SetItemState( long item, long state, long stateMask )
3566 {
3567 m_mainWin->SetItemState( item, state, stateMask );
3568 return TRUE;
3569 }
3570
3571 bool wxListCtrl::SetItemImage( long item, int image, int WXUNUSED(selImage) )
3572 {
3573 wxListItem info;
3574 info.m_image = image;
3575 info.m_mask = wxLIST_MASK_IMAGE;
3576 info.m_itemId = item;
3577 m_mainWin->SetItem( info );
3578 return TRUE;
3579 }
3580
3581 wxString wxListCtrl::GetItemText( long item ) const
3582 {
3583 wxListItem info;
3584 info.m_itemId = item;
3585 m_mainWin->GetItem( info );
3586 return info.m_text;
3587 }
3588
3589 void wxListCtrl::SetItemText( long item, const wxString &str )
3590 {
3591 wxListItem info;
3592 info.m_mask = wxLIST_MASK_TEXT;
3593 info.m_itemId = item;
3594 info.m_text = str;
3595 m_mainWin->SetItem( info );
3596 }
3597
3598 long wxListCtrl::GetItemData( long item ) const
3599 {
3600 wxListItem info;
3601 info.m_itemId = item;
3602 m_mainWin->GetItem( info );
3603 return info.m_data;
3604 }
3605
3606 bool wxListCtrl::SetItemData( long item, long data )
3607 {
3608 wxListItem info;
3609 info.m_mask = wxLIST_MASK_DATA;
3610 info.m_itemId = item;
3611 info.m_data = data;
3612 m_mainWin->SetItem( info );
3613 return TRUE;
3614 }
3615
3616 bool wxListCtrl::GetItemRect( long item, wxRect &rect, int WXUNUSED(code) ) const
3617 {
3618 m_mainWin->GetItemRect( item, rect );
3619 return TRUE;
3620 }
3621
3622 bool wxListCtrl::GetItemPosition( long item, wxPoint& pos ) const
3623 {
3624 m_mainWin->GetItemPosition( item, pos );
3625 return TRUE;
3626 }
3627
3628 bool wxListCtrl::SetItemPosition( long WXUNUSED(item), const wxPoint& WXUNUSED(pos) )
3629 {
3630 return 0;
3631 }
3632
3633 int wxListCtrl::GetItemCount() const
3634 {
3635 return m_mainWin->GetItemCount();
3636 }
3637
3638 int wxListCtrl::GetColumnCount() const
3639 {
3640 return m_mainWin->GetColumnCount();
3641 }
3642
3643 void wxListCtrl::SetItemSpacing( int spacing, bool isSmall )
3644 {
3645 m_mainWin->SetItemSpacing( spacing, isSmall );
3646 }
3647
3648 int wxListCtrl::GetItemSpacing( bool isSmall ) const
3649 {
3650 return m_mainWin->GetItemSpacing( isSmall );
3651 }
3652
3653 int wxListCtrl::GetSelectedItemCount() const
3654 {
3655 return m_mainWin->GetSelectedItemCount();
3656 }
3657
3658 wxColour wxListCtrl::GetTextColour() const
3659 {
3660 return GetForegroundColour();
3661 }
3662
3663 void wxListCtrl::SetTextColour(const wxColour& col)
3664 {
3665 SetForegroundColour(col);
3666 }
3667
3668 long wxListCtrl::GetTopItem() const
3669 {
3670 return 0;
3671 }
3672
3673 long wxListCtrl::GetNextItem( long item, int geom, int state ) const
3674 {
3675 return m_mainWin->GetNextItem( item, geom, state );
3676 }
3677
3678 wxImageList *wxListCtrl::GetImageList(int which) const
3679 {
3680 if (which == wxIMAGE_LIST_NORMAL)
3681 {
3682 return m_imageListNormal;
3683 }
3684 else if (which == wxIMAGE_LIST_SMALL)
3685 {
3686 return m_imageListSmall;
3687 }
3688 else if (which == wxIMAGE_LIST_STATE)
3689 {
3690 return m_imageListState;
3691 }
3692 return (wxImageList *) NULL;
3693 }
3694
3695 void wxListCtrl::SetImageList( wxImageList *imageList, int which )
3696 {
3697 if ( which == wxIMAGE_LIST_NORMAL )
3698 {
3699 if (m_ownsImageListNormal) delete m_imageListNormal;
3700 m_imageListNormal = imageList;
3701 m_ownsImageListNormal = FALSE;
3702 }
3703 else if ( which == wxIMAGE_LIST_SMALL )
3704 {
3705 if (m_ownsImageListSmall) delete m_imageListSmall;
3706 m_imageListSmall = imageList;
3707 m_ownsImageListSmall = FALSE;
3708 }
3709 else if ( which == wxIMAGE_LIST_STATE )
3710 {
3711 if (m_ownsImageListState) delete m_imageListState;
3712 m_imageListState = imageList;
3713 m_ownsImageListState = FALSE;
3714 }
3715
3716 m_mainWin->SetImageList( imageList, which );
3717 }
3718
3719 void wxListCtrl::AssignImageList(wxImageList *imageList, int which)
3720 {
3721 SetImageList(imageList, which);
3722 if ( which == wxIMAGE_LIST_NORMAL )
3723 m_ownsImageListNormal = TRUE;
3724 else if ( which == wxIMAGE_LIST_SMALL )
3725 m_ownsImageListSmall = TRUE;
3726 else if ( which == wxIMAGE_LIST_STATE )
3727 m_ownsImageListState = TRUE;
3728 }
3729
3730 bool wxListCtrl::Arrange( int WXUNUSED(flag) )
3731 {
3732 return 0;
3733 }
3734
3735 bool wxListCtrl::DeleteItem( long item )
3736 {
3737 m_mainWin->DeleteItem( item );
3738 return TRUE;
3739 }
3740
3741 bool wxListCtrl::DeleteAllItems()
3742 {
3743 m_mainWin->DeleteAllItems();
3744 return TRUE;
3745 }
3746
3747 bool wxListCtrl::DeleteAllColumns()
3748 {
3749 size_t count = m_mainWin->m_columns.GetCount();
3750 for ( size_t n = 0; n < count; n++ )
3751 DeleteColumn(n);
3752
3753 return TRUE;
3754 }
3755
3756 void wxListCtrl::ClearAll()
3757 {
3758 m_mainWin->DeleteEverything();
3759 }
3760
3761 bool wxListCtrl::DeleteColumn( int col )
3762 {
3763 m_mainWin->DeleteColumn( col );
3764 return TRUE;
3765 }
3766
3767 void wxListCtrl::Edit( long item )
3768 {
3769 m_mainWin->Edit( item );
3770 }
3771
3772 bool wxListCtrl::EnsureVisible( long item )
3773 {
3774 m_mainWin->EnsureVisible( item );
3775 return TRUE;
3776 }
3777
3778 long wxListCtrl::FindItem( long start, const wxString& str, bool partial )
3779 {
3780 return m_mainWin->FindItem( start, str, partial );
3781 }
3782
3783 long wxListCtrl::FindItem( long start, long data )
3784 {
3785 return m_mainWin->FindItem( start, data );
3786 }
3787
3788 long wxListCtrl::FindItem( long WXUNUSED(start), const wxPoint& WXUNUSED(pt),
3789 int WXUNUSED(direction))
3790 {
3791 return 0;
3792 }
3793
3794 long wxListCtrl::HitTest( const wxPoint &point, int &flags )
3795 {
3796 return m_mainWin->HitTest( (int)point.x, (int)point.y, flags );
3797 }
3798
3799 long wxListCtrl::InsertItem( wxListItem& info )
3800 {
3801 m_mainWin->InsertItem( info );
3802 return info.m_itemId;
3803 }
3804
3805 long wxListCtrl::InsertItem( long index, const wxString &label )
3806 {
3807 wxListItem info;
3808 info.m_text = label;
3809 info.m_mask = wxLIST_MASK_TEXT;
3810 info.m_itemId = index;
3811 return InsertItem( info );
3812 }
3813
3814 long wxListCtrl::InsertItem( long index, int imageIndex )
3815 {
3816 wxListItem info;
3817 info.m_mask = wxLIST_MASK_IMAGE;
3818 info.m_image = imageIndex;
3819 info.m_itemId = index;
3820 return InsertItem( info );
3821 }
3822
3823 long wxListCtrl::InsertItem( long index, const wxString &label, int imageIndex )
3824 {
3825 wxListItem info;
3826 info.m_text = label;
3827 info.m_image = imageIndex;
3828 info.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE;
3829 info.m_itemId = index;
3830 return InsertItem( info );
3831 }
3832
3833 long wxListCtrl::InsertColumn( long col, wxListItem &item )
3834 {
3835 wxASSERT( m_headerWin );
3836 m_mainWin->InsertColumn( col, item );
3837 m_headerWin->Refresh();
3838
3839 return 0;
3840 }
3841
3842 long wxListCtrl::InsertColumn( long col, const wxString &heading,
3843 int format, int width )
3844 {
3845 wxListItem item;
3846 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
3847 item.m_text = heading;
3848 if (width >= -2)
3849 {
3850 item.m_mask |= wxLIST_MASK_WIDTH;
3851 item.m_width = width;
3852 }
3853 item.m_format = format;
3854
3855 return InsertColumn( col, item );
3856 }
3857
3858 bool wxListCtrl::ScrollList( int WXUNUSED(dx), int WXUNUSED(dy) )
3859 {
3860 return 0;
3861 }
3862
3863 // Sort items.
3864 // fn is a function which takes 3 long arguments: item1, item2, data.
3865 // item1 is the long data associated with a first item (NOT the index).
3866 // item2 is the long data associated with a second item (NOT the index).
3867 // data is the same value as passed to SortItems.
3868 // The return value is a negative number if the first item should precede the second
3869 // item, a positive number of the second item should precede the first,
3870 // or zero if the two items are equivalent.
3871 // data is arbitrary data to be passed to the sort function.
3872
3873 bool wxListCtrl::SortItems( wxListCtrlCompare fn, long data )
3874 {
3875 m_mainWin->SortItems( fn, data );
3876 return TRUE;
3877 }
3878
3879 void wxListCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) )
3880 {
3881 if (!m_mainWin->m_dirty) return;
3882
3883 int cw = 0;
3884 int ch = 0;
3885 GetClientSize( &cw, &ch );
3886
3887 int x = 0;
3888 int y = 0;
3889 int w = 0;
3890 int h = 0;
3891
3892 if (HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER))
3893 {
3894 m_headerWin->GetPosition( &x, &y );
3895 m_headerWin->GetSize( &w, &h );
3896 if ((x != 0) || (y != 0) || (w != cw) || (h != 23))
3897 m_headerWin->SetSize( 0, 0, cw, 23 );
3898
3899 m_mainWin->GetPosition( &x, &y );
3900 m_mainWin->GetSize( &w, &h );
3901 if ((x != 0) || (y != 24) || (w != cw) || (h != ch-24))
3902 m_mainWin->SetSize( 0, 24, cw, ch-24 );
3903 }
3904 else
3905 {
3906 m_mainWin->GetPosition( &x, &y );
3907 m_mainWin->GetSize( &w, &h );
3908 if ((x != 0) || (y != 24) || (w != cw) || (h != ch))
3909 m_mainWin->SetSize( 0, 0, cw, ch );
3910 }
3911
3912 m_mainWin->CalculatePositions();
3913 m_mainWin->RealizeChanges();
3914 m_mainWin->m_dirty = FALSE;
3915 m_mainWin->Refresh();
3916
3917 if ( m_headerWin && m_headerWin->m_dirty )
3918 {
3919 m_headerWin->m_dirty = FALSE;
3920 m_headerWin->Refresh();
3921 }
3922 }
3923
3924 bool wxListCtrl::SetBackgroundColour( const wxColour &colour )
3925 {
3926 if (m_mainWin)
3927 {
3928 m_mainWin->SetBackgroundColour( colour );
3929 m_mainWin->m_dirty = TRUE;
3930 }
3931
3932 return TRUE;
3933 }
3934
3935 bool wxListCtrl::SetForegroundColour( const wxColour &colour )
3936 {
3937 if ( !wxWindow::SetForegroundColour( colour ) )
3938 return FALSE;
3939
3940 if (m_mainWin)
3941 {
3942 m_mainWin->SetForegroundColour( colour );
3943 m_mainWin->m_dirty = TRUE;
3944 }
3945
3946 if (m_headerWin)
3947 {
3948 m_headerWin->SetForegroundColour( colour );
3949 }
3950
3951 return TRUE;
3952 }
3953
3954 bool wxListCtrl::SetFont( const wxFont &font )
3955 {
3956 if ( !wxWindow::SetFont( font ) )
3957 return FALSE;
3958
3959 if (m_mainWin)
3960 {
3961 m_mainWin->SetFont( font );
3962 m_mainWin->m_dirty = TRUE;
3963 }
3964
3965 if (m_headerWin)
3966 {
3967 m_headerWin->SetFont( font );
3968 }
3969
3970 return TRUE;
3971 }
3972
3973 #if wxUSE_DRAG_AND_DROP
3974
3975 void wxListCtrl::SetDropTarget( wxDropTarget *dropTarget )
3976 {
3977 m_mainWin->SetDropTarget( dropTarget );
3978 }
3979
3980 wxDropTarget *wxListCtrl::GetDropTarget() const
3981 {
3982 return m_mainWin->GetDropTarget();
3983 }
3984
3985 #endif // wxUSE_DRAG_AND_DROP
3986
3987 bool wxListCtrl::SetCursor( const wxCursor &cursor )
3988 {
3989 return m_mainWin ? m_mainWin->wxWindow::SetCursor(cursor) : FALSE;
3990 }
3991
3992 wxColour wxListCtrl::GetBackgroundColour() const
3993 {
3994 return m_mainWin ? m_mainWin->GetBackgroundColour() : wxColour();
3995 }
3996
3997 wxColour wxListCtrl::GetForegroundColour() const
3998 {
3999 return m_mainWin ? m_mainWin->GetForegroundColour() : wxColour();
4000 }
4001
4002 bool wxListCtrl::DoPopupMenu( wxMenu *menu, int x, int y )
4003 {
4004 #if wxUSE_MENUS
4005 return m_mainWin->PopupMenu( menu, x, y );
4006 #else
4007 return FALSE;
4008 #endif // wxUSE_MENUS
4009 }
4010
4011 void wxListCtrl::SetFocus()
4012 {
4013 /* The test in window.cpp fails as we are a composite
4014 window, so it checks against "this", but not m_mainWin. */
4015 if ( FindFocus() != this )
4016 m_mainWin->SetFocus();
4017 }
4018
4019 // ----------------------------------------------------------------------------
4020 // virtual list control support
4021 // ----------------------------------------------------------------------------
4022
4023 wxString wxListCtrl::OnGetItemText(long item, long col) const
4024 {
4025 // this is a pure virtual function, in fact - which is not really pure
4026 // because the controls which are not virtual don't need to implement it
4027 wxFAIL_MSG( _T("not supposed to be called") );
4028
4029 return wxEmptyString;
4030 }
4031
4032 int wxListCtrl::OnGetItemImage(long item) const
4033 {
4034 // same as above
4035 wxFAIL_MSG( _T("not supposed to be called") );
4036
4037 return -1;
4038 }
4039
4040 void wxListCtrl::SetItemCount(long count)
4041 {
4042 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4043
4044 m_mainWin->SetItemCount(count);
4045 }
4046
4047 #endif // wxUSE_LISTCTRL