1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/listctrl.cpp
3 // Purpose: generic implementation of wxListCtrl
4 // Author: Robert Roebling
5 // Vadim Zeitlin (virtual list control support)
7 // Copyright: (c) 1998 Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 FIXME for virtual list controls
14 +1. clicking on the item with a mouse is awfully slow, what is going on?
15 note that selecting with keyboard seems to be much faster
16 => fixed HighlightAll() - iterating over 1000000 items *is* slow
18 2. background colour is wrong?
22 TODO for better virtual list control support:
24 1. less dumb line caching, we should cache at least all those visible
25 in the control itself and probably twice as many (we might also need to
26 cache the first one always for geometry calculations?)
28 +2. storing selections: we can't use an array to store the selected indices
29 like right now as selecting all in a control with 1000000 items is not
30 doable like this - instead, store selections as collection of individual
35 3. we need to implement searching/sorting somehow
37 4. the idea of storing the line index in the line itself is really stupid,
38 we shouldn't need it - but for this we have to get rid of all calles to
39 wxListLineData::GetFoo() and replace them with something like
41 ... we have it ourselves ...
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
55 #pragma implementation "listctrl.h"
56 #pragma implementation "listctrlbase.h"
59 // For compilers that support precompilation, includes "wx.h".
60 #include "wx/wxprec.h"
68 #include "wx/dcscreen.h"
70 #include "wx/listctrl.h"
71 #include "wx/imaglist.h"
72 #include "wx/dynarray.h"
76 #include "wx/gtk/win_gtk.h"
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG
)
84 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG
)
85 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
)
86 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT
)
87 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM
)
88 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
)
89 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO
)
90 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO
)
91 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED
)
92 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED
)
93 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN
)
94 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM
)
95 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK
)
96 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
)
97 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
)
98 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED
)
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 // the height of the header window (FIXME: should depend on its font!)
105 static const int HEADER_HEIGHT
= 23;
107 // the scrollbar units
108 static const int SCROLL_UNIT_X
= 15;
109 static const int SCROLL_UNIT_Y
= 15;
111 // the spacing between the lines (in report mode)
112 static const int LINE_SPACING
= 0;
114 // extra margins around the text label
115 static const int EXTRA_WIDTH
= 3;
116 static const int EXTRA_HEIGHT
= 4;
118 // offset for the header window
119 static const int HEADER_OFFSET_X
= 1;
120 static const int HEADER_OFFSET_Y
= 1;
122 // when autosizing the columns, add some slack
123 static const int AUTOSIZE_COL_MARGIN
= 10;
125 // default and minimal widths for the header columns
126 static const int WIDTH_COL_DEFAULT
= 80;
127 static const int WIDTH_COL_MIN
= 10;
129 // ============================================================================
131 // ============================================================================
133 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
137 int CMPFUNC_CONV
wxSizeTCmpFn(size_t n1
, size_t n2
) { return n1
- n2
; }
139 WX_DEFINE_SORTED_EXPORTED_ARRAY(size_t, wxIndexArray
);
141 // this class is used to store the selected items in the virtual list control
142 // (but it is not tied to list control and so can be used with other controls
143 // such as wxListBox in wxUniv)
145 // the idea is to make it really smart later (i.e. store the selections as an
146 // array of ranes + individual items) but, as I don't have time to do it now
147 // (this would require writing code to merge/break ranges and much more) keep
148 // it simple but define a clean interface to it which allows it to be made
150 class WXDLLEXPORT wxSelectionStore
153 wxSelectionStore() : m_itemsSel(wxSizeTCmpFn
) { Init(); }
155 // set the total number of items we handle
156 void SetItemCount(size_t count
) { m_count
= count
; }
158 // special case of SetItemCount(0)
159 void Clear() { m_itemsSel
.Clear(); m_count
= 0; }
161 // must be called when a new item is inserted/added
162 void OnItemAdd(size_t item
) { wxFAIL_MSG( _T("TODO") ); }
164 // must be called when an item is deleted
165 void OnItemDelete(size_t item
);
167 // select one item, use SelectRange() insted if possible!
169 // returns true if the items selection really changed
170 bool SelectItem(size_t item
, bool select
= TRUE
);
172 // select the range of items
173 void SelectRange(size_t itemFrom
, size_t itemTo
, bool select
= TRUE
);
175 // return true if the given item is selected
176 bool IsSelected(size_t item
) const;
178 // return the total number of selected items
179 size_t GetSelectedCount() const
181 return m_defaultState
? m_count
- m_itemsSel
.GetCount()
182 : m_itemsSel
.GetCount();
187 void Init() { m_defaultState
= FALSE
; }
189 // the total number of items we handle
192 // the default state: normally, FALSE (i.e. off) but maybe set to TRUE if
193 // there are more selected items than non selected ones - this allows to
194 // handle selection of all items efficiently
197 // the array of items whose selection state is different from default
198 wxIndexArray m_itemsSel
;
200 DECLARE_NO_COPY_CLASS(wxSelectionStore
)
203 //-----------------------------------------------------------------------------
204 // wxListItemData (internal)
205 //-----------------------------------------------------------------------------
207 class WXDLLEXPORT wxListItemData
210 wxListItemData(wxListMainWindow
*owner
);
211 ~wxListItemData() { delete m_attr
; delete m_rect
; }
213 void SetItem( const wxListItem
&info
);
214 void SetImage( int image
) { m_image
= image
; }
215 void SetData( long data
) { m_data
= data
; }
216 void SetPosition( int x
, int y
);
217 void SetSize( int width
, int height
);
219 bool HasText() const { return !m_text
.empty(); }
220 const wxString
& GetText() const { return m_text
; }
221 void SetText(const wxString
& text
) { m_text
= text
; }
223 // we can't use empty string for measuring the string width/height, so
224 // always return something
225 wxString
GetTextForMeasuring() const
227 wxString s
= GetText();
234 bool IsHit( int x
, int y
) const;
238 int GetWidth() const;
239 int GetHeight() const;
241 int GetImage() const { return m_image
; }
242 bool HasImage() const { return GetImage() != -1; }
244 void GetItem( wxListItem
&info
) const;
246 wxListItemAttr
*GetAttributes() const { return m_attr
; }
249 // the item image or -1
252 // user data associated with the item
255 // the item coordinates are not used in report mode, instead this pointer
256 // is NULL and the owner window is used to retrieve the item position and
260 // the list ctrl we are in
261 wxListMainWindow
*m_owner
;
263 // custom attributes or NULL
264 wxListItemAttr
*m_attr
;
267 // common part of all ctors
273 //-----------------------------------------------------------------------------
274 // wxListHeaderData (internal)
275 //-----------------------------------------------------------------------------
277 class WXDLLEXPORT wxListHeaderData
: public wxObject
291 wxListHeaderData( const wxListItem
&info
);
292 void SetItem( const wxListItem
&item
);
293 void SetPosition( int x
, int y
);
294 void SetWidth( int w
);
295 void SetFormat( int format
);
296 void SetHeight( int h
);
297 bool HasImage() const;
299 bool HasText() const { return !m_text
.empty(); }
300 const wxString
& GetText() const { return m_text
; }
301 void SetText(const wxString
& text
) { m_text
= text
; }
303 void GetItem( wxListItem
&item
);
305 bool IsHit( int x
, int y
) const;
306 int GetImage() const;
307 int GetWidth() const;
308 int GetFormat() const;
311 DECLARE_DYNAMIC_CLASS(wxListHeaderData
);
314 //-----------------------------------------------------------------------------
315 // wxListLineData (internal)
316 //-----------------------------------------------------------------------------
318 WX_DECLARE_LIST(wxListItemData
, wxListItemDataList
);
319 #include "wx/listimpl.cpp"
320 WX_DEFINE_LIST(wxListItemDataList
);
322 class WXDLLEXPORT wxListLineData
325 // the list of subitems: only may have more than one item in report mode
326 wxListItemDataList m_items
;
328 // this is not used in report view
340 // the part to be highlighted
341 wxRect m_rectHighlight
;
344 // is this item selected? [NB: not used in virtual mode]
347 // back pointer to the list ctrl
348 wxListMainWindow
*m_owner
;
351 wxListLineData( wxListMainWindow
*owner
, size_t line
);
353 ~wxListLineData() { delete m_gi
; }
355 // are we in report mode?
356 inline bool InReportView() const;
358 // are we in virtual report mode?
359 inline bool IsVirtual() const;
361 // these 2 methods shouldn't be called for report view controls, in that
362 // case we determine our position/size ourselves
364 // calculate the size of the line
365 void CalculateSize( wxDC
*dc
, int spacing
);
367 // remember the position this line appears at
368 void SetPosition( int x
, int y
, int window_width
, int spacing
);
370 long IsHit( int x
, int y
);
372 void SetItem( int index
, const wxListItem
&info
);
373 void GetItem( int index
, wxListItem
&info
);
375 wxString
GetText(int index
) const;
376 void SetText( int index
, const wxString s
);
378 void SetImage( int index
, int image
);
379 int GetImage( int index
) const;
381 // get the bound rect of this line
382 wxRect
GetRect() const;
384 // get the bound rect of the label
385 wxRect
GetLabelRect() const;
387 // get the bound rect of the items icon (only may be called if we do have
389 wxRect
GetIconRect() const;
391 // get the rect to be highlighted when the item has focus
392 wxRect
GetHighlightRect() const;
394 // get the size of the total line rect
395 wxSize
GetSize() const { return GetRect().GetSize(); }
397 // return true if the highlighting really changed
398 bool Highlight( bool on
);
400 void ReverseHighlight();
402 // draw the line on the given DC
403 void Draw( wxDC
*dc
, int y
= 0, int height
= 0, bool highlighted
= FALSE
);
405 bool IsHighlighted() const
407 wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") );
409 return m_highlighted
;
412 // only for wxListMainWindow::CacheLineData()
413 void SetLineIndex(size_t line
) { m_lineIndex
= line
; }
416 // set the line to contain num items (only can be > 1 in report mode)
417 void InitItems( int num
);
419 // get the mode (i.e. style) of the list control
420 inline int GetMode() const;
422 void SetAttributes(wxDC
*dc
,
423 const wxListItemAttr
*attr
,
424 const wxColour
& colText
,
428 // the index of this line (only used in report mode)
433 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData
, wxListLineDataArray
);
434 #include "wx/arrimpl.cpp"
435 WX_DEFINE_OBJARRAY(wxListLineDataArray
);
437 //-----------------------------------------------------------------------------
438 // wxListHeaderWindow (internal)
439 //-----------------------------------------------------------------------------
441 class WXDLLEXPORT wxListHeaderWindow
: public wxWindow
444 wxListMainWindow
*m_owner
;
445 wxCursor
*m_currentCursor
;
446 wxCursor
*m_resizeCursor
;
449 // column being resized
452 // divider line position in logical (unscrolled) coords
455 // minimal position beyond which the divider line can't be dragged in
460 wxListHeaderWindow();
461 virtual ~wxListHeaderWindow();
463 wxListHeaderWindow( wxWindow
*win
,
465 wxListMainWindow
*owner
,
466 const wxPoint
&pos
= wxDefaultPosition
,
467 const wxSize
&size
= wxDefaultSize
,
469 const wxString
&name
= "wxlistctrlcolumntitles" );
471 void DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
);
473 void AdjustDC(wxDC
& dc
);
475 void OnPaint( wxPaintEvent
&event
);
476 void OnMouse( wxMouseEvent
&event
);
477 void OnSetFocus( wxFocusEvent
&event
);
483 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow
)
484 DECLARE_EVENT_TABLE()
487 //-----------------------------------------------------------------------------
488 // wxListRenameTimer (internal)
489 //-----------------------------------------------------------------------------
491 class WXDLLEXPORT wxListRenameTimer
: public wxTimer
494 wxListMainWindow
*m_owner
;
497 wxListRenameTimer( wxListMainWindow
*owner
);
501 //-----------------------------------------------------------------------------
502 // wxListTextCtrl (internal)
503 //-----------------------------------------------------------------------------
505 class WXDLLEXPORT wxListTextCtrl
: public wxTextCtrl
510 wxListMainWindow
*m_owner
;
511 wxString m_startValue
;
515 wxListTextCtrl( wxWindow
*parent
, const wxWindowID id
,
516 bool *accept
, wxString
*res
, wxListMainWindow
*owner
,
517 const wxString
&value
= "",
518 const wxPoint
&pos
= wxDefaultPosition
, const wxSize
&size
= wxDefaultSize
,
520 const wxValidator
& validator
= wxDefaultValidator
,
521 const wxString
&name
= "listctrltextctrl" );
522 void OnChar( wxKeyEvent
&event
);
523 void OnKeyUp( wxKeyEvent
&event
);
524 void OnKillFocus( wxFocusEvent
&event
);
527 DECLARE_DYNAMIC_CLASS(wxListTextCtrl
);
528 DECLARE_EVENT_TABLE()
531 //-----------------------------------------------------------------------------
532 // wxListMainWindow (internal)
533 //-----------------------------------------------------------------------------
535 WX_DECLARE_LIST(wxListHeaderData
, wxListHeaderDataList
);
536 #include "wx/listimpl.cpp"
537 WX_DEFINE_LIST(wxListHeaderDataList
);
539 class WXDLLEXPORT wxListMainWindow
: public wxScrolledWindow
543 wxListMainWindow( wxWindow
*parent
,
545 const wxPoint
& pos
= wxDefaultPosition
,
546 const wxSize
& size
= wxDefaultSize
,
548 const wxString
&name
= _T("listctrlmainwindow") );
550 virtual ~wxListMainWindow();
552 bool HasFlag(int flag
) const { return m_parent
->HasFlag(flag
); }
554 // return true if this is a virtual list control
555 bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL
); }
557 // return true if we are in single selection mode, false if multi sel
558 bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL
); }
560 // do we have a header window?
561 bool HasHeader() const
562 { return HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
); }
564 void HighlightAll( bool on
);
566 // all these functions only do something if the line is currently visible
568 // change the line "selected" state, return TRUE if it really changed
569 bool HighlightLine( size_t line
, bool highlight
= TRUE
);
571 // as HighlightLine() but do it for the range of lines: this is incredibly
572 // more efficient for virtual list controls!
574 // NB: unlike HighlightLine() this one does refresh the lines on screen
575 void HighlightLines( size_t lineFrom
, size_t lineTo
, bool on
= TRUE
);
577 // toggle the line state and refresh it
578 void ReverseHighlight( size_t line
)
579 { HighlightLine(line
, !IsHighlighted(line
)); RefreshLine(line
); }
581 // refresh one or several lines at once
582 void RefreshLine( size_t line
);
583 void RefreshLines( size_t lineFrom
, size_t lineTo
);
585 // return true if the line is highlighted
586 bool IsHighlighted(size_t line
) const;
588 void EditLabel( long item
);
589 void OnRenameTimer();
590 void OnRenameAccept();
592 void OnMouse( wxMouseEvent
&event
);
595 // called to switch the selection from the current item to newCurrent,
596 void OnArrowChar( size_t newCurrent
, const wxKeyEvent
& event
);
598 void OnChar( wxKeyEvent
&event
);
599 void OnKeyDown( wxKeyEvent
&event
);
600 void OnSetFocus( wxFocusEvent
&event
);
601 void OnKillFocus( wxFocusEvent
&event
);
602 void OnScroll(wxScrollWinEvent
& event
) ;
604 void OnPaint( wxPaintEvent
&event
);
606 void DrawImage( int index
, wxDC
*dc
, int x
, int y
);
607 void GetImageSize( int index
, int &width
, int &height
);
608 int GetTextLength( const wxString
&s
);
610 void SetImageList( wxImageList
*imageList
, int which
);
611 void SetItemSpacing( int spacing
, bool isSmall
= FALSE
);
612 int GetItemSpacing( bool isSmall
= FALSE
);
614 void SetColumn( int col
, wxListItem
&item
);
615 void SetColumnWidth( int col
, int width
);
616 void GetColumn( int col
, wxListItem
&item
) const;
617 int GetColumnWidth( int col
) const;
618 int GetColumnCount() const { return m_columns
.GetCount(); }
620 // returns the sum of the heights of all columns
621 int GetHeaderWidth() const;
623 int GetCountPerPage() { return m_linesPerPage
; }
625 void SetItem( wxListItem
&item
);
626 void GetItem( wxListItem
&item
);
627 void SetItemState( long item
, long state
, long stateMask
);
628 int GetItemState( long item
, long stateMask
);
629 void GetItemRect( long index
, wxRect
&rect
);
630 bool GetItemPosition( long item
, wxPoint
& pos
);
631 int GetSelectedItemCount();
633 // set the scrollbars and update the positions of the items
634 void RecalculatePositions();
636 // refresh the window and the header
639 long GetNextItem( long item
, int geometry
, int state
);
640 void DeleteItem( long index
);
641 void DeleteAllItems();
642 void DeleteColumn( int col
);
643 void DeleteEverything();
644 void EnsureVisible( long index
);
645 long FindItem( long start
, const wxString
& str
, bool partial
= FALSE
);
646 long FindItem( long start
, long data
);
647 long HitTest( int x
, int y
, int &flags
);
648 void InsertItem( wxListItem
&item
);
649 void InsertColumn( long col
, wxListItem
&item
);
650 void SortItems( wxListCtrlCompare fn
, long data
);
652 size_t GetItemCount() const;
653 bool IsEmpty() const { return GetItemCount() == 0; }
654 void SetItemCount(long count
);
656 void ResetCurrent() { m_current
= (size_t)-1; }
657 bool HasCurrent() const { return m_current
!= (size_t)-1; }
659 // send out a wxListEvent
660 void SendNotify( size_t line
,
662 wxPoint point
= wxDefaultPosition
);
664 // override base class virtual to reset m_lineHeight when the font changes
665 virtual bool SetFont(const wxFont
& font
)
667 if ( !wxScrolledWindow::SetFont(font
) )
675 // these are for wxListLineData usage only
677 // get the backpointer to the list ctrl
678 wxListCtrl
*GetListCtrl() const
680 return wxStaticCast(GetParent(), wxListCtrl
);
683 // get the height of all lines (assuming they all do have the same height)
684 wxCoord
GetLineHeight() const;
686 // get the y position of the given line (only for report view)
687 wxCoord
GetLineY(size_t line
) const;
690 // the array of all line objects for a non virtual list control
691 wxListLineDataArray m_lines
;
693 // the list of column objects
694 wxListHeaderDataList m_columns
;
696 // currently focused item or -1
699 // the item currently being edited or -1
700 size_t m_currentEdit
;
702 // the number of lines per page
705 // this flag is set when something which should result in the window
706 // redrawing happens (i.e. an item was added or deleted, or its appearance
707 // changed) and OnPaint() doesn't redraw the window while it is set which
708 // allows to minimize the number of repaintings when a lot of items are
709 // being added. The real repainting occurs only after the next OnIdle()
713 wxBrush
*m_highlightBrush
;
714 wxColour
*m_highlightColour
;
717 wxImageList
*m_small_image_list
;
718 wxImageList
*m_normal_image_list
;
720 int m_normal_spacing
;
724 wxTimer
*m_renameTimer
;
726 wxString m_renameRes
;
731 // for double click logic
732 size_t m_lineLastClicked
,
733 m_lineBeforeLastClicked
;
736 // the total count of items in a virtual list control
739 // the object maintaining the items selection state, only used in virtual
741 wxSelectionStore m_selStore
;
743 // common part of all ctors
746 // intiialize m_[xy]Scroll
747 void InitScrolling();
749 // get the line data for the given index
750 wxListLineData
*GetLine(size_t n
) const
752 wxASSERT_MSG( n
!= (size_t)-1, _T("invalid line index") );
756 wxConstCast(this, wxListMainWindow
)->CacheLineData(n
);
764 // get a dummy line which can be used for geometry calculations and such:
765 // you must use GetLine() if you want to really draw the line
766 wxListLineData
*GetDummyLine() const;
768 // cache the line data of the n-th line in m_lines[0]
769 void CacheLineData(size_t line
);
771 // get the range of visible lines
772 void GetVisibleLinesRange(size_t *from
, size_t *to
);
774 // force us to recalculate the range of visible lines
775 void ResetVisibleLinesRange() { m_lineFrom
= (size_t)-1; }
777 // get the colour to be used for drawing the rules
778 wxColour
GetRuleColour() const
783 return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT
);
788 // initialize the current item if needed
789 void UpdateCurrent();
791 // called when an item is [un]focuded, i.e. becomes [not] current
794 void OnFocusLine( size_t line
);
795 void OnUnfocusLine( size_t line
);
797 // the height of one line using the current font
798 wxCoord m_lineHeight
;
800 // the total header width or 0 if not calculated yet
801 wxCoord m_headerWidth
;
803 // the first and last lines being shown on screen right now (inclusive),
804 // both may be -1 if they must be calculated so never access them directly:
805 // use GetVisibleLinesRange() above instead
809 DECLARE_DYNAMIC_CLASS(wxListMainWindow
);
810 DECLARE_EVENT_TABLE()
813 // ============================================================================
815 // ============================================================================
817 // ----------------------------------------------------------------------------
819 // ----------------------------------------------------------------------------
821 bool wxSelectionStore::IsSelected(size_t item
) const
823 bool isSel
= m_itemsSel
.Index(item
) != wxNOT_FOUND
;
825 // if the default state is to be selected, being in m_itemsSel means that
826 // the item is not selected, so we have to inverse the logic
827 return m_defaultState
? !isSel
: isSel
;
830 bool wxSelectionStore::SelectItem(size_t item
, bool select
)
832 // search for the item ourselves as like this we get the index where to
833 // insert it later if needed, so we do only one search in the array instead
834 // of two (adding item to a sorted array requires a search)
835 size_t index
= m_itemsSel
.IndexForInsert(item
);
836 bool isSel
= index
< m_itemsSel
.GetCount() && m_itemsSel
[index
] == item
;
838 if ( select
!= m_defaultState
)
842 m_itemsSel
.AddAt(item
, index
);
847 else // reset to default state
851 m_itemsSel
.RemoveAt(index
);
859 void wxSelectionStore::SelectRange(size_t itemFrom
, size_t itemTo
, bool select
)
861 wxASSERT_MSG( itemFrom
<= itemTo
, _T("should be in order") );
863 // are we going to have more [un]selected items than the other ones?
864 if ( itemTo
- itemFrom
> m_count
/ 2 )
866 if ( select
!= m_defaultState
)
868 // the default state now becomes the same as 'select'
869 m_defaultState
= select
;
871 // so all the old selections (which had state select) shouldn't be
872 // selected any more, but all the other ones should
873 wxIndexArray selOld
= m_itemsSel
;
876 // TODO: it should be possible to optimize the searches a bit
877 // knowing the possible range
880 for ( item
= 0; item
< itemFrom
; item
++ )
882 if ( selOld
.Index(item
) == wxNOT_FOUND
)
883 m_itemsSel
.Add(item
);
886 for ( item
= itemTo
+ 1; item
< m_count
; item
++ )
888 if ( selOld
.Index(item
) == wxNOT_FOUND
)
889 m_itemsSel
.Add(item
);
892 else // select == m_defaultState
894 // get the inclusive range of items between itemFrom and itemTo
895 size_t count
= m_itemsSel
.GetCount(),
896 start
= m_itemsSel
.IndexForInsert(itemFrom
),
897 end
= m_itemsSel
.IndexForInsert(itemTo
);
899 if ( start
== count
|| m_itemsSel
[start
] < itemFrom
)
904 if ( end
== count
|| m_itemsSel
[end
] > itemTo
)
911 // delete all of them (from end to avoid changing indices)
912 for ( int i
= end
; i
>= (int)start
; i
-- )
914 m_itemsSel
.RemoveAt(i
);
919 else // "few" items change state
921 // just add the items to the selection
922 for ( size_t item
= itemFrom
; item
<= itemTo
; item
++ )
924 SelectItem(item
, select
);
929 void wxSelectionStore::OnItemDelete(size_t item
)
931 size_t count
= m_itemsSel
.GetCount(),
932 i
= m_itemsSel
.IndexForInsert(item
);
934 if ( i
< count
&& m_itemsSel
[i
] == item
)
936 // this item itself was in m_itemsSel, remove it from there
937 m_itemsSel
.RemoveAt(i
);
940 // and adjust the index of all which follow it
943 // all following elements must be greater than the one we deleted
944 wxASSERT_MSG( m_itemsSel
[i
] > item
, _T("logic error") );
950 //-----------------------------------------------------------------------------
952 //-----------------------------------------------------------------------------
954 void wxListItemData::Init()
962 wxListItemData::wxListItemData(wxListMainWindow
*owner
)
968 if ( owner
->HasFlag(wxLC_REPORT
) )
978 void wxListItemData::SetItem( const wxListItem
&info
)
980 if ( info
.m_mask
& wxLIST_MASK_TEXT
)
981 SetText(info
.m_text
);
982 if ( info
.m_mask
& wxLIST_MASK_IMAGE
)
983 m_image
= info
.m_image
;
984 if ( info
.m_mask
& wxLIST_MASK_DATA
)
985 m_data
= info
.m_data
;
987 if ( info
.HasAttributes() )
990 *m_attr
= *info
.GetAttributes();
992 m_attr
= new wxListItemAttr(*info
.GetAttributes());
1000 m_rect
->width
= info
.m_width
;
1004 void wxListItemData::SetPosition( int x
, int y
)
1006 wxCHECK_RET( m_rect
, _T("unexpected SetPosition() call") );
1012 void wxListItemData::SetSize( int width
, int height
)
1014 wxCHECK_RET( m_rect
, _T("unexpected SetSize() call") );
1017 m_rect
->width
= width
;
1019 m_rect
->height
= height
;
1022 bool wxListItemData::IsHit( int x
, int y
) const
1024 wxCHECK_MSG( m_rect
, FALSE
, _T("can't be called in this mode") );
1026 return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x
, y
);
1029 int wxListItemData::GetX() const
1031 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1036 int wxListItemData::GetY() const
1038 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1043 int wxListItemData::GetWidth() const
1045 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1047 return m_rect
->width
;
1050 int wxListItemData::GetHeight() const
1052 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1054 return m_rect
->height
;
1057 void wxListItemData::GetItem( wxListItem
&info
) const
1059 info
.m_text
= m_text
;
1060 info
.m_image
= m_image
;
1061 info
.m_data
= m_data
;
1065 if ( m_attr
->HasTextColour() )
1066 info
.SetTextColour(m_attr
->GetTextColour());
1067 if ( m_attr
->HasBackgroundColour() )
1068 info
.SetBackgroundColour(m_attr
->GetBackgroundColour());
1069 if ( m_attr
->HasFont() )
1070 info
.SetFont(m_attr
->GetFont());
1074 //-----------------------------------------------------------------------------
1076 //-----------------------------------------------------------------------------
1078 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData
,wxObject
);
1080 wxListHeaderData::wxListHeaderData()
1091 wxListHeaderData::wxListHeaderData( const wxListItem
&item
)
1099 void wxListHeaderData::SetItem( const wxListItem
&item
)
1101 m_mask
= item
.m_mask
;
1102 m_text
= item
.m_text
;
1103 m_image
= item
.m_image
;
1104 m_format
= item
.m_format
;
1106 SetWidth(item
.m_width
);
1109 void wxListHeaderData::SetPosition( int x
, int y
)
1115 void wxListHeaderData::SetHeight( int h
)
1120 void wxListHeaderData::SetWidth( int w
)
1124 m_width
= WIDTH_COL_DEFAULT
;
1125 if (m_width
< WIDTH_COL_MIN
)
1126 m_width
= WIDTH_COL_MIN
;
1129 void wxListHeaderData::SetFormat( int format
)
1134 bool wxListHeaderData::HasImage() const
1136 return (m_image
!= 0);
1139 bool wxListHeaderData::IsHit( int x
, int y
) const
1141 return ((x
>= m_xpos
) && (x
<= m_xpos
+m_width
) && (y
>= m_ypos
) && (y
<= m_ypos
+m_height
));
1144 void wxListHeaderData::GetItem( wxListItem
&item
)
1146 item
.m_mask
= m_mask
;
1147 item
.m_text
= m_text
;
1148 item
.m_image
= m_image
;
1149 item
.m_format
= m_format
;
1150 item
.m_width
= m_width
;
1153 int wxListHeaderData::GetImage() const
1158 int wxListHeaderData::GetWidth() const
1163 int wxListHeaderData::GetFormat() const
1168 //-----------------------------------------------------------------------------
1170 //-----------------------------------------------------------------------------
1172 inline int wxListLineData::GetMode() const
1174 return m_owner
->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE
;
1177 inline bool wxListLineData::InReportView() const
1179 return m_owner
->HasFlag(wxLC_REPORT
);
1182 inline bool wxListLineData::IsVirtual() const
1184 return m_owner
->IsVirtual();
1187 wxListLineData::wxListLineData( wxListMainWindow
*owner
, size_t line
)
1190 m_items
.DeleteContents( TRUE
);
1194 if ( InReportView() )
1200 m_gi
= new GeometryInfo
;
1203 m_highlighted
= FALSE
;
1205 InitItems( GetMode() == wxLC_REPORT
? m_owner
->GetColumnCount() : 1 );
1208 wxRect
wxListLineData::GetRect() const
1210 if ( !InReportView() )
1211 return m_gi
->m_rectAll
;
1214 rect
.x
= HEADER_OFFSET_X
;
1215 rect
.y
= m_owner
->GetLineY(m_lineIndex
);
1216 rect
.width
= m_owner
->GetHeaderWidth();
1217 rect
.height
= m_owner
->GetLineHeight();
1222 wxRect
wxListLineData::GetLabelRect() const
1224 if ( !InReportView() )
1225 return m_gi
->m_rectLabel
;
1228 rect
.x
= HEADER_OFFSET_X
;
1229 rect
.y
= m_owner
->GetLineY(m_lineIndex
);
1230 rect
.width
= m_owner
->GetColumnWidth(0);
1231 rect
.height
= m_owner
->GetLineHeight();
1236 wxRect
wxListLineData::GetIconRect() const
1238 if ( !InReportView() )
1239 return m_gi
->m_rectIcon
;
1243 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1244 wxCHECK_MSG( node
, rect
, _T("no subitems at all??") );
1246 wxListItemData
*item
= node
->GetData();
1247 wxASSERT_MSG( item
->HasImage(), _T("GetIconRect() called but no image") );
1249 rect
.x
= HEADER_OFFSET_X
;
1250 rect
.y
= m_owner
->GetLineY(m_lineIndex
);
1251 m_owner
->GetImageSize(item
->GetImage(), rect
.width
, rect
.height
);
1256 wxRect
wxListLineData::GetHighlightRect() const
1258 return InReportView() ? GetRect() : m_gi
->m_rectHighlight
;
1261 void wxListLineData::CalculateSize( wxDC
*dc
, int spacing
)
1263 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1264 wxCHECK_RET( node
, _T("no subitems at all??") );
1266 wxListItemData
*item
= node
->GetData();
1268 switch ( GetMode() )
1271 case wxLC_SMALL_ICON
:
1273 m_gi
->m_rectAll
.width
= spacing
;
1275 wxString s
= item
->GetText();
1281 m_gi
->m_rectLabel
.width
=
1282 m_gi
->m_rectLabel
.height
= 0;
1286 dc
->GetTextExtent( s
, &lw
, &lh
);
1287 if (lh
< SCROLL_UNIT_Y
)
1292 m_gi
->m_rectAll
.height
= spacing
+ lh
;
1294 m_gi
->m_rectAll
.width
= lw
;
1296 m_gi
->m_rectLabel
.width
= lw
;
1297 m_gi
->m_rectLabel
.height
= lh
;
1300 if (item
->HasImage())
1303 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1304 m_gi
->m_rectIcon
.width
= w
+ 8;
1305 m_gi
->m_rectIcon
.height
= h
+ 8;
1307 if ( m_gi
->m_rectIcon
.width
> m_gi
->m_rectAll
.width
)
1308 m_gi
->m_rectAll
.width
= m_gi
->m_rectIcon
.width
;
1309 if ( m_gi
->m_rectIcon
.height
+ lh
> m_gi
->m_rectAll
.height
- 4 )
1310 m_gi
->m_rectAll
.height
= m_gi
->m_rectIcon
.height
+ lh
+ 4;
1313 if ( item
->HasText() )
1315 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectLabel
.width
;
1316 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectLabel
.height
;
1318 else // no text, highlight the icon
1320 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectIcon
.width
;
1321 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectIcon
.height
;
1328 wxString s
= item
->GetTextForMeasuring();
1331 dc
->GetTextExtent( s
, &lw
, &lh
);
1332 if (lh
< SCROLL_UNIT_Y
)
1337 m_gi
->m_rectLabel
.width
= lw
;
1338 m_gi
->m_rectLabel
.height
= lh
;
1340 m_gi
->m_rectAll
.width
= lw
;
1341 m_gi
->m_rectAll
.height
= lh
;
1343 if (item
->HasImage())
1346 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1347 m_gi
->m_rectIcon
.width
= w
;
1348 m_gi
->m_rectIcon
.height
= h
;
1350 m_gi
->m_rectAll
.width
+= 4 + w
;
1351 if (h
> m_gi
->m_rectAll
.height
)
1352 m_gi
->m_rectAll
.height
= h
;
1355 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectAll
.width
;
1356 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectAll
.height
;
1361 wxFAIL_MSG( _T("unexpected call to SetSize") );
1365 wxFAIL_MSG( _T("unknown mode") );
1369 void wxListLineData::SetPosition( int x
, int y
,
1373 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1374 wxCHECK_RET( node
, _T("no subitems at all??") );
1376 wxListItemData
*item
= node
->GetData();
1378 switch ( GetMode() )
1381 case wxLC_SMALL_ICON
:
1382 m_gi
->m_rectAll
.x
= x
;
1383 m_gi
->m_rectAll
.y
= y
;
1385 if ( item
->HasImage() )
1387 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 4
1388 + (spacing
- m_gi
->m_rectIcon
.width
)/2;
1389 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 4;
1392 if ( item
->HasText() )
1394 if (m_gi
->m_rectAll
.width
> spacing
)
1395 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1397 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2 + (spacing
/2) - (m_gi
->m_rectLabel
.width
/2);
1398 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ m_gi
->m_rectAll
.height
+ 2 - m_gi
->m_rectLabel
.height
;
1399 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectLabel
.x
- 2;
1400 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectLabel
.y
- 2;
1402 else // no text, highlight the icon
1404 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectIcon
.x
- 4;
1405 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectIcon
.y
- 4;
1410 m_gi
->m_rectAll
.x
= x
;
1411 m_gi
->m_rectAll
.y
= y
;
1413 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectAll
.x
;
1414 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectAll
.y
;
1415 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ 2;
1417 if (item
->HasImage())
1419 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 2;
1420 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 2;
1421 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 6 + m_gi
->m_rectIcon
.width
;
1425 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1430 wxFAIL_MSG( _T("unexpected call to SetPosition") );
1434 wxFAIL_MSG( _T("unknown mode") );
1438 long wxListLineData::IsHit( int x
, int y
)
1440 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1441 wxCHECK_MSG( node
, 0, _T("no subitems at all??") );
1443 wxListItemData
*item
= node
->GetData();
1444 if ( item
->HasImage() && GetIconRect().Inside(x
, y
) )
1445 return wxLIST_HITTEST_ONITEMICON
;
1447 if ( item
->HasText() )
1449 wxRect rect
= InReportView() ? GetRect() : GetLabelRect();
1450 if ( rect
.Inside(x
, y
) )
1451 return wxLIST_HITTEST_ONITEMLABEL
;
1457 void wxListLineData::InitItems( int num
)
1459 for (int i
= 0; i
< num
; i
++)
1460 m_items
.Append( new wxListItemData(m_owner
) );
1463 void wxListLineData::SetItem( int index
, const wxListItem
&info
)
1465 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1466 wxCHECK_RET( node
, _T("invalid column index in SetItem") );
1468 wxListItemData
*item
= node
->GetData();
1469 item
->SetItem( info
);
1472 void wxListLineData::GetItem( int index
, wxListItem
&info
)
1474 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1477 wxListItemData
*item
= node
->GetData();
1478 item
->GetItem( info
);
1482 wxString
wxListLineData::GetText(int index
) const
1486 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1489 wxListItemData
*item
= node
->GetData();
1490 s
= item
->GetText();
1496 void wxListLineData::SetText( int index
, const wxString s
)
1498 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1501 wxListItemData
*item
= node
->GetData();
1506 void wxListLineData::SetImage( int index
, int image
)
1508 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1509 wxCHECK_RET( node
, _T("invalid column index in SetImage()") );
1511 wxListItemData
*item
= node
->GetData();
1512 item
->SetImage(image
);
1515 int wxListLineData::GetImage( int index
) const
1517 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1518 wxCHECK_MSG( node
, -1, _T("invalid column index in GetImage()") );
1520 wxListItemData
*item
= node
->GetData();
1521 return item
->GetImage();
1524 void wxListLineData::SetAttributes(wxDC
*dc
,
1525 const wxListItemAttr
*attr
,
1526 const wxColour
& colText
,
1530 // don't use foregroud colour for drawing highlighted items - this might
1531 // make them completely invisible (and there is no way to do bit
1532 // arithmetics on wxColour, unfortunately)
1533 if ( !highlight
&& attr
&& attr
->HasTextColour() )
1535 dc
->SetTextForeground(attr
->GetTextColour());
1539 dc
->SetTextForeground(colText
);
1542 if ( attr
&& attr
->HasFont() )
1544 dc
->SetFont(attr
->GetFont());
1552 void wxListLineData::Draw( wxDC
*dc
, int y
, int height
, bool highlighted
)
1554 wxRect rect
= GetRect();
1555 m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
1557 if ( !m_owner
->IsExposed( rect
) )
1560 wxWindow
*listctrl
= m_owner
->GetParent();
1562 // use our own flag if we maintain it
1563 if ( !m_owner
->IsVirtual() )
1564 highlighted
= m_highlighted
;
1566 // default foreground colour
1570 colText
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT
);
1574 colText
= listctrl
->GetForegroundColour();
1578 wxFont font
= listctrl
->GetFont();
1580 // VZ: currently we set the colours/fonts only once, but like this (i.e.
1581 // using SetAttributes() inside the loop), it will be trivial to
1582 // customize the subitems (in report mode) too.
1583 wxListItemData
*item
= m_items
.GetFirst()->GetData();
1584 wxListItemAttr
*attr
= item
->GetAttributes();
1585 SetAttributes(dc
, attr
, colText
, font
, highlighted
);
1587 bool hasBgCol
= attr
&& attr
->HasBackgroundColour();
1588 if ( highlighted
|| hasBgCol
)
1592 dc
->SetBrush( *m_owner
->m_highlightBrush
);
1597 dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
));
1599 dc
->SetBrush( * wxWHITE_BRUSH
);
1602 dc
->SetPen( * wxTRANSPARENT_PEN
);
1603 dc
->DrawRectangle( GetHighlightRect() );
1606 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1608 if ( GetMode() == wxLC_REPORT
)
1611 int x
= HEADER_OFFSET_X
;
1613 y
+= (LINE_SPACING
+ EXTRA_HEIGHT
) / 2;
1617 wxListItemData
*item
= node
->GetData();
1621 if ( item
->HasImage() )
1624 m_owner
->DrawImage( item
->GetImage(), dc
, x
, y
);
1625 m_owner
->GetImageSize( item
->GetImage(), ix
, iy
);
1626 x
+= ix
+ 5; // FIXME: what is "5"?
1629 int width
= m_owner
->GetColumnWidth(col
++);
1631 dc
->SetClippingRegion(x
, y
, width
, height
);
1633 if ( item
->HasText() )
1635 dc
->DrawText( item
->GetText(), x
, y
+ 1 );
1638 dc
->DestroyClippingRegion();
1642 node
= node
->GetNext();
1649 wxListItemData
*item
= node
->GetData();
1650 if (item
->HasImage())
1652 wxRect rectIcon
= GetIconRect();
1653 m_owner
->DrawImage( item
->GetImage(), dc
,
1654 rectIcon
.x
, rectIcon
.y
);
1657 if (item
->HasText())
1659 wxRect rectLabel
= GetLabelRect();
1660 dc
->DrawText( item
->GetText(), rectLabel
.x
, rectLabel
.y
);
1666 bool wxListLineData::Highlight( bool on
)
1668 wxCHECK_MSG( !m_owner
->IsVirtual(), FALSE
, _T("unexpected call to Highlight") );
1670 if ( on
== m_highlighted
)
1678 void wxListLineData::ReverseHighlight( void )
1680 Highlight(!IsHighlighted());
1683 //-----------------------------------------------------------------------------
1684 // wxListHeaderWindow
1685 //-----------------------------------------------------------------------------
1687 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
);
1689 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
)
1690 EVT_PAINT (wxListHeaderWindow::OnPaint
)
1691 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse
)
1692 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus
)
1695 wxListHeaderWindow::wxListHeaderWindow( void )
1697 m_owner
= (wxListMainWindow
*) NULL
;
1698 m_currentCursor
= (wxCursor
*) NULL
;
1699 m_resizeCursor
= (wxCursor
*) NULL
;
1700 m_isDragging
= FALSE
;
1703 wxListHeaderWindow::wxListHeaderWindow( wxWindow
*win
, wxWindowID id
, wxListMainWindow
*owner
,
1704 const wxPoint
&pos
, const wxSize
&size
,
1705 long style
, const wxString
&name
) :
1706 wxWindow( win
, id
, pos
, size
, style
, name
)
1709 // m_currentCursor = wxSTANDARD_CURSOR;
1710 m_currentCursor
= (wxCursor
*) NULL
;
1711 m_resizeCursor
= new wxCursor( wxCURSOR_SIZEWE
);
1712 m_isDragging
= FALSE
;
1715 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
) );
1718 wxListHeaderWindow::~wxListHeaderWindow( void )
1720 delete m_resizeCursor
;
1723 void wxListHeaderWindow::DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
)
1726 GtkStateType state
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
1727 : GTK_STATE_INSENSITIVE
;
1729 x
= dc
->XLOG2DEV( x
);
1731 gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
,
1732 state
, GTK_SHADOW_OUT
,
1733 (GdkRectangle
*) NULL
, m_wxwindow
, "button",
1734 x
-1, y
-1, w
+2, h
+2);
1735 #elif defined( __WXMAC__ )
1736 const int m_corner
= 1;
1738 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1740 dc
->SetPen( wxPen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
) , 1 , wxSOLID
) );
1741 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1742 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1744 wxPen
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID
);
1747 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1748 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1750 dc
->SetPen( *wxWHITE_PEN
);
1751 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1752 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1753 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1754 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1756 const int m_corner
= 1;
1758 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1760 dc
->SetPen( *wxBLACK_PEN
);
1761 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1762 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1764 wxPen
pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
), 1, wxSOLID
);
1767 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1768 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1770 dc
->SetPen( *wxWHITE_PEN
);
1771 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1772 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1773 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1774 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1778 // shift the DC origin to match the position of the main window horz
1779 // scrollbar: this allows us to always use logical coords
1780 void wxListHeaderWindow::AdjustDC(wxDC
& dc
)
1783 m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL
);
1786 m_owner
->GetViewStart( &x
, NULL
);
1788 // account for the horz scrollbar offset
1789 dc
.SetDeviceOrigin( -x
* xpix
, 0 );
1792 void wxListHeaderWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
1795 wxClientDC
dc( this );
1797 wxPaintDC
dc( this );
1805 dc
.SetFont( GetFont() );
1807 // width and height of the entire header window
1809 GetClientSize( &w
, &h
);
1810 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1812 dc
.SetBackgroundMode(wxTRANSPARENT
);
1814 // do *not* use the listctrl colour for headers - one day we will have a
1815 // function to set it separately
1816 //dc.SetTextForeground( *wxBLACK );
1817 dc
.SetTextForeground(wxSystemSettings::
1818 GetSystemColour( wxSYS_COLOUR_WINDOWTEXT
));
1820 int x
= HEADER_OFFSET_X
;
1822 int numColumns
= m_owner
->GetColumnCount();
1824 for (int i
= 0; i
< numColumns
; i
++)
1826 m_owner
->GetColumn( i
, item
);
1827 int wCol
= item
.m_width
;
1828 int cw
= wCol
- 2; // the width of the rect to draw
1830 int xEnd
= x
+ wCol
;
1832 dc
.SetPen( *wxWHITE_PEN
);
1834 DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 );
1835 dc
.SetClippingRegion( x
, HEADER_OFFSET_Y
, cw
-5, h
-4 );
1836 dc
.DrawText( item
.GetText(), x
+ EXTRA_WIDTH
, HEADER_OFFSET_Y
+ EXTRA_HEIGHT
);
1837 dc
.DestroyClippingRegion();
1846 void wxListHeaderWindow::DrawCurrent()
1848 int x1
= m_currentX
;
1850 ClientToScreen( &x1
, &y1
);
1852 int x2
= m_currentX
-1;
1854 m_owner
->GetClientSize( NULL
, &y2
);
1855 m_owner
->ClientToScreen( &x2
, &y2
);
1858 dc
.SetLogicalFunction( wxINVERT
);
1859 dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID
) );
1860 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1864 dc
.DrawLine( x1
, y1
, x2
, y2
);
1866 dc
.SetLogicalFunction( wxCOPY
);
1868 dc
.SetPen( wxNullPen
);
1869 dc
.SetBrush( wxNullBrush
);
1872 void wxListHeaderWindow::OnMouse( wxMouseEvent
&event
)
1874 // we want to work with logical coords
1876 m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
);
1877 int y
= event
.GetY();
1881 // we don't draw the line beyond our window, but we allow dragging it
1884 GetClientSize( &w
, NULL
);
1885 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1888 // erase the line if it was drawn
1889 if ( m_currentX
< w
)
1892 if (event
.ButtonUp())
1895 m_isDragging
= FALSE
;
1897 m_owner
->SetColumnWidth( m_column
, m_currentX
- m_minX
);
1904 m_currentX
= m_minX
+ 7;
1906 // draw in the new location
1907 if ( m_currentX
< w
)
1911 else // not dragging
1914 bool hit_border
= FALSE
;
1916 // end of the current column
1919 // find the column where this event occured
1920 int countCol
= m_owner
->GetColumnCount();
1921 for (int col
= 0; col
< countCol
; col
++)
1923 xpos
+= m_owner
->GetColumnWidth( col
);
1926 if ( (abs(x
-xpos
) < 3) && (y
< 22) )
1928 // near the column border
1935 // inside the column
1942 if (event
.LeftDown())
1946 m_isDragging
= TRUE
;
1953 wxWindow
*parent
= GetParent();
1954 wxListEvent
le( wxEVT_COMMAND_LIST_COL_CLICK
, parent
->GetId() );
1955 le
.SetEventObject( parent
);
1956 le
.m_col
= m_column
;
1957 parent
->GetEventHandler()->ProcessEvent( le
);
1960 else if (event
.Moving())
1965 setCursor
= m_currentCursor
== wxSTANDARD_CURSOR
;
1966 m_currentCursor
= m_resizeCursor
;
1970 setCursor
= m_currentCursor
!= wxSTANDARD_CURSOR
;
1971 m_currentCursor
= wxSTANDARD_CURSOR
;
1975 SetCursor(*m_currentCursor
);
1980 void wxListHeaderWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
1982 m_owner
->SetFocus();
1985 //-----------------------------------------------------------------------------
1986 // wxListRenameTimer (internal)
1987 //-----------------------------------------------------------------------------
1989 wxListRenameTimer::wxListRenameTimer( wxListMainWindow
*owner
)
1994 void wxListRenameTimer::Notify()
1996 m_owner
->OnRenameTimer();
1999 //-----------------------------------------------------------------------------
2000 // wxListTextCtrl (internal)
2001 //-----------------------------------------------------------------------------
2003 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl
,wxTextCtrl
);
2005 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
)
2006 EVT_CHAR (wxListTextCtrl::OnChar
)
2007 EVT_KEY_UP (wxListTextCtrl::OnKeyUp
)
2008 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus
)
2011 wxListTextCtrl::wxListTextCtrl( wxWindow
*parent
,
2012 const wxWindowID id
,
2015 wxListMainWindow
*owner
,
2016 const wxString
&value
,
2020 const wxValidator
& validator
,
2021 const wxString
&name
)
2022 : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name
)
2027 (*m_accept
) = FALSE
;
2029 m_startValue
= value
;
2032 void wxListTextCtrl::OnChar( wxKeyEvent
&event
)
2034 if (event
.m_keyCode
== WXK_RETURN
)
2037 (*m_res
) = GetValue();
2039 if (!wxPendingDelete
.Member(this))
2040 wxPendingDelete
.Append(this);
2042 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2043 m_owner
->OnRenameAccept();
2047 if (event
.m_keyCode
== WXK_ESCAPE
)
2049 (*m_accept
) = FALSE
;
2052 if (!wxPendingDelete
.Member(this))
2053 wxPendingDelete
.Append(this);
2061 void wxListTextCtrl::OnKeyUp( wxKeyEvent
&event
)
2063 // auto-grow the textctrl:
2064 wxSize parentSize
= m_owner
->GetSize();
2065 wxPoint myPos
= GetPosition();
2066 wxSize mySize
= GetSize();
2068 GetTextExtent(GetValue() + _T("MM"), &sx
, &sy
); // FIXME: MM??
2069 if (myPos
.x
+ sx
> parentSize
.x
)
2070 sx
= parentSize
.x
- myPos
.x
;
2078 void wxListTextCtrl::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
2080 if (!wxPendingDelete
.Member(this))
2081 wxPendingDelete
.Append(this);
2083 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2084 m_owner
->OnRenameAccept();
2087 //-----------------------------------------------------------------------------
2089 //-----------------------------------------------------------------------------
2091 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
);
2093 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
)
2094 EVT_PAINT (wxListMainWindow::OnPaint
)
2095 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse
)
2096 EVT_CHAR (wxListMainWindow::OnChar
)
2097 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown
)
2098 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus
)
2099 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus
)
2100 EVT_SCROLLWIN (wxListMainWindow::OnScroll
)
2103 void wxListMainWindow::Init()
2105 m_columns
.DeleteContents( TRUE
);
2109 m_lineTo
= (size_t)-1;
2115 m_small_image_list
= (wxImageList
*) NULL
;
2116 m_normal_image_list
= (wxImageList
*) NULL
;
2118 m_small_spacing
= 30;
2119 m_normal_spacing
= 40;
2123 m_isCreated
= FALSE
;
2125 m_lastOnSame
= FALSE
;
2126 m_renameTimer
= new wxListRenameTimer( this );
2127 m_renameAccept
= FALSE
;
2132 m_lineBeforeLastClicked
= (size_t)-1;
2135 void wxListMainWindow::InitScrolling()
2137 if ( HasFlag(wxLC_REPORT
) )
2139 m_xScroll
= SCROLL_UNIT_X
;
2140 m_yScroll
= SCROLL_UNIT_Y
;
2144 m_xScroll
= SCROLL_UNIT_Y
;
2149 wxListMainWindow::wxListMainWindow()
2153 m_highlightBrush
= (wxBrush
*) NULL
;
2159 wxListMainWindow::wxListMainWindow( wxWindow
*parent
,
2164 const wxString
&name
)
2165 : wxScrolledWindow( parent
, id
, pos
, size
,
2166 style
| wxHSCROLL
| wxVSCROLL
, name
)
2170 m_highlightBrush
= new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
), wxSOLID
);
2175 SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 );
2177 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX
) );
2180 wxListMainWindow::~wxListMainWindow()
2184 delete m_highlightBrush
;
2186 delete m_renameTimer
;
2189 void wxListMainWindow::CacheLineData(size_t line
)
2191 wxListCtrl
*listctrl
= GetListCtrl();
2193 wxListLineData
*ld
= GetDummyLine();
2195 size_t countCol
= GetColumnCount();
2196 for ( size_t col
= 0; col
< countCol
; col
++ )
2198 ld
->SetText(col
, listctrl
->OnGetItemText(line
, col
));
2201 ld
->SetImage(0, listctrl
->OnGetItemImage(line
));
2202 ld
->SetLineIndex(line
);
2205 wxListLineData
*wxListMainWindow::GetDummyLine() const
2207 wxASSERT_MSG( !IsEmpty(), _T("invalid line index") );
2209 if ( m_lines
.IsEmpty() )
2211 // normal controls are supposed to have something in m_lines
2212 // already if it's not empty
2213 wxASSERT_MSG( IsVirtual(), _T("logic error") );
2215 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2216 wxListLineData
*line
= new wxListLineData( self
, 0 );
2217 self
->m_lines
.Add(line
);
2220 m_lines
[0].SetLineIndex(0);
2225 wxCoord
wxListMainWindow::GetLineHeight() const
2227 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2229 // we cache the line height as calling GetTextExtent() is slow
2230 if ( !m_lineHeight
)
2232 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2234 wxClientDC
dc( self
);
2235 dc
.SetFont( GetFont() );
2238 dc
.GetTextExtent(_T("H"), NULL
, &y
);
2240 if ( y
< SCROLL_UNIT_Y
)
2244 self
->m_lineHeight
= y
+ LINE_SPACING
;
2247 return m_lineHeight
;
2250 wxCoord
wxListMainWindow::GetLineY(size_t line
) const
2252 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2254 return LINE_SPACING
+ line
*GetLineHeight();
2257 bool wxListMainWindow::IsHighlighted(size_t line
) const
2261 return m_selStore
.IsSelected(line
);
2265 wxListLineData
*ld
= GetLine(line
);
2266 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2268 return ld
->IsHighlighted();
2272 void wxListMainWindow::HighlightLines( size_t lineFrom
, size_t lineTo
, bool highlight
)
2276 m_selStore
.SelectRange(lineFrom
, lineTo
, highlight
);
2277 RefreshLines(lineFrom
, lineTo
);
2281 // do it the dumb way
2282 bool needsRefresh
= FALSE
;
2283 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2285 if ( HighlightLine(line
, highlight
) )
2286 needsRefresh
= TRUE
;
2290 RefreshLines(lineFrom
, lineTo
);
2294 bool wxListMainWindow::HighlightLine( size_t line
, bool highlight
)
2300 changed
= m_selStore
.SelectItem(line
, highlight
);
2304 wxListLineData
*ld
= GetLine(line
);
2305 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2307 changed
= ld
->Highlight(highlight
);
2312 SendNotify( line
, highlight
? wxEVT_COMMAND_LIST_ITEM_SELECTED
2313 : wxEVT_COMMAND_LIST_ITEM_DESELECTED
);
2319 void wxListMainWindow::RefreshLine( size_t line
)
2321 wxRect rect
= GetLine(line
)->GetRect();
2323 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2324 RefreshRect( rect
);
2327 void wxListMainWindow::RefreshLines( size_t lineFrom
, size_t lineTo
)
2329 // we suppose that they are ordered by caller
2330 wxASSERT_MSG( lineFrom
<= lineTo
, _T("indices in disorder") );
2332 if ( HasFlag(wxLC_REPORT
) )
2334 size_t visibleFrom
, visibleTo
;
2335 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2337 if ( lineFrom
< visibleFrom
)
2338 lineFrom
= visibleFrom
;
2339 if ( lineTo
> visibleTo
)
2344 rect
.y
= GetLineY(lineFrom
);
2345 rect
.width
= GetClientSize().x
;
2346 rect
.height
= GetLineY(lineTo
) - rect
.y
;
2348 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2349 RefreshRect( rect
);
2353 // TODO: this should be optimized...
2354 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2361 void wxListMainWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
2363 // Note: a wxPaintDC must be constructed even if no drawing is
2364 // done (a Windows requirement).
2365 wxPaintDC
dc( this );
2369 // empty control. nothing to draw
2376 CalcScrolledPosition( 0, 0, &dev_x
, &dev_y
);
2380 dc
.SetFont( GetFont() );
2382 if ( HasFlag(wxLC_REPORT
) )
2384 int lineHeight
= GetLineHeight();
2386 size_t visibleFrom
, visibleTo
;
2387 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2388 for ( size_t line
= visibleFrom
; line
<= visibleTo
; line
++ )
2390 GetLine(line
)->Draw( &dc
,
2393 IsHighlighted(line
) );
2396 if ( HasFlag(wxLC_HRULES
) )
2398 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2399 wxSize clientSize
= GetClientSize();
2401 for ( size_t i
= visibleFrom
; i
<= visibleTo
; i
++ )
2404 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2405 dc
.DrawLine(0 - dev_x
, i
*lineHeight
,
2406 clientSize
.x
- dev_x
, i
*lineHeight
);
2409 // Draw last horizontal rule
2410 if ( visibleTo
> visibleFrom
)
2413 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2414 dc
.DrawLine(0 - dev_x
, m_lineTo
*lineHeight
,
2415 clientSize
.x
- dev_x
, m_lineTo
*lineHeight
);
2419 // Draw vertical rules if required
2420 if ( HasFlag(wxLC_VRULES
) && !IsEmpty() )
2422 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2425 wxRect firstItemRect
;
2426 wxRect lastItemRect
;
2427 GetItemRect(0, firstItemRect
);
2428 GetItemRect(GetItemCount() - 1, lastItemRect
);
2429 int x
= firstItemRect
.GetX();
2431 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
2432 for (col
= 0; col
< GetColumnCount(); col
++)
2434 int colWidth
= GetColumnWidth(col
);
2436 dc
.DrawLine(x
- dev_x
, firstItemRect
.GetY() - 1 - dev_y
,
2437 x
- dev_x
, lastItemRect
.GetBottom() + 1 - dev_y
);
2443 size_t count
= GetItemCount();
2444 for ( size_t i
= 0; i
< count
; i
++ )
2446 GetLine(i
)->Draw( &dc
);
2450 if ( HasCurrent() && m_hasFocus
)
2456 // just offset the rect of the first line to position it correctly
2457 wxListLineData
*line
= GetDummyLine();
2458 rect
= line
->GetHighlightRect();
2459 rect
.y
= GetLineY(m_current
);
2463 rect
= GetLine(m_current
)->GetHighlightRect();
2466 // no rect outline, we already have the background color
2468 dc
.SetPen( *wxBLACK_PEN
);
2469 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2470 dc
.DrawRectangle( rect
);
2477 void wxListMainWindow::HighlightAll( bool on
)
2479 if ( IsSingleSel() )
2481 wxASSERT_MSG( !on
, _T("can't do this in a single sel control") );
2483 // we just have one item to turn off
2484 if ( HasCurrent() && IsHighlighted(m_current
) )
2486 HighlightLine(m_current
, FALSE
);
2487 RefreshLine(m_current
);
2492 HighlightLines(0, GetItemCount() - 1, on
);
2496 void wxListMainWindow::SendNotify( size_t line
,
2497 wxEventType command
,
2500 wxListEvent
le( command
, GetParent()->GetId() );
2501 le
.SetEventObject( GetParent() );
2502 le
.m_itemIndex
= line
;
2504 // set only for events which have position
2505 if ( point
!= wxDefaultPosition
)
2506 le
.m_pointDrag
= point
;
2508 GetLine(line
)->GetItem( 0, le
.m_item
);
2509 GetParent()->GetEventHandler()->ProcessEvent( le
);
2512 void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line
) )
2514 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
2517 void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line
) )
2519 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
2522 void wxListMainWindow::EditLabel( long item
)
2524 wxCHECK_RET( (item
>= 0) && ((size_t)item
< GetItemCount()),
2525 wxT("wrong index in wxListCtrl::EditLabel()") );
2527 m_currentEdit
= (size_t)item
;
2529 wxListEvent
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() );
2530 le
.SetEventObject( GetParent() );
2531 le
.m_itemIndex
= item
;
2532 wxListLineData
*data
= GetLine(m_currentEdit
);
2533 wxCHECK_RET( data
, _T("invalid index in EditLabel()") );
2534 data
->GetItem( 0, le
.m_item
);
2535 GetParent()->GetEventHandler()->ProcessEvent( le
);
2537 if (!le
.IsAllowed())
2540 // We have to call this here because the label in question might just have
2541 // been added and no screen update taken place.
2545 wxClientDC
dc(this);
2548 wxString s
= data
->GetText(0);
2549 wxRect rectLabel
= data
->GetLabelRect();
2551 rectLabel
.x
= dc
.LogicalToDeviceX( rectLabel
.x
);
2552 rectLabel
.y
= dc
.LogicalToDeviceY( rectLabel
.y
);
2554 wxListTextCtrl
*text
= new wxListTextCtrl
2561 wxPoint(rectLabel
.x
-4,rectLabel
.y
-4),
2562 wxSize(rectLabel
.width
+11,rectLabel
.height
+8)
2567 void wxListMainWindow::OnRenameTimer()
2569 wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") );
2571 EditLabel( m_current
);
2574 void wxListMainWindow::OnRenameAccept()
2576 wxListEvent
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() );
2577 le
.SetEventObject( GetParent() );
2578 le
.m_itemIndex
= m_currentEdit
;
2580 wxListLineData
*data
= GetLine(m_currentEdit
);
2581 wxCHECK_RET( data
, _T("invalid index in OnRenameAccept()") );
2583 data
->GetItem( 0, le
.m_item
);
2584 le
.m_item
.m_text
= m_renameRes
;
2585 GetParent()->GetEventHandler()->ProcessEvent( le
);
2587 if (!le
.IsAllowed()) return;
2590 info
.m_mask
= wxLIST_MASK_TEXT
;
2591 info
.m_itemId
= le
.m_itemIndex
;
2592 info
.m_text
= m_renameRes
;
2593 info
.SetTextColour(le
.m_item
.GetTextColour());
2597 void wxListMainWindow::OnMouse( wxMouseEvent
&event
)
2599 event
.SetEventObject( GetParent() );
2600 if ( GetParent()->GetEventHandler()->ProcessEvent( event
) )
2603 if ( !HasCurrent() || IsEmpty() )
2609 if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() ||
2610 event
.ButtonDClick()) )
2613 int x
= event
.GetX();
2614 int y
= event
.GetY();
2615 CalcUnscrolledPosition( x
, y
, &x
, &y
);
2617 /* Did we actually hit an item ? */
2620 size_t count
= GetItemCount(),
2623 if ( HasFlag(wxLC_REPORT
) )
2625 wxCoord lineHeight
= GetLineHeight();
2627 current
= y
/ lineHeight
;
2628 hitResult
= GetDummyLine()->IsHit( x
, y
% lineHeight
);
2632 // TODO: optimize it too! this is less simple than for report view but
2633 // enumerating all items is still not a way to do it!!
2634 for ( current
= 0; current
< count
; current
++ )
2636 wxListLineData
*line
= (wxListLineData
*) NULL
;
2637 line
= GetLine(current
);
2638 hitResult
= line
->IsHit( x
, y
);
2644 if (event
.Dragging())
2646 if (m_dragCount
== 0)
2647 m_dragStart
= wxPoint(x
,y
);
2651 if (m_dragCount
!= 3)
2654 int command
= event
.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2655 : wxEVT_COMMAND_LIST_BEGIN_DRAG
;
2657 wxListEvent
le( command
, GetParent()->GetId() );
2658 le
.SetEventObject( GetParent() );
2659 le
.m_pointDrag
= m_dragStart
;
2660 GetParent()->GetEventHandler()->ProcessEvent( le
);
2671 // outside of any item
2675 bool forceClick
= FALSE
;
2676 if (event
.ButtonDClick())
2678 m_renameTimer
->Stop();
2679 m_lastOnSame
= FALSE
;
2681 if ( current
== m_lineBeforeLastClicked
)
2683 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
);
2689 // the first click was on another item, so don't interpret this as
2690 // a double click, but as a simple click instead
2695 if (event
.LeftUp() && m_lastOnSame
)
2697 if ((current
== m_current
) &&
2698 (hitResult
== wxLIST_HITTEST_ONITEMLABEL
) &&
2699 HasFlag(wxLC_EDIT_LABELS
) )
2701 m_renameTimer
->Start( 100, TRUE
);
2703 m_lastOnSame
= FALSE
;
2705 else if (event
.RightDown())
2707 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
,
2708 event
.GetPosition() );
2710 else if (event
.MiddleDown())
2712 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
);
2714 else if ( event
.LeftDown() || forceClick
)
2716 m_lineBeforeLastClicked
= m_lineLastClicked
;
2717 m_lineLastClicked
= current
;
2719 size_t oldCurrent
= m_current
;
2721 if ( IsSingleSel() || !(event
.ControlDown() || event
.ShiftDown()) )
2723 HighlightAll( FALSE
);
2724 m_current
= current
;
2726 ReverseHighlight(m_current
);
2728 else // multi sel & either ctrl or shift is down
2730 if (event
.ControlDown())
2732 m_current
= current
;
2734 ReverseHighlight(m_current
);
2736 else if (event
.ShiftDown())
2738 m_current
= current
;
2740 size_t lineFrom
= oldCurrent
,
2743 if ( lineTo
< lineFrom
)
2746 lineFrom
= m_current
;
2749 HighlightLines(lineFrom
, lineTo
);
2751 else // !ctrl, !shift
2753 // test in the enclosing if should make it impossible
2754 wxFAIL_MSG( _T("how did we get here?") );
2758 if (m_current
!= oldCurrent
)
2760 RefreshLine( oldCurrent
);
2761 OnUnfocusLine( oldCurrent
);
2762 OnFocusLine( m_current
);
2765 // forceClick is only set if the previous click was on another item
2766 m_lastOnSame
= !forceClick
&& (m_current
== oldCurrent
);
2770 void wxListMainWindow::MoveToFocus()
2772 if ( !HasCurrent() )
2779 // just offset the rect of the first line to position it correctly
2780 wxListLineData
*line
= GetDummyLine();
2781 rect
= line
->GetRect();
2782 rect
.y
= GetLineY(m_current
);
2786 rect
= GetLine(m_current
)->GetRect();
2789 int client_w
, client_h
;
2790 GetClientSize( &client_w
, &client_h
);
2792 int view_x
= m_xScroll
*GetScrollPos( wxHORIZONTAL
);
2793 int view_y
= m_yScroll
*GetScrollPos( wxVERTICAL
);
2795 if ( HasFlag(wxLC_REPORT
) )
2797 // the next we need the range of lines shown it might be different, so
2799 ResetVisibleLinesRange();
2801 if (rect
.y
< view_y
)
2802 Scroll( -1, rect
.y
/m_yScroll
);
2803 if (rect
.y
+rect
.height
+5 > view_y
+client_h
)
2804 Scroll( -1, (rect
.y
+rect
.height
-client_h
+SCROLL_UNIT_Y
)/m_yScroll
);
2808 if (rect
.x
-view_x
< 5)
2809 Scroll( (rect
.x
-5)/m_xScroll
, -1 );
2810 if (rect
.x
+rect
.width
-5 > view_x
+client_w
)
2811 Scroll( (rect
.x
+rect
.width
-client_w
+SCROLL_UNIT_X
)/m_xScroll
, -1 );
2815 // ----------------------------------------------------------------------------
2816 // keyboard handling
2817 // ----------------------------------------------------------------------------
2819 void wxListMainWindow::OnArrowChar(size_t newCurrent
, const wxKeyEvent
& event
)
2821 wxCHECK_RET( newCurrent
< (size_t)GetItemCount(),
2822 _T("invalid item index in OnArrowChar()") );
2824 size_t oldCurrent
= m_current
;
2826 // in single selection we just ignore Shift as we can't select several
2828 if ( event
.ShiftDown() && !IsSingleSel() )
2830 m_current
= newCurrent
;
2832 // select all the items between the old and the new one
2833 if ( oldCurrent
> newCurrent
)
2835 newCurrent
= oldCurrent
;
2836 oldCurrent
= m_current
;
2839 HighlightLines(oldCurrent
, newCurrent
);
2843 // all previously selected items are unselected unless ctrl is held
2844 if ( !event
.ControlDown() )
2845 HighlightAll(FALSE
);
2847 m_current
= newCurrent
;
2849 HighlightLine( oldCurrent
, FALSE
);
2850 RefreshLine( oldCurrent
);
2852 if ( !event
.ControlDown() )
2854 HighlightLine( m_current
, TRUE
);
2858 OnUnfocusLine( oldCurrent
);
2859 OnFocusLine( m_current
);
2860 RefreshLine( m_current
);
2865 void wxListMainWindow::OnKeyDown( wxKeyEvent
&event
)
2867 wxWindow
*parent
= GetParent();
2869 /* we propagate the key event up */
2870 wxKeyEvent
ke( wxEVT_KEY_DOWN
);
2871 ke
.m_shiftDown
= event
.m_shiftDown
;
2872 ke
.m_controlDown
= event
.m_controlDown
;
2873 ke
.m_altDown
= event
.m_altDown
;
2874 ke
.m_metaDown
= event
.m_metaDown
;
2875 ke
.m_keyCode
= event
.m_keyCode
;
2878 ke
.SetEventObject( parent
);
2879 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2884 void wxListMainWindow::OnChar( wxKeyEvent
&event
)
2886 wxWindow
*parent
= GetParent();
2888 /* we send a list_key event up */
2891 wxListEvent
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() );
2892 le
.m_itemIndex
= m_current
;
2893 GetLine(m_current
)->GetItem( 0, le
.m_item
);
2894 le
.m_code
= (int)event
.KeyCode();
2895 le
.SetEventObject( parent
);
2896 parent
->GetEventHandler()->ProcessEvent( le
);
2899 /* we propagate the char event up */
2900 wxKeyEvent
ke( wxEVT_CHAR
);
2901 ke
.m_shiftDown
= event
.m_shiftDown
;
2902 ke
.m_controlDown
= event
.m_controlDown
;
2903 ke
.m_altDown
= event
.m_altDown
;
2904 ke
.m_metaDown
= event
.m_metaDown
;
2905 ke
.m_keyCode
= event
.m_keyCode
;
2908 ke
.SetEventObject( parent
);
2909 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2911 if (event
.KeyCode() == WXK_TAB
)
2913 wxNavigationKeyEvent nevent
;
2914 nevent
.SetWindowChange( event
.ControlDown() );
2915 nevent
.SetDirection( !event
.ShiftDown() );
2916 nevent
.SetEventObject( GetParent()->GetParent() );
2917 nevent
.SetCurrentFocus( m_parent
);
2918 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent
)) return;
2921 /* no item -> nothing to do */
2928 switch (event
.KeyCode())
2931 if ( m_current
> 0 )
2932 OnArrowChar( m_current
- 1, event
);
2936 if ( m_current
< (size_t)GetItemCount() - 1 )
2937 OnArrowChar( m_current
+ 1, event
);
2942 OnArrowChar( GetItemCount() - 1, event
);
2947 OnArrowChar( 0, event
);
2953 if ( HasFlag(wxLC_REPORT
) )
2955 steps
= m_linesPerPage
- 1;
2959 steps
= m_current
% m_linesPerPage
;
2962 int index
= m_current
- steps
;
2966 OnArrowChar( index
, event
);
2973 if ( HasFlag(wxLC_REPORT
) )
2975 steps
= m_linesPerPage
- 1;
2979 steps
= m_linesPerPage
- (m_current
% m_linesPerPage
) - 1;
2982 size_t index
= m_current
+ steps
;
2983 size_t count
= GetItemCount();
2984 if ( index
>= count
)
2987 OnArrowChar( index
, event
);
2992 if ( !HasFlag(wxLC_REPORT
) )
2994 int index
= m_current
- m_linesPerPage
;
2998 OnArrowChar( index
, event
);
3003 if ( !HasFlag(wxLC_REPORT
) )
3005 size_t index
= m_current
+ m_linesPerPage
;
3007 size_t count
= GetItemCount();
3008 if ( index
>= count
)
3011 OnArrowChar( index
, event
);
3016 if ( IsSingleSel() )
3018 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3019 GetParent()->GetId() );
3020 le
.SetEventObject( GetParent() );
3021 le
.m_itemIndex
= m_current
;
3022 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3023 GetParent()->GetEventHandler()->ProcessEvent( le
);
3027 ReverseHighlight(m_current
);
3034 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3035 GetParent()->GetId() );
3036 le
.SetEventObject( GetParent() );
3037 le
.m_itemIndex
= m_current
;
3038 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3039 GetParent()->GetEventHandler()->ProcessEvent( le
);
3048 // ----------------------------------------------------------------------------
3050 // ----------------------------------------------------------------------------
3053 extern wxWindow
*g_focusWindow
;
3056 void wxListMainWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
3061 RefreshLine( m_current
);
3067 g_focusWindow
= GetParent();
3070 wxFocusEvent
event( wxEVT_SET_FOCUS
, GetParent()->GetId() );
3071 event
.SetEventObject( GetParent() );
3072 GetParent()->GetEventHandler()->ProcessEvent( event
);
3075 void wxListMainWindow::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
3080 RefreshLine( m_current
);
3083 void wxListMainWindow::DrawImage( int index
, wxDC
*dc
, int x
, int y
)
3085 if ( HasFlag(wxLC_ICON
) && (m_normal_image_list
))
3087 m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3089 else if ( HasFlag(wxLC_SMALL_ICON
) && (m_small_image_list
))
3091 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3093 else if ( HasFlag(wxLC_LIST
) && (m_small_image_list
))
3095 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3097 else if ( HasFlag(wxLC_REPORT
) && (m_small_image_list
))
3099 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3103 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height
)
3105 if ( HasFlag(wxLC_ICON
) && m_normal_image_list
)
3107 m_normal_image_list
->GetSize( index
, width
, height
);
3109 else if ( HasFlag(wxLC_SMALL_ICON
) && m_small_image_list
)
3111 m_small_image_list
->GetSize( index
, width
, height
);
3113 else if ( HasFlag(wxLC_LIST
) && m_small_image_list
)
3115 m_small_image_list
->GetSize( index
, width
, height
);
3117 else if ( HasFlag(wxLC_REPORT
) && m_small_image_list
)
3119 m_small_image_list
->GetSize( index
, width
, height
);
3128 int wxListMainWindow::GetTextLength( const wxString
&s
)
3130 wxClientDC
dc( this );
3131 dc
.SetFont( GetFont() );
3134 dc
.GetTextExtent( s
, &lw
, NULL
);
3136 return lw
+ AUTOSIZE_COL_MARGIN
;
3139 void wxListMainWindow::SetImageList( wxImageList
*imageList
, int which
)
3143 // calc the spacing from the icon size
3146 if ((imageList
) && (imageList
->GetImageCount()) )
3148 imageList
->GetSize(0, width
, height
);
3151 if (which
== wxIMAGE_LIST_NORMAL
)
3153 m_normal_image_list
= imageList
;
3154 m_normal_spacing
= width
+ 8;
3157 if (which
== wxIMAGE_LIST_SMALL
)
3159 m_small_image_list
= imageList
;
3160 m_small_spacing
= width
+ 14;
3164 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall
)
3169 m_small_spacing
= spacing
;
3173 m_normal_spacing
= spacing
;
3177 int wxListMainWindow::GetItemSpacing( bool isSmall
)
3179 return isSmall
? m_small_spacing
: m_normal_spacing
;
3182 // ----------------------------------------------------------------------------
3184 // ----------------------------------------------------------------------------
3186 void wxListMainWindow::SetColumn( int col
, wxListItem
&item
)
3188 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3190 wxCHECK_RET( node
, _T("invalid column index in SetColumn") );
3192 if ( item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3193 item
.m_width
= GetTextLength( item
.m_text
);
3195 wxListHeaderData
*column
= node
->GetData();
3196 column
->SetItem( item
);
3198 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3200 headerWin
->m_dirty
= TRUE
;
3204 // invalidate it as it has to be recalculated
3208 void wxListMainWindow::SetColumnWidth( int col
, int width
)
3210 wxCHECK_RET( col
>= 0 && col
< GetColumnCount(),
3211 _T("invalid column index") );
3213 wxCHECK_RET( HasFlag(wxLC_REPORT
),
3214 _T("SetColumnWidth() can only be called in report mode.") );
3218 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3219 wxCHECK_RET( node
, _T("no column?") );
3221 wxListHeaderData
*column
= node
->GetData();
3223 size_t count
= GetItemCount();
3225 if (width
== wxLIST_AUTOSIZE_USEHEADER
)
3227 width
= GetTextLength(column
->GetText());
3229 else if ( width
== wxLIST_AUTOSIZE
)
3233 // TODO: determine the max width somehow...
3234 width
= WIDTH_COL_DEFAULT
;
3238 wxClientDC
dc(this);
3239 dc
.SetFont( GetFont() );
3241 int max
= AUTOSIZE_COL_MARGIN
;
3243 for ( size_t i
= 0; i
< count
; i
++ )
3245 wxListLineData
*line
= GetLine(i
);
3246 wxListItemDataList::Node
*n
= line
->m_items
.Item( col
);
3248 wxCHECK_RET( n
, _T("no subitem?") );
3250 wxListItemData
*item
= n
->GetData();
3253 if (item
->HasImage())
3256 GetImageSize( item
->GetImage(), ix
, iy
);
3260 if (item
->HasText())
3263 dc
.GetTextExtent( item
->GetText(), &w
, NULL
);
3271 width
= max
+ AUTOSIZE_COL_MARGIN
;
3275 column
->SetWidth( width
);
3277 // invalidate it as it has to be recalculated
3281 int wxListMainWindow::GetHeaderWidth() const
3283 if ( !m_headerWidth
)
3285 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
3287 size_t count
= GetColumnCount();
3288 for ( size_t col
= 0; col
< count
; col
++ )
3290 self
->m_headerWidth
+= GetColumnWidth(col
);
3294 return m_headerWidth
;
3297 void wxListMainWindow::GetColumn( int col
, wxListItem
&item
) const
3299 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3300 wxCHECK_RET( node
, _T("invalid column index in GetColumn") );
3302 wxListHeaderData
*column
= node
->GetData();
3303 column
->GetItem( item
);
3306 int wxListMainWindow::GetColumnWidth( int col
) const
3308 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3309 wxCHECK_MSG( node
, 0, _T("invalid column index") );
3311 wxListHeaderData
*column
= node
->GetData();
3312 return column
->GetWidth();
3315 // ----------------------------------------------------------------------------
3317 // ----------------------------------------------------------------------------
3319 void wxListMainWindow::SetItem( wxListItem
&item
)
3321 long id
= item
.m_itemId
;
3322 wxCHECK_RET( id
>= 0 && (size_t)id
< GetItemCount(),
3323 _T("invalid item index in SetItem") );
3327 // just refresh the line to show the new value of the text/image
3328 RefreshLine((size_t)id
);
3334 wxListLineData
*line
= GetLine((size_t)id
);
3335 if ( HasFlag(wxLC_REPORT
) )
3336 item
.m_width
= GetColumnWidth( item
.m_col
);
3337 line
->SetItem( item
.m_col
, item
);
3341 void wxListMainWindow::SetItemState( long litem
, long state
, long stateMask
)
3343 wxCHECK_RET( litem
>= 0 && (size_t)litem
< GetItemCount(),
3344 _T("invalid list ctrl item index in SetItem") );
3346 size_t oldCurrent
= m_current
;
3347 size_t item
= (size_t)litem
; // sdafe because of the check above
3349 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3351 if ( state
& wxLIST_STATE_FOCUSED
)
3353 // don't do anything if this item is already focused
3354 if ( item
!= m_current
)
3356 OnUnfocusLine( m_current
);
3358 OnFocusLine( m_current
);
3360 if ( IsSingleSel() && (oldCurrent
!= (size_t)-1) )
3362 HighlightLine(oldCurrent
, FALSE
);
3363 RefreshLine(oldCurrent
);
3366 RefreshLine( m_current
);
3371 // don't do anything if this item is not focused
3372 if ( item
== m_current
)
3374 OnUnfocusLine( m_current
);
3375 m_current
= (size_t)-1;
3380 if ( stateMask
& wxLIST_STATE_SELECTED
)
3382 bool on
= (state
& wxLIST_STATE_SELECTED
) != 0;
3384 if ( IsSingleSel() )
3388 // selecting the item also makes it the focused one in the
3390 if ( m_current
!= item
)
3392 OnUnfocusLine( m_current
);
3394 OnFocusLine( m_current
);
3396 if ( oldCurrent
!= (size_t)-1 )
3398 HighlightLine( oldCurrent
, FALSE
);
3399 RefreshLine( oldCurrent
);
3405 // only the current item may be selected anyhow
3406 if ( item
!= m_current
)
3411 if ( HighlightLine(item
, on
) )
3418 int wxListMainWindow::GetItemState( long item
, long stateMask
)
3420 wxCHECK_MSG( item
>= 0 && (size_t)item
< GetItemCount(), 0,
3421 _T("invalid list ctrl item index in GetItemState()") );
3423 int ret
= wxLIST_STATE_DONTCARE
;
3425 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3427 if ( (size_t)item
== m_current
)
3428 ret
|= wxLIST_STATE_FOCUSED
;
3431 if ( stateMask
& wxLIST_STATE_SELECTED
)
3433 if ( IsHighlighted(item
) )
3434 ret
|= wxLIST_STATE_SELECTED
;
3440 void wxListMainWindow::GetItem( wxListItem
&item
)
3442 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
< GetItemCount(),
3443 _T("invalid item index in GetItem") );
3445 wxListLineData
*line
= GetLine((size_t)item
.m_itemId
);
3446 line
->GetItem( item
.m_col
, item
);
3449 // ----------------------------------------------------------------------------
3451 // ----------------------------------------------------------------------------
3453 size_t wxListMainWindow::GetItemCount() const
3455 return IsVirtual() ? m_countVirt
: m_lines
.GetCount();
3458 void wxListMainWindow::SetItemCount(long count
)
3460 m_selStore
.SetItemCount(count
);
3461 m_countVirt
= count
;
3466 int wxListMainWindow::GetSelectedItemCount()
3468 // deal with the quick case first
3469 if ( IsSingleSel() )
3471 return HasCurrent() ? IsHighlighted(m_current
) : FALSE
;
3474 // virtual controls remmebers all its selections itself
3476 return m_selStore
.GetSelectedCount();
3478 // TODO: we probably should maintain the number of items selected even for
3479 // non virtual controls as enumerating all lines is really slow...
3480 size_t countSel
= 0;
3481 size_t count
= GetItemCount();
3482 for ( size_t line
= 0; line
< count
; line
++ )
3484 if ( GetLine(line
)->IsHighlighted() )
3491 // ----------------------------------------------------------------------------
3492 // item position/size
3493 // ----------------------------------------------------------------------------
3495 void wxListMainWindow::GetItemRect( long index
, wxRect
&rect
)
3497 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3498 _T("invalid index in GetItemRect") );
3500 if ( HasFlag(wxLC_REPORT
) )
3502 rect
= GetDummyLine()->GetRect();
3503 rect
.y
= GetLineY((size_t)index
);
3507 rect
= GetLine((size_t)index
)->GetRect();
3510 CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
3513 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
)
3516 GetItemRect(item
, rect
);
3524 // ----------------------------------------------------------------------------
3525 // geometry calculation
3526 // ----------------------------------------------------------------------------
3528 void wxListMainWindow::RecalculatePositions()
3533 wxClientDC
dc( this );
3534 dc
.SetFont( GetFont() );
3537 if ( HasFlag(wxLC_ICON
) )
3538 iconSpacing
= m_normal_spacing
;
3539 else if ( HasFlag(wxLC_SMALL_ICON
) )
3540 iconSpacing
= m_small_spacing
;
3546 GetClientSize( &clientWidth
, &clientHeight
);
3548 if ( HasFlag(wxLC_REPORT
) )
3550 // all lines have the same height
3551 int lineHeight
= GetLineHeight();
3553 // scroll one line per step
3554 m_yScroll
= lineHeight
;
3556 size_t lineCount
= GetItemCount();
3557 int entireHeight
= lineCount
*lineHeight
+ LINE_SPACING
;
3559 m_linesPerPage
= clientHeight
/ lineHeight
;
3561 ResetVisibleLinesRange();
3563 SetScrollbars( m_xScroll
, m_yScroll
,
3564 (GetHeaderWidth() + m_xScroll
- 1)/m_xScroll
,
3565 (entireHeight
+ m_yScroll
- 1)/m_yScroll
,
3566 GetScrollPos(wxHORIZONTAL
),
3567 GetScrollPos(wxVERTICAL
),
3570 // we must have an integer number of lines on screen and so we fit
3571 // the real control size to the line height
3574 rect
.y
= LINE_SPACING
;
3575 rect
.width
= clientWidth
;
3576 rect
.height
= ((clientHeight
- LINE_SPACING
) / lineHeight
)*lineHeight
;
3577 SetTargetRect(rect
);
3581 // at first we try without any scrollbar. if the items don't
3582 // fit into the window, we recalculate after subtracting an
3583 // approximated 15 pt for the horizontal scrollbar
3585 clientHeight
-= 4; // sunken frame
3587 int entireWidth
= 0;
3589 for (int tries
= 0; tries
< 2; tries
++)
3596 int currentlyVisibleLines
= 0;
3598 size_t count
= GetItemCount();
3599 for (size_t i
= 0; i
< count
; i
++)
3601 currentlyVisibleLines
++;
3602 wxListLineData
*line
= GetLine(i
);
3603 line
->CalculateSize( &dc
, iconSpacing
);
3604 line
->SetPosition( x
, y
, clientWidth
, iconSpacing
);
3606 wxSize sizeLine
= line
->GetSize();
3608 if ( maxWidth
< sizeLine
.x
)
3609 maxWidth
= sizeLine
.x
;
3612 if (currentlyVisibleLines
> m_linesPerPage
)
3613 m_linesPerPage
= currentlyVisibleLines
;
3615 // assume that the size of the next one is the same... (FIXME)
3616 if ( y
+ sizeLine
.y
- 6 >= clientHeight
)
3618 currentlyVisibleLines
= 0;
3621 entireWidth
+= maxWidth
+6;
3624 if ( i
== count
- 1 )
3625 entireWidth
+= maxWidth
;
3626 if ((tries
== 0) && (entireWidth
> clientWidth
))
3628 clientHeight
-= 15; // scrollbar height
3630 currentlyVisibleLines
= 0;
3633 if ( i
== count
- 1 )
3634 tries
= 1; // everything fits, no second try required
3638 int scroll_pos
= GetScrollPos( wxHORIZONTAL
);
3639 SetScrollbars( m_xScroll
, m_yScroll
, (entireWidth
+SCROLL_UNIT_X
) / m_xScroll
, 0, scroll_pos
, 0, TRUE
);
3642 // FIXME: why should we call it from here?
3648 void wxListMainWindow::RefreshAll()
3653 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3656 headerWin
->m_dirty
= FALSE
;
3657 headerWin
->Refresh();
3661 void wxListMainWindow::UpdateCurrent()
3663 if ( !HasCurrent() && !IsEmpty() )
3668 if ( m_current
!= (size_t)-1 )
3670 OnFocusLine( m_current
);
3674 long wxListMainWindow::GetNextItem( long item
,
3675 int WXUNUSED(geometry
),
3679 max
= GetItemCount();
3680 wxCHECK_MSG( (ret
== -1) || (ret
< max
), -1,
3681 _T("invalid listctrl index in GetNextItem()") );
3683 // notice that we start with the next item (or the first one if item == -1)
3684 // and this is intentional to allow writing a simple loop to iterate over
3685 // all selected items
3689 // this is not an error because the index was ok initially, just no
3700 size_t count
= GetItemCount();
3701 for ( size_t line
= (size_t)ret
; line
< count
; line
++ )
3703 if ( (state
& wxLIST_STATE_FOCUSED
) && (line
== m_current
) )
3706 if ( (state
& wxLIST_STATE_SELECTED
) && IsHighlighted(line
) )
3713 // ----------------------------------------------------------------------------
3715 // ----------------------------------------------------------------------------
3717 void wxListMainWindow::DeleteItem( long lindex
)
3719 size_t count
= GetItemCount();
3721 wxCHECK_RET( (lindex
>= 0) && ((size_t)lindex
< count
),
3722 _T("invalid item index in DeleteItem") );
3724 size_t index
= (size_t)lindex
;
3728 // select the next item when the selected one is deleted
3729 if ( m_current
== index
)
3731 // the last valid index after deleting the item will be count-2
3732 if ( ++m_current
>= count
- 2 )
3734 m_current
= count
- 2;
3738 SendNotify( index
, wxEVT_COMMAND_LIST_DELETE_ITEM
);
3742 if ( m_lineTo
== --m_countVirt
)
3747 m_selStore
.OnItemDelete(index
);
3751 m_lines
.RemoveAt( index
);
3755 void wxListMainWindow::DeleteColumn( int col
)
3757 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3759 wxCHECK_RET( node
, wxT("invalid column index in DeleteColumn()") );
3762 m_columns
.DeleteNode( node
);
3765 void wxListMainWindow::DeleteAllItems()
3769 // nothing to do - in particular, don't send the event
3777 // to make the deletion of all items faster, we don't send the
3778 // notifications for each item deletion in this case but only one event
3779 // for all of them: this is compatible with wxMSW and documented in
3780 // DeleteAllItems() description
3782 wxListEvent
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() );
3783 event
.SetEventObject( GetParent() );
3784 GetParent()->GetEventHandler()->ProcessEvent( event
);
3790 ResetVisibleLinesRange();
3798 void wxListMainWindow::DeleteEverything()
3805 // ----------------------------------------------------------------------------
3806 // scanning for an item
3807 // ----------------------------------------------------------------------------
3809 void wxListMainWindow::EnsureVisible( long index
)
3811 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3812 _T("invalid index in EnsureVisible") );
3814 // We have to call this here because the label in question might just have
3815 // been added and no screen update taken place.
3819 size_t oldCurrent
= m_current
;
3820 m_current
= (size_t)index
;
3822 m_current
= oldCurrent
;
3825 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) )
3832 size_t count
= GetItemCount();
3833 for ( size_t i
= (size_t)pos
; i
< count
; i
++ )
3835 wxListLineData
*line
= GetLine(i
);
3836 if ( line
->GetText(0) == tmp
)
3843 long wxListMainWindow::FindItem(long start
, long data
)
3849 size_t count
= GetItemCount();
3850 for (size_t i
= (size_t)pos
; i
< count
; i
++)
3852 wxListLineData
*line
= GetLine(i
);
3854 line
->GetItem( 0, item
);
3855 if (item
.m_data
== data
)
3862 long wxListMainWindow::HitTest( int x
, int y
, int &flags
)
3864 CalcUnscrolledPosition( x
, y
, &x
, &y
);
3866 size_t count
= GetItemCount();
3867 for (size_t i
= 0; i
< count
; i
++)
3869 wxListLineData
*line
= GetLine(i
);
3870 long ret
= line
->IsHit( x
, y
);
3881 // ----------------------------------------------------------------------------
3883 // ----------------------------------------------------------------------------
3885 void wxListMainWindow::InsertItem( wxListItem
&item
)
3887 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") );
3889 size_t count
= GetItemCount();
3890 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
<= count
,
3891 _T("invalid item index") );
3893 size_t id
= item
.m_itemId
;
3898 if ( HasFlag(wxLC_REPORT
) )
3900 else if ( HasFlag(wxLC_LIST
) )
3902 else if ( HasFlag(wxLC_ICON
) )
3904 else if ( HasFlag(wxLC_SMALL_ICON
) )
3905 mode
= wxLC_ICON
; // no typo
3908 wxFAIL_MSG( _T("unknown mode") );
3911 wxListLineData
*line
= new wxListLineData( this, id
);
3913 line
->SetItem( 0, item
);
3915 m_lines
.Insert( line
, id
);
3918 void wxListMainWindow::InsertColumn( long col
, wxListItem
&item
)
3921 if ( HasFlag(wxLC_REPORT
) )
3923 if (item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3924 item
.m_width
= GetTextLength( item
.m_text
);
3925 wxListHeaderData
*column
= new wxListHeaderData( item
);
3926 if ((col
>= 0) && (col
< (int)m_columns
.GetCount()))
3928 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3929 m_columns
.Insert( node
, column
);
3933 m_columns
.Append( column
);
3938 // ----------------------------------------------------------------------------
3940 // ----------------------------------------------------------------------------
3942 wxListCtrlCompare list_ctrl_compare_func_2
;
3943 long list_ctrl_compare_data
;
3945 int LINKAGEMODE
list_ctrl_compare_func_1( wxListLineData
**arg1
, wxListLineData
**arg2
)
3947 wxListLineData
*line1
= *arg1
;
3948 wxListLineData
*line2
= *arg2
;
3950 line1
->GetItem( 0, item
);
3951 long data1
= item
.m_data
;
3952 line2
->GetItem( 0, item
);
3953 long data2
= item
.m_data
;
3954 return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data
);
3957 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data
)
3959 list_ctrl_compare_func_2
= fn
;
3960 list_ctrl_compare_data
= data
;
3961 m_lines
.Sort( list_ctrl_compare_func_1
);
3965 // ----------------------------------------------------------------------------
3967 // ----------------------------------------------------------------------------
3969 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
)
3971 // update our idea of which lines are shown when we redraw the window the
3973 ResetVisibleLinesRange();
3976 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
3977 wxScrolledWindow::OnScroll(event
);
3979 HandleOnScroll( event
);
3982 if ( event
.GetOrientation() == wxHORIZONTAL
&& HasHeader() )
3984 wxListCtrl
* lc
= GetListCtrl();
3985 wxCHECK_RET( lc
, _T("no listctrl window?") );
3987 lc
->m_headerWin
->Refresh() ;
3989 lc
->m_headerWin
->MacUpdateImmediately() ;
3994 void wxListMainWindow::GetVisibleLinesRange(size_t *from
, size_t *to
)
3996 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("this is for report mode only") );
3998 if ( m_lineFrom
== (size_t)-1 )
4000 m_lineFrom
= GetScrollPos(wxVERTICAL
);
4002 size_t count
= GetItemCount();
4004 wxASSERT_MSG( m_lineFrom
< count
, _T("invalid scroll position?") );
4006 m_lineTo
= m_lineFrom
+ m_linesPerPage
- 1;
4007 if ( m_lineTo
>= count
)
4008 m_lineTo
= count
- 1;
4017 // -------------------------------------------------------------------------------------
4019 // -------------------------------------------------------------------------------------
4021 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
)
4023 wxListItem::wxListItem()
4032 m_format
= wxLIST_FORMAT_CENTRE
;
4038 void wxListItem::Clear()
4047 m_format
= wxLIST_FORMAT_CENTRE
;
4054 void wxListItem::ClearAttributes()
4063 // -------------------------------------------------------------------------------------
4065 // -------------------------------------------------------------------------------------
4067 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
)
4069 wxListEvent::wxListEvent( wxEventType commandType
, int id
)
4070 : wxNotifyEvent( commandType
, id
)
4076 m_cancelled
= FALSE
;
4081 void wxListEvent::CopyObject(wxObject
& object_dest
) const
4083 wxListEvent
*obj
= (wxListEvent
*)&object_dest
;
4085 wxNotifyEvent::CopyObject(object_dest
);
4087 obj
->m_code
= m_code
;
4088 obj
->m_itemIndex
= m_itemIndex
;
4089 obj
->m_oldItemIndex
= m_oldItemIndex
;
4091 obj
->m_cancelled
= m_cancelled
;
4092 obj
->m_pointDrag
= m_pointDrag
;
4093 obj
->m_item
.m_mask
= m_item
.m_mask
;
4094 obj
->m_item
.m_itemId
= m_item
.m_itemId
;
4095 obj
->m_item
.m_col
= m_item
.m_col
;
4096 obj
->m_item
.m_state
= m_item
.m_state
;
4097 obj
->m_item
.m_stateMask
= m_item
.m_stateMask
;
4098 obj
->m_item
.m_text
= m_item
.m_text
;
4099 obj
->m_item
.m_image
= m_item
.m_image
;
4100 obj
->m_item
.m_data
= m_item
.m_data
;
4101 obj
->m_item
.m_format
= m_item
.m_format
;
4102 obj
->m_item
.m_width
= m_item
.m_width
;
4104 if ( m_item
.HasAttributes() )
4106 obj
->m_item
.SetTextColour(m_item
.GetTextColour());
4110 // -------------------------------------------------------------------------------------
4112 // -------------------------------------------------------------------------------------
4114 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
)
4116 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
)
4117 EVT_SIZE(wxListCtrl::OnSize
)
4118 EVT_IDLE(wxListCtrl::OnIdle
)
4121 wxListCtrl::wxListCtrl()
4123 m_imageListNormal
= (wxImageList
*) NULL
;
4124 m_imageListSmall
= (wxImageList
*) NULL
;
4125 m_imageListState
= (wxImageList
*) NULL
;
4127 m_ownsImageListNormal
=
4128 m_ownsImageListSmall
=
4129 m_ownsImageListState
= FALSE
;
4131 m_mainWin
= (wxListMainWindow
*) NULL
;
4132 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4135 wxListCtrl::~wxListCtrl()
4138 m_mainWin
->ResetCurrent();
4140 if (m_ownsImageListNormal
)
4141 delete m_imageListNormal
;
4142 if (m_ownsImageListSmall
)
4143 delete m_imageListSmall
;
4144 if (m_ownsImageListState
)
4145 delete m_imageListState
;
4148 void wxListCtrl::CreateHeaderWindow()
4150 m_headerWin
= new wxListHeaderWindow
4152 this, -1, m_mainWin
,
4154 wxSize(GetClientSize().x
, HEADER_HEIGHT
),
4159 bool wxListCtrl::Create(wxWindow
*parent
,
4164 const wxValidator
&validator
,
4165 const wxString
&name
)
4169 m_imageListState
= (wxImageList
*) NULL
;
4170 m_ownsImageListNormal
=
4171 m_ownsImageListSmall
=
4172 m_ownsImageListState
= FALSE
;
4174 m_mainWin
= (wxListMainWindow
*) NULL
;
4175 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4177 if ( !(style
& wxLC_MASK_TYPE
) )
4179 style
= style
| wxLC_LIST
;
4182 if ( !wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name
) )
4185 // don't create the inner window with the border
4186 style
&= ~wxSUNKEN_BORDER
;
4188 m_mainWin
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style
);
4190 if ( HasFlag(wxLC_REPORT
) )
4192 CreateHeaderWindow();
4194 if ( HasFlag(wxLC_NO_HEADER
) )
4196 // VZ: why do we create it at all then?
4197 m_headerWin
->Show( FALSE
);
4204 void wxListCtrl::SetSingleStyle( long style
, bool add
)
4206 wxASSERT_MSG( !(style
& wxLC_VIRTUAL
),
4207 _T("wxLC_VIRTUAL can't be [un]set") );
4209 long flag
= GetWindowStyle();
4213 if (style
& wxLC_MASK_TYPE
)
4214 flag
&= ~(wxLC_MASK_TYPE
| wxLC_VIRTUAL
);
4215 if (style
& wxLC_MASK_ALIGN
)
4216 flag
&= ~wxLC_MASK_ALIGN
;
4217 if (style
& wxLC_MASK_SORT
)
4218 flag
&= ~wxLC_MASK_SORT
;
4230 SetWindowStyleFlag( flag
);
4233 void wxListCtrl::SetWindowStyleFlag( long flag
)
4237 m_mainWin
->DeleteEverything();
4241 GetClientSize( &width
, &height
);
4243 if (flag
& wxLC_REPORT
)
4245 if (!HasFlag(wxLC_REPORT
))
4249 CreateHeaderWindow();
4251 if (HasFlag(wxLC_NO_HEADER
))
4252 m_headerWin
->Show( FALSE
);
4256 if (flag
& wxLC_NO_HEADER
)
4257 m_headerWin
->Show( FALSE
);
4259 m_headerWin
->Show( TRUE
);
4265 if ( m_mainWin
->HasHeader() )
4267 m_headerWin
->Show( FALSE
);
4272 wxWindow::SetWindowStyleFlag( flag
);
4275 bool wxListCtrl::GetColumn(int col
, wxListItem
&item
) const
4277 m_mainWin
->GetColumn( col
, item
);
4281 bool wxListCtrl::SetColumn( int col
, wxListItem
& item
)
4283 m_mainWin
->SetColumn( col
, item
);
4287 int wxListCtrl::GetColumnWidth( int col
) const
4289 return m_mainWin
->GetColumnWidth( col
);
4292 bool wxListCtrl::SetColumnWidth( int col
, int width
)
4294 m_mainWin
->SetColumnWidth( col
, width
);
4298 int wxListCtrl::GetCountPerPage() const
4300 return m_mainWin
->GetCountPerPage(); // different from Windows ?
4303 bool wxListCtrl::GetItem( wxListItem
&info
) const
4305 m_mainWin
->GetItem( info
);
4309 bool wxListCtrl::SetItem( wxListItem
&info
)
4311 m_mainWin
->SetItem( info
);
4315 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId
)
4318 info
.m_text
= label
;
4319 info
.m_mask
= wxLIST_MASK_TEXT
;
4320 info
.m_itemId
= index
;
4324 info
.m_image
= imageId
;
4325 info
.m_mask
|= wxLIST_MASK_IMAGE
;
4327 m_mainWin
->SetItem(info
);
4331 int wxListCtrl::GetItemState( long item
, long stateMask
) const
4333 return m_mainWin
->GetItemState( item
, stateMask
);
4336 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask
)
4338 m_mainWin
->SetItemState( item
, state
, stateMask
);
4342 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) )
4345 info
.m_image
= image
;
4346 info
.m_mask
= wxLIST_MASK_IMAGE
;
4347 info
.m_itemId
= item
;
4348 m_mainWin
->SetItem( info
);
4352 wxString
wxListCtrl::GetItemText( long item
) const
4355 info
.m_itemId
= item
;
4356 m_mainWin
->GetItem( info
);
4360 void wxListCtrl::SetItemText( long item
, const wxString
&str
)
4363 info
.m_mask
= wxLIST_MASK_TEXT
;
4364 info
.m_itemId
= item
;
4366 m_mainWin
->SetItem( info
);
4369 long wxListCtrl::GetItemData( long item
) const
4372 info
.m_itemId
= item
;
4373 m_mainWin
->GetItem( info
);
4377 bool wxListCtrl::SetItemData( long item
, long data
)
4380 info
.m_mask
= wxLIST_MASK_DATA
;
4381 info
.m_itemId
= item
;
4383 m_mainWin
->SetItem( info
);
4387 bool wxListCtrl::GetItemRect( long item
, wxRect
&rect
, int WXUNUSED(code
) ) const
4389 m_mainWin
->GetItemRect( item
, rect
);
4393 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos
) const
4395 m_mainWin
->GetItemPosition( item
, pos
);
4399 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) )
4404 int wxListCtrl::GetItemCount() const
4406 return m_mainWin
->GetItemCount();
4409 int wxListCtrl::GetColumnCount() const
4411 return m_mainWin
->GetColumnCount();
4414 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall
)
4416 m_mainWin
->SetItemSpacing( spacing
, isSmall
);
4419 int wxListCtrl::GetItemSpacing( bool isSmall
) const
4421 return m_mainWin
->GetItemSpacing( isSmall
);
4424 int wxListCtrl::GetSelectedItemCount() const
4426 return m_mainWin
->GetSelectedItemCount();
4429 wxColour
wxListCtrl::GetTextColour() const
4431 return GetForegroundColour();
4434 void wxListCtrl::SetTextColour(const wxColour
& col
)
4436 SetForegroundColour(col
);
4439 long wxListCtrl::GetTopItem() const
4444 long wxListCtrl::GetNextItem( long item
, int geom
, int state
) const
4446 return m_mainWin
->GetNextItem( item
, geom
, state
);
4449 wxImageList
*wxListCtrl::GetImageList(int which
) const
4451 if (which
== wxIMAGE_LIST_NORMAL
)
4453 return m_imageListNormal
;
4455 else if (which
== wxIMAGE_LIST_SMALL
)
4457 return m_imageListSmall
;
4459 else if (which
== wxIMAGE_LIST_STATE
)
4461 return m_imageListState
;
4463 return (wxImageList
*) NULL
;
4466 void wxListCtrl::SetImageList( wxImageList
*imageList
, int which
)
4468 if ( which
== wxIMAGE_LIST_NORMAL
)
4470 if (m_ownsImageListNormal
) delete m_imageListNormal
;
4471 m_imageListNormal
= imageList
;
4472 m_ownsImageListNormal
= FALSE
;
4474 else if ( which
== wxIMAGE_LIST_SMALL
)
4476 if (m_ownsImageListSmall
) delete m_imageListSmall
;
4477 m_imageListSmall
= imageList
;
4478 m_ownsImageListSmall
= FALSE
;
4480 else if ( which
== wxIMAGE_LIST_STATE
)
4482 if (m_ownsImageListState
) delete m_imageListState
;
4483 m_imageListState
= imageList
;
4484 m_ownsImageListState
= FALSE
;
4487 m_mainWin
->SetImageList( imageList
, which
);
4490 void wxListCtrl::AssignImageList(wxImageList
*imageList
, int which
)
4492 SetImageList(imageList
, which
);
4493 if ( which
== wxIMAGE_LIST_NORMAL
)
4494 m_ownsImageListNormal
= TRUE
;
4495 else if ( which
== wxIMAGE_LIST_SMALL
)
4496 m_ownsImageListSmall
= TRUE
;
4497 else if ( which
== wxIMAGE_LIST_STATE
)
4498 m_ownsImageListState
= TRUE
;
4501 bool wxListCtrl::Arrange( int WXUNUSED(flag
) )
4506 bool wxListCtrl::DeleteItem( long item
)
4508 m_mainWin
->DeleteItem( item
);
4512 bool wxListCtrl::DeleteAllItems()
4514 m_mainWin
->DeleteAllItems();
4518 bool wxListCtrl::DeleteAllColumns()
4520 size_t count
= m_mainWin
->m_columns
.GetCount();
4521 for ( size_t n
= 0; n
< count
; n
++ )
4527 void wxListCtrl::ClearAll()
4529 m_mainWin
->DeleteEverything();
4532 bool wxListCtrl::DeleteColumn( int col
)
4534 m_mainWin
->DeleteColumn( col
);
4538 void wxListCtrl::Edit( long item
)
4540 m_mainWin
->EditLabel( item
);
4543 bool wxListCtrl::EnsureVisible( long item
)
4545 m_mainWin
->EnsureVisible( item
);
4549 long wxListCtrl::FindItem( long start
, const wxString
& str
, bool partial
)
4551 return m_mainWin
->FindItem( start
, str
, partial
);
4554 long wxListCtrl::FindItem( long start
, long data
)
4556 return m_mainWin
->FindItem( start
, data
);
4559 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
),
4560 int WXUNUSED(direction
))
4565 long wxListCtrl::HitTest( const wxPoint
&point
, int &flags
)
4567 return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags
);
4570 long wxListCtrl::InsertItem( wxListItem
& info
)
4572 m_mainWin
->InsertItem( info
);
4573 return info
.m_itemId
;
4576 long wxListCtrl::InsertItem( long index
, const wxString
&label
)
4579 info
.m_text
= label
;
4580 info
.m_mask
= wxLIST_MASK_TEXT
;
4581 info
.m_itemId
= index
;
4582 return InsertItem( info
);
4585 long wxListCtrl::InsertItem( long index
, int imageIndex
)
4588 info
.m_mask
= wxLIST_MASK_IMAGE
;
4589 info
.m_image
= imageIndex
;
4590 info
.m_itemId
= index
;
4591 return InsertItem( info
);
4594 long wxListCtrl::InsertItem( long index
, const wxString
&label
, int imageIndex
)
4597 info
.m_text
= label
;
4598 info
.m_image
= imageIndex
;
4599 info
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_IMAGE
;
4600 info
.m_itemId
= index
;
4601 return InsertItem( info
);
4604 long wxListCtrl::InsertColumn( long col
, wxListItem
&item
)
4606 wxASSERT( m_headerWin
);
4607 m_mainWin
->InsertColumn( col
, item
);
4608 m_headerWin
->Refresh();
4613 long wxListCtrl::InsertColumn( long col
, const wxString
&heading
,
4614 int format
, int width
)
4617 item
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_FORMAT
;
4618 item
.m_text
= heading
;
4621 item
.m_mask
|= wxLIST_MASK_WIDTH
;
4622 item
.m_width
= width
;
4624 item
.m_format
= format
;
4626 return InsertColumn( col
, item
);
4629 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) )
4635 // fn is a function which takes 3 long arguments: item1, item2, data.
4636 // item1 is the long data associated with a first item (NOT the index).
4637 // item2 is the long data associated with a second item (NOT the index).
4638 // data is the same value as passed to SortItems.
4639 // The return value is a negative number if the first item should precede the second
4640 // item, a positive number of the second item should precede the first,
4641 // or zero if the two items are equivalent.
4642 // data is arbitrary data to be passed to the sort function.
4644 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data
)
4646 m_mainWin
->SortItems( fn
, data
);
4650 // ----------------------------------------------------------------------------
4652 // ----------------------------------------------------------------------------
4654 void wxListCtrl::OnSize(wxSizeEvent
& event
)
4660 GetClientSize( &cw
, &ch
);
4662 if ( m_mainWin
->HasHeader() )
4664 m_headerWin
->SetSize( 0, 0, cw
, HEADER_HEIGHT
);
4665 m_mainWin
->SetSize( 0, HEADER_HEIGHT
+ 1, cw
, ch
- HEADER_HEIGHT
- 1 );
4667 else // no header window
4669 m_mainWin
->SetSize( 0, 0, cw
, ch
);
4672 m_mainWin
->RecalculatePositions();
4675 void wxListCtrl::OnIdle( wxIdleEvent
& event
)
4679 // do it only if needed
4680 if ( !m_mainWin
->m_dirty
)
4683 m_mainWin
->RecalculatePositions();
4686 // ----------------------------------------------------------------------------
4688 // ----------------------------------------------------------------------------
4690 bool wxListCtrl::SetBackgroundColour( const wxColour
&colour
)
4694 m_mainWin
->SetBackgroundColour( colour
);
4695 m_mainWin
->m_dirty
= TRUE
;
4701 bool wxListCtrl::SetForegroundColour( const wxColour
&colour
)
4703 if ( !wxWindow::SetForegroundColour( colour
) )
4708 m_mainWin
->SetForegroundColour( colour
);
4709 m_mainWin
->m_dirty
= TRUE
;
4714 m_headerWin
->SetForegroundColour( colour
);
4720 bool wxListCtrl::SetFont( const wxFont
&font
)
4722 if ( !wxWindow::SetFont( font
) )
4727 m_mainWin
->SetFont( font
);
4728 m_mainWin
->m_dirty
= TRUE
;
4733 m_headerWin
->SetFont( font
);
4739 // ----------------------------------------------------------------------------
4740 // methods forwarded to m_mainWin
4741 // ----------------------------------------------------------------------------
4743 #if wxUSE_DRAG_AND_DROP
4745 void wxListCtrl::SetDropTarget( wxDropTarget
*dropTarget
)
4747 m_mainWin
->SetDropTarget( dropTarget
);
4750 wxDropTarget
*wxListCtrl::GetDropTarget() const
4752 return m_mainWin
->GetDropTarget();
4755 #endif // wxUSE_DRAG_AND_DROP
4757 bool wxListCtrl::SetCursor( const wxCursor
&cursor
)
4759 return m_mainWin
? m_mainWin
->wxWindow::SetCursor(cursor
) : FALSE
;
4762 wxColour
wxListCtrl::GetBackgroundColour() const
4764 return m_mainWin
? m_mainWin
->GetBackgroundColour() : wxColour();
4767 wxColour
wxListCtrl::GetForegroundColour() const
4769 return m_mainWin
? m_mainWin
->GetForegroundColour() : wxColour();
4772 bool wxListCtrl::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
4775 return m_mainWin
->PopupMenu( menu
, x
, y
);
4778 #endif // wxUSE_MENUS
4781 void wxListCtrl::SetFocus()
4783 /* The test in window.cpp fails as we are a composite
4784 window, so it checks against "this", but not m_mainWin. */
4785 if ( FindFocus() != this )
4786 m_mainWin
->SetFocus();
4789 // ----------------------------------------------------------------------------
4790 // virtual list control support
4791 // ----------------------------------------------------------------------------
4793 wxString
wxListCtrl::OnGetItemText(long item
, long col
) const
4795 // this is a pure virtual function, in fact - which is not really pure
4796 // because the controls which are not virtual don't need to implement it
4797 wxFAIL_MSG( _T("not supposed to be called") );
4799 return wxEmptyString
;
4802 int wxListCtrl::OnGetItemImage(long item
) const
4805 wxFAIL_MSG( _T("not supposed to be called") );
4810 void wxListCtrl::SetItemCount(long count
)
4812 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4814 m_mainWin
->SetItemCount(count
);
4817 #endif // wxUSE_LISTCTRL