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
);
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
);
372 void SetImage( int image
) { SetImage(0, image
); }
373 int GetImage() const { return GetImage(0); }
374 bool HasImage() const { return GetImage() != -1; }
375 bool HasText() const { return !GetText(0).empty(); }
377 void SetItem( int index
, const wxListItem
&info
);
378 void GetItem( int index
, wxListItem
&info
);
380 wxString
GetText(int index
) const;
381 void SetText( int index
, const wxString s
);
383 // return true if the highlighting really changed
384 bool Highlight( bool on
);
386 void ReverseHighlight();
388 bool IsHighlighted() const
390 wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") );
392 return m_highlighted
;
395 // draw the line on the given DC in icon/list mode
396 void Draw( wxDC
*dc
);
398 // the same in report mode
399 void DrawInReportMode( wxDC
*dc
,
401 const wxRect
& rectHL
,
405 // set the line to contain num items (only can be > 1 in report mode)
406 void InitItems( int num
);
408 // get the mode (i.e. style) of the list control
409 inline int GetMode() const;
411 void SetAttributes(wxDC
*dc
,
412 const wxListItemAttr
*attr
,
413 const wxColour
& colText
,
417 // these are only used by GetImage/SetImage above, we don't support images
418 // with subitems at the public API level yet
419 void SetImage( int index
, int image
);
420 int GetImage( int index
) const;
423 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData
, wxListLineDataArray
);
424 #include "wx/arrimpl.cpp"
425 WX_DEFINE_OBJARRAY(wxListLineDataArray
);
427 //-----------------------------------------------------------------------------
428 // wxListHeaderWindow (internal)
429 //-----------------------------------------------------------------------------
431 class WXDLLEXPORT wxListHeaderWindow
: public wxWindow
434 wxListMainWindow
*m_owner
;
435 wxCursor
*m_currentCursor
;
436 wxCursor
*m_resizeCursor
;
439 // column being resized
442 // divider line position in logical (unscrolled) coords
445 // minimal position beyond which the divider line can't be dragged in
450 wxListHeaderWindow();
451 virtual ~wxListHeaderWindow();
453 wxListHeaderWindow( wxWindow
*win
,
455 wxListMainWindow
*owner
,
456 const wxPoint
&pos
= wxDefaultPosition
,
457 const wxSize
&size
= wxDefaultSize
,
459 const wxString
&name
= "wxlistctrlcolumntitles" );
461 void DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
);
463 void AdjustDC(wxDC
& dc
);
465 void OnPaint( wxPaintEvent
&event
);
466 void OnMouse( wxMouseEvent
&event
);
467 void OnSetFocus( wxFocusEvent
&event
);
473 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow
)
474 DECLARE_EVENT_TABLE()
477 //-----------------------------------------------------------------------------
478 // wxListRenameTimer (internal)
479 //-----------------------------------------------------------------------------
481 class WXDLLEXPORT wxListRenameTimer
: public wxTimer
484 wxListMainWindow
*m_owner
;
487 wxListRenameTimer( wxListMainWindow
*owner
);
491 //-----------------------------------------------------------------------------
492 // wxListTextCtrl (internal)
493 //-----------------------------------------------------------------------------
495 class WXDLLEXPORT wxListTextCtrl
: public wxTextCtrl
500 wxListMainWindow
*m_owner
;
501 wxString m_startValue
;
505 wxListTextCtrl( wxWindow
*parent
, const wxWindowID id
,
506 bool *accept
, wxString
*res
, wxListMainWindow
*owner
,
507 const wxString
&value
= "",
508 const wxPoint
&pos
= wxDefaultPosition
, const wxSize
&size
= wxDefaultSize
,
510 const wxValidator
& validator
= wxDefaultValidator
,
511 const wxString
&name
= "listctrltextctrl" );
512 void OnChar( wxKeyEvent
&event
);
513 void OnKeyUp( wxKeyEvent
&event
);
514 void OnKillFocus( wxFocusEvent
&event
);
517 DECLARE_DYNAMIC_CLASS(wxListTextCtrl
);
518 DECLARE_EVENT_TABLE()
521 //-----------------------------------------------------------------------------
522 // wxListMainWindow (internal)
523 //-----------------------------------------------------------------------------
525 WX_DECLARE_LIST(wxListHeaderData
, wxListHeaderDataList
);
526 #include "wx/listimpl.cpp"
527 WX_DEFINE_LIST(wxListHeaderDataList
);
529 class WXDLLEXPORT wxListMainWindow
: public wxScrolledWindow
533 wxListMainWindow( wxWindow
*parent
,
535 const wxPoint
& pos
= wxDefaultPosition
,
536 const wxSize
& size
= wxDefaultSize
,
538 const wxString
&name
= _T("listctrlmainwindow") );
540 virtual ~wxListMainWindow();
542 bool HasFlag(int flag
) const { return m_parent
->HasFlag(flag
); }
544 // return true if this is a virtual list control
545 bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL
); }
547 // return true if the control is in report mode
548 bool InReportView() const { return HasFlag(wxLC_REPORT
); }
550 // return true if we are in single selection mode, false if multi sel
551 bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL
); }
553 // do we have a header window?
554 bool HasHeader() const
555 { return HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
); }
557 void HighlightAll( bool on
);
559 // all these functions only do something if the line is currently visible
561 // change the line "selected" state, return TRUE if it really changed
562 bool HighlightLine( size_t line
, bool highlight
= TRUE
);
564 // as HighlightLine() but do it for the range of lines: this is incredibly
565 // more efficient for virtual list controls!
567 // NB: unlike HighlightLine() this one does refresh the lines on screen
568 void HighlightLines( size_t lineFrom
, size_t lineTo
, bool on
= TRUE
);
570 // toggle the line state and refresh it
571 void ReverseHighlight( size_t line
)
572 { HighlightLine(line
, !IsHighlighted(line
)); RefreshLine(line
); }
574 // return true if the line is highlighted
575 bool IsHighlighted(size_t line
) const;
577 // refresh one or several lines at once
578 void RefreshLine( size_t line
);
579 void RefreshLines( size_t lineFrom
, size_t lineTo
);
581 // refresh all lines below the given one: the difference with
582 // RefreshLines() is that the index here might not be a valid one (happens
583 // when the last line is deleted)
584 void RefreshAfter( size_t lineFrom
);
586 // the methods which are forwarded to wxListLineData itself in list/icon
587 // modes but are here because the lines don't store their positions in the
590 // get the bound rect for the entire line
591 wxRect
GetLineRect(size_t line
) const;
593 // get the bound rect of the label
594 wxRect
GetLineLabelRect(size_t line
) const;
596 // get the bound rect of the items icon (only may be called if we do have
598 wxRect
GetLineIconRect(size_t line
) const;
600 // get the rect to be highlighted when the item has focus
601 wxRect
GetLineHighlightRect(size_t line
) const;
603 // get the size of the total line rect
604 wxSize
GetLineSize(size_t line
) const
605 { return GetLineRect(line
).GetSize(); }
607 // return the hit code for the corresponding position (in this line)
608 long HitTestLine(size_t line
, int x
, int y
) const;
610 void EditLabel( long item
);
611 void OnRenameTimer();
612 void OnRenameAccept();
614 void OnMouse( wxMouseEvent
&event
);
617 // called to switch the selection from the current item to newCurrent,
618 void OnArrowChar( size_t newCurrent
, const wxKeyEvent
& event
);
620 void OnChar( wxKeyEvent
&event
);
621 void OnKeyDown( wxKeyEvent
&event
);
622 void OnSetFocus( wxFocusEvent
&event
);
623 void OnKillFocus( wxFocusEvent
&event
);
624 void OnScroll(wxScrollWinEvent
& event
) ;
626 void OnPaint( wxPaintEvent
&event
);
628 void DrawImage( int index
, wxDC
*dc
, int x
, int y
);
629 void GetImageSize( int index
, int &width
, int &height
) const;
630 int GetTextLength( const wxString
&s
) const;
632 void SetImageList( wxImageList
*imageList
, int which
);
633 void SetItemSpacing( int spacing
, bool isSmall
= FALSE
);
634 int GetItemSpacing( bool isSmall
= FALSE
);
636 void SetColumn( int col
, wxListItem
&item
);
637 void SetColumnWidth( int col
, int width
);
638 void GetColumn( int col
, wxListItem
&item
) const;
639 int GetColumnWidth( int col
) const;
640 int GetColumnCount() const { return m_columns
.GetCount(); }
642 // returns the sum of the heights of all columns
643 int GetHeaderWidth() const;
645 int GetCountPerPage() const;
647 void SetItem( wxListItem
&item
);
648 void GetItem( wxListItem
&item
);
649 void SetItemState( long item
, long state
, long stateMask
);
650 int GetItemState( long item
, long stateMask
);
651 void GetItemRect( long index
, wxRect
&rect
);
652 bool GetItemPosition( long item
, wxPoint
& pos
);
653 int GetSelectedItemCount();
655 // set the scrollbars and update the positions of the items
656 void RecalculatePositions();
658 // refresh the window and the header
661 long GetNextItem( long item
, int geometry
, int state
);
662 void DeleteItem( long index
);
663 void DeleteAllItems();
664 void DeleteColumn( int col
);
665 void DeleteEverything();
666 void EnsureVisible( long index
);
667 long FindItem( long start
, const wxString
& str
, bool partial
= FALSE
);
668 long FindItem( long start
, long data
);
669 long HitTest( int x
, int y
, int &flags
);
670 void InsertItem( wxListItem
&item
);
671 void InsertColumn( long col
, wxListItem
&item
);
672 void SortItems( wxListCtrlCompare fn
, long data
);
674 size_t GetItemCount() const;
675 bool IsEmpty() const { return GetItemCount() == 0; }
676 void SetItemCount(long count
);
678 void ResetCurrent() { m_current
= (size_t)-1; }
679 bool HasCurrent() const { return m_current
!= (size_t)-1; }
681 // send out a wxListEvent
682 void SendNotify( size_t line
,
684 wxPoint point
= wxDefaultPosition
);
686 // override base class virtual to reset m_lineHeight when the font changes
687 virtual bool SetFont(const wxFont
& font
)
689 if ( !wxScrolledWindow::SetFont(font
) )
697 // these are for wxListLineData usage only
699 // get the backpointer to the list ctrl
700 wxListCtrl
*GetListCtrl() const
702 return wxStaticCast(GetParent(), wxListCtrl
);
705 // get the height of all lines (assuming they all do have the same height)
706 wxCoord
GetLineHeight() const;
708 // get the y position of the given line (only for report view)
709 wxCoord
GetLineY(size_t line
) const;
712 // the array of all line objects for a non virtual list control
713 wxListLineDataArray m_lines
;
715 // the list of column objects
716 wxListHeaderDataList m_columns
;
718 // currently focused item or -1
721 // the item currently being edited or -1
722 size_t m_currentEdit
;
724 // the number of lines per page
727 // this flag is set when something which should result in the window
728 // redrawing happens (i.e. an item was added or deleted, or its appearance
729 // changed) and OnPaint() doesn't redraw the window while it is set which
730 // allows to minimize the number of repaintings when a lot of items are
731 // being added. The real repainting occurs only after the next OnIdle()
735 wxBrush
*m_highlightBrush
;
736 wxColour
*m_highlightColour
;
739 wxImageList
*m_small_image_list
;
740 wxImageList
*m_normal_image_list
;
742 int m_normal_spacing
;
746 wxTimer
*m_renameTimer
;
748 wxString m_renameRes
;
753 // for double click logic
754 size_t m_lineLastClicked
,
755 m_lineBeforeLastClicked
;
758 // the total count of items in a virtual list control
761 // the object maintaining the items selection state, only used in virtual
763 wxSelectionStore m_selStore
;
765 // common part of all ctors
768 // intiialize m_[xy]Scroll
769 void InitScrolling();
771 // get the line data for the given index
772 wxListLineData
*GetLine(size_t n
) const
774 wxASSERT_MSG( n
!= (size_t)-1, _T("invalid line index") );
778 wxConstCast(this, wxListMainWindow
)->CacheLineData(n
);
786 // get a dummy line which can be used for geometry calculations and such:
787 // you must use GetLine() if you want to really draw the line
788 wxListLineData
*GetDummyLine() const;
790 // cache the line data of the n-th line in m_lines[0]
791 void CacheLineData(size_t line
);
793 // get the range of visible lines
794 void GetVisibleLinesRange(size_t *from
, size_t *to
);
796 // force us to recalculate the range of visible lines
797 void ResetVisibleLinesRange() { m_lineFrom
= (size_t)-1; }
799 // get the colour to be used for drawing the rules
800 wxColour
GetRuleColour() const
805 return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT
);
810 // initialize the current item if needed
811 void UpdateCurrent();
813 // called when an item is [un]focuded, i.e. becomes [not] current
816 void OnFocusLine( size_t line
);
817 void OnUnfocusLine( size_t line
);
819 // the height of one line using the current font
820 wxCoord m_lineHeight
;
822 // the total header width or 0 if not calculated yet
823 wxCoord m_headerWidth
;
825 // the first and last lines being shown on screen right now (inclusive),
826 // both may be -1 if they must be calculated so never access them directly:
827 // use GetVisibleLinesRange() above instead
831 DECLARE_DYNAMIC_CLASS(wxListMainWindow
);
832 DECLARE_EVENT_TABLE()
835 // ============================================================================
837 // ============================================================================
839 // ----------------------------------------------------------------------------
841 // ----------------------------------------------------------------------------
843 bool wxSelectionStore::IsSelected(size_t item
) const
845 bool isSel
= m_itemsSel
.Index(item
) != wxNOT_FOUND
;
847 // if the default state is to be selected, being in m_itemsSel means that
848 // the item is not selected, so we have to inverse the logic
849 return m_defaultState
? !isSel
: isSel
;
852 bool wxSelectionStore::SelectItem(size_t item
, bool select
)
854 // search for the item ourselves as like this we get the index where to
855 // insert it later if needed, so we do only one search in the array instead
856 // of two (adding item to a sorted array requires a search)
857 size_t index
= m_itemsSel
.IndexForInsert(item
);
858 bool isSel
= index
< m_itemsSel
.GetCount() && m_itemsSel
[index
] == item
;
860 if ( select
!= m_defaultState
)
864 m_itemsSel
.AddAt(item
, index
);
869 else // reset to default state
873 m_itemsSel
.RemoveAt(index
);
881 void wxSelectionStore::SelectRange(size_t itemFrom
, size_t itemTo
, bool select
)
883 wxASSERT_MSG( itemFrom
<= itemTo
, _T("should be in order") );
885 // are we going to have more [un]selected items than the other ones?
886 if ( itemTo
- itemFrom
> m_count
/ 2 )
888 if ( select
!= m_defaultState
)
890 // the default state now becomes the same as 'select'
891 m_defaultState
= select
;
893 // so all the old selections (which had state select) shouldn't be
894 // selected any more, but all the other ones should
895 wxIndexArray selOld
= m_itemsSel
;
898 // TODO: it should be possible to optimize the searches a bit
899 // knowing the possible range
902 for ( item
= 0; item
< itemFrom
; item
++ )
904 if ( selOld
.Index(item
) == wxNOT_FOUND
)
905 m_itemsSel
.Add(item
);
908 for ( item
= itemTo
+ 1; item
< m_count
; item
++ )
910 if ( selOld
.Index(item
) == wxNOT_FOUND
)
911 m_itemsSel
.Add(item
);
914 else // select == m_defaultState
916 // get the inclusive range of items between itemFrom and itemTo
917 size_t count
= m_itemsSel
.GetCount(),
918 start
= m_itemsSel
.IndexForInsert(itemFrom
),
919 end
= m_itemsSel
.IndexForInsert(itemTo
);
921 if ( start
== count
|| m_itemsSel
[start
] < itemFrom
)
926 if ( end
== count
|| m_itemsSel
[end
] > itemTo
)
933 // delete all of them (from end to avoid changing indices)
934 for ( int i
= end
; i
>= (int)start
; i
-- )
936 m_itemsSel
.RemoveAt(i
);
941 else // "few" items change state
943 // just add the items to the selection
944 for ( size_t item
= itemFrom
; item
<= itemTo
; item
++ )
946 SelectItem(item
, select
);
951 void wxSelectionStore::OnItemDelete(size_t item
)
953 size_t count
= m_itemsSel
.GetCount(),
954 i
= m_itemsSel
.IndexForInsert(item
);
956 if ( i
< count
&& m_itemsSel
[i
] == item
)
958 // this item itself was in m_itemsSel, remove it from there
959 m_itemsSel
.RemoveAt(i
);
964 // and adjust the index of all which follow it
967 // all following elements must be greater than the one we deleted
968 wxASSERT_MSG( m_itemsSel
[i
] > item
, _T("logic error") );
974 //-----------------------------------------------------------------------------
976 //-----------------------------------------------------------------------------
978 void wxListItemData::Init()
986 wxListItemData::wxListItemData(wxListMainWindow
*owner
)
992 if ( owner
->HasFlag(wxLC_REPORT
) )
1002 void wxListItemData::SetItem( const wxListItem
&info
)
1004 if ( info
.m_mask
& wxLIST_MASK_TEXT
)
1005 SetText(info
.m_text
);
1006 if ( info
.m_mask
& wxLIST_MASK_IMAGE
)
1007 m_image
= info
.m_image
;
1008 if ( info
.m_mask
& wxLIST_MASK_DATA
)
1009 m_data
= info
.m_data
;
1011 if ( info
.HasAttributes() )
1014 *m_attr
= *info
.GetAttributes();
1016 m_attr
= new wxListItemAttr(*info
.GetAttributes());
1024 m_rect
->width
= info
.m_width
;
1028 void wxListItemData::SetPosition( int x
, int y
)
1030 wxCHECK_RET( m_rect
, _T("unexpected SetPosition() call") );
1036 void wxListItemData::SetSize( int width
, int height
)
1038 wxCHECK_RET( m_rect
, _T("unexpected SetSize() call") );
1041 m_rect
->width
= width
;
1043 m_rect
->height
= height
;
1046 bool wxListItemData::IsHit( int x
, int y
) const
1048 wxCHECK_MSG( m_rect
, FALSE
, _T("can't be called in this mode") );
1050 return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x
, y
);
1053 int wxListItemData::GetX() const
1055 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1060 int wxListItemData::GetY() const
1062 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1067 int wxListItemData::GetWidth() const
1069 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1071 return m_rect
->width
;
1074 int wxListItemData::GetHeight() const
1076 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1078 return m_rect
->height
;
1081 void wxListItemData::GetItem( wxListItem
&info
) const
1083 info
.m_text
= m_text
;
1084 info
.m_image
= m_image
;
1085 info
.m_data
= m_data
;
1089 if ( m_attr
->HasTextColour() )
1090 info
.SetTextColour(m_attr
->GetTextColour());
1091 if ( m_attr
->HasBackgroundColour() )
1092 info
.SetBackgroundColour(m_attr
->GetBackgroundColour());
1093 if ( m_attr
->HasFont() )
1094 info
.SetFont(m_attr
->GetFont());
1098 //-----------------------------------------------------------------------------
1100 //-----------------------------------------------------------------------------
1102 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData
,wxObject
);
1104 wxListHeaderData::wxListHeaderData()
1115 wxListHeaderData::wxListHeaderData( const wxListItem
&item
)
1123 void wxListHeaderData::SetItem( const wxListItem
&item
)
1125 m_mask
= item
.m_mask
;
1126 m_text
= item
.m_text
;
1127 m_image
= item
.m_image
;
1128 m_format
= item
.m_format
;
1130 SetWidth(item
.m_width
);
1133 void wxListHeaderData::SetPosition( int x
, int y
)
1139 void wxListHeaderData::SetHeight( int h
)
1144 void wxListHeaderData::SetWidth( int w
)
1148 m_width
= WIDTH_COL_DEFAULT
;
1149 if (m_width
< WIDTH_COL_MIN
)
1150 m_width
= WIDTH_COL_MIN
;
1153 void wxListHeaderData::SetFormat( int format
)
1158 bool wxListHeaderData::HasImage() const
1160 return (m_image
!= 0);
1163 bool wxListHeaderData::IsHit( int x
, int y
) const
1165 return ((x
>= m_xpos
) && (x
<= m_xpos
+m_width
) && (y
>= m_ypos
) && (y
<= m_ypos
+m_height
));
1168 void wxListHeaderData::GetItem( wxListItem
&item
)
1170 item
.m_mask
= m_mask
;
1171 item
.m_text
= m_text
;
1172 item
.m_image
= m_image
;
1173 item
.m_format
= m_format
;
1174 item
.m_width
= m_width
;
1177 int wxListHeaderData::GetImage() const
1182 int wxListHeaderData::GetWidth() const
1187 int wxListHeaderData::GetFormat() const
1192 //-----------------------------------------------------------------------------
1194 //-----------------------------------------------------------------------------
1196 inline int wxListLineData::GetMode() const
1198 return m_owner
->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE
;
1201 inline bool wxListLineData::InReportView() const
1203 return m_owner
->HasFlag(wxLC_REPORT
);
1206 inline bool wxListLineData::IsVirtual() const
1208 return m_owner
->IsVirtual();
1211 wxListLineData::wxListLineData( wxListMainWindow
*owner
)
1214 m_items
.DeleteContents( TRUE
);
1216 if ( InReportView() )
1222 m_gi
= new GeometryInfo
;
1225 m_highlighted
= FALSE
;
1227 InitItems( GetMode() == wxLC_REPORT
? m_owner
->GetColumnCount() : 1 );
1230 void wxListLineData::CalculateSize( wxDC
*dc
, int spacing
)
1232 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1233 wxCHECK_RET( node
, _T("no subitems at all??") );
1235 wxListItemData
*item
= node
->GetData();
1237 switch ( GetMode() )
1240 case wxLC_SMALL_ICON
:
1242 m_gi
->m_rectAll
.width
= spacing
;
1244 wxString s
= item
->GetText();
1250 m_gi
->m_rectLabel
.width
=
1251 m_gi
->m_rectLabel
.height
= 0;
1255 dc
->GetTextExtent( s
, &lw
, &lh
);
1256 if (lh
< SCROLL_UNIT_Y
)
1261 m_gi
->m_rectAll
.height
= spacing
+ lh
;
1263 m_gi
->m_rectAll
.width
= lw
;
1265 m_gi
->m_rectLabel
.width
= lw
;
1266 m_gi
->m_rectLabel
.height
= lh
;
1269 if (item
->HasImage())
1272 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1273 m_gi
->m_rectIcon
.width
= w
+ 8;
1274 m_gi
->m_rectIcon
.height
= h
+ 8;
1276 if ( m_gi
->m_rectIcon
.width
> m_gi
->m_rectAll
.width
)
1277 m_gi
->m_rectAll
.width
= m_gi
->m_rectIcon
.width
;
1278 if ( m_gi
->m_rectIcon
.height
+ lh
> m_gi
->m_rectAll
.height
- 4 )
1279 m_gi
->m_rectAll
.height
= m_gi
->m_rectIcon
.height
+ lh
+ 4;
1282 if ( item
->HasText() )
1284 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectLabel
.width
;
1285 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectLabel
.height
;
1287 else // no text, highlight the icon
1289 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectIcon
.width
;
1290 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectIcon
.height
;
1297 wxString s
= item
->GetTextForMeasuring();
1300 dc
->GetTextExtent( s
, &lw
, &lh
);
1301 if (lh
< SCROLL_UNIT_Y
)
1306 m_gi
->m_rectLabel
.width
= lw
;
1307 m_gi
->m_rectLabel
.height
= lh
;
1309 m_gi
->m_rectAll
.width
= lw
;
1310 m_gi
->m_rectAll
.height
= lh
;
1312 if (item
->HasImage())
1315 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1316 m_gi
->m_rectIcon
.width
= w
;
1317 m_gi
->m_rectIcon
.height
= h
;
1319 m_gi
->m_rectAll
.width
+= 4 + w
;
1320 if (h
> m_gi
->m_rectAll
.height
)
1321 m_gi
->m_rectAll
.height
= h
;
1324 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectAll
.width
;
1325 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectAll
.height
;
1330 wxFAIL_MSG( _T("unexpected call to SetSize") );
1334 wxFAIL_MSG( _T("unknown mode") );
1338 void wxListLineData::SetPosition( int x
, int y
,
1342 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1343 wxCHECK_RET( node
, _T("no subitems at all??") );
1345 wxListItemData
*item
= node
->GetData();
1347 switch ( GetMode() )
1350 case wxLC_SMALL_ICON
:
1351 m_gi
->m_rectAll
.x
= x
;
1352 m_gi
->m_rectAll
.y
= y
;
1354 if ( item
->HasImage() )
1356 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 4
1357 + (spacing
- m_gi
->m_rectIcon
.width
)/2;
1358 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 4;
1361 if ( item
->HasText() )
1363 if (m_gi
->m_rectAll
.width
> spacing
)
1364 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1366 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2 + (spacing
/2) - (m_gi
->m_rectLabel
.width
/2);
1367 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ m_gi
->m_rectAll
.height
+ 2 - m_gi
->m_rectLabel
.height
;
1368 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectLabel
.x
- 2;
1369 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectLabel
.y
- 2;
1371 else // no text, highlight the icon
1373 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectIcon
.x
- 4;
1374 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectIcon
.y
- 4;
1379 m_gi
->m_rectAll
.x
= x
;
1380 m_gi
->m_rectAll
.y
= y
;
1382 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectAll
.x
;
1383 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectAll
.y
;
1384 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ 2;
1386 if (item
->HasImage())
1388 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 2;
1389 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 2;
1390 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 6 + m_gi
->m_rectIcon
.width
;
1394 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1399 wxFAIL_MSG( _T("unexpected call to SetPosition") );
1403 wxFAIL_MSG( _T("unknown mode") );
1407 void wxListLineData::InitItems( int num
)
1409 for (int i
= 0; i
< num
; i
++)
1410 m_items
.Append( new wxListItemData(m_owner
) );
1413 void wxListLineData::SetItem( int index
, const wxListItem
&info
)
1415 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1416 wxCHECK_RET( node
, _T("invalid column index in SetItem") );
1418 wxListItemData
*item
= node
->GetData();
1419 item
->SetItem( info
);
1422 void wxListLineData::GetItem( int index
, wxListItem
&info
)
1424 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1427 wxListItemData
*item
= node
->GetData();
1428 item
->GetItem( info
);
1432 wxString
wxListLineData::GetText(int index
) const
1436 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1439 wxListItemData
*item
= node
->GetData();
1440 s
= item
->GetText();
1446 void wxListLineData::SetText( int index
, const wxString s
)
1448 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1451 wxListItemData
*item
= node
->GetData();
1456 void wxListLineData::SetImage( int index
, int image
)
1458 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1459 wxCHECK_RET( node
, _T("invalid column index in SetImage()") );
1461 wxListItemData
*item
= node
->GetData();
1462 item
->SetImage(image
);
1465 int wxListLineData::GetImage( int index
) const
1467 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1468 wxCHECK_MSG( node
, -1, _T("invalid column index in GetImage()") );
1470 wxListItemData
*item
= node
->GetData();
1471 return item
->GetImage();
1474 void wxListLineData::SetAttributes(wxDC
*dc
,
1475 const wxListItemAttr
*attr
,
1476 const wxColour
& colText
,
1480 // don't use foregroud colour for drawing highlighted items - this might
1481 // make them completely invisible (and there is no way to do bit
1482 // arithmetics on wxColour, unfortunately)
1483 if ( !highlight
&& attr
&& attr
->HasTextColour() )
1485 dc
->SetTextForeground(attr
->GetTextColour());
1489 dc
->SetTextForeground(colText
);
1492 if ( attr
&& attr
->HasFont() )
1494 dc
->SetFont(attr
->GetFont());
1502 void wxListLineData::Draw( wxDC
*dc
)
1504 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1505 wxCHECK_RET( node
, _T("no subitems at all??") );
1507 wxListItemData
*item
= node
->GetData();
1508 if (item
->HasImage())
1510 wxRect rectIcon
= m_gi
->m_rectIcon
;
1511 m_owner
->DrawImage( item
->GetImage(), dc
,
1512 rectIcon
.x
, rectIcon
.y
);
1515 if (item
->HasText())
1517 wxRect rectLabel
= m_gi
->m_rectLabel
;
1518 dc
->DrawText( item
->GetText(), rectLabel
.x
, rectLabel
.y
);
1522 void wxListLineData::DrawInReportMode( wxDC
*dc
,
1524 const wxRect
& rectHL
,
1527 // use our own flag if we maintain it
1529 highlighted
= m_highlighted
;
1531 // default foreground colour
1532 wxWindow
*listctrl
= m_owner
->GetParent();
1536 colText
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT
);
1540 colText
= listctrl
->GetForegroundColour();
1544 wxFont font
= listctrl
->GetFont();
1546 // VZ: currently we set the colours/fonts only once, but like this (i.e.
1547 // using SetAttributes() inside the loop), it will be trivial to
1548 // customize the subitems (in report mode) too.
1549 wxListItemData
*item
= m_items
.GetFirst()->GetData();
1550 wxListItemAttr
*attr
= item
->GetAttributes();
1551 SetAttributes(dc
, attr
, colText
, font
, highlighted
);
1553 bool hasBgCol
= attr
&& attr
->HasBackgroundColour();
1554 if ( highlighted
|| hasBgCol
)
1558 dc
->SetBrush( *m_owner
->m_highlightBrush
);
1563 dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
));
1565 dc
->SetBrush( * wxWHITE_BRUSH
);
1568 dc
->SetPen( * wxTRANSPARENT_PEN
);
1569 dc
->DrawRectangle( rectHL
);
1572 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1573 wxCHECK_RET( node
, _T("no subitems at all??") );
1576 wxCoord x
= rect
.x
+ HEADER_OFFSET_X
,
1577 y
= rect
.y
+ (LINE_SPACING
+ EXTRA_HEIGHT
) / 2;
1581 wxListItemData
*item
= node
->GetData();
1585 if ( item
->HasImage() )
1588 m_owner
->DrawImage( item
->GetImage(), dc
, x
, y
);
1589 m_owner
->GetImageSize( item
->GetImage(), ix
, iy
);
1590 x
+= ix
+ 5; // FIXME: what is "5"?
1593 int width
= m_owner
->GetColumnWidth(col
++);
1595 wxDCClipper
clipper(*dc
, x
, y
, width
, rect
.height
);
1597 if ( item
->HasText() )
1599 dc
->DrawText( item
->GetText(), x
, y
);
1604 node
= node
->GetNext();
1608 bool wxListLineData::Highlight( bool on
)
1610 wxCHECK_MSG( !m_owner
->IsVirtual(), FALSE
, _T("unexpected call to Highlight") );
1612 if ( on
== m_highlighted
)
1620 void wxListLineData::ReverseHighlight( void )
1622 Highlight(!IsHighlighted());
1625 //-----------------------------------------------------------------------------
1626 // wxListHeaderWindow
1627 //-----------------------------------------------------------------------------
1629 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
);
1631 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
)
1632 EVT_PAINT (wxListHeaderWindow::OnPaint
)
1633 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse
)
1634 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus
)
1637 wxListHeaderWindow::wxListHeaderWindow( void )
1639 m_owner
= (wxListMainWindow
*) NULL
;
1640 m_currentCursor
= (wxCursor
*) NULL
;
1641 m_resizeCursor
= (wxCursor
*) NULL
;
1642 m_isDragging
= FALSE
;
1645 wxListHeaderWindow::wxListHeaderWindow( wxWindow
*win
, wxWindowID id
, wxListMainWindow
*owner
,
1646 const wxPoint
&pos
, const wxSize
&size
,
1647 long style
, const wxString
&name
) :
1648 wxWindow( win
, id
, pos
, size
, style
, name
)
1651 // m_currentCursor = wxSTANDARD_CURSOR;
1652 m_currentCursor
= (wxCursor
*) NULL
;
1653 m_resizeCursor
= new wxCursor( wxCURSOR_SIZEWE
);
1654 m_isDragging
= FALSE
;
1657 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
) );
1660 wxListHeaderWindow::~wxListHeaderWindow( void )
1662 delete m_resizeCursor
;
1665 void wxListHeaderWindow::DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
)
1668 GtkStateType state
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
1669 : GTK_STATE_INSENSITIVE
;
1671 x
= dc
->XLOG2DEV( x
);
1673 gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
,
1674 state
, GTK_SHADOW_OUT
,
1675 (GdkRectangle
*) NULL
, m_wxwindow
, "button",
1676 x
-1, y
-1, w
+2, h
+2);
1677 #elif defined( __WXMAC__ )
1678 const int m_corner
= 1;
1680 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1682 dc
->SetPen( wxPen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
) , 1 , wxSOLID
) );
1683 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1684 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1686 wxPen
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID
);
1689 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1690 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1692 dc
->SetPen( *wxWHITE_PEN
);
1693 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1694 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1695 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1696 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1698 const int m_corner
= 1;
1700 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1702 dc
->SetPen( *wxBLACK_PEN
);
1703 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1704 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1706 wxPen
pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
), 1, wxSOLID
);
1709 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1710 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1712 dc
->SetPen( *wxWHITE_PEN
);
1713 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1714 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1715 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1716 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1720 // shift the DC origin to match the position of the main window horz
1721 // scrollbar: this allows us to always use logical coords
1722 void wxListHeaderWindow::AdjustDC(wxDC
& dc
)
1725 m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL
);
1728 m_owner
->GetViewStart( &x
, NULL
);
1730 // account for the horz scrollbar offset
1731 dc
.SetDeviceOrigin( -x
* xpix
, 0 );
1734 void wxListHeaderWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
1737 wxClientDC
dc( this );
1739 wxPaintDC
dc( this );
1747 dc
.SetFont( GetFont() );
1749 // width and height of the entire header window
1751 GetClientSize( &w
, &h
);
1752 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1754 dc
.SetBackgroundMode(wxTRANSPARENT
);
1756 // do *not* use the listctrl colour for headers - one day we will have a
1757 // function to set it separately
1758 //dc.SetTextForeground( *wxBLACK );
1759 dc
.SetTextForeground(wxSystemSettings::
1760 GetSystemColour( wxSYS_COLOUR_WINDOWTEXT
));
1762 int x
= HEADER_OFFSET_X
;
1764 int numColumns
= m_owner
->GetColumnCount();
1766 for (int i
= 0; i
< numColumns
; i
++)
1768 m_owner
->GetColumn( i
, item
);
1769 int wCol
= item
.m_width
;
1770 int cw
= wCol
- 2; // the width of the rect to draw
1772 int xEnd
= x
+ wCol
;
1774 dc
.SetPen( *wxWHITE_PEN
);
1776 DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 );
1777 dc
.SetClippingRegion( x
, HEADER_OFFSET_Y
, cw
-5, h
-4 );
1778 dc
.DrawText( item
.GetText(), x
+ EXTRA_WIDTH
, HEADER_OFFSET_Y
+ EXTRA_HEIGHT
);
1779 dc
.DestroyClippingRegion();
1788 void wxListHeaderWindow::DrawCurrent()
1790 int x1
= m_currentX
;
1792 ClientToScreen( &x1
, &y1
);
1794 int x2
= m_currentX
-1;
1796 m_owner
->GetClientSize( NULL
, &y2
);
1797 m_owner
->ClientToScreen( &x2
, &y2
);
1800 dc
.SetLogicalFunction( wxINVERT
);
1801 dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID
) );
1802 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1806 dc
.DrawLine( x1
, y1
, x2
, y2
);
1808 dc
.SetLogicalFunction( wxCOPY
);
1810 dc
.SetPen( wxNullPen
);
1811 dc
.SetBrush( wxNullBrush
);
1814 void wxListHeaderWindow::OnMouse( wxMouseEvent
&event
)
1816 // we want to work with logical coords
1818 m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
);
1819 int y
= event
.GetY();
1823 // we don't draw the line beyond our window, but we allow dragging it
1826 GetClientSize( &w
, NULL
);
1827 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1830 // erase the line if it was drawn
1831 if ( m_currentX
< w
)
1834 if (event
.ButtonUp())
1837 m_isDragging
= FALSE
;
1839 m_owner
->SetColumnWidth( m_column
, m_currentX
- m_minX
);
1846 m_currentX
= m_minX
+ 7;
1848 // draw in the new location
1849 if ( m_currentX
< w
)
1853 else // not dragging
1856 bool hit_border
= FALSE
;
1858 // end of the current column
1861 // find the column where this event occured
1862 int countCol
= m_owner
->GetColumnCount();
1863 for (int col
= 0; col
< countCol
; col
++)
1865 xpos
+= m_owner
->GetColumnWidth( col
);
1868 if ( (abs(x
-xpos
) < 3) && (y
< 22) )
1870 // near the column border
1877 // inside the column
1884 if (event
.LeftDown())
1888 m_isDragging
= TRUE
;
1895 wxWindow
*parent
= GetParent();
1896 wxListEvent
le( wxEVT_COMMAND_LIST_COL_CLICK
, parent
->GetId() );
1897 le
.SetEventObject( parent
);
1898 le
.m_col
= m_column
;
1899 parent
->GetEventHandler()->ProcessEvent( le
);
1902 else if (event
.Moving())
1907 setCursor
= m_currentCursor
== wxSTANDARD_CURSOR
;
1908 m_currentCursor
= m_resizeCursor
;
1912 setCursor
= m_currentCursor
!= wxSTANDARD_CURSOR
;
1913 m_currentCursor
= wxSTANDARD_CURSOR
;
1917 SetCursor(*m_currentCursor
);
1922 void wxListHeaderWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
1924 m_owner
->SetFocus();
1927 //-----------------------------------------------------------------------------
1928 // wxListRenameTimer (internal)
1929 //-----------------------------------------------------------------------------
1931 wxListRenameTimer::wxListRenameTimer( wxListMainWindow
*owner
)
1936 void wxListRenameTimer::Notify()
1938 m_owner
->OnRenameTimer();
1941 //-----------------------------------------------------------------------------
1942 // wxListTextCtrl (internal)
1943 //-----------------------------------------------------------------------------
1945 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl
,wxTextCtrl
);
1947 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
)
1948 EVT_CHAR (wxListTextCtrl::OnChar
)
1949 EVT_KEY_UP (wxListTextCtrl::OnKeyUp
)
1950 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus
)
1953 wxListTextCtrl::wxListTextCtrl( wxWindow
*parent
,
1954 const wxWindowID id
,
1957 wxListMainWindow
*owner
,
1958 const wxString
&value
,
1962 const wxValidator
& validator
,
1963 const wxString
&name
)
1964 : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name
)
1969 (*m_accept
) = FALSE
;
1971 m_startValue
= value
;
1974 void wxListTextCtrl::OnChar( wxKeyEvent
&event
)
1976 if (event
.m_keyCode
== WXK_RETURN
)
1979 (*m_res
) = GetValue();
1981 if (!wxPendingDelete
.Member(this))
1982 wxPendingDelete
.Append(this);
1984 if ((*m_accept
) && ((*m_res
) != m_startValue
))
1985 m_owner
->OnRenameAccept();
1989 if (event
.m_keyCode
== WXK_ESCAPE
)
1991 (*m_accept
) = FALSE
;
1994 if (!wxPendingDelete
.Member(this))
1995 wxPendingDelete
.Append(this);
2003 void wxListTextCtrl::OnKeyUp( wxKeyEvent
&event
)
2005 // auto-grow the textctrl:
2006 wxSize parentSize
= m_owner
->GetSize();
2007 wxPoint myPos
= GetPosition();
2008 wxSize mySize
= GetSize();
2010 GetTextExtent(GetValue() + _T("MM"), &sx
, &sy
); // FIXME: MM??
2011 if (myPos
.x
+ sx
> parentSize
.x
)
2012 sx
= parentSize
.x
- myPos
.x
;
2020 void wxListTextCtrl::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
2022 if (!wxPendingDelete
.Member(this))
2023 wxPendingDelete
.Append(this);
2025 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2026 m_owner
->OnRenameAccept();
2029 //-----------------------------------------------------------------------------
2031 //-----------------------------------------------------------------------------
2033 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
);
2035 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
)
2036 EVT_PAINT (wxListMainWindow::OnPaint
)
2037 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse
)
2038 EVT_CHAR (wxListMainWindow::OnChar
)
2039 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown
)
2040 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus
)
2041 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus
)
2042 EVT_SCROLLWIN (wxListMainWindow::OnScroll
)
2045 void wxListMainWindow::Init()
2047 m_columns
.DeleteContents( TRUE
);
2051 m_lineTo
= (size_t)-1;
2057 m_small_image_list
= (wxImageList
*) NULL
;
2058 m_normal_image_list
= (wxImageList
*) NULL
;
2060 m_small_spacing
= 30;
2061 m_normal_spacing
= 40;
2065 m_isCreated
= FALSE
;
2067 m_lastOnSame
= FALSE
;
2068 m_renameTimer
= new wxListRenameTimer( this );
2069 m_renameAccept
= FALSE
;
2074 m_lineBeforeLastClicked
= (size_t)-1;
2077 void wxListMainWindow::InitScrolling()
2079 if ( HasFlag(wxLC_REPORT
) )
2081 m_xScroll
= SCROLL_UNIT_X
;
2082 m_yScroll
= SCROLL_UNIT_Y
;
2086 m_xScroll
= SCROLL_UNIT_Y
;
2091 wxListMainWindow::wxListMainWindow()
2095 m_highlightBrush
= (wxBrush
*) NULL
;
2101 wxListMainWindow::wxListMainWindow( wxWindow
*parent
,
2106 const wxString
&name
)
2107 : wxScrolledWindow( parent
, id
, pos
, size
,
2108 style
| wxHSCROLL
| wxVSCROLL
, name
)
2112 m_highlightBrush
= new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
), wxSOLID
);
2117 SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 );
2119 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX
) );
2122 wxListMainWindow::~wxListMainWindow()
2126 delete m_highlightBrush
;
2128 delete m_renameTimer
;
2131 void wxListMainWindow::CacheLineData(size_t line
)
2133 wxListCtrl
*listctrl
= GetListCtrl();
2135 wxListLineData
*ld
= GetDummyLine();
2137 size_t countCol
= GetColumnCount();
2138 for ( size_t col
= 0; col
< countCol
; col
++ )
2140 ld
->SetText(col
, listctrl
->OnGetItemText(line
, col
));
2143 ld
->SetImage(listctrl
->OnGetItemImage(line
));
2146 wxListLineData
*wxListMainWindow::GetDummyLine() const
2148 wxASSERT_MSG( !IsEmpty(), _T("invalid line index") );
2150 if ( m_lines
.IsEmpty() )
2152 // normal controls are supposed to have something in m_lines
2153 // already if it's not empty
2154 wxASSERT_MSG( IsVirtual(), _T("logic error") );
2156 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2157 wxListLineData
*line
= new wxListLineData(self
);
2158 self
->m_lines
.Add(line
);
2164 // ----------------------------------------------------------------------------
2165 // line geometry (report mode only)
2166 // ----------------------------------------------------------------------------
2168 wxCoord
wxListMainWindow::GetLineHeight() const
2170 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2172 // we cache the line height as calling GetTextExtent() is slow
2173 if ( !m_lineHeight
)
2175 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2177 wxClientDC
dc( self
);
2178 dc
.SetFont( GetFont() );
2181 dc
.GetTextExtent(_T("H"), NULL
, &y
);
2183 if ( y
< SCROLL_UNIT_Y
)
2187 self
->m_lineHeight
= y
+ LINE_SPACING
;
2190 return m_lineHeight
;
2193 wxCoord
wxListMainWindow::GetLineY(size_t line
) const
2195 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2197 return LINE_SPACING
+ line
*GetLineHeight();
2200 wxRect
wxListMainWindow::GetLineRect(size_t line
) const
2202 if ( !InReportView() )
2203 return GetLine(line
)->m_gi
->m_rectAll
;
2206 rect
.x
= HEADER_OFFSET_X
;
2207 rect
.y
= GetLineY(line
);
2208 rect
.width
= GetHeaderWidth();
2209 rect
.height
= GetLineHeight();
2214 wxRect
wxListMainWindow::GetLineLabelRect(size_t line
) const
2216 if ( !InReportView() )
2217 return GetLine(line
)->m_gi
->m_rectLabel
;
2220 rect
.x
= HEADER_OFFSET_X
;
2221 rect
.y
= GetLineY(line
);
2222 rect
.width
= GetColumnWidth(0);
2223 rect
.height
= GetLineHeight();
2228 wxRect
wxListMainWindow::GetLineIconRect(size_t line
) const
2230 if ( !InReportView() )
2231 return GetLine(line
)->m_gi
->m_rectIcon
;
2233 wxListLineData
*ld
= GetLine(line
);
2234 wxASSERT_MSG( ld
->HasImage(), _T("should have an image") );
2237 rect
.x
= HEADER_OFFSET_X
;
2238 rect
.y
= GetLineY(line
);
2239 GetImageSize(ld
->GetImage(), rect
.width
, rect
.height
);
2244 wxRect
wxListMainWindow::GetLineHighlightRect(size_t line
) const
2246 return InReportView() ? GetLineRect(line
)
2247 : GetLine(line
)->m_gi
->m_rectHighlight
;
2250 long wxListMainWindow::HitTestLine(size_t line
, int x
, int y
) const
2252 wxListLineData
*ld
= GetLine(line
);
2254 if ( ld
->HasImage() && GetLineIconRect(line
).Inside(x
, y
) )
2255 return wxLIST_HITTEST_ONITEMICON
;
2257 if ( ld
->HasText() )
2259 wxRect rect
= InReportView() ? GetLineRect(line
)
2260 : GetLineLabelRect(line
);
2262 if ( rect
.Inside(x
, y
) )
2263 return wxLIST_HITTEST_ONITEMLABEL
;
2269 // ----------------------------------------------------------------------------
2270 // highlight (selection) handling
2271 // ----------------------------------------------------------------------------
2273 bool wxListMainWindow::IsHighlighted(size_t line
) const
2277 return m_selStore
.IsSelected(line
);
2281 wxListLineData
*ld
= GetLine(line
);
2282 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2284 return ld
->IsHighlighted();
2288 void wxListMainWindow::HighlightLines( size_t lineFrom
, size_t lineTo
, bool highlight
)
2292 m_selStore
.SelectRange(lineFrom
, lineTo
, highlight
);
2293 RefreshLines(lineFrom
, lineTo
);
2297 // do it the dumb way
2298 bool needsRefresh
= FALSE
;
2299 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2301 if ( HighlightLine(line
, highlight
) )
2302 needsRefresh
= TRUE
;
2306 RefreshLines(lineFrom
, lineTo
);
2310 bool wxListMainWindow::HighlightLine( size_t line
, bool highlight
)
2316 changed
= m_selStore
.SelectItem(line
, highlight
);
2320 wxListLineData
*ld
= GetLine(line
);
2321 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2323 changed
= ld
->Highlight(highlight
);
2328 SendNotify( line
, highlight
? wxEVT_COMMAND_LIST_ITEM_SELECTED
2329 : wxEVT_COMMAND_LIST_ITEM_DESELECTED
);
2335 void wxListMainWindow::RefreshLine( size_t line
)
2337 wxRect rect
= GetLineRect(line
);
2339 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2340 RefreshRect( rect
);
2343 void wxListMainWindow::RefreshLines( size_t lineFrom
, size_t lineTo
)
2345 // we suppose that they are ordered by caller
2346 wxASSERT_MSG( lineFrom
<= lineTo
, _T("indices in disorder") );
2348 wxASSERT_MSG( lineTo
< GetItemCount(), _T("invalid line range") );
2350 if ( HasFlag(wxLC_REPORT
) )
2352 size_t visibleFrom
, visibleTo
;
2353 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2355 if ( lineFrom
< visibleFrom
)
2356 lineFrom
= visibleFrom
;
2357 if ( lineTo
> visibleTo
)
2362 rect
.y
= GetLineY(lineFrom
);
2363 rect
.width
= GetClientSize().x
;
2364 rect
.height
= GetLineY(lineTo
) - rect
.y
;
2366 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2367 RefreshRect( rect
);
2371 // TODO: this should be optimized...
2372 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2379 void wxListMainWindow::RefreshAfter( size_t lineFrom
)
2381 if ( HasFlag(wxLC_REPORT
) )
2384 GetVisibleLinesRange(&visibleFrom
, NULL
);
2386 if ( lineFrom
< visibleFrom
)
2387 lineFrom
= visibleFrom
;
2391 rect
.y
= GetLineY(lineFrom
);
2393 wxSize size
= GetClientSize();
2394 rect
.width
= size
.x
;
2395 // refresh till the bottom of the window
2396 rect
.height
= size
.y
- rect
.y
;
2398 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2399 RefreshRect( rect
);
2404 // TODO: how to do it more efficiently?
2409 void wxListMainWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
2411 // Note: a wxPaintDC must be constructed even if no drawing is
2412 // done (a Windows requirement).
2413 wxPaintDC
dc( this );
2417 // empty control. nothing to draw
2424 CalcScrolledPosition( 0, 0, &dev_x
, &dev_y
);
2428 dc
.SetFont( GetFont() );
2430 if ( HasFlag(wxLC_REPORT
) )
2432 int lineHeight
= GetLineHeight();
2434 size_t visibleFrom
, visibleTo
;
2435 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2436 for ( size_t line
= visibleFrom
; line
<= visibleTo
; line
++ )
2438 GetLine(line
)->DrawInReportMode( &dc
,
2440 GetLineHighlightRect(line
),
2441 IsHighlighted(line
) );
2444 if ( HasFlag(wxLC_HRULES
) )
2446 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2447 wxSize clientSize
= GetClientSize();
2449 for ( size_t i
= visibleFrom
; i
<= visibleTo
; i
++ )
2452 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2453 dc
.DrawLine(0 - dev_x
, i
*lineHeight
,
2454 clientSize
.x
- dev_x
, i
*lineHeight
);
2457 // Draw last horizontal rule
2458 if ( visibleTo
> visibleFrom
)
2461 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2462 dc
.DrawLine(0 - dev_x
, m_lineTo
*lineHeight
,
2463 clientSize
.x
- dev_x
, m_lineTo
*lineHeight
);
2467 // Draw vertical rules if required
2468 if ( HasFlag(wxLC_VRULES
) && !IsEmpty() )
2470 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2473 wxRect firstItemRect
;
2474 wxRect lastItemRect
;
2475 GetItemRect(0, firstItemRect
);
2476 GetItemRect(GetItemCount() - 1, lastItemRect
);
2477 int x
= firstItemRect
.GetX();
2479 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
2480 for (col
= 0; col
< GetColumnCount(); col
++)
2482 int colWidth
= GetColumnWidth(col
);
2484 dc
.DrawLine(x
- dev_x
, firstItemRect
.GetY() - 1 - dev_y
,
2485 x
- dev_x
, lastItemRect
.GetBottom() + 1 - dev_y
);
2491 size_t count
= GetItemCount();
2492 for ( size_t i
= 0; i
< count
; i
++ )
2494 GetLine(i
)->Draw( &dc
);
2498 if ( HasCurrent() && m_hasFocus
)
2501 // no rect outline, we already have the background color
2503 dc
.SetPen( *wxBLACK_PEN
);
2504 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2505 dc
.DrawRectangle( GetLineHighlightRect(m_current
) );
2512 void wxListMainWindow::HighlightAll( bool on
)
2514 if ( IsSingleSel() )
2516 wxASSERT_MSG( !on
, _T("can't do this in a single sel control") );
2518 // we just have one item to turn off
2519 if ( HasCurrent() && IsHighlighted(m_current
) )
2521 HighlightLine(m_current
, FALSE
);
2522 RefreshLine(m_current
);
2527 HighlightLines(0, GetItemCount() - 1, on
);
2531 void wxListMainWindow::SendNotify( size_t line
,
2532 wxEventType command
,
2535 wxListEvent
le( command
, GetParent()->GetId() );
2536 le
.SetEventObject( GetParent() );
2537 le
.m_itemIndex
= line
;
2539 // set only for events which have position
2540 if ( point
!= wxDefaultPosition
)
2541 le
.m_pointDrag
= point
;
2543 GetLine(line
)->GetItem( 0, le
.m_item
);
2544 GetParent()->GetEventHandler()->ProcessEvent( le
);
2547 void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line
) )
2549 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
2552 void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line
) )
2554 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
2557 void wxListMainWindow::EditLabel( long item
)
2559 wxCHECK_RET( (item
>= 0) && ((size_t)item
< GetItemCount()),
2560 wxT("wrong index in wxListCtrl::EditLabel()") );
2562 m_currentEdit
= (size_t)item
;
2564 wxListEvent
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() );
2565 le
.SetEventObject( GetParent() );
2566 le
.m_itemIndex
= item
;
2567 wxListLineData
*data
= GetLine(m_currentEdit
);
2568 wxCHECK_RET( data
, _T("invalid index in EditLabel()") );
2569 data
->GetItem( 0, le
.m_item
);
2570 GetParent()->GetEventHandler()->ProcessEvent( le
);
2572 if (!le
.IsAllowed())
2575 // We have to call this here because the label in question might just have
2576 // been added and no screen update taken place.
2580 wxClientDC
dc(this);
2583 wxString s
= data
->GetText(0);
2584 wxRect rectLabel
= GetLineLabelRect(m_currentEdit
);
2586 rectLabel
.x
= dc
.LogicalToDeviceX( rectLabel
.x
);
2587 rectLabel
.y
= dc
.LogicalToDeviceY( rectLabel
.y
);
2589 wxListTextCtrl
*text
= new wxListTextCtrl
2596 wxPoint(rectLabel
.x
-4,rectLabel
.y
-4),
2597 wxSize(rectLabel
.width
+11,rectLabel
.height
+8)
2602 void wxListMainWindow::OnRenameTimer()
2604 wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") );
2606 EditLabel( m_current
);
2609 void wxListMainWindow::OnRenameAccept()
2611 wxListEvent
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() );
2612 le
.SetEventObject( GetParent() );
2613 le
.m_itemIndex
= m_currentEdit
;
2615 wxListLineData
*data
= GetLine(m_currentEdit
);
2616 wxCHECK_RET( data
, _T("invalid index in OnRenameAccept()") );
2618 data
->GetItem( 0, le
.m_item
);
2619 le
.m_item
.m_text
= m_renameRes
;
2620 GetParent()->GetEventHandler()->ProcessEvent( le
);
2622 if (!le
.IsAllowed()) return;
2625 info
.m_mask
= wxLIST_MASK_TEXT
;
2626 info
.m_itemId
= le
.m_itemIndex
;
2627 info
.m_text
= m_renameRes
;
2628 info
.SetTextColour(le
.m_item
.GetTextColour());
2632 void wxListMainWindow::OnMouse( wxMouseEvent
&event
)
2634 event
.SetEventObject( GetParent() );
2635 if ( GetParent()->GetEventHandler()->ProcessEvent( event
) )
2638 if ( !HasCurrent() || IsEmpty() )
2644 if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() ||
2645 event
.ButtonDClick()) )
2648 int x
= event
.GetX();
2649 int y
= event
.GetY();
2650 CalcUnscrolledPosition( x
, y
, &x
, &y
);
2652 /* Did we actually hit an item ? */
2655 size_t count
= GetItemCount(),
2658 if ( HasFlag(wxLC_REPORT
) )
2660 current
= y
/ GetLineHeight();
2661 hitResult
= HitTestLine(current
, x
, y
);
2665 // TODO: optimize it too! this is less simple than for report view but
2666 // enumerating all items is still not a way to do it!!
2667 for ( current
= 0; current
< count
&& !hitResult
; current
++ )
2669 hitResult
= HitTestLine(current
, x
, y
);
2673 if (event
.Dragging())
2675 if (m_dragCount
== 0)
2676 m_dragStart
= wxPoint(x
,y
);
2680 if (m_dragCount
!= 3)
2683 int command
= event
.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2684 : wxEVT_COMMAND_LIST_BEGIN_DRAG
;
2686 wxListEvent
le( command
, GetParent()->GetId() );
2687 le
.SetEventObject( GetParent() );
2688 le
.m_pointDrag
= m_dragStart
;
2689 GetParent()->GetEventHandler()->ProcessEvent( le
);
2700 // outside of any item
2704 bool forceClick
= FALSE
;
2705 if (event
.ButtonDClick())
2707 m_renameTimer
->Stop();
2708 m_lastOnSame
= FALSE
;
2710 if ( current
== m_lineBeforeLastClicked
)
2712 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
);
2718 // the first click was on another item, so don't interpret this as
2719 // a double click, but as a simple click instead
2724 if (event
.LeftUp() && m_lastOnSame
)
2726 if ((current
== m_current
) &&
2727 (hitResult
== wxLIST_HITTEST_ONITEMLABEL
) &&
2728 HasFlag(wxLC_EDIT_LABELS
) )
2730 m_renameTimer
->Start( 100, TRUE
);
2732 m_lastOnSame
= FALSE
;
2734 else if (event
.RightDown())
2736 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
,
2737 event
.GetPosition() );
2739 else if (event
.MiddleDown())
2741 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
);
2743 else if ( event
.LeftDown() || forceClick
)
2745 m_lineBeforeLastClicked
= m_lineLastClicked
;
2746 m_lineLastClicked
= current
;
2748 size_t oldCurrent
= m_current
;
2750 if ( IsSingleSel() || !(event
.ControlDown() || event
.ShiftDown()) )
2752 HighlightAll( FALSE
);
2753 m_current
= current
;
2755 ReverseHighlight(m_current
);
2757 else // multi sel & either ctrl or shift is down
2759 if (event
.ControlDown())
2761 m_current
= current
;
2763 ReverseHighlight(m_current
);
2765 else if (event
.ShiftDown())
2767 m_current
= current
;
2769 size_t lineFrom
= oldCurrent
,
2772 if ( lineTo
< lineFrom
)
2775 lineFrom
= m_current
;
2778 HighlightLines(lineFrom
, lineTo
);
2780 else // !ctrl, !shift
2782 // test in the enclosing if should make it impossible
2783 wxFAIL_MSG( _T("how did we get here?") );
2787 if (m_current
!= oldCurrent
)
2789 RefreshLine( oldCurrent
);
2790 OnUnfocusLine( oldCurrent
);
2791 OnFocusLine( m_current
);
2794 // forceClick is only set if the previous click was on another item
2795 m_lastOnSame
= !forceClick
&& (m_current
== oldCurrent
);
2799 void wxListMainWindow::MoveToFocus()
2801 if ( !HasCurrent() )
2804 wxRect rect
= GetLineRect(m_current
);
2806 int client_w
, client_h
;
2807 GetClientSize( &client_w
, &client_h
);
2809 int view_x
= m_xScroll
*GetScrollPos( wxHORIZONTAL
);
2810 int view_y
= m_yScroll
*GetScrollPos( wxVERTICAL
);
2812 if ( HasFlag(wxLC_REPORT
) )
2814 // the next we need the range of lines shown it might be different, so
2816 ResetVisibleLinesRange();
2818 if (rect
.y
< view_y
)
2819 Scroll( -1, rect
.y
/m_yScroll
);
2820 if (rect
.y
+rect
.height
+5 > view_y
+client_h
)
2821 Scroll( -1, (rect
.y
+rect
.height
-client_h
+SCROLL_UNIT_Y
)/m_yScroll
);
2825 if (rect
.x
-view_x
< 5)
2826 Scroll( (rect
.x
-5)/m_xScroll
, -1 );
2827 if (rect
.x
+rect
.width
-5 > view_x
+client_w
)
2828 Scroll( (rect
.x
+rect
.width
-client_w
+SCROLL_UNIT_X
)/m_xScroll
, -1 );
2832 // ----------------------------------------------------------------------------
2833 // keyboard handling
2834 // ----------------------------------------------------------------------------
2836 void wxListMainWindow::OnArrowChar(size_t newCurrent
, const wxKeyEvent
& event
)
2838 wxCHECK_RET( newCurrent
< (size_t)GetItemCount(),
2839 _T("invalid item index in OnArrowChar()") );
2841 size_t oldCurrent
= m_current
;
2843 // in single selection we just ignore Shift as we can't select several
2845 if ( event
.ShiftDown() && !IsSingleSel() )
2847 m_current
= newCurrent
;
2849 // select all the items between the old and the new one
2850 if ( oldCurrent
> newCurrent
)
2852 newCurrent
= oldCurrent
;
2853 oldCurrent
= m_current
;
2856 HighlightLines(oldCurrent
, newCurrent
);
2860 // all previously selected items are unselected unless ctrl is held
2861 if ( !event
.ControlDown() )
2862 HighlightAll(FALSE
);
2864 m_current
= newCurrent
;
2866 HighlightLine( oldCurrent
, FALSE
);
2867 RefreshLine( oldCurrent
);
2869 if ( !event
.ControlDown() )
2871 HighlightLine( m_current
, TRUE
);
2875 OnUnfocusLine( oldCurrent
);
2876 OnFocusLine( m_current
);
2877 RefreshLine( m_current
);
2882 void wxListMainWindow::OnKeyDown( wxKeyEvent
&event
)
2884 wxWindow
*parent
= GetParent();
2886 /* we propagate the key event up */
2887 wxKeyEvent
ke( wxEVT_KEY_DOWN
);
2888 ke
.m_shiftDown
= event
.m_shiftDown
;
2889 ke
.m_controlDown
= event
.m_controlDown
;
2890 ke
.m_altDown
= event
.m_altDown
;
2891 ke
.m_metaDown
= event
.m_metaDown
;
2892 ke
.m_keyCode
= event
.m_keyCode
;
2895 ke
.SetEventObject( parent
);
2896 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2901 void wxListMainWindow::OnChar( wxKeyEvent
&event
)
2903 wxWindow
*parent
= GetParent();
2905 /* we send a list_key event up */
2908 wxListEvent
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() );
2909 le
.m_itemIndex
= m_current
;
2910 GetLine(m_current
)->GetItem( 0, le
.m_item
);
2911 le
.m_code
= (int)event
.KeyCode();
2912 le
.SetEventObject( parent
);
2913 parent
->GetEventHandler()->ProcessEvent( le
);
2916 /* we propagate the char event up */
2917 wxKeyEvent
ke( wxEVT_CHAR
);
2918 ke
.m_shiftDown
= event
.m_shiftDown
;
2919 ke
.m_controlDown
= event
.m_controlDown
;
2920 ke
.m_altDown
= event
.m_altDown
;
2921 ke
.m_metaDown
= event
.m_metaDown
;
2922 ke
.m_keyCode
= event
.m_keyCode
;
2925 ke
.SetEventObject( parent
);
2926 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2928 if (event
.KeyCode() == WXK_TAB
)
2930 wxNavigationKeyEvent nevent
;
2931 nevent
.SetWindowChange( event
.ControlDown() );
2932 nevent
.SetDirection( !event
.ShiftDown() );
2933 nevent
.SetEventObject( GetParent()->GetParent() );
2934 nevent
.SetCurrentFocus( m_parent
);
2935 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent
)) return;
2938 /* no item -> nothing to do */
2945 switch (event
.KeyCode())
2948 if ( m_current
> 0 )
2949 OnArrowChar( m_current
- 1, event
);
2953 if ( m_current
< (size_t)GetItemCount() - 1 )
2954 OnArrowChar( m_current
+ 1, event
);
2959 OnArrowChar( GetItemCount() - 1, event
);
2964 OnArrowChar( 0, event
);
2970 if ( HasFlag(wxLC_REPORT
) )
2972 steps
= m_linesPerPage
- 1;
2976 steps
= m_current
% m_linesPerPage
;
2979 int index
= m_current
- steps
;
2983 OnArrowChar( index
, event
);
2990 if ( HasFlag(wxLC_REPORT
) )
2992 steps
= m_linesPerPage
- 1;
2996 steps
= m_linesPerPage
- (m_current
% m_linesPerPage
) - 1;
2999 size_t index
= m_current
+ steps
;
3000 size_t count
= GetItemCount();
3001 if ( index
>= count
)
3004 OnArrowChar( index
, event
);
3009 if ( !HasFlag(wxLC_REPORT
) )
3011 int index
= m_current
- m_linesPerPage
;
3015 OnArrowChar( index
, event
);
3020 if ( !HasFlag(wxLC_REPORT
) )
3022 size_t index
= m_current
+ m_linesPerPage
;
3024 size_t count
= GetItemCount();
3025 if ( index
>= count
)
3028 OnArrowChar( index
, event
);
3033 if ( IsSingleSel() )
3035 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3036 GetParent()->GetId() );
3037 le
.SetEventObject( GetParent() );
3038 le
.m_itemIndex
= m_current
;
3039 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3040 GetParent()->GetEventHandler()->ProcessEvent( le
);
3044 ReverseHighlight(m_current
);
3051 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3052 GetParent()->GetId() );
3053 le
.SetEventObject( GetParent() );
3054 le
.m_itemIndex
= m_current
;
3055 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3056 GetParent()->GetEventHandler()->ProcessEvent( le
);
3065 // ----------------------------------------------------------------------------
3067 // ----------------------------------------------------------------------------
3070 extern wxWindow
*g_focusWindow
;
3073 void wxListMainWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
3078 RefreshLine( m_current
);
3084 g_focusWindow
= GetParent();
3087 wxFocusEvent
event( wxEVT_SET_FOCUS
, GetParent()->GetId() );
3088 event
.SetEventObject( GetParent() );
3089 GetParent()->GetEventHandler()->ProcessEvent( event
);
3092 void wxListMainWindow::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
3097 RefreshLine( m_current
);
3100 void wxListMainWindow::DrawImage( int index
, wxDC
*dc
, int x
, int y
)
3102 if ( HasFlag(wxLC_ICON
) && (m_normal_image_list
))
3104 m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3106 else if ( HasFlag(wxLC_SMALL_ICON
) && (m_small_image_list
))
3108 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3110 else if ( HasFlag(wxLC_LIST
) && (m_small_image_list
))
3112 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3114 else if ( HasFlag(wxLC_REPORT
) && (m_small_image_list
))
3116 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3120 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height
) const
3122 if ( HasFlag(wxLC_ICON
) && m_normal_image_list
)
3124 m_normal_image_list
->GetSize( index
, width
, height
);
3126 else if ( HasFlag(wxLC_SMALL_ICON
) && m_small_image_list
)
3128 m_small_image_list
->GetSize( index
, width
, height
);
3130 else if ( HasFlag(wxLC_LIST
) && m_small_image_list
)
3132 m_small_image_list
->GetSize( index
, width
, height
);
3134 else if ( HasFlag(wxLC_REPORT
) && m_small_image_list
)
3136 m_small_image_list
->GetSize( index
, width
, height
);
3145 int wxListMainWindow::GetTextLength( const wxString
&s
) const
3147 wxClientDC
dc( wxConstCast(this, wxListMainWindow
) );
3148 dc
.SetFont( GetFont() );
3151 dc
.GetTextExtent( s
, &lw
, NULL
);
3153 return lw
+ AUTOSIZE_COL_MARGIN
;
3156 void wxListMainWindow::SetImageList( wxImageList
*imageList
, int which
)
3160 // calc the spacing from the icon size
3163 if ((imageList
) && (imageList
->GetImageCount()) )
3165 imageList
->GetSize(0, width
, height
);
3168 if (which
== wxIMAGE_LIST_NORMAL
)
3170 m_normal_image_list
= imageList
;
3171 m_normal_spacing
= width
+ 8;
3174 if (which
== wxIMAGE_LIST_SMALL
)
3176 m_small_image_list
= imageList
;
3177 m_small_spacing
= width
+ 14;
3181 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall
)
3186 m_small_spacing
= spacing
;
3190 m_normal_spacing
= spacing
;
3194 int wxListMainWindow::GetItemSpacing( bool isSmall
)
3196 return isSmall
? m_small_spacing
: m_normal_spacing
;
3199 // ----------------------------------------------------------------------------
3201 // ----------------------------------------------------------------------------
3203 void wxListMainWindow::SetColumn( int col
, wxListItem
&item
)
3205 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3207 wxCHECK_RET( node
, _T("invalid column index in SetColumn") );
3209 if ( item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3210 item
.m_width
= GetTextLength( item
.m_text
);
3212 wxListHeaderData
*column
= node
->GetData();
3213 column
->SetItem( item
);
3215 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3217 headerWin
->m_dirty
= TRUE
;
3221 // invalidate it as it has to be recalculated
3225 void wxListMainWindow::SetColumnWidth( int col
, int width
)
3227 wxCHECK_RET( col
>= 0 && col
< GetColumnCount(),
3228 _T("invalid column index") );
3230 wxCHECK_RET( HasFlag(wxLC_REPORT
),
3231 _T("SetColumnWidth() can only be called in report mode.") );
3235 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3236 wxCHECK_RET( node
, _T("no column?") );
3238 wxListHeaderData
*column
= node
->GetData();
3240 size_t count
= GetItemCount();
3242 if (width
== wxLIST_AUTOSIZE_USEHEADER
)
3244 width
= GetTextLength(column
->GetText());
3246 else if ( width
== wxLIST_AUTOSIZE
)
3250 // TODO: determine the max width somehow...
3251 width
= WIDTH_COL_DEFAULT
;
3255 wxClientDC
dc(this);
3256 dc
.SetFont( GetFont() );
3258 int max
= AUTOSIZE_COL_MARGIN
;
3260 for ( size_t i
= 0; i
< count
; i
++ )
3262 wxListLineData
*line
= GetLine(i
);
3263 wxListItemDataList::Node
*n
= line
->m_items
.Item( col
);
3265 wxCHECK_RET( n
, _T("no subitem?") );
3267 wxListItemData
*item
= n
->GetData();
3270 if (item
->HasImage())
3273 GetImageSize( item
->GetImage(), ix
, iy
);
3277 if (item
->HasText())
3280 dc
.GetTextExtent( item
->GetText(), &w
, NULL
);
3288 width
= max
+ AUTOSIZE_COL_MARGIN
;
3292 column
->SetWidth( width
);
3294 // invalidate it as it has to be recalculated
3298 int wxListMainWindow::GetHeaderWidth() const
3300 if ( !m_headerWidth
)
3302 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
3304 size_t count
= GetColumnCount();
3305 for ( size_t col
= 0; col
< count
; col
++ )
3307 self
->m_headerWidth
+= GetColumnWidth(col
);
3311 return m_headerWidth
;
3314 void wxListMainWindow::GetColumn( int col
, wxListItem
&item
) const
3316 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3317 wxCHECK_RET( node
, _T("invalid column index in GetColumn") );
3319 wxListHeaderData
*column
= node
->GetData();
3320 column
->GetItem( item
);
3323 int wxListMainWindow::GetColumnWidth( int col
) const
3325 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3326 wxCHECK_MSG( node
, 0, _T("invalid column index") );
3328 wxListHeaderData
*column
= node
->GetData();
3329 return column
->GetWidth();
3332 // ----------------------------------------------------------------------------
3334 // ----------------------------------------------------------------------------
3336 void wxListMainWindow::SetItem( wxListItem
&item
)
3338 long id
= item
.m_itemId
;
3339 wxCHECK_RET( id
>= 0 && (size_t)id
< GetItemCount(),
3340 _T("invalid item index in SetItem") );
3344 // just refresh the line to show the new value of the text/image
3345 RefreshLine((size_t)id
);
3351 wxListLineData
*line
= GetLine((size_t)id
);
3352 if ( HasFlag(wxLC_REPORT
) )
3353 item
.m_width
= GetColumnWidth( item
.m_col
);
3354 line
->SetItem( item
.m_col
, item
);
3358 void wxListMainWindow::SetItemState( long litem
, long state
, long stateMask
)
3360 wxCHECK_RET( litem
>= 0 && (size_t)litem
< GetItemCount(),
3361 _T("invalid list ctrl item index in SetItem") );
3363 size_t oldCurrent
= m_current
;
3364 size_t item
= (size_t)litem
; // sdafe because of the check above
3366 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3368 if ( state
& wxLIST_STATE_FOCUSED
)
3370 // don't do anything if this item is already focused
3371 if ( item
!= m_current
)
3373 OnUnfocusLine( m_current
);
3375 OnFocusLine( m_current
);
3377 if ( IsSingleSel() && (oldCurrent
!= (size_t)-1) )
3379 HighlightLine(oldCurrent
, FALSE
);
3380 RefreshLine(oldCurrent
);
3383 RefreshLine( m_current
);
3388 // don't do anything if this item is not focused
3389 if ( item
== m_current
)
3391 OnUnfocusLine( m_current
);
3392 m_current
= (size_t)-1;
3397 if ( stateMask
& wxLIST_STATE_SELECTED
)
3399 bool on
= (state
& wxLIST_STATE_SELECTED
) != 0;
3401 if ( IsSingleSel() )
3405 // selecting the item also makes it the focused one in the
3407 if ( m_current
!= item
)
3409 OnUnfocusLine( m_current
);
3411 OnFocusLine( m_current
);
3413 if ( oldCurrent
!= (size_t)-1 )
3415 HighlightLine( oldCurrent
, FALSE
);
3416 RefreshLine( oldCurrent
);
3422 // only the current item may be selected anyhow
3423 if ( item
!= m_current
)
3428 if ( HighlightLine(item
, on
) )
3435 int wxListMainWindow::GetItemState( long item
, long stateMask
)
3437 wxCHECK_MSG( item
>= 0 && (size_t)item
< GetItemCount(), 0,
3438 _T("invalid list ctrl item index in GetItemState()") );
3440 int ret
= wxLIST_STATE_DONTCARE
;
3442 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3444 if ( (size_t)item
== m_current
)
3445 ret
|= wxLIST_STATE_FOCUSED
;
3448 if ( stateMask
& wxLIST_STATE_SELECTED
)
3450 if ( IsHighlighted(item
) )
3451 ret
|= wxLIST_STATE_SELECTED
;
3457 void wxListMainWindow::GetItem( wxListItem
&item
)
3459 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
< GetItemCount(),
3460 _T("invalid item index in GetItem") );
3462 wxListLineData
*line
= GetLine((size_t)item
.m_itemId
);
3463 line
->GetItem( item
.m_col
, item
);
3466 // ----------------------------------------------------------------------------
3468 // ----------------------------------------------------------------------------
3470 size_t wxListMainWindow::GetItemCount() const
3472 return IsVirtual() ? m_countVirt
: m_lines
.GetCount();
3475 void wxListMainWindow::SetItemCount(long count
)
3477 m_selStore
.SetItemCount(count
);
3478 m_countVirt
= count
;
3483 int wxListMainWindow::GetSelectedItemCount()
3485 // deal with the quick case first
3486 if ( IsSingleSel() )
3488 return HasCurrent() ? IsHighlighted(m_current
) : FALSE
;
3491 // virtual controls remmebers all its selections itself
3493 return m_selStore
.GetSelectedCount();
3495 // TODO: we probably should maintain the number of items selected even for
3496 // non virtual controls as enumerating all lines is really slow...
3497 size_t countSel
= 0;
3498 size_t count
= GetItemCount();
3499 for ( size_t line
= 0; line
< count
; line
++ )
3501 if ( GetLine(line
)->IsHighlighted() )
3508 // ----------------------------------------------------------------------------
3509 // item position/size
3510 // ----------------------------------------------------------------------------
3512 void wxListMainWindow::GetItemRect( long index
, wxRect
&rect
)
3514 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3515 _T("invalid index in GetItemRect") );
3517 rect
= GetLineRect((size_t)index
);
3519 CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
3522 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
)
3525 GetItemRect(item
, rect
);
3533 // ----------------------------------------------------------------------------
3534 // geometry calculation
3535 // ----------------------------------------------------------------------------
3537 void wxListMainWindow::RecalculatePositions()
3542 wxClientDC
dc( this );
3543 dc
.SetFont( GetFont() );
3546 if ( HasFlag(wxLC_ICON
) )
3547 iconSpacing
= m_normal_spacing
;
3548 else if ( HasFlag(wxLC_SMALL_ICON
) )
3549 iconSpacing
= m_small_spacing
;
3555 GetClientSize( &clientWidth
, &clientHeight
);
3557 if ( HasFlag(wxLC_REPORT
) )
3559 // all lines have the same height
3560 int lineHeight
= GetLineHeight();
3562 // scroll one line per step
3563 m_yScroll
= lineHeight
;
3565 size_t lineCount
= GetItemCount();
3566 int entireHeight
= lineCount
*lineHeight
+ LINE_SPACING
;
3568 m_linesPerPage
= clientHeight
/ lineHeight
;
3570 ResetVisibleLinesRange();
3572 SetScrollbars( m_xScroll
, m_yScroll
,
3573 (GetHeaderWidth() + m_xScroll
- 1)/m_xScroll
,
3574 (entireHeight
+ m_yScroll
- 1)/m_yScroll
,
3575 GetScrollPos(wxHORIZONTAL
),
3576 GetScrollPos(wxVERTICAL
),
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
= GetLineSize(i
);
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
- 1 )
3738 SendNotify( index
, wxEVT_COMMAND_LIST_DELETE_ITEM
);
3740 if ( InReportView() )
3742 ResetVisibleLinesRange();
3749 m_selStore
.OnItemDelete(index
);
3753 m_lines
.RemoveAt( index
);
3756 RefreshAfter(index
);
3759 void wxListMainWindow::DeleteColumn( int col
)
3761 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3763 wxCHECK_RET( node
, wxT("invalid column index in DeleteColumn()") );
3766 m_columns
.DeleteNode( node
);
3769 void wxListMainWindow::DeleteAllItems()
3773 // nothing to do - in particular, don't send the event
3781 // to make the deletion of all items faster, we don't send the
3782 // notifications for each item deletion in this case but only one event
3783 // for all of them: this is compatible with wxMSW and documented in
3784 // DeleteAllItems() description
3786 wxListEvent
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() );
3787 event
.SetEventObject( GetParent() );
3788 GetParent()->GetEventHandler()->ProcessEvent( event
);
3794 ResetVisibleLinesRange();
3797 if ( InReportView() )
3799 ResetVisibleLinesRange();
3807 void wxListMainWindow::DeleteEverything()
3814 // ----------------------------------------------------------------------------
3815 // scanning for an item
3816 // ----------------------------------------------------------------------------
3818 void wxListMainWindow::EnsureVisible( long index
)
3820 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3821 _T("invalid index in EnsureVisible") );
3823 // We have to call this here because the label in question might just have
3824 // been added and no screen update taken place.
3828 size_t oldCurrent
= m_current
;
3829 m_current
= (size_t)index
;
3831 m_current
= oldCurrent
;
3834 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) )
3841 size_t count
= GetItemCount();
3842 for ( size_t i
= (size_t)pos
; i
< count
; i
++ )
3844 wxListLineData
*line
= GetLine(i
);
3845 if ( line
->GetText(0) == tmp
)
3852 long wxListMainWindow::FindItem(long start
, long data
)
3858 size_t count
= GetItemCount();
3859 for (size_t i
= (size_t)pos
; i
< count
; i
++)
3861 wxListLineData
*line
= GetLine(i
);
3863 line
->GetItem( 0, item
);
3864 if (item
.m_data
== data
)
3871 long wxListMainWindow::HitTest( int x
, int y
, int &flags
)
3873 CalcUnscrolledPosition( x
, y
, &x
, &y
);
3875 if ( HasFlag(wxLC_REPORT
) )
3877 size_t current
= y
/ GetLineHeight();
3878 flags
= HitTestLine(current
, x
, y
);
3884 // TODO: optimize it too! this is less simple than for report view but
3885 // enumerating all items is still not a way to do it!!
3886 size_t count
= GetItemCount();
3887 for ( size_t current
= 0; current
< count
; current
++ )
3889 flags
= HitTestLine(current
, x
, y
);
3898 // ----------------------------------------------------------------------------
3900 // ----------------------------------------------------------------------------
3902 void wxListMainWindow::InsertItem( wxListItem
&item
)
3904 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") );
3906 size_t count
= GetItemCount();
3907 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
<= count
,
3908 _T("invalid item index") );
3910 size_t id
= item
.m_itemId
;
3915 if ( HasFlag(wxLC_REPORT
) )
3917 else if ( HasFlag(wxLC_LIST
) )
3919 else if ( HasFlag(wxLC_ICON
) )
3921 else if ( HasFlag(wxLC_SMALL_ICON
) )
3922 mode
= wxLC_ICON
; // no typo
3925 wxFAIL_MSG( _T("unknown mode") );
3928 wxListLineData
*line
= new wxListLineData(this);
3930 line
->SetItem( 0, item
);
3932 m_lines
.Insert( line
, id
);
3934 RefreshLines(id
, GetItemCount() - 1);
3937 void wxListMainWindow::InsertColumn( long col
, wxListItem
&item
)
3940 if ( HasFlag(wxLC_REPORT
) )
3942 if (item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3943 item
.m_width
= GetTextLength( item
.m_text
);
3944 wxListHeaderData
*column
= new wxListHeaderData( item
);
3945 if ((col
>= 0) && (col
< (int)m_columns
.GetCount()))
3947 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3948 m_columns
.Insert( node
, column
);
3952 m_columns
.Append( column
);
3957 // ----------------------------------------------------------------------------
3959 // ----------------------------------------------------------------------------
3961 wxListCtrlCompare list_ctrl_compare_func_2
;
3962 long list_ctrl_compare_data
;
3964 int LINKAGEMODE
list_ctrl_compare_func_1( wxListLineData
**arg1
, wxListLineData
**arg2
)
3966 wxListLineData
*line1
= *arg1
;
3967 wxListLineData
*line2
= *arg2
;
3969 line1
->GetItem( 0, item
);
3970 long data1
= item
.m_data
;
3971 line2
->GetItem( 0, item
);
3972 long data2
= item
.m_data
;
3973 return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data
);
3976 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data
)
3978 list_ctrl_compare_func_2
= fn
;
3979 list_ctrl_compare_data
= data
;
3980 m_lines
.Sort( list_ctrl_compare_func_1
);
3984 // ----------------------------------------------------------------------------
3986 // ----------------------------------------------------------------------------
3988 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
)
3990 // update our idea of which lines are shown when we redraw the window the
3992 ResetVisibleLinesRange();
3995 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
3996 wxScrolledWindow::OnScroll(event
);
3998 HandleOnScroll( event
);
4001 if ( event
.GetOrientation() == wxHORIZONTAL
&& HasHeader() )
4003 wxListCtrl
* lc
= GetListCtrl();
4004 wxCHECK_RET( lc
, _T("no listctrl window?") );
4006 lc
->m_headerWin
->Refresh() ;
4008 lc
->m_headerWin
->MacUpdateImmediately() ;
4013 int wxListMainWindow::GetCountPerPage() const
4015 if ( !m_linesPerPage
)
4017 wxConstCast(this, wxListMainWindow
)->
4018 m_linesPerPage
= GetClientSize().y
/ GetLineHeight();
4021 return m_linesPerPage
;
4024 void wxListMainWindow::GetVisibleLinesRange(size_t *from
, size_t *to
)
4026 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("this is for report mode only") );
4028 if ( m_lineFrom
== (size_t)-1 )
4030 size_t count
= GetItemCount();
4033 m_lineFrom
= GetScrollPos(wxVERTICAL
);
4035 wxASSERT_MSG( m_lineFrom
< count
, _T("invalid scroll position?") );
4037 // we redraw one extra line but this is needed to make the redrawing
4038 // logic work when there is a fractional number of lines on screen
4039 m_lineTo
= m_lineFrom
+ m_linesPerPage
;
4040 if ( m_lineTo
>= count
)
4041 m_lineTo
= count
- 1;
4043 else // empty control
4046 m_lineTo
= (size_t)-1;
4050 wxASSERT_MSG( m_lineFrom
<= m_lineTo
&& m_lineTo
< GetItemCount(),
4051 _T("GetVisibleLinesRange() returns incorrect result") );
4059 // -------------------------------------------------------------------------------------
4061 // -------------------------------------------------------------------------------------
4063 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
)
4065 wxListItem::wxListItem()
4074 m_format
= wxLIST_FORMAT_CENTRE
;
4080 void wxListItem::Clear()
4089 m_format
= wxLIST_FORMAT_CENTRE
;
4096 void wxListItem::ClearAttributes()
4105 // -------------------------------------------------------------------------------------
4107 // -------------------------------------------------------------------------------------
4109 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
)
4111 wxListEvent::wxListEvent( wxEventType commandType
, int id
)
4112 : wxNotifyEvent( commandType
, id
)
4118 m_cancelled
= FALSE
;
4123 void wxListEvent::CopyObject(wxObject
& object_dest
) const
4125 wxListEvent
*obj
= (wxListEvent
*)&object_dest
;
4127 wxNotifyEvent::CopyObject(object_dest
);
4129 obj
->m_code
= m_code
;
4130 obj
->m_itemIndex
= m_itemIndex
;
4131 obj
->m_oldItemIndex
= m_oldItemIndex
;
4133 obj
->m_cancelled
= m_cancelled
;
4134 obj
->m_pointDrag
= m_pointDrag
;
4135 obj
->m_item
.m_mask
= m_item
.m_mask
;
4136 obj
->m_item
.m_itemId
= m_item
.m_itemId
;
4137 obj
->m_item
.m_col
= m_item
.m_col
;
4138 obj
->m_item
.m_state
= m_item
.m_state
;
4139 obj
->m_item
.m_stateMask
= m_item
.m_stateMask
;
4140 obj
->m_item
.m_text
= m_item
.m_text
;
4141 obj
->m_item
.m_image
= m_item
.m_image
;
4142 obj
->m_item
.m_data
= m_item
.m_data
;
4143 obj
->m_item
.m_format
= m_item
.m_format
;
4144 obj
->m_item
.m_width
= m_item
.m_width
;
4146 if ( m_item
.HasAttributes() )
4148 obj
->m_item
.SetTextColour(m_item
.GetTextColour());
4152 // -------------------------------------------------------------------------------------
4154 // -------------------------------------------------------------------------------------
4156 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
)
4158 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
)
4159 EVT_SIZE(wxListCtrl::OnSize
)
4160 EVT_IDLE(wxListCtrl::OnIdle
)
4163 wxListCtrl::wxListCtrl()
4165 m_imageListNormal
= (wxImageList
*) NULL
;
4166 m_imageListSmall
= (wxImageList
*) NULL
;
4167 m_imageListState
= (wxImageList
*) NULL
;
4169 m_ownsImageListNormal
=
4170 m_ownsImageListSmall
=
4171 m_ownsImageListState
= FALSE
;
4173 m_mainWin
= (wxListMainWindow
*) NULL
;
4174 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4177 wxListCtrl::~wxListCtrl()
4180 m_mainWin
->ResetCurrent();
4182 if (m_ownsImageListNormal
)
4183 delete m_imageListNormal
;
4184 if (m_ownsImageListSmall
)
4185 delete m_imageListSmall
;
4186 if (m_ownsImageListState
)
4187 delete m_imageListState
;
4190 void wxListCtrl::CreateHeaderWindow()
4192 m_headerWin
= new wxListHeaderWindow
4194 this, -1, m_mainWin
,
4196 wxSize(GetClientSize().x
, HEADER_HEIGHT
),
4201 bool wxListCtrl::Create(wxWindow
*parent
,
4206 const wxValidator
&validator
,
4207 const wxString
&name
)
4211 m_imageListState
= (wxImageList
*) NULL
;
4212 m_ownsImageListNormal
=
4213 m_ownsImageListSmall
=
4214 m_ownsImageListState
= FALSE
;
4216 m_mainWin
= (wxListMainWindow
*) NULL
;
4217 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4219 if ( !(style
& wxLC_MASK_TYPE
) )
4221 style
= style
| wxLC_LIST
;
4224 if ( !wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name
) )
4227 // don't create the inner window with the border
4228 style
&= ~wxSUNKEN_BORDER
;
4230 m_mainWin
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style
);
4232 if ( HasFlag(wxLC_REPORT
) )
4234 CreateHeaderWindow();
4236 if ( HasFlag(wxLC_NO_HEADER
) )
4238 // VZ: why do we create it at all then?
4239 m_headerWin
->Show( FALSE
);
4246 void wxListCtrl::SetSingleStyle( long style
, bool add
)
4248 wxASSERT_MSG( !(style
& wxLC_VIRTUAL
),
4249 _T("wxLC_VIRTUAL can't be [un]set") );
4251 long flag
= GetWindowStyle();
4255 if (style
& wxLC_MASK_TYPE
)
4256 flag
&= ~(wxLC_MASK_TYPE
| wxLC_VIRTUAL
);
4257 if (style
& wxLC_MASK_ALIGN
)
4258 flag
&= ~wxLC_MASK_ALIGN
;
4259 if (style
& wxLC_MASK_SORT
)
4260 flag
&= ~wxLC_MASK_SORT
;
4272 SetWindowStyleFlag( flag
);
4275 void wxListCtrl::SetWindowStyleFlag( long flag
)
4279 m_mainWin
->DeleteEverything();
4283 GetClientSize( &width
, &height
);
4285 if (flag
& wxLC_REPORT
)
4287 if (!HasFlag(wxLC_REPORT
))
4291 CreateHeaderWindow();
4293 if (HasFlag(wxLC_NO_HEADER
))
4294 m_headerWin
->Show( FALSE
);
4298 if (flag
& wxLC_NO_HEADER
)
4299 m_headerWin
->Show( FALSE
);
4301 m_headerWin
->Show( TRUE
);
4307 if ( m_mainWin
->HasHeader() )
4309 m_headerWin
->Show( FALSE
);
4314 wxWindow::SetWindowStyleFlag( flag
);
4317 bool wxListCtrl::GetColumn(int col
, wxListItem
&item
) const
4319 m_mainWin
->GetColumn( col
, item
);
4323 bool wxListCtrl::SetColumn( int col
, wxListItem
& item
)
4325 m_mainWin
->SetColumn( col
, item
);
4329 int wxListCtrl::GetColumnWidth( int col
) const
4331 return m_mainWin
->GetColumnWidth( col
);
4334 bool wxListCtrl::SetColumnWidth( int col
, int width
)
4336 m_mainWin
->SetColumnWidth( col
, width
);
4340 int wxListCtrl::GetCountPerPage() const
4342 return m_mainWin
->GetCountPerPage(); // different from Windows ?
4345 bool wxListCtrl::GetItem( wxListItem
&info
) const
4347 m_mainWin
->GetItem( info
);
4351 bool wxListCtrl::SetItem( wxListItem
&info
)
4353 m_mainWin
->SetItem( info
);
4357 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId
)
4360 info
.m_text
= label
;
4361 info
.m_mask
= wxLIST_MASK_TEXT
;
4362 info
.m_itemId
= index
;
4366 info
.m_image
= imageId
;
4367 info
.m_mask
|= wxLIST_MASK_IMAGE
;
4369 m_mainWin
->SetItem(info
);
4373 int wxListCtrl::GetItemState( long item
, long stateMask
) const
4375 return m_mainWin
->GetItemState( item
, stateMask
);
4378 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask
)
4380 m_mainWin
->SetItemState( item
, state
, stateMask
);
4384 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) )
4387 info
.m_image
= image
;
4388 info
.m_mask
= wxLIST_MASK_IMAGE
;
4389 info
.m_itemId
= item
;
4390 m_mainWin
->SetItem( info
);
4394 wxString
wxListCtrl::GetItemText( long item
) const
4397 info
.m_itemId
= item
;
4398 m_mainWin
->GetItem( info
);
4402 void wxListCtrl::SetItemText( long item
, const wxString
&str
)
4405 info
.m_mask
= wxLIST_MASK_TEXT
;
4406 info
.m_itemId
= item
;
4408 m_mainWin
->SetItem( info
);
4411 long wxListCtrl::GetItemData( long item
) const
4414 info
.m_itemId
= item
;
4415 m_mainWin
->GetItem( info
);
4419 bool wxListCtrl::SetItemData( long item
, long data
)
4422 info
.m_mask
= wxLIST_MASK_DATA
;
4423 info
.m_itemId
= item
;
4425 m_mainWin
->SetItem( info
);
4429 bool wxListCtrl::GetItemRect( long item
, wxRect
&rect
, int WXUNUSED(code
) ) const
4431 m_mainWin
->GetItemRect( item
, rect
);
4435 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos
) const
4437 m_mainWin
->GetItemPosition( item
, pos
);
4441 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) )
4446 int wxListCtrl::GetItemCount() const
4448 return m_mainWin
->GetItemCount();
4451 int wxListCtrl::GetColumnCount() const
4453 return m_mainWin
->GetColumnCount();
4456 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall
)
4458 m_mainWin
->SetItemSpacing( spacing
, isSmall
);
4461 int wxListCtrl::GetItemSpacing( bool isSmall
) const
4463 return m_mainWin
->GetItemSpacing( isSmall
);
4466 int wxListCtrl::GetSelectedItemCount() const
4468 return m_mainWin
->GetSelectedItemCount();
4471 wxColour
wxListCtrl::GetTextColour() const
4473 return GetForegroundColour();
4476 void wxListCtrl::SetTextColour(const wxColour
& col
)
4478 SetForegroundColour(col
);
4481 long wxListCtrl::GetTopItem() const
4486 long wxListCtrl::GetNextItem( long item
, int geom
, int state
) const
4488 return m_mainWin
->GetNextItem( item
, geom
, state
);
4491 wxImageList
*wxListCtrl::GetImageList(int which
) const
4493 if (which
== wxIMAGE_LIST_NORMAL
)
4495 return m_imageListNormal
;
4497 else if (which
== wxIMAGE_LIST_SMALL
)
4499 return m_imageListSmall
;
4501 else if (which
== wxIMAGE_LIST_STATE
)
4503 return m_imageListState
;
4505 return (wxImageList
*) NULL
;
4508 void wxListCtrl::SetImageList( wxImageList
*imageList
, int which
)
4510 if ( which
== wxIMAGE_LIST_NORMAL
)
4512 if (m_ownsImageListNormal
) delete m_imageListNormal
;
4513 m_imageListNormal
= imageList
;
4514 m_ownsImageListNormal
= FALSE
;
4516 else if ( which
== wxIMAGE_LIST_SMALL
)
4518 if (m_ownsImageListSmall
) delete m_imageListSmall
;
4519 m_imageListSmall
= imageList
;
4520 m_ownsImageListSmall
= FALSE
;
4522 else if ( which
== wxIMAGE_LIST_STATE
)
4524 if (m_ownsImageListState
) delete m_imageListState
;
4525 m_imageListState
= imageList
;
4526 m_ownsImageListState
= FALSE
;
4529 m_mainWin
->SetImageList( imageList
, which
);
4532 void wxListCtrl::AssignImageList(wxImageList
*imageList
, int which
)
4534 SetImageList(imageList
, which
);
4535 if ( which
== wxIMAGE_LIST_NORMAL
)
4536 m_ownsImageListNormal
= TRUE
;
4537 else if ( which
== wxIMAGE_LIST_SMALL
)
4538 m_ownsImageListSmall
= TRUE
;
4539 else if ( which
== wxIMAGE_LIST_STATE
)
4540 m_ownsImageListState
= TRUE
;
4543 bool wxListCtrl::Arrange( int WXUNUSED(flag
) )
4548 bool wxListCtrl::DeleteItem( long item
)
4550 m_mainWin
->DeleteItem( item
);
4554 bool wxListCtrl::DeleteAllItems()
4556 m_mainWin
->DeleteAllItems();
4560 bool wxListCtrl::DeleteAllColumns()
4562 size_t count
= m_mainWin
->m_columns
.GetCount();
4563 for ( size_t n
= 0; n
< count
; n
++ )
4569 void wxListCtrl::ClearAll()
4571 m_mainWin
->DeleteEverything();
4574 bool wxListCtrl::DeleteColumn( int col
)
4576 m_mainWin
->DeleteColumn( col
);
4580 void wxListCtrl::Edit( long item
)
4582 m_mainWin
->EditLabel( item
);
4585 bool wxListCtrl::EnsureVisible( long item
)
4587 m_mainWin
->EnsureVisible( item
);
4591 long wxListCtrl::FindItem( long start
, const wxString
& str
, bool partial
)
4593 return m_mainWin
->FindItem( start
, str
, partial
);
4596 long wxListCtrl::FindItem( long start
, long data
)
4598 return m_mainWin
->FindItem( start
, data
);
4601 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
),
4602 int WXUNUSED(direction
))
4607 long wxListCtrl::HitTest( const wxPoint
&point
, int &flags
)
4609 return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags
);
4612 long wxListCtrl::InsertItem( wxListItem
& info
)
4614 m_mainWin
->InsertItem( info
);
4615 return info
.m_itemId
;
4618 long wxListCtrl::InsertItem( long index
, const wxString
&label
)
4621 info
.m_text
= label
;
4622 info
.m_mask
= wxLIST_MASK_TEXT
;
4623 info
.m_itemId
= index
;
4624 return InsertItem( info
);
4627 long wxListCtrl::InsertItem( long index
, int imageIndex
)
4630 info
.m_mask
= wxLIST_MASK_IMAGE
;
4631 info
.m_image
= imageIndex
;
4632 info
.m_itemId
= index
;
4633 return InsertItem( info
);
4636 long wxListCtrl::InsertItem( long index
, const wxString
&label
, int imageIndex
)
4639 info
.m_text
= label
;
4640 info
.m_image
= imageIndex
;
4641 info
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_IMAGE
;
4642 info
.m_itemId
= index
;
4643 return InsertItem( info
);
4646 long wxListCtrl::InsertColumn( long col
, wxListItem
&item
)
4648 wxASSERT( m_headerWin
);
4649 m_mainWin
->InsertColumn( col
, item
);
4650 m_headerWin
->Refresh();
4655 long wxListCtrl::InsertColumn( long col
, const wxString
&heading
,
4656 int format
, int width
)
4659 item
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_FORMAT
;
4660 item
.m_text
= heading
;
4663 item
.m_mask
|= wxLIST_MASK_WIDTH
;
4664 item
.m_width
= width
;
4666 item
.m_format
= format
;
4668 return InsertColumn( col
, item
);
4671 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) )
4677 // fn is a function which takes 3 long arguments: item1, item2, data.
4678 // item1 is the long data associated with a first item (NOT the index).
4679 // item2 is the long data associated with a second item (NOT the index).
4680 // data is the same value as passed to SortItems.
4681 // The return value is a negative number if the first item should precede the second
4682 // item, a positive number of the second item should precede the first,
4683 // or zero if the two items are equivalent.
4684 // data is arbitrary data to be passed to the sort function.
4686 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data
)
4688 m_mainWin
->SortItems( fn
, data
);
4692 // ----------------------------------------------------------------------------
4694 // ----------------------------------------------------------------------------
4696 void wxListCtrl::OnSize(wxSizeEvent
& event
)
4702 GetClientSize( &cw
, &ch
);
4704 if ( m_mainWin
->HasHeader() )
4706 m_headerWin
->SetSize( 0, 0, cw
, HEADER_HEIGHT
);
4707 m_mainWin
->SetSize( 0, HEADER_HEIGHT
+ 1, cw
, ch
- HEADER_HEIGHT
- 1 );
4709 else // no header window
4711 m_mainWin
->SetSize( 0, 0, cw
, ch
);
4714 m_mainWin
->RecalculatePositions();
4717 void wxListCtrl::OnIdle( wxIdleEvent
& event
)
4721 // do it only if needed
4722 if ( !m_mainWin
->m_dirty
)
4725 m_mainWin
->RecalculatePositions();
4728 // ----------------------------------------------------------------------------
4730 // ----------------------------------------------------------------------------
4732 bool wxListCtrl::SetBackgroundColour( const wxColour
&colour
)
4736 m_mainWin
->SetBackgroundColour( colour
);
4737 m_mainWin
->m_dirty
= TRUE
;
4743 bool wxListCtrl::SetForegroundColour( const wxColour
&colour
)
4745 if ( !wxWindow::SetForegroundColour( colour
) )
4750 m_mainWin
->SetForegroundColour( colour
);
4751 m_mainWin
->m_dirty
= TRUE
;
4756 m_headerWin
->SetForegroundColour( colour
);
4762 bool wxListCtrl::SetFont( const wxFont
&font
)
4764 if ( !wxWindow::SetFont( font
) )
4769 m_mainWin
->SetFont( font
);
4770 m_mainWin
->m_dirty
= TRUE
;
4775 m_headerWin
->SetFont( font
);
4781 // ----------------------------------------------------------------------------
4782 // methods forwarded to m_mainWin
4783 // ----------------------------------------------------------------------------
4785 #if wxUSE_DRAG_AND_DROP
4787 void wxListCtrl::SetDropTarget( wxDropTarget
*dropTarget
)
4789 m_mainWin
->SetDropTarget( dropTarget
);
4792 wxDropTarget
*wxListCtrl::GetDropTarget() const
4794 return m_mainWin
->GetDropTarget();
4797 #endif // wxUSE_DRAG_AND_DROP
4799 bool wxListCtrl::SetCursor( const wxCursor
&cursor
)
4801 return m_mainWin
? m_mainWin
->wxWindow::SetCursor(cursor
) : FALSE
;
4804 wxColour
wxListCtrl::GetBackgroundColour() const
4806 return m_mainWin
? m_mainWin
->GetBackgroundColour() : wxColour();
4809 wxColour
wxListCtrl::GetForegroundColour() const
4811 return m_mainWin
? m_mainWin
->GetForegroundColour() : wxColour();
4814 bool wxListCtrl::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
4817 return m_mainWin
->PopupMenu( menu
, x
, y
);
4820 #endif // wxUSE_MENUS
4823 void wxListCtrl::SetFocus()
4825 /* The test in window.cpp fails as we are a composite
4826 window, so it checks against "this", but not m_mainWin. */
4827 if ( FindFocus() != this )
4828 m_mainWin
->SetFocus();
4831 // ----------------------------------------------------------------------------
4832 // virtual list control support
4833 // ----------------------------------------------------------------------------
4835 wxString
wxListCtrl::OnGetItemText(long item
, long col
) const
4837 // this is a pure virtual function, in fact - which is not really pure
4838 // because the controls which are not virtual don't need to implement it
4839 wxFAIL_MSG( _T("not supposed to be called") );
4841 return wxEmptyString
;
4844 int wxListCtrl::OnGetItemImage(long item
) const
4847 wxFAIL_MSG( _T("not supposed to be called") );
4852 void wxListCtrl::SetItemCount(long count
)
4854 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4856 m_mainWin
->SetItemCount(count
);
4859 #endif // wxUSE_LISTCTRL