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 ...
47 5. attributes support: we need OnGetItemAttr() as well!
50 // ============================================================================
52 // ============================================================================
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
59 #pragma implementation "listctrl.h"
60 #pragma implementation "listctrlbase.h"
63 // For compilers that support precompilation, includes "wx.h".
64 #include "wx/wxprec.h"
72 #include "wx/dcscreen.h"
74 #include "wx/listctrl.h"
75 #include "wx/imaglist.h"
76 #include "wx/dynarray.h"
80 #include "wx/gtk/win_gtk.h"
83 // ----------------------------------------------------------------------------
85 // ----------------------------------------------------------------------------
87 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG
)
88 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG
)
89 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
)
90 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT
)
91 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM
)
92 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
)
93 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO
)
94 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO
)
95 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED
)
96 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED
)
97 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN
)
98 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM
)
99 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK
)
100 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
)
101 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
)
102 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED
)
103 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT
)
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
109 // the height of the header window (FIXME: should depend on its font!)
110 static const int HEADER_HEIGHT
= 23;
112 // the scrollbar units
113 static const int SCROLL_UNIT_X
= 15;
114 static const int SCROLL_UNIT_Y
= 15;
116 // the spacing between the lines (in report mode)
117 static const int LINE_SPACING
= 0;
119 // extra margins around the text label
120 static const int EXTRA_WIDTH
= 3;
121 static const int EXTRA_HEIGHT
= 4;
123 // offset for the header window
124 static const int HEADER_OFFSET_X
= 1;
125 static const int HEADER_OFFSET_Y
= 1;
127 // when autosizing the columns, add some slack
128 static const int AUTOSIZE_COL_MARGIN
= 10;
130 // default and minimal widths for the header columns
131 static const int WIDTH_COL_DEFAULT
= 80;
132 static const int WIDTH_COL_MIN
= 10;
134 // ============================================================================
136 // ============================================================================
138 // ----------------------------------------------------------------------------
140 // ----------------------------------------------------------------------------
142 int CMPFUNC_CONV
wxSizeTCmpFn(size_t n1
, size_t n2
) { return n1
- n2
; }
144 WX_DEFINE_SORTED_EXPORTED_ARRAY(size_t, wxIndexArray
);
146 // this class is used to store the selected items in the virtual list control
147 // (but it is not tied to list control and so can be used with other controls
148 // such as wxListBox in wxUniv)
150 // the idea is to make it really smart later (i.e. store the selections as an
151 // array of ranes + individual items) but, as I don't have time to do it now
152 // (this would require writing code to merge/break ranges and much more) keep
153 // it simple but define a clean interface to it which allows it to be made
155 class WXDLLEXPORT wxSelectionStore
158 wxSelectionStore() : m_itemsSel(wxSizeTCmpFn
) { Init(); }
160 // set the total number of items we handle
161 void SetItemCount(size_t count
) { m_count
= count
; }
163 // special case of SetItemCount(0)
164 void Clear() { m_itemsSel
.Clear(); m_count
= 0; }
166 // must be called when a new item is inserted/added
167 void OnItemAdd(size_t item
) { wxFAIL_MSG( _T("TODO") ); }
169 // must be called when an item is deleted
170 void OnItemDelete(size_t item
);
172 // select one item, use SelectRange() insted if possible!
174 // returns true if the items selection really changed
175 bool SelectItem(size_t item
, bool select
= TRUE
);
177 // select the range of items
178 void SelectRange(size_t itemFrom
, size_t itemTo
, bool select
= TRUE
);
180 // return true if the given item is selected
181 bool IsSelected(size_t item
) const;
183 // return the total number of selected items
184 size_t GetSelectedCount() const
186 return m_defaultState
? m_count
- m_itemsSel
.GetCount()
187 : m_itemsSel
.GetCount();
192 void Init() { m_defaultState
= FALSE
; }
194 // the total number of items we handle
197 // the default state: normally, FALSE (i.e. off) but maybe set to TRUE if
198 // there are more selected items than non selected ones - this allows to
199 // handle selection of all items efficiently
202 // the array of items whose selection state is different from default
203 wxIndexArray m_itemsSel
;
205 DECLARE_NO_COPY_CLASS(wxSelectionStore
)
208 //-----------------------------------------------------------------------------
209 // wxListItemData (internal)
210 //-----------------------------------------------------------------------------
212 class WXDLLEXPORT wxListItemData
215 wxListItemData(wxListMainWindow
*owner
);
218 void SetItem( const wxListItem
&info
);
219 void SetImage( int image
) { m_image
= image
; }
220 void SetData( long data
) { m_data
= data
; }
221 void SetPosition( int x
, int y
);
222 void SetSize( int width
, int height
);
224 bool HasText() const { return !m_text
.empty(); }
225 const wxString
& GetText() const { return m_text
; }
226 void SetText(const wxString
& text
) { m_text
= text
; }
228 // we can't use empty string for measuring the string width/height, so
229 // always return something
230 wxString
GetTextForMeasuring() const
232 wxString s
= GetText();
239 bool IsHit( int x
, int y
) const;
243 int GetWidth() const;
244 int GetHeight() const;
246 int GetImage() const { return m_image
; }
247 bool HasImage() const { return GetImage() != -1; }
249 void GetItem( wxListItem
&info
) const;
251 void SetAttr(wxListItemAttr
*attr
) { m_attr
= attr
; }
252 wxListItemAttr
*GetAttr() const { return m_attr
; }
255 // the item image or -1
258 // user data associated with the item
261 // the item coordinates are not used in report mode, instead this pointer
262 // is NULL and the owner window is used to retrieve the item position and
266 // the list ctrl we are in
267 wxListMainWindow
*m_owner
;
269 // custom attributes or NULL
270 wxListItemAttr
*m_attr
;
273 // common part of all ctors
279 //-----------------------------------------------------------------------------
280 // wxListHeaderData (internal)
281 //-----------------------------------------------------------------------------
283 class WXDLLEXPORT wxListHeaderData
: public wxObject
297 wxListHeaderData( const wxListItem
&info
);
298 void SetItem( const wxListItem
&item
);
299 void SetPosition( int x
, int y
);
300 void SetWidth( int w
);
301 void SetFormat( int format
);
302 void SetHeight( int h
);
303 bool HasImage() const;
305 bool HasText() const { return !m_text
.empty(); }
306 const wxString
& GetText() const { return m_text
; }
307 void SetText(const wxString
& text
) { m_text
= text
; }
309 void GetItem( wxListItem
&item
);
311 bool IsHit( int x
, int y
) const;
312 int GetImage() const;
313 int GetWidth() const;
314 int GetFormat() const;
317 DECLARE_DYNAMIC_CLASS(wxListHeaderData
);
320 //-----------------------------------------------------------------------------
321 // wxListLineData (internal)
322 //-----------------------------------------------------------------------------
324 WX_DECLARE_LIST(wxListItemData
, wxListItemDataList
);
325 #include "wx/listimpl.cpp"
326 WX_DEFINE_LIST(wxListItemDataList
);
328 class WXDLLEXPORT wxListLineData
331 // the list of subitems: only may have more than one item in report mode
332 wxListItemDataList m_items
;
334 // this is not used in report view
346 // the part to be highlighted
347 wxRect m_rectHighlight
;
350 // is this item selected? [NB: not used in virtual mode]
353 // back pointer to the list ctrl
354 wxListMainWindow
*m_owner
;
357 wxListLineData(wxListMainWindow
*owner
);
359 ~wxListLineData() { delete m_gi
; }
361 // are we in report mode?
362 inline bool InReportView() const;
364 // are we in virtual report mode?
365 inline bool IsVirtual() const;
367 // these 2 methods shouldn't be called for report view controls, in that
368 // case we determine our position/size ourselves
370 // calculate the size of the line
371 void CalculateSize( wxDC
*dc
, int spacing
);
373 // remember the position this line appears at
374 void SetPosition( int x
, int y
, int window_width
, int spacing
);
378 void SetImage( int image
) { SetImage(0, image
); }
379 int GetImage() const { return GetImage(0); }
380 bool HasImage() const { return GetImage() != -1; }
381 bool HasText() const { return !GetText(0).empty(); }
383 void SetItem( int index
, const wxListItem
&info
);
384 void GetItem( int index
, wxListItem
&info
);
386 wxString
GetText(int index
) const;
387 void SetText( int index
, const wxString s
);
389 wxListItemAttr
*GetAttr() const;
390 void SetAttr(wxListItemAttr
*attr
);
392 // return true if the highlighting really changed
393 bool Highlight( bool on
);
395 void ReverseHighlight();
397 bool IsHighlighted() const
399 wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") );
401 return m_highlighted
;
404 // draw the line on the given DC in icon/list mode
405 void Draw( wxDC
*dc
);
407 // the same in report mode
408 void DrawInReportMode( wxDC
*dc
,
410 const wxRect
& rectHL
,
414 // set the line to contain num items (only can be > 1 in report mode)
415 void InitItems( int num
);
417 // get the mode (i.e. style) of the list control
418 inline int GetMode() const;
420 void SetAttributes(wxDC
*dc
,
421 const wxListItemAttr
*attr
,
422 const wxColour
& colText
,
426 // these are only used by GetImage/SetImage above, we don't support images
427 // with subitems at the public API level yet
428 void SetImage( int index
, int image
);
429 int GetImage( int index
) const;
432 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData
, wxListLineDataArray
);
433 #include "wx/arrimpl.cpp"
434 WX_DEFINE_OBJARRAY(wxListLineDataArray
);
436 //-----------------------------------------------------------------------------
437 // wxListHeaderWindow (internal)
438 //-----------------------------------------------------------------------------
440 class WXDLLEXPORT wxListHeaderWindow
: public wxWindow
443 wxListMainWindow
*m_owner
;
444 wxCursor
*m_currentCursor
;
445 wxCursor
*m_resizeCursor
;
448 // column being resized
451 // divider line position in logical (unscrolled) coords
454 // minimal position beyond which the divider line can't be dragged in
459 wxListHeaderWindow();
460 virtual ~wxListHeaderWindow();
462 wxListHeaderWindow( wxWindow
*win
,
464 wxListMainWindow
*owner
,
465 const wxPoint
&pos
= wxDefaultPosition
,
466 const wxSize
&size
= wxDefaultSize
,
468 const wxString
&name
= "wxlistctrlcolumntitles" );
470 void DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
);
472 void AdjustDC(wxDC
& dc
);
474 void OnPaint( wxPaintEvent
&event
);
475 void OnMouse( wxMouseEvent
&event
);
476 void OnSetFocus( wxFocusEvent
&event
);
482 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow
)
483 DECLARE_EVENT_TABLE()
486 //-----------------------------------------------------------------------------
487 // wxListRenameTimer (internal)
488 //-----------------------------------------------------------------------------
490 class WXDLLEXPORT wxListRenameTimer
: public wxTimer
493 wxListMainWindow
*m_owner
;
496 wxListRenameTimer( wxListMainWindow
*owner
);
500 //-----------------------------------------------------------------------------
501 // wxListTextCtrl (internal)
502 //-----------------------------------------------------------------------------
504 class WXDLLEXPORT wxListTextCtrl
: public wxTextCtrl
509 wxListMainWindow
*m_owner
;
510 wxString m_startValue
;
514 wxListTextCtrl( wxWindow
*parent
, const wxWindowID id
,
515 bool *accept
, wxString
*res
, wxListMainWindow
*owner
,
516 const wxString
&value
= "",
517 const wxPoint
&pos
= wxDefaultPosition
, const wxSize
&size
= wxDefaultSize
,
519 const wxValidator
& validator
= wxDefaultValidator
,
520 const wxString
&name
= "listctrltextctrl" );
521 void OnChar( wxKeyEvent
&event
);
522 void OnKeyUp( wxKeyEvent
&event
);
523 void OnKillFocus( wxFocusEvent
&event
);
526 DECLARE_DYNAMIC_CLASS(wxListTextCtrl
);
527 DECLARE_EVENT_TABLE()
530 //-----------------------------------------------------------------------------
531 // wxListMainWindow (internal)
532 //-----------------------------------------------------------------------------
534 WX_DECLARE_LIST(wxListHeaderData
, wxListHeaderDataList
);
535 #include "wx/listimpl.cpp"
536 WX_DEFINE_LIST(wxListHeaderDataList
);
538 class WXDLLEXPORT wxListMainWindow
: public wxScrolledWindow
542 wxListMainWindow( wxWindow
*parent
,
544 const wxPoint
& pos
= wxDefaultPosition
,
545 const wxSize
& size
= wxDefaultSize
,
547 const wxString
&name
= _T("listctrlmainwindow") );
549 virtual ~wxListMainWindow();
551 bool HasFlag(int flag
) const { return m_parent
->HasFlag(flag
); }
553 // return true if this is a virtual list control
554 bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL
); }
556 // return true if the control is in report mode
557 bool InReportView() const { return HasFlag(wxLC_REPORT
); }
559 // return true if we are in single selection mode, false if multi sel
560 bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL
); }
562 // do we have a header window?
563 bool HasHeader() const
564 { return HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
); }
566 void HighlightAll( bool on
);
568 // all these functions only do something if the line is currently visible
570 // change the line "selected" state, return TRUE if it really changed
571 bool HighlightLine( size_t line
, bool highlight
= TRUE
);
573 // as HighlightLine() but do it for the range of lines: this is incredibly
574 // more efficient for virtual list controls!
576 // NB: unlike HighlightLine() this one does refresh the lines on screen
577 void HighlightLines( size_t lineFrom
, size_t lineTo
, bool on
= TRUE
);
579 // toggle the line state and refresh it
580 void ReverseHighlight( size_t line
)
581 { HighlightLine(line
, !IsHighlighted(line
)); RefreshLine(line
); }
583 // return true if the line is highlighted
584 bool IsHighlighted(size_t line
) const;
586 // refresh one or several lines at once
587 void RefreshLine( size_t line
);
588 void RefreshLines( size_t lineFrom
, size_t lineTo
);
590 // refresh all lines below the given one: the difference with
591 // RefreshLines() is that the index here might not be a valid one (happens
592 // when the last line is deleted)
593 void RefreshAfter( size_t lineFrom
);
595 // the methods which are forwarded to wxListLineData itself in list/icon
596 // modes but are here because the lines don't store their positions in the
599 // get the bound rect for the entire line
600 wxRect
GetLineRect(size_t line
) const;
602 // get the bound rect of the label
603 wxRect
GetLineLabelRect(size_t line
) const;
605 // get the bound rect of the items icon (only may be called if we do have
607 wxRect
GetLineIconRect(size_t line
) const;
609 // get the rect to be highlighted when the item has focus
610 wxRect
GetLineHighlightRect(size_t line
) const;
612 // get the size of the total line rect
613 wxSize
GetLineSize(size_t line
) const
614 { return GetLineRect(line
).GetSize(); }
616 // return the hit code for the corresponding position (in this line)
617 long HitTestLine(size_t line
, int x
, int y
) const;
619 void EditLabel( long item
);
620 void OnRenameTimer();
621 void OnRenameAccept();
623 void OnMouse( wxMouseEvent
&event
);
626 // called to switch the selection from the current item to newCurrent,
627 void OnArrowChar( size_t newCurrent
, const wxKeyEvent
& event
);
629 void OnChar( wxKeyEvent
&event
);
630 void OnKeyDown( wxKeyEvent
&event
);
631 void OnSetFocus( wxFocusEvent
&event
);
632 void OnKillFocus( wxFocusEvent
&event
);
633 void OnScroll(wxScrollWinEvent
& event
) ;
635 void OnPaint( wxPaintEvent
&event
);
637 void DrawImage( int index
, wxDC
*dc
, int x
, int y
);
638 void GetImageSize( int index
, int &width
, int &height
) const;
639 int GetTextLength( const wxString
&s
) const;
641 void SetImageList( wxImageList
*imageList
, int which
);
642 void SetItemSpacing( int spacing
, bool isSmall
= FALSE
);
643 int GetItemSpacing( bool isSmall
= FALSE
);
645 void SetColumn( int col
, wxListItem
&item
);
646 void SetColumnWidth( int col
, int width
);
647 void GetColumn( int col
, wxListItem
&item
) const;
648 int GetColumnWidth( int col
) const;
649 int GetColumnCount() const { return m_columns
.GetCount(); }
651 // returns the sum of the heights of all columns
652 int GetHeaderWidth() const;
654 int GetCountPerPage() const;
656 void SetItem( wxListItem
&item
);
657 void GetItem( wxListItem
&item
);
658 void SetItemState( long item
, long state
, long stateMask
);
659 int GetItemState( long item
, long stateMask
);
660 void GetItemRect( long index
, wxRect
&rect
);
661 bool GetItemPosition( long item
, wxPoint
& pos
);
662 int GetSelectedItemCount();
664 // set the scrollbars and update the positions of the items
665 void RecalculatePositions();
667 // refresh the window and the header
670 long GetNextItem( long item
, int geometry
, int state
);
671 void DeleteItem( long index
);
672 void DeleteAllItems();
673 void DeleteColumn( int col
);
674 void DeleteEverything();
675 void EnsureVisible( long index
);
676 long FindItem( long start
, const wxString
& str
, bool partial
= FALSE
);
677 long FindItem( long start
, long data
);
678 long HitTest( int x
, int y
, int &flags
);
679 void InsertItem( wxListItem
&item
);
680 void InsertColumn( long col
, wxListItem
&item
);
681 void SortItems( wxListCtrlCompare fn
, long data
);
683 size_t GetItemCount() const;
684 bool IsEmpty() const { return GetItemCount() == 0; }
685 void SetItemCount(long count
);
687 void ResetCurrent() { m_current
= (size_t)-1; }
688 bool HasCurrent() const { return m_current
!= (size_t)-1; }
690 // send out a wxListEvent
691 void SendNotify( size_t line
,
693 wxPoint point
= wxDefaultPosition
);
695 // override base class virtual to reset m_lineHeight when the font changes
696 virtual bool SetFont(const wxFont
& font
)
698 if ( !wxScrolledWindow::SetFont(font
) )
706 // these are for wxListLineData usage only
708 // get the backpointer to the list ctrl
709 wxListCtrl
*GetListCtrl() const
711 return wxStaticCast(GetParent(), wxListCtrl
);
714 // get the height of all lines (assuming they all do have the same height)
715 wxCoord
GetLineHeight() const;
717 // get the y position of the given line (only for report view)
718 wxCoord
GetLineY(size_t line
) const;
721 // the array of all line objects for a non virtual list control
722 wxListLineDataArray m_lines
;
724 // the list of column objects
725 wxListHeaderDataList m_columns
;
727 // currently focused item or -1
730 // the item currently being edited or -1
731 size_t m_currentEdit
;
733 // the number of lines per page
736 // this flag is set when something which should result in the window
737 // redrawing happens (i.e. an item was added or deleted, or its appearance
738 // changed) and OnPaint() doesn't redraw the window while it is set which
739 // allows to minimize the number of repaintings when a lot of items are
740 // being added. The real repainting occurs only after the next OnIdle()
744 wxBrush
*m_highlightBrush
;
745 wxColour
*m_highlightColour
;
748 wxImageList
*m_small_image_list
;
749 wxImageList
*m_normal_image_list
;
751 int m_normal_spacing
;
755 wxTimer
*m_renameTimer
;
757 wxString m_renameRes
;
762 // for double click logic
763 size_t m_lineLastClicked
,
764 m_lineBeforeLastClicked
;
767 // the total count of items in a virtual list control
770 // the object maintaining the items selection state, only used in virtual
772 wxSelectionStore m_selStore
;
774 // common part of all ctors
777 // intiialize m_[xy]Scroll
778 void InitScrolling();
780 // get the line data for the given index
781 wxListLineData
*GetLine(size_t n
) const
783 wxASSERT_MSG( n
!= (size_t)-1, _T("invalid line index") );
787 wxConstCast(this, wxListMainWindow
)->CacheLineData(n
);
795 // get a dummy line which can be used for geometry calculations and such:
796 // you must use GetLine() if you want to really draw the line
797 wxListLineData
*GetDummyLine() const;
799 // cache the line data of the n-th line in m_lines[0]
800 void CacheLineData(size_t line
);
802 // get the range of visible lines
803 void GetVisibleLinesRange(size_t *from
, size_t *to
);
805 // force us to recalculate the range of visible lines
806 void ResetVisibleLinesRange() { m_lineFrom
= (size_t)-1; }
808 // get the colour to be used for drawing the rules
809 wxColour
GetRuleColour() const
814 return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT
);
819 // initialize the current item if needed
820 void UpdateCurrent();
822 // called when an item is [un]focuded, i.e. becomes [not] current
825 void OnFocusLine( size_t line
);
826 void OnUnfocusLine( size_t line
);
828 // the height of one line using the current font
829 wxCoord m_lineHeight
;
831 // the total header width or 0 if not calculated yet
832 wxCoord m_headerWidth
;
834 // the first and last lines being shown on screen right now (inclusive),
835 // both may be -1 if they must be calculated so never access them directly:
836 // use GetVisibleLinesRange() above instead
840 DECLARE_DYNAMIC_CLASS(wxListMainWindow
);
841 DECLARE_EVENT_TABLE()
844 // ============================================================================
846 // ============================================================================
848 // ----------------------------------------------------------------------------
850 // ----------------------------------------------------------------------------
852 bool wxSelectionStore::IsSelected(size_t item
) const
854 bool isSel
= m_itemsSel
.Index(item
) != wxNOT_FOUND
;
856 // if the default state is to be selected, being in m_itemsSel means that
857 // the item is not selected, so we have to inverse the logic
858 return m_defaultState
? !isSel
: isSel
;
861 bool wxSelectionStore::SelectItem(size_t item
, bool select
)
863 // search for the item ourselves as like this we get the index where to
864 // insert it later if needed, so we do only one search in the array instead
865 // of two (adding item to a sorted array requires a search)
866 size_t index
= m_itemsSel
.IndexForInsert(item
);
867 bool isSel
= index
< m_itemsSel
.GetCount() && m_itemsSel
[index
] == item
;
869 if ( select
!= m_defaultState
)
873 m_itemsSel
.AddAt(item
, index
);
878 else // reset to default state
882 m_itemsSel
.RemoveAt(index
);
890 void wxSelectionStore::SelectRange(size_t itemFrom
, size_t itemTo
, bool select
)
892 wxASSERT_MSG( itemFrom
<= itemTo
, _T("should be in order") );
894 // are we going to have more [un]selected items than the other ones?
895 if ( itemTo
- itemFrom
> m_count
/ 2 )
897 if ( select
!= m_defaultState
)
899 // the default state now becomes the same as 'select'
900 m_defaultState
= select
;
902 // so all the old selections (which had state select) shouldn't be
903 // selected any more, but all the other ones should
904 wxIndexArray selOld
= m_itemsSel
;
907 // TODO: it should be possible to optimize the searches a bit
908 // knowing the possible range
911 for ( item
= 0; item
< itemFrom
; item
++ )
913 if ( selOld
.Index(item
) == wxNOT_FOUND
)
914 m_itemsSel
.Add(item
);
917 for ( item
= itemTo
+ 1; item
< m_count
; item
++ )
919 if ( selOld
.Index(item
) == wxNOT_FOUND
)
920 m_itemsSel
.Add(item
);
923 else // select == m_defaultState
925 // get the inclusive range of items between itemFrom and itemTo
926 size_t count
= m_itemsSel
.GetCount(),
927 start
= m_itemsSel
.IndexForInsert(itemFrom
),
928 end
= m_itemsSel
.IndexForInsert(itemTo
);
930 if ( start
== count
|| m_itemsSel
[start
] < itemFrom
)
935 if ( end
== count
|| m_itemsSel
[end
] > itemTo
)
942 // delete all of them (from end to avoid changing indices)
943 for ( int i
= end
; i
>= (int)start
; i
-- )
945 m_itemsSel
.RemoveAt(i
);
950 else // "few" items change state
952 // just add the items to the selection
953 for ( size_t item
= itemFrom
; item
<= itemTo
; item
++ )
955 SelectItem(item
, select
);
960 void wxSelectionStore::OnItemDelete(size_t item
)
962 size_t count
= m_itemsSel
.GetCount(),
963 i
= m_itemsSel
.IndexForInsert(item
);
965 if ( i
< count
&& m_itemsSel
[i
] == item
)
967 // this item itself was in m_itemsSel, remove it from there
968 m_itemsSel
.RemoveAt(i
);
973 // and adjust the index of all which follow it
976 // all following elements must be greater than the one we deleted
977 wxASSERT_MSG( m_itemsSel
[i
] > item
, _T("logic error") );
983 //-----------------------------------------------------------------------------
985 //-----------------------------------------------------------------------------
987 wxListItemData::~wxListItemData()
989 // in the virtual list control the attributes are managed by the main
990 // program, so don't delete them
991 if ( !m_owner
->IsVirtual() )
999 void wxListItemData::Init()
1007 wxListItemData::wxListItemData(wxListMainWindow
*owner
)
1013 if ( owner
->InReportView() )
1019 m_rect
= new wxRect
;
1023 void wxListItemData::SetItem( const wxListItem
&info
)
1025 if ( info
.m_mask
& wxLIST_MASK_TEXT
)
1026 SetText(info
.m_text
);
1027 if ( info
.m_mask
& wxLIST_MASK_IMAGE
)
1028 m_image
= info
.m_image
;
1029 if ( info
.m_mask
& wxLIST_MASK_DATA
)
1030 m_data
= info
.m_data
;
1032 if ( info
.HasAttributes() )
1035 *m_attr
= *info
.GetAttributes();
1037 m_attr
= new wxListItemAttr(*info
.GetAttributes());
1045 m_rect
->width
= info
.m_width
;
1049 void wxListItemData::SetPosition( int x
, int y
)
1051 wxCHECK_RET( m_rect
, _T("unexpected SetPosition() call") );
1057 void wxListItemData::SetSize( int width
, int height
)
1059 wxCHECK_RET( m_rect
, _T("unexpected SetSize() call") );
1062 m_rect
->width
= width
;
1064 m_rect
->height
= height
;
1067 bool wxListItemData::IsHit( int x
, int y
) const
1069 wxCHECK_MSG( m_rect
, FALSE
, _T("can't be called in this mode") );
1071 return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x
, y
);
1074 int wxListItemData::GetX() const
1076 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1081 int wxListItemData::GetY() const
1083 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1088 int wxListItemData::GetWidth() const
1090 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1092 return m_rect
->width
;
1095 int wxListItemData::GetHeight() const
1097 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1099 return m_rect
->height
;
1102 void wxListItemData::GetItem( wxListItem
&info
) const
1104 info
.m_text
= m_text
;
1105 info
.m_image
= m_image
;
1106 info
.m_data
= m_data
;
1110 if ( m_attr
->HasTextColour() )
1111 info
.SetTextColour(m_attr
->GetTextColour());
1112 if ( m_attr
->HasBackgroundColour() )
1113 info
.SetBackgroundColour(m_attr
->GetBackgroundColour());
1114 if ( m_attr
->HasFont() )
1115 info
.SetFont(m_attr
->GetFont());
1119 //-----------------------------------------------------------------------------
1121 //-----------------------------------------------------------------------------
1123 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData
,wxObject
);
1125 wxListHeaderData::wxListHeaderData()
1136 wxListHeaderData::wxListHeaderData( const wxListItem
&item
)
1144 void wxListHeaderData::SetItem( const wxListItem
&item
)
1146 m_mask
= item
.m_mask
;
1147 m_text
= item
.m_text
;
1148 m_image
= item
.m_image
;
1149 m_format
= item
.m_format
;
1151 SetWidth(item
.m_width
);
1154 void wxListHeaderData::SetPosition( int x
, int y
)
1160 void wxListHeaderData::SetHeight( int h
)
1165 void wxListHeaderData::SetWidth( int w
)
1169 m_width
= WIDTH_COL_DEFAULT
;
1170 if (m_width
< WIDTH_COL_MIN
)
1171 m_width
= WIDTH_COL_MIN
;
1174 void wxListHeaderData::SetFormat( int format
)
1179 bool wxListHeaderData::HasImage() const
1181 return (m_image
!= 0);
1184 bool wxListHeaderData::IsHit( int x
, int y
) const
1186 return ((x
>= m_xpos
) && (x
<= m_xpos
+m_width
) && (y
>= m_ypos
) && (y
<= m_ypos
+m_height
));
1189 void wxListHeaderData::GetItem( wxListItem
&item
)
1191 item
.m_mask
= m_mask
;
1192 item
.m_text
= m_text
;
1193 item
.m_image
= m_image
;
1194 item
.m_format
= m_format
;
1195 item
.m_width
= m_width
;
1198 int wxListHeaderData::GetImage() const
1203 int wxListHeaderData::GetWidth() const
1208 int wxListHeaderData::GetFormat() const
1213 //-----------------------------------------------------------------------------
1215 //-----------------------------------------------------------------------------
1217 inline int wxListLineData::GetMode() const
1219 return m_owner
->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE
;
1222 inline bool wxListLineData::InReportView() const
1224 return m_owner
->HasFlag(wxLC_REPORT
);
1227 inline bool wxListLineData::IsVirtual() const
1229 return m_owner
->IsVirtual();
1232 wxListLineData::wxListLineData( wxListMainWindow
*owner
)
1235 m_items
.DeleteContents( TRUE
);
1237 if ( InReportView() )
1243 m_gi
= new GeometryInfo
;
1246 m_highlighted
= FALSE
;
1248 InitItems( GetMode() == wxLC_REPORT
? m_owner
->GetColumnCount() : 1 );
1251 void wxListLineData::CalculateSize( wxDC
*dc
, int spacing
)
1253 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1254 wxCHECK_RET( node
, _T("no subitems at all??") );
1256 wxListItemData
*item
= node
->GetData();
1258 switch ( GetMode() )
1261 case wxLC_SMALL_ICON
:
1263 m_gi
->m_rectAll
.width
= spacing
;
1265 wxString s
= item
->GetText();
1271 m_gi
->m_rectLabel
.width
=
1272 m_gi
->m_rectLabel
.height
= 0;
1276 dc
->GetTextExtent( s
, &lw
, &lh
);
1277 if (lh
< SCROLL_UNIT_Y
)
1282 m_gi
->m_rectAll
.height
= spacing
+ lh
;
1284 m_gi
->m_rectAll
.width
= lw
;
1286 m_gi
->m_rectLabel
.width
= lw
;
1287 m_gi
->m_rectLabel
.height
= lh
;
1290 if (item
->HasImage())
1293 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1294 m_gi
->m_rectIcon
.width
= w
+ 8;
1295 m_gi
->m_rectIcon
.height
= h
+ 8;
1297 if ( m_gi
->m_rectIcon
.width
> m_gi
->m_rectAll
.width
)
1298 m_gi
->m_rectAll
.width
= m_gi
->m_rectIcon
.width
;
1299 if ( m_gi
->m_rectIcon
.height
+ lh
> m_gi
->m_rectAll
.height
- 4 )
1300 m_gi
->m_rectAll
.height
= m_gi
->m_rectIcon
.height
+ lh
+ 4;
1303 if ( item
->HasText() )
1305 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectLabel
.width
;
1306 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectLabel
.height
;
1308 else // no text, highlight the icon
1310 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectIcon
.width
;
1311 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectIcon
.height
;
1318 wxString s
= item
->GetTextForMeasuring();
1321 dc
->GetTextExtent( s
, &lw
, &lh
);
1322 if (lh
< SCROLL_UNIT_Y
)
1327 m_gi
->m_rectLabel
.width
= lw
;
1328 m_gi
->m_rectLabel
.height
= lh
;
1330 m_gi
->m_rectAll
.width
= lw
;
1331 m_gi
->m_rectAll
.height
= lh
;
1333 if (item
->HasImage())
1336 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1337 m_gi
->m_rectIcon
.width
= w
;
1338 m_gi
->m_rectIcon
.height
= h
;
1340 m_gi
->m_rectAll
.width
+= 4 + w
;
1341 if (h
> m_gi
->m_rectAll
.height
)
1342 m_gi
->m_rectAll
.height
= h
;
1345 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectAll
.width
;
1346 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectAll
.height
;
1351 wxFAIL_MSG( _T("unexpected call to SetSize") );
1355 wxFAIL_MSG( _T("unknown mode") );
1359 void wxListLineData::SetPosition( int x
, int y
,
1363 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1364 wxCHECK_RET( node
, _T("no subitems at all??") );
1366 wxListItemData
*item
= node
->GetData();
1368 switch ( GetMode() )
1371 case wxLC_SMALL_ICON
:
1372 m_gi
->m_rectAll
.x
= x
;
1373 m_gi
->m_rectAll
.y
= y
;
1375 if ( item
->HasImage() )
1377 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 4
1378 + (spacing
- m_gi
->m_rectIcon
.width
)/2;
1379 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 4;
1382 if ( item
->HasText() )
1384 if (m_gi
->m_rectAll
.width
> spacing
)
1385 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1387 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2 + (spacing
/2) - (m_gi
->m_rectLabel
.width
/2);
1388 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ m_gi
->m_rectAll
.height
+ 2 - m_gi
->m_rectLabel
.height
;
1389 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectLabel
.x
- 2;
1390 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectLabel
.y
- 2;
1392 else // no text, highlight the icon
1394 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectIcon
.x
- 4;
1395 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectIcon
.y
- 4;
1400 m_gi
->m_rectAll
.x
= x
;
1401 m_gi
->m_rectAll
.y
= y
;
1403 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectAll
.x
;
1404 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectAll
.y
;
1405 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ 2;
1407 if (item
->HasImage())
1409 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 2;
1410 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 2;
1411 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 6 + m_gi
->m_rectIcon
.width
;
1415 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1420 wxFAIL_MSG( _T("unexpected call to SetPosition") );
1424 wxFAIL_MSG( _T("unknown mode") );
1428 void wxListLineData::InitItems( int num
)
1430 for (int i
= 0; i
< num
; i
++)
1431 m_items
.Append( new wxListItemData(m_owner
) );
1434 void wxListLineData::SetItem( int index
, const wxListItem
&info
)
1436 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1437 wxCHECK_RET( node
, _T("invalid column index in SetItem") );
1439 wxListItemData
*item
= node
->GetData();
1440 item
->SetItem( info
);
1443 void wxListLineData::GetItem( int index
, wxListItem
&info
)
1445 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1448 wxListItemData
*item
= node
->GetData();
1449 item
->GetItem( info
);
1453 wxString
wxListLineData::GetText(int index
) const
1457 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1460 wxListItemData
*item
= node
->GetData();
1461 s
= item
->GetText();
1467 void wxListLineData::SetText( int index
, const wxString s
)
1469 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1472 wxListItemData
*item
= node
->GetData();
1477 void wxListLineData::SetImage( int index
, int image
)
1479 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1480 wxCHECK_RET( node
, _T("invalid column index in SetImage()") );
1482 wxListItemData
*item
= node
->GetData();
1483 item
->SetImage(image
);
1486 int wxListLineData::GetImage( int index
) const
1488 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1489 wxCHECK_MSG( node
, -1, _T("invalid column index in GetImage()") );
1491 wxListItemData
*item
= node
->GetData();
1492 return item
->GetImage();
1495 wxListItemAttr
*wxListLineData::GetAttr() const
1497 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1498 wxCHECK_MSG( node
, NULL
, _T("invalid column index in GetAttr()") );
1500 wxListItemData
*item
= node
->GetData();
1501 return item
->GetAttr();
1504 void wxListLineData::SetAttr(wxListItemAttr
*attr
)
1506 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1507 wxCHECK_RET( node
, _T("invalid column index in SetAttr()") );
1509 wxListItemData
*item
= node
->GetData();
1510 item
->SetAttr(attr
);
1513 void wxListLineData::SetAttributes(wxDC
*dc
,
1514 const wxListItemAttr
*attr
,
1515 const wxColour
& colText
,
1519 // don't use foregroud colour for drawing highlighted items - this might
1520 // make them completely invisible (and there is no way to do bit
1521 // arithmetics on wxColour, unfortunately)
1522 if ( !highlight
&& attr
&& attr
->HasTextColour() )
1524 dc
->SetTextForeground(attr
->GetTextColour());
1528 dc
->SetTextForeground(colText
);
1531 if ( attr
&& attr
->HasFont() )
1533 dc
->SetFont(attr
->GetFont());
1541 void wxListLineData::Draw( wxDC
*dc
)
1543 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1544 wxCHECK_RET( node
, _T("no subitems at all??") );
1546 wxListItemData
*item
= node
->GetData();
1547 if (item
->HasImage())
1549 wxRect rectIcon
= m_gi
->m_rectIcon
;
1550 m_owner
->DrawImage( item
->GetImage(), dc
,
1551 rectIcon
.x
, rectIcon
.y
);
1554 if (item
->HasText())
1556 wxRect rectLabel
= m_gi
->m_rectLabel
;
1557 dc
->DrawText( item
->GetText(), rectLabel
.x
, rectLabel
.y
);
1561 void wxListLineData::DrawInReportMode( wxDC
*dc
,
1563 const wxRect
& rectHL
,
1566 // use our own flag if we maintain it
1568 highlighted
= m_highlighted
;
1570 // default foreground colour
1571 wxWindow
*listctrl
= m_owner
->GetParent();
1575 colText
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT
);
1579 colText
= listctrl
->GetForegroundColour();
1583 wxFont font
= listctrl
->GetFont();
1585 // TODO: later we should support setting different attributes for
1586 // different columns - to do it, just add "col" argument to
1587 // GetAttr() and move this code into the loop below
1588 wxListItemAttr
*attr
= GetAttr();
1589 SetAttributes(dc
, attr
, colText
, font
, highlighted
);
1591 bool hasBgCol
= attr
&& attr
->HasBackgroundColour();
1592 if ( highlighted
|| hasBgCol
)
1596 dc
->SetBrush( *m_owner
->m_highlightBrush
);
1601 dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
));
1603 dc
->SetBrush( * wxWHITE_BRUSH
);
1606 dc
->SetPen( * wxTRANSPARENT_PEN
);
1607 dc
->DrawRectangle( rectHL
);
1610 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1611 wxCHECK_RET( node
, _T("no subitems at all??") );
1614 wxCoord x
= rect
.x
+ HEADER_OFFSET_X
,
1615 y
= rect
.y
+ (LINE_SPACING
+ EXTRA_HEIGHT
) / 2;
1619 wxListItemData
*item
= node
->GetData();
1623 if ( item
->HasImage() )
1626 m_owner
->DrawImage( item
->GetImage(), dc
, x
, y
);
1627 m_owner
->GetImageSize( item
->GetImage(), ix
, iy
);
1628 x
+= ix
+ 5; // FIXME: what is "5"?
1631 int width
= m_owner
->GetColumnWidth(col
++);
1633 wxDCClipper
clipper(*dc
, x
, y
, width
, rect
.height
);
1635 if ( item
->HasText() )
1637 dc
->DrawText( item
->GetText(), x
, y
);
1642 node
= node
->GetNext();
1646 bool wxListLineData::Highlight( bool on
)
1648 wxCHECK_MSG( !m_owner
->IsVirtual(), FALSE
, _T("unexpected call to Highlight") );
1650 if ( on
== m_highlighted
)
1658 void wxListLineData::ReverseHighlight( void )
1660 Highlight(!IsHighlighted());
1663 //-----------------------------------------------------------------------------
1664 // wxListHeaderWindow
1665 //-----------------------------------------------------------------------------
1667 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
);
1669 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
)
1670 EVT_PAINT (wxListHeaderWindow::OnPaint
)
1671 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse
)
1672 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus
)
1675 wxListHeaderWindow::wxListHeaderWindow( void )
1677 m_owner
= (wxListMainWindow
*) NULL
;
1678 m_currentCursor
= (wxCursor
*) NULL
;
1679 m_resizeCursor
= (wxCursor
*) NULL
;
1680 m_isDragging
= FALSE
;
1683 wxListHeaderWindow::wxListHeaderWindow( wxWindow
*win
, wxWindowID id
, wxListMainWindow
*owner
,
1684 const wxPoint
&pos
, const wxSize
&size
,
1685 long style
, const wxString
&name
) :
1686 wxWindow( win
, id
, pos
, size
, style
, name
)
1689 // m_currentCursor = wxSTANDARD_CURSOR;
1690 m_currentCursor
= (wxCursor
*) NULL
;
1691 m_resizeCursor
= new wxCursor( wxCURSOR_SIZEWE
);
1692 m_isDragging
= FALSE
;
1695 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
) );
1698 wxListHeaderWindow::~wxListHeaderWindow( void )
1700 delete m_resizeCursor
;
1703 void wxListHeaderWindow::DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
)
1706 GtkStateType state
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
1707 : GTK_STATE_INSENSITIVE
;
1709 x
= dc
->XLOG2DEV( x
);
1711 gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
,
1712 state
, GTK_SHADOW_OUT
,
1713 (GdkRectangle
*) NULL
, m_wxwindow
, "button",
1714 x
-1, y
-1, w
+2, h
+2);
1715 #elif defined( __WXMAC__ )
1716 const int m_corner
= 1;
1718 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1720 dc
->SetPen( wxPen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
) , 1 , wxSOLID
) );
1721 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1722 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1724 wxPen
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID
);
1727 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1728 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1730 dc
->SetPen( *wxWHITE_PEN
);
1731 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1732 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1733 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1734 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1736 const int m_corner
= 1;
1738 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1740 dc
->SetPen( *wxBLACK_PEN
);
1741 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1742 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1744 wxPen
pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
), 1, wxSOLID
);
1747 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1748 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1750 dc
->SetPen( *wxWHITE_PEN
);
1751 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1752 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1753 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1754 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1758 // shift the DC origin to match the position of the main window horz
1759 // scrollbar: this allows us to always use logical coords
1760 void wxListHeaderWindow::AdjustDC(wxDC
& dc
)
1763 m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL
);
1766 m_owner
->GetViewStart( &x
, NULL
);
1768 // account for the horz scrollbar offset
1769 dc
.SetDeviceOrigin( -x
* xpix
, 0 );
1772 void wxListHeaderWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
1775 wxClientDC
dc( this );
1777 wxPaintDC
dc( this );
1785 dc
.SetFont( GetFont() );
1787 // width and height of the entire header window
1789 GetClientSize( &w
, &h
);
1790 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1792 dc
.SetBackgroundMode(wxTRANSPARENT
);
1794 // do *not* use the listctrl colour for headers - one day we will have a
1795 // function to set it separately
1796 //dc.SetTextForeground( *wxBLACK );
1797 dc
.SetTextForeground(wxSystemSettings::
1798 GetSystemColour( wxSYS_COLOUR_WINDOWTEXT
));
1800 int x
= HEADER_OFFSET_X
;
1802 int numColumns
= m_owner
->GetColumnCount();
1804 for (int i
= 0; i
< numColumns
; i
++)
1806 m_owner
->GetColumn( i
, item
);
1807 int wCol
= item
.m_width
;
1808 int cw
= wCol
- 2; // the width of the rect to draw
1810 int xEnd
= x
+ wCol
;
1812 dc
.SetPen( *wxWHITE_PEN
);
1814 DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 );
1815 dc
.SetClippingRegion( x
, HEADER_OFFSET_Y
, cw
-5, h
-4 );
1816 dc
.DrawText( item
.GetText(), x
+ EXTRA_WIDTH
, HEADER_OFFSET_Y
+ EXTRA_HEIGHT
);
1817 dc
.DestroyClippingRegion();
1826 void wxListHeaderWindow::DrawCurrent()
1828 int x1
= m_currentX
;
1830 ClientToScreen( &x1
, &y1
);
1832 int x2
= m_currentX
-1;
1834 m_owner
->GetClientSize( NULL
, &y2
);
1835 m_owner
->ClientToScreen( &x2
, &y2
);
1838 dc
.SetLogicalFunction( wxINVERT
);
1839 dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID
) );
1840 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1844 dc
.DrawLine( x1
, y1
, x2
, y2
);
1846 dc
.SetLogicalFunction( wxCOPY
);
1848 dc
.SetPen( wxNullPen
);
1849 dc
.SetBrush( wxNullBrush
);
1852 void wxListHeaderWindow::OnMouse( wxMouseEvent
&event
)
1854 // we want to work with logical coords
1856 m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
);
1857 int y
= event
.GetY();
1861 // we don't draw the line beyond our window, but we allow dragging it
1864 GetClientSize( &w
, NULL
);
1865 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1868 // erase the line if it was drawn
1869 if ( m_currentX
< w
)
1872 if (event
.ButtonUp())
1875 m_isDragging
= FALSE
;
1877 m_owner
->SetColumnWidth( m_column
, m_currentX
- m_minX
);
1884 m_currentX
= m_minX
+ 7;
1886 // draw in the new location
1887 if ( m_currentX
< w
)
1891 else // not dragging
1894 bool hit_border
= FALSE
;
1896 // end of the current column
1899 // find the column where this event occured
1900 int countCol
= m_owner
->GetColumnCount();
1901 for (int col
= 0; col
< countCol
; col
++)
1903 xpos
+= m_owner
->GetColumnWidth( col
);
1906 if ( (abs(x
-xpos
) < 3) && (y
< 22) )
1908 // near the column border
1915 // inside the column
1922 if (event
.LeftDown())
1926 m_isDragging
= TRUE
;
1933 wxWindow
*parent
= GetParent();
1934 wxListEvent
le( wxEVT_COMMAND_LIST_COL_CLICK
, parent
->GetId() );
1935 le
.SetEventObject( parent
);
1936 le
.m_col
= m_column
;
1937 parent
->GetEventHandler()->ProcessEvent( le
);
1940 else if (event
.Moving())
1945 setCursor
= m_currentCursor
== wxSTANDARD_CURSOR
;
1946 m_currentCursor
= m_resizeCursor
;
1950 setCursor
= m_currentCursor
!= wxSTANDARD_CURSOR
;
1951 m_currentCursor
= wxSTANDARD_CURSOR
;
1955 SetCursor(*m_currentCursor
);
1960 void wxListHeaderWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
1962 m_owner
->SetFocus();
1965 //-----------------------------------------------------------------------------
1966 // wxListRenameTimer (internal)
1967 //-----------------------------------------------------------------------------
1969 wxListRenameTimer::wxListRenameTimer( wxListMainWindow
*owner
)
1974 void wxListRenameTimer::Notify()
1976 m_owner
->OnRenameTimer();
1979 //-----------------------------------------------------------------------------
1980 // wxListTextCtrl (internal)
1981 //-----------------------------------------------------------------------------
1983 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl
,wxTextCtrl
);
1985 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
)
1986 EVT_CHAR (wxListTextCtrl::OnChar
)
1987 EVT_KEY_UP (wxListTextCtrl::OnKeyUp
)
1988 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus
)
1991 wxListTextCtrl::wxListTextCtrl( wxWindow
*parent
,
1992 const wxWindowID id
,
1995 wxListMainWindow
*owner
,
1996 const wxString
&value
,
2000 const wxValidator
& validator
,
2001 const wxString
&name
)
2002 : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name
)
2007 (*m_accept
) = FALSE
;
2009 m_startValue
= value
;
2012 void wxListTextCtrl::OnChar( wxKeyEvent
&event
)
2014 if (event
.m_keyCode
== WXK_RETURN
)
2017 (*m_res
) = GetValue();
2019 if (!wxPendingDelete
.Member(this))
2020 wxPendingDelete
.Append(this);
2022 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2023 m_owner
->OnRenameAccept();
2027 if (event
.m_keyCode
== WXK_ESCAPE
)
2029 (*m_accept
) = FALSE
;
2032 if (!wxPendingDelete
.Member(this))
2033 wxPendingDelete
.Append(this);
2041 void wxListTextCtrl::OnKeyUp( wxKeyEvent
&event
)
2043 // auto-grow the textctrl:
2044 wxSize parentSize
= m_owner
->GetSize();
2045 wxPoint myPos
= GetPosition();
2046 wxSize mySize
= GetSize();
2048 GetTextExtent(GetValue() + _T("MM"), &sx
, &sy
); // FIXME: MM??
2049 if (myPos
.x
+ sx
> parentSize
.x
)
2050 sx
= parentSize
.x
- myPos
.x
;
2058 void wxListTextCtrl::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
2060 if (!wxPendingDelete
.Member(this))
2061 wxPendingDelete
.Append(this);
2063 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2064 m_owner
->OnRenameAccept();
2067 //-----------------------------------------------------------------------------
2069 //-----------------------------------------------------------------------------
2071 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
);
2073 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
)
2074 EVT_PAINT (wxListMainWindow::OnPaint
)
2075 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse
)
2076 EVT_CHAR (wxListMainWindow::OnChar
)
2077 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown
)
2078 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus
)
2079 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus
)
2080 EVT_SCROLLWIN (wxListMainWindow::OnScroll
)
2083 void wxListMainWindow::Init()
2085 m_columns
.DeleteContents( TRUE
);
2089 m_lineTo
= (size_t)-1;
2095 m_small_image_list
= (wxImageList
*) NULL
;
2096 m_normal_image_list
= (wxImageList
*) NULL
;
2098 m_small_spacing
= 30;
2099 m_normal_spacing
= 40;
2103 m_isCreated
= FALSE
;
2105 m_lastOnSame
= FALSE
;
2106 m_renameTimer
= new wxListRenameTimer( this );
2107 m_renameAccept
= FALSE
;
2112 m_lineBeforeLastClicked
= (size_t)-1;
2115 void wxListMainWindow::InitScrolling()
2117 if ( HasFlag(wxLC_REPORT
) )
2119 m_xScroll
= SCROLL_UNIT_X
;
2120 m_yScroll
= SCROLL_UNIT_Y
;
2124 m_xScroll
= SCROLL_UNIT_Y
;
2129 wxListMainWindow::wxListMainWindow()
2133 m_highlightBrush
= (wxBrush
*) NULL
;
2139 wxListMainWindow::wxListMainWindow( wxWindow
*parent
,
2144 const wxString
&name
)
2145 : wxScrolledWindow( parent
, id
, pos
, size
,
2146 style
| wxHSCROLL
| wxVSCROLL
, name
)
2150 m_highlightBrush
= new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
), wxSOLID
);
2155 SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 );
2157 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX
) );
2160 wxListMainWindow::~wxListMainWindow()
2164 delete m_highlightBrush
;
2166 delete m_renameTimer
;
2169 void wxListMainWindow::CacheLineData(size_t line
)
2171 wxListCtrl
*listctrl
= GetListCtrl();
2173 wxListLineData
*ld
= GetDummyLine();
2175 size_t countCol
= GetColumnCount();
2176 for ( size_t col
= 0; col
< countCol
; col
++ )
2178 ld
->SetText(col
, listctrl
->OnGetItemText(line
, col
));
2181 ld
->SetImage(listctrl
->OnGetItemImage(line
));
2182 ld
->SetAttr(listctrl
->OnGetItemAttr(line
));
2185 wxListLineData
*wxListMainWindow::GetDummyLine() const
2187 wxASSERT_MSG( !IsEmpty(), _T("invalid line index") );
2189 if ( m_lines
.IsEmpty() )
2191 // normal controls are supposed to have something in m_lines
2192 // already if it's not empty
2193 wxASSERT_MSG( IsVirtual(), _T("logic error") );
2195 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2196 wxListLineData
*line
= new wxListLineData(self
);
2197 self
->m_lines
.Add(line
);
2203 // ----------------------------------------------------------------------------
2204 // line geometry (report mode only)
2205 // ----------------------------------------------------------------------------
2207 wxCoord
wxListMainWindow::GetLineHeight() const
2209 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2211 // we cache the line height as calling GetTextExtent() is slow
2212 if ( !m_lineHeight
)
2214 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2216 wxClientDC
dc( self
);
2217 dc
.SetFont( GetFont() );
2220 dc
.GetTextExtent(_T("H"), NULL
, &y
);
2222 if ( y
< SCROLL_UNIT_Y
)
2226 self
->m_lineHeight
= y
+ LINE_SPACING
;
2229 return m_lineHeight
;
2232 wxCoord
wxListMainWindow::GetLineY(size_t line
) const
2234 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2236 return LINE_SPACING
+ line
*GetLineHeight();
2239 wxRect
wxListMainWindow::GetLineRect(size_t line
) const
2241 if ( !InReportView() )
2242 return GetLine(line
)->m_gi
->m_rectAll
;
2245 rect
.x
= HEADER_OFFSET_X
;
2246 rect
.y
= GetLineY(line
);
2247 rect
.width
= GetHeaderWidth();
2248 rect
.height
= GetLineHeight();
2253 wxRect
wxListMainWindow::GetLineLabelRect(size_t line
) const
2255 if ( !InReportView() )
2256 return GetLine(line
)->m_gi
->m_rectLabel
;
2259 rect
.x
= HEADER_OFFSET_X
;
2260 rect
.y
= GetLineY(line
);
2261 rect
.width
= GetColumnWidth(0);
2262 rect
.height
= GetLineHeight();
2267 wxRect
wxListMainWindow::GetLineIconRect(size_t line
) const
2269 if ( !InReportView() )
2270 return GetLine(line
)->m_gi
->m_rectIcon
;
2272 wxListLineData
*ld
= GetLine(line
);
2273 wxASSERT_MSG( ld
->HasImage(), _T("should have an image") );
2276 rect
.x
= HEADER_OFFSET_X
;
2277 rect
.y
= GetLineY(line
);
2278 GetImageSize(ld
->GetImage(), rect
.width
, rect
.height
);
2283 wxRect
wxListMainWindow::GetLineHighlightRect(size_t line
) const
2285 return InReportView() ? GetLineRect(line
)
2286 : GetLine(line
)->m_gi
->m_rectHighlight
;
2289 long wxListMainWindow::HitTestLine(size_t line
, int x
, int y
) const
2291 wxListLineData
*ld
= GetLine(line
);
2293 if ( ld
->HasImage() && GetLineIconRect(line
).Inside(x
, y
) )
2294 return wxLIST_HITTEST_ONITEMICON
;
2296 if ( ld
->HasText() )
2298 wxRect rect
= InReportView() ? GetLineRect(line
)
2299 : GetLineLabelRect(line
);
2301 if ( rect
.Inside(x
, y
) )
2302 return wxLIST_HITTEST_ONITEMLABEL
;
2308 // ----------------------------------------------------------------------------
2309 // highlight (selection) handling
2310 // ----------------------------------------------------------------------------
2312 bool wxListMainWindow::IsHighlighted(size_t line
) const
2316 return m_selStore
.IsSelected(line
);
2320 wxListLineData
*ld
= GetLine(line
);
2321 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2323 return ld
->IsHighlighted();
2327 void wxListMainWindow::HighlightLines( size_t lineFrom
, size_t lineTo
, bool highlight
)
2331 m_selStore
.SelectRange(lineFrom
, lineTo
, highlight
);
2332 RefreshLines(lineFrom
, lineTo
);
2336 // do it the dumb way
2337 bool needsRefresh
= FALSE
;
2338 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2340 if ( HighlightLine(line
, highlight
) )
2341 needsRefresh
= TRUE
;
2345 RefreshLines(lineFrom
, lineTo
);
2349 bool wxListMainWindow::HighlightLine( size_t line
, bool highlight
)
2355 changed
= m_selStore
.SelectItem(line
, highlight
);
2359 wxListLineData
*ld
= GetLine(line
);
2360 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2362 changed
= ld
->Highlight(highlight
);
2367 SendNotify( line
, highlight
? wxEVT_COMMAND_LIST_ITEM_SELECTED
2368 : wxEVT_COMMAND_LIST_ITEM_DESELECTED
);
2374 void wxListMainWindow::RefreshLine( size_t line
)
2376 wxRect rect
= GetLineRect(line
);
2378 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2379 RefreshRect( rect
);
2382 void wxListMainWindow::RefreshLines( size_t lineFrom
, size_t lineTo
)
2384 // we suppose that they are ordered by caller
2385 wxASSERT_MSG( lineFrom
<= lineTo
, _T("indices in disorder") );
2387 wxASSERT_MSG( lineTo
< GetItemCount(), _T("invalid line range") );
2389 if ( HasFlag(wxLC_REPORT
) )
2391 size_t visibleFrom
, visibleTo
;
2392 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2394 if ( lineFrom
< visibleFrom
)
2395 lineFrom
= visibleFrom
;
2396 if ( lineTo
> visibleTo
)
2401 rect
.y
= GetLineY(lineFrom
);
2402 rect
.width
= GetClientSize().x
;
2403 rect
.height
= GetLineY(lineTo
) - rect
.y
;
2405 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2406 RefreshRect( rect
);
2410 // TODO: this should be optimized...
2411 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2418 void wxListMainWindow::RefreshAfter( size_t lineFrom
)
2420 if ( HasFlag(wxLC_REPORT
) )
2423 GetVisibleLinesRange(&visibleFrom
, NULL
);
2425 if ( lineFrom
< visibleFrom
)
2426 lineFrom
= visibleFrom
;
2430 rect
.y
= GetLineY(lineFrom
);
2432 wxSize size
= GetClientSize();
2433 rect
.width
= size
.x
;
2434 // refresh till the bottom of the window
2435 rect
.height
= size
.y
- rect
.y
;
2437 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2438 RefreshRect( rect
);
2442 // TODO: how to do it more efficiently?
2447 void wxListMainWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
2449 // Note: a wxPaintDC must be constructed even if no drawing is
2450 // done (a Windows requirement).
2451 wxPaintDC
dc( this );
2455 // empty control. nothing to draw
2461 // delay the repainting until we calculate all the items positions
2468 CalcScrolledPosition( 0, 0, &dev_x
, &dev_y
);
2472 dc
.SetFont( GetFont() );
2474 if ( HasFlag(wxLC_REPORT
) )
2476 int lineHeight
= GetLineHeight();
2478 size_t visibleFrom
, visibleTo
;
2479 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2482 wxCoord xOrig
, yOrig
;
2483 CalcUnscrolledPosition(0, 0, &xOrig
, &yOrig
);
2485 // tell the caller cache to cache the data
2486 wxListEvent
evCache(wxEVT_COMMAND_LIST_CACHE_HINT
, GetParent()->GetId());
2487 evCache
.SetEventObject( GetParent() );
2488 evCache
.m_oldItemIndex
= visibleFrom
;
2489 evCache
.m_itemIndex
= visibleTo
;
2490 GetParent()->GetEventHandler()->ProcessEvent( evCache
);
2492 for ( size_t line
= visibleFrom
; line
<= visibleTo
; line
++ )
2494 rectLine
= GetLineRect(line
);
2496 if ( !IsExposed(rectLine
.x
- xOrig
, rectLine
.y
- yOrig
,
2497 rectLine
.width
, rectLine
.height
) )
2499 // don't redraw unaffected lines to avoid flicker
2503 GetLine(line
)->DrawInReportMode( &dc
,
2505 GetLineHighlightRect(line
),
2506 IsHighlighted(line
) );
2509 if ( HasFlag(wxLC_HRULES
) )
2511 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2512 wxSize clientSize
= GetClientSize();
2514 for ( size_t i
= visibleFrom
; i
<= visibleTo
; i
++ )
2517 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2518 dc
.DrawLine(0 - dev_x
, i
*lineHeight
,
2519 clientSize
.x
- dev_x
, i
*lineHeight
);
2522 // Draw last horizontal rule
2523 if ( visibleTo
> visibleFrom
)
2526 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2527 dc
.DrawLine(0 - dev_x
, m_lineTo
*lineHeight
,
2528 clientSize
.x
- dev_x
, m_lineTo
*lineHeight
);
2532 // Draw vertical rules if required
2533 if ( HasFlag(wxLC_VRULES
) && !IsEmpty() )
2535 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2538 wxRect firstItemRect
;
2539 wxRect lastItemRect
;
2540 GetItemRect(0, firstItemRect
);
2541 GetItemRect(GetItemCount() - 1, lastItemRect
);
2542 int x
= firstItemRect
.GetX();
2544 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
2545 for (col
= 0; col
< GetColumnCount(); col
++)
2547 int colWidth
= GetColumnWidth(col
);
2549 dc
.DrawLine(x
- dev_x
, firstItemRect
.GetY() - 1 - dev_y
,
2550 x
- dev_x
, lastItemRect
.GetBottom() + 1 - dev_y
);
2556 size_t count
= GetItemCount();
2557 for ( size_t i
= 0; i
< count
; i
++ )
2559 GetLine(i
)->Draw( &dc
);
2563 if ( HasCurrent() && m_hasFocus
)
2566 // no rect outline, we already have the background color
2568 dc
.SetPen( *wxBLACK_PEN
);
2569 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2570 dc
.DrawRectangle( GetLineHighlightRect(m_current
) );
2577 void wxListMainWindow::HighlightAll( bool on
)
2579 if ( IsSingleSel() )
2581 wxASSERT_MSG( !on
, _T("can't do this in a single sel control") );
2583 // we just have one item to turn off
2584 if ( HasCurrent() && IsHighlighted(m_current
) )
2586 HighlightLine(m_current
, FALSE
);
2587 RefreshLine(m_current
);
2592 HighlightLines(0, GetItemCount() - 1, on
);
2596 void wxListMainWindow::SendNotify( size_t line
,
2597 wxEventType command
,
2600 wxListEvent
le( command
, GetParent()->GetId() );
2601 le
.SetEventObject( GetParent() );
2602 le
.m_itemIndex
= line
;
2604 // set only for events which have position
2605 if ( point
!= wxDefaultPosition
)
2606 le
.m_pointDrag
= point
;
2608 GetLine(line
)->GetItem( 0, le
.m_item
);
2609 GetParent()->GetEventHandler()->ProcessEvent( le
);
2612 void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line
) )
2614 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
2617 void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line
) )
2619 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
2622 void wxListMainWindow::EditLabel( long item
)
2624 wxCHECK_RET( (item
>= 0) && ((size_t)item
< GetItemCount()),
2625 wxT("wrong index in wxListCtrl::EditLabel()") );
2627 m_currentEdit
= (size_t)item
;
2629 wxListEvent
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() );
2630 le
.SetEventObject( GetParent() );
2631 le
.m_itemIndex
= item
;
2632 wxListLineData
*data
= GetLine(m_currentEdit
);
2633 wxCHECK_RET( data
, _T("invalid index in EditLabel()") );
2634 data
->GetItem( 0, le
.m_item
);
2635 GetParent()->GetEventHandler()->ProcessEvent( le
);
2637 if (!le
.IsAllowed())
2640 // We have to call this here because the label in question might just have
2641 // been added and no screen update taken place.
2645 wxClientDC
dc(this);
2648 wxString s
= data
->GetText(0);
2649 wxRect rectLabel
= GetLineLabelRect(m_currentEdit
);
2651 rectLabel
.x
= dc
.LogicalToDeviceX( rectLabel
.x
);
2652 rectLabel
.y
= dc
.LogicalToDeviceY( rectLabel
.y
);
2654 wxListTextCtrl
*text
= new wxListTextCtrl
2661 wxPoint(rectLabel
.x
-4,rectLabel
.y
-4),
2662 wxSize(rectLabel
.width
+11,rectLabel
.height
+8)
2667 void wxListMainWindow::OnRenameTimer()
2669 wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") );
2671 EditLabel( m_current
);
2674 void wxListMainWindow::OnRenameAccept()
2676 wxListEvent
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() );
2677 le
.SetEventObject( GetParent() );
2678 le
.m_itemIndex
= m_currentEdit
;
2680 wxListLineData
*data
= GetLine(m_currentEdit
);
2681 wxCHECK_RET( data
, _T("invalid index in OnRenameAccept()") );
2683 data
->GetItem( 0, le
.m_item
);
2684 le
.m_item
.m_text
= m_renameRes
;
2685 GetParent()->GetEventHandler()->ProcessEvent( le
);
2687 if (!le
.IsAllowed()) return;
2690 info
.m_mask
= wxLIST_MASK_TEXT
;
2691 info
.m_itemId
= le
.m_itemIndex
;
2692 info
.m_text
= m_renameRes
;
2693 info
.SetTextColour(le
.m_item
.GetTextColour());
2697 void wxListMainWindow::OnMouse( wxMouseEvent
&event
)
2699 event
.SetEventObject( GetParent() );
2700 if ( GetParent()->GetEventHandler()->ProcessEvent( event
) )
2703 if ( !HasCurrent() || IsEmpty() )
2709 if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() ||
2710 event
.ButtonDClick()) )
2713 int x
= event
.GetX();
2714 int y
= event
.GetY();
2715 CalcUnscrolledPosition( x
, y
, &x
, &y
);
2717 // where did we hit it (if we did)?
2720 size_t count
= GetItemCount(),
2723 if ( HasFlag(wxLC_REPORT
) )
2725 current
= y
/ GetLineHeight();
2726 if ( current
< count
)
2727 hitResult
= HitTestLine(current
, x
, y
);
2731 // TODO: optimize it too! this is less simple than for report view but
2732 // enumerating all items is still not a way to do it!!
2733 for ( current
= 0; current
< count
; current
++ )
2735 hitResult
= HitTestLine(current
, x
, y
);
2741 if (event
.Dragging())
2743 if (m_dragCount
== 0)
2744 m_dragStart
= wxPoint(x
,y
);
2748 if (m_dragCount
!= 3)
2751 int command
= event
.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2752 : wxEVT_COMMAND_LIST_BEGIN_DRAG
;
2754 wxListEvent
le( command
, GetParent()->GetId() );
2755 le
.SetEventObject( GetParent() );
2756 le
.m_pointDrag
= m_dragStart
;
2757 GetParent()->GetEventHandler()->ProcessEvent( le
);
2768 // outside of any item
2772 bool forceClick
= FALSE
;
2773 if (event
.ButtonDClick())
2775 m_renameTimer
->Stop();
2776 m_lastOnSame
= FALSE
;
2778 if ( current
== m_lineBeforeLastClicked
)
2780 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
);
2786 // the first click was on another item, so don't interpret this as
2787 // a double click, but as a simple click instead
2792 if (event
.LeftUp() && m_lastOnSame
)
2794 if ((current
== m_current
) &&
2795 (hitResult
== wxLIST_HITTEST_ONITEMLABEL
) &&
2796 HasFlag(wxLC_EDIT_LABELS
) )
2798 m_renameTimer
->Start( 100, TRUE
);
2800 m_lastOnSame
= FALSE
;
2802 else if (event
.RightDown())
2804 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
,
2805 event
.GetPosition() );
2807 else if (event
.MiddleDown())
2809 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
);
2811 else if ( event
.LeftDown() || forceClick
)
2813 m_lineBeforeLastClicked
= m_lineLastClicked
;
2814 m_lineLastClicked
= current
;
2816 size_t oldCurrent
= m_current
;
2818 if ( IsSingleSel() || !(event
.ControlDown() || event
.ShiftDown()) )
2820 HighlightAll( FALSE
);
2821 m_current
= current
;
2823 ReverseHighlight(m_current
);
2825 else // multi sel & either ctrl or shift is down
2827 if (event
.ControlDown())
2829 m_current
= current
;
2831 ReverseHighlight(m_current
);
2833 else if (event
.ShiftDown())
2835 m_current
= current
;
2837 size_t lineFrom
= oldCurrent
,
2840 if ( lineTo
< lineFrom
)
2843 lineFrom
= m_current
;
2846 HighlightLines(lineFrom
, lineTo
);
2848 else // !ctrl, !shift
2850 // test in the enclosing if should make it impossible
2851 wxFAIL_MSG( _T("how did we get here?") );
2855 if (m_current
!= oldCurrent
)
2857 RefreshLine( oldCurrent
);
2858 OnUnfocusLine( oldCurrent
);
2859 OnFocusLine( m_current
);
2862 // forceClick is only set if the previous click was on another item
2863 m_lastOnSame
= !forceClick
&& (m_current
== oldCurrent
);
2867 void wxListMainWindow::MoveToFocus()
2869 if ( !HasCurrent() )
2872 wxRect rect
= GetLineRect(m_current
);
2874 int client_w
, client_h
;
2875 GetClientSize( &client_w
, &client_h
);
2877 int view_x
= m_xScroll
*GetScrollPos( wxHORIZONTAL
);
2878 int view_y
= m_yScroll
*GetScrollPos( wxVERTICAL
);
2880 if ( HasFlag(wxLC_REPORT
) )
2882 // the next we need the range of lines shown it might be different, so
2884 ResetVisibleLinesRange();
2886 if (rect
.y
< view_y
)
2887 Scroll( -1, rect
.y
/m_yScroll
);
2888 if (rect
.y
+rect
.height
+5 > view_y
+client_h
)
2889 Scroll( -1, (rect
.y
+rect
.height
-client_h
+SCROLL_UNIT_Y
)/m_yScroll
);
2893 if (rect
.x
-view_x
< 5)
2894 Scroll( (rect
.x
-5)/m_xScroll
, -1 );
2895 if (rect
.x
+rect
.width
-5 > view_x
+client_w
)
2896 Scroll( (rect
.x
+rect
.width
-client_w
+SCROLL_UNIT_X
)/m_xScroll
, -1 );
2900 // ----------------------------------------------------------------------------
2901 // keyboard handling
2902 // ----------------------------------------------------------------------------
2904 void wxListMainWindow::OnArrowChar(size_t newCurrent
, const wxKeyEvent
& event
)
2906 wxCHECK_RET( newCurrent
< (size_t)GetItemCount(),
2907 _T("invalid item index in OnArrowChar()") );
2909 size_t oldCurrent
= m_current
;
2911 // in single selection we just ignore Shift as we can't select several
2913 if ( event
.ShiftDown() && !IsSingleSel() )
2915 m_current
= newCurrent
;
2917 // select all the items between the old and the new one
2918 if ( oldCurrent
> newCurrent
)
2920 newCurrent
= oldCurrent
;
2921 oldCurrent
= m_current
;
2924 HighlightLines(oldCurrent
, newCurrent
);
2928 // all previously selected items are unselected unless ctrl is held
2929 if ( !event
.ControlDown() )
2930 HighlightAll(FALSE
);
2932 m_current
= newCurrent
;
2934 HighlightLine( oldCurrent
, FALSE
);
2935 RefreshLine( oldCurrent
);
2937 if ( !event
.ControlDown() )
2939 HighlightLine( m_current
, TRUE
);
2943 OnUnfocusLine( oldCurrent
);
2944 OnFocusLine( m_current
);
2945 RefreshLine( m_current
);
2950 void wxListMainWindow::OnKeyDown( wxKeyEvent
&event
)
2952 wxWindow
*parent
= GetParent();
2954 /* we propagate the key event up */
2955 wxKeyEvent
ke( wxEVT_KEY_DOWN
);
2956 ke
.m_shiftDown
= event
.m_shiftDown
;
2957 ke
.m_controlDown
= event
.m_controlDown
;
2958 ke
.m_altDown
= event
.m_altDown
;
2959 ke
.m_metaDown
= event
.m_metaDown
;
2960 ke
.m_keyCode
= event
.m_keyCode
;
2963 ke
.SetEventObject( parent
);
2964 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2969 void wxListMainWindow::OnChar( wxKeyEvent
&event
)
2971 wxWindow
*parent
= GetParent();
2973 /* we send a list_key event up */
2976 wxListEvent
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() );
2977 le
.m_itemIndex
= m_current
;
2978 GetLine(m_current
)->GetItem( 0, le
.m_item
);
2979 le
.m_code
= (int)event
.KeyCode();
2980 le
.SetEventObject( parent
);
2981 parent
->GetEventHandler()->ProcessEvent( le
);
2984 /* we propagate the char event up */
2985 wxKeyEvent
ke( wxEVT_CHAR
);
2986 ke
.m_shiftDown
= event
.m_shiftDown
;
2987 ke
.m_controlDown
= event
.m_controlDown
;
2988 ke
.m_altDown
= event
.m_altDown
;
2989 ke
.m_metaDown
= event
.m_metaDown
;
2990 ke
.m_keyCode
= event
.m_keyCode
;
2993 ke
.SetEventObject( parent
);
2994 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2996 if (event
.KeyCode() == WXK_TAB
)
2998 wxNavigationKeyEvent nevent
;
2999 nevent
.SetWindowChange( event
.ControlDown() );
3000 nevent
.SetDirection( !event
.ShiftDown() );
3001 nevent
.SetEventObject( GetParent()->GetParent() );
3002 nevent
.SetCurrentFocus( m_parent
);
3003 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent
)) return;
3006 /* no item -> nothing to do */
3013 switch (event
.KeyCode())
3016 if ( m_current
> 0 )
3017 OnArrowChar( m_current
- 1, event
);
3021 if ( m_current
< (size_t)GetItemCount() - 1 )
3022 OnArrowChar( m_current
+ 1, event
);
3027 OnArrowChar( GetItemCount() - 1, event
);
3032 OnArrowChar( 0, event
);
3038 if ( HasFlag(wxLC_REPORT
) )
3040 steps
= m_linesPerPage
- 1;
3044 steps
= m_current
% m_linesPerPage
;
3047 int index
= m_current
- steps
;
3051 OnArrowChar( index
, event
);
3058 if ( HasFlag(wxLC_REPORT
) )
3060 steps
= m_linesPerPage
- 1;
3064 steps
= m_linesPerPage
- (m_current
% m_linesPerPage
) - 1;
3067 size_t index
= m_current
+ steps
;
3068 size_t count
= GetItemCount();
3069 if ( index
>= count
)
3072 OnArrowChar( index
, event
);
3077 if ( !HasFlag(wxLC_REPORT
) )
3079 int index
= m_current
- m_linesPerPage
;
3083 OnArrowChar( index
, event
);
3088 if ( !HasFlag(wxLC_REPORT
) )
3090 size_t index
= m_current
+ m_linesPerPage
;
3092 size_t count
= GetItemCount();
3093 if ( index
>= count
)
3096 OnArrowChar( index
, event
);
3101 if ( IsSingleSel() )
3103 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3104 GetParent()->GetId() );
3105 le
.SetEventObject( GetParent() );
3106 le
.m_itemIndex
= m_current
;
3107 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3108 GetParent()->GetEventHandler()->ProcessEvent( le
);
3112 ReverseHighlight(m_current
);
3119 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3120 GetParent()->GetId() );
3121 le
.SetEventObject( GetParent() );
3122 le
.m_itemIndex
= m_current
;
3123 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3124 GetParent()->GetEventHandler()->ProcessEvent( le
);
3133 // ----------------------------------------------------------------------------
3135 // ----------------------------------------------------------------------------
3138 extern wxWindow
*g_focusWindow
;
3141 void wxListMainWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
3146 RefreshLine( m_current
);
3152 g_focusWindow
= GetParent();
3155 wxFocusEvent
event( wxEVT_SET_FOCUS
, GetParent()->GetId() );
3156 event
.SetEventObject( GetParent() );
3157 GetParent()->GetEventHandler()->ProcessEvent( event
);
3160 void wxListMainWindow::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
3165 RefreshLine( m_current
);
3168 void wxListMainWindow::DrawImage( int index
, wxDC
*dc
, int x
, int y
)
3170 if ( HasFlag(wxLC_ICON
) && (m_normal_image_list
))
3172 m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3174 else if ( HasFlag(wxLC_SMALL_ICON
) && (m_small_image_list
))
3176 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3178 else if ( HasFlag(wxLC_LIST
) && (m_small_image_list
))
3180 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3182 else if ( HasFlag(wxLC_REPORT
) && (m_small_image_list
))
3184 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3188 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height
) const
3190 if ( HasFlag(wxLC_ICON
) && m_normal_image_list
)
3192 m_normal_image_list
->GetSize( index
, width
, height
);
3194 else if ( HasFlag(wxLC_SMALL_ICON
) && m_small_image_list
)
3196 m_small_image_list
->GetSize( index
, width
, height
);
3198 else if ( HasFlag(wxLC_LIST
) && m_small_image_list
)
3200 m_small_image_list
->GetSize( index
, width
, height
);
3202 else if ( HasFlag(wxLC_REPORT
) && m_small_image_list
)
3204 m_small_image_list
->GetSize( index
, width
, height
);
3213 int wxListMainWindow::GetTextLength( const wxString
&s
) const
3215 wxClientDC
dc( wxConstCast(this, wxListMainWindow
) );
3216 dc
.SetFont( GetFont() );
3219 dc
.GetTextExtent( s
, &lw
, NULL
);
3221 return lw
+ AUTOSIZE_COL_MARGIN
;
3224 void wxListMainWindow::SetImageList( wxImageList
*imageList
, int which
)
3228 // calc the spacing from the icon size
3231 if ((imageList
) && (imageList
->GetImageCount()) )
3233 imageList
->GetSize(0, width
, height
);
3236 if (which
== wxIMAGE_LIST_NORMAL
)
3238 m_normal_image_list
= imageList
;
3239 m_normal_spacing
= width
+ 8;
3242 if (which
== wxIMAGE_LIST_SMALL
)
3244 m_small_image_list
= imageList
;
3245 m_small_spacing
= width
+ 14;
3249 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall
)
3254 m_small_spacing
= spacing
;
3258 m_normal_spacing
= spacing
;
3262 int wxListMainWindow::GetItemSpacing( bool isSmall
)
3264 return isSmall
? m_small_spacing
: m_normal_spacing
;
3267 // ----------------------------------------------------------------------------
3269 // ----------------------------------------------------------------------------
3271 void wxListMainWindow::SetColumn( int col
, wxListItem
&item
)
3273 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3275 wxCHECK_RET( node
, _T("invalid column index in SetColumn") );
3277 if ( item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3278 item
.m_width
= GetTextLength( item
.m_text
);
3280 wxListHeaderData
*column
= node
->GetData();
3281 column
->SetItem( item
);
3283 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3285 headerWin
->m_dirty
= TRUE
;
3289 // invalidate it as it has to be recalculated
3293 void wxListMainWindow::SetColumnWidth( int col
, int width
)
3295 wxCHECK_RET( col
>= 0 && col
< GetColumnCount(),
3296 _T("invalid column index") );
3298 wxCHECK_RET( HasFlag(wxLC_REPORT
),
3299 _T("SetColumnWidth() can only be called in report mode.") );
3303 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3304 wxCHECK_RET( node
, _T("no column?") );
3306 wxListHeaderData
*column
= node
->GetData();
3308 size_t count
= GetItemCount();
3310 if (width
== wxLIST_AUTOSIZE_USEHEADER
)
3312 width
= GetTextLength(column
->GetText());
3314 else if ( width
== wxLIST_AUTOSIZE
)
3318 // TODO: determine the max width somehow...
3319 width
= WIDTH_COL_DEFAULT
;
3323 wxClientDC
dc(this);
3324 dc
.SetFont( GetFont() );
3326 int max
= AUTOSIZE_COL_MARGIN
;
3328 for ( size_t i
= 0; i
< count
; i
++ )
3330 wxListLineData
*line
= GetLine(i
);
3331 wxListItemDataList::Node
*n
= line
->m_items
.Item( col
);
3333 wxCHECK_RET( n
, _T("no subitem?") );
3335 wxListItemData
*item
= n
->GetData();
3338 if (item
->HasImage())
3341 GetImageSize( item
->GetImage(), ix
, iy
);
3345 if (item
->HasText())
3348 dc
.GetTextExtent( item
->GetText(), &w
, NULL
);
3356 width
= max
+ AUTOSIZE_COL_MARGIN
;
3360 column
->SetWidth( width
);
3362 // invalidate it as it has to be recalculated
3366 int wxListMainWindow::GetHeaderWidth() const
3368 if ( !m_headerWidth
)
3370 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
3372 size_t count
= GetColumnCount();
3373 for ( size_t col
= 0; col
< count
; col
++ )
3375 self
->m_headerWidth
+= GetColumnWidth(col
);
3379 return m_headerWidth
;
3382 void wxListMainWindow::GetColumn( int col
, wxListItem
&item
) const
3384 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3385 wxCHECK_RET( node
, _T("invalid column index in GetColumn") );
3387 wxListHeaderData
*column
= node
->GetData();
3388 column
->GetItem( item
);
3391 int wxListMainWindow::GetColumnWidth( int col
) const
3393 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3394 wxCHECK_MSG( node
, 0, _T("invalid column index") );
3396 wxListHeaderData
*column
= node
->GetData();
3397 return column
->GetWidth();
3400 // ----------------------------------------------------------------------------
3402 // ----------------------------------------------------------------------------
3404 void wxListMainWindow::SetItem( wxListItem
&item
)
3406 long id
= item
.m_itemId
;
3407 wxCHECK_RET( id
>= 0 && (size_t)id
< GetItemCount(),
3408 _T("invalid item index in SetItem") );
3412 wxListLineData
*line
= GetLine((size_t)id
);
3413 line
->SetItem( item
.m_col
, item
);
3416 if ( InReportView() )
3418 // just refresh the line to show the new value of the text/image
3419 RefreshLine((size_t)id
);
3423 // refresh everything (resulting in horrible flicker - FIXME!)
3428 void wxListMainWindow::SetItemState( long litem
, long state
, long stateMask
)
3430 wxCHECK_RET( litem
>= 0 && (size_t)litem
< GetItemCount(),
3431 _T("invalid list ctrl item index in SetItem") );
3433 size_t oldCurrent
= m_current
;
3434 size_t item
= (size_t)litem
; // sdafe because of the check above
3436 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3438 if ( state
& wxLIST_STATE_FOCUSED
)
3440 // don't do anything if this item is already focused
3441 if ( item
!= m_current
)
3443 OnUnfocusLine( m_current
);
3445 OnFocusLine( m_current
);
3447 if ( IsSingleSel() && (oldCurrent
!= (size_t)-1) )
3449 HighlightLine(oldCurrent
, FALSE
);
3450 RefreshLine(oldCurrent
);
3453 RefreshLine( m_current
);
3458 // don't do anything if this item is not focused
3459 if ( item
== m_current
)
3461 OnUnfocusLine( m_current
);
3462 m_current
= (size_t)-1;
3467 if ( stateMask
& wxLIST_STATE_SELECTED
)
3469 bool on
= (state
& wxLIST_STATE_SELECTED
) != 0;
3471 if ( IsSingleSel() )
3475 // selecting the item also makes it the focused one in the
3477 if ( m_current
!= item
)
3479 OnUnfocusLine( m_current
);
3481 OnFocusLine( m_current
);
3483 if ( oldCurrent
!= (size_t)-1 )
3485 HighlightLine( oldCurrent
, FALSE
);
3486 RefreshLine( oldCurrent
);
3492 // only the current item may be selected anyhow
3493 if ( item
!= m_current
)
3498 if ( HighlightLine(item
, on
) )
3505 int wxListMainWindow::GetItemState( long item
, long stateMask
)
3507 wxCHECK_MSG( item
>= 0 && (size_t)item
< GetItemCount(), 0,
3508 _T("invalid list ctrl item index in GetItemState()") );
3510 int ret
= wxLIST_STATE_DONTCARE
;
3512 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3514 if ( (size_t)item
== m_current
)
3515 ret
|= wxLIST_STATE_FOCUSED
;
3518 if ( stateMask
& wxLIST_STATE_SELECTED
)
3520 if ( IsHighlighted(item
) )
3521 ret
|= wxLIST_STATE_SELECTED
;
3527 void wxListMainWindow::GetItem( wxListItem
&item
)
3529 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
< GetItemCount(),
3530 _T("invalid item index in GetItem") );
3532 wxListLineData
*line
= GetLine((size_t)item
.m_itemId
);
3533 line
->GetItem( item
.m_col
, item
);
3536 // ----------------------------------------------------------------------------
3538 // ----------------------------------------------------------------------------
3540 size_t wxListMainWindow::GetItemCount() const
3542 return IsVirtual() ? m_countVirt
: m_lines
.GetCount();
3545 void wxListMainWindow::SetItemCount(long count
)
3547 m_selStore
.SetItemCount(count
);
3548 m_countVirt
= count
;
3550 ResetVisibleLinesRange();
3555 int wxListMainWindow::GetSelectedItemCount()
3557 // deal with the quick case first
3558 if ( IsSingleSel() )
3560 return HasCurrent() ? IsHighlighted(m_current
) : FALSE
;
3563 // virtual controls remmebers all its selections itself
3565 return m_selStore
.GetSelectedCount();
3567 // TODO: we probably should maintain the number of items selected even for
3568 // non virtual controls as enumerating all lines is really slow...
3569 size_t countSel
= 0;
3570 size_t count
= GetItemCount();
3571 for ( size_t line
= 0; line
< count
; line
++ )
3573 if ( GetLine(line
)->IsHighlighted() )
3580 // ----------------------------------------------------------------------------
3581 // item position/size
3582 // ----------------------------------------------------------------------------
3584 void wxListMainWindow::GetItemRect( long index
, wxRect
&rect
)
3586 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3587 _T("invalid index in GetItemRect") );
3589 rect
= GetLineRect((size_t)index
);
3591 CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
3594 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
)
3597 GetItemRect(item
, rect
);
3605 // ----------------------------------------------------------------------------
3606 // geometry calculation
3607 // ----------------------------------------------------------------------------
3609 void wxListMainWindow::RecalculatePositions()
3614 wxClientDC
dc( this );
3615 dc
.SetFont( GetFont() );
3618 if ( HasFlag(wxLC_ICON
) )
3619 iconSpacing
= m_normal_spacing
;
3620 else if ( HasFlag(wxLC_SMALL_ICON
) )
3621 iconSpacing
= m_small_spacing
;
3627 GetClientSize( &clientWidth
, &clientHeight
);
3629 if ( HasFlag(wxLC_REPORT
) )
3631 // all lines have the same height
3632 int lineHeight
= GetLineHeight();
3634 // scroll one line per step
3635 m_yScroll
= lineHeight
;
3637 size_t lineCount
= GetItemCount();
3638 int entireHeight
= lineCount
*lineHeight
+ LINE_SPACING
;
3640 m_linesPerPage
= clientHeight
/ lineHeight
;
3642 ResetVisibleLinesRange();
3644 SetScrollbars( m_xScroll
, m_yScroll
,
3645 (GetHeaderWidth() + m_xScroll
- 1)/m_xScroll
,
3646 (entireHeight
+ m_yScroll
- 1)/m_yScroll
,
3647 GetScrollPos(wxHORIZONTAL
),
3648 GetScrollPos(wxVERTICAL
),
3653 // at first we try without any scrollbar. if the items don't
3654 // fit into the window, we recalculate after subtracting an
3655 // approximated 15 pt for the horizontal scrollbar
3657 clientHeight
-= 4; // sunken frame
3659 int entireWidth
= 0;
3661 for (int tries
= 0; tries
< 2; tries
++)
3668 int currentlyVisibleLines
= 0;
3670 size_t count
= GetItemCount();
3671 for (size_t i
= 0; i
< count
; i
++)
3673 currentlyVisibleLines
++;
3674 wxListLineData
*line
= GetLine(i
);
3675 line
->CalculateSize( &dc
, iconSpacing
);
3676 line
->SetPosition( x
, y
, clientWidth
, iconSpacing
);
3678 wxSize sizeLine
= GetLineSize(i
);
3680 if ( maxWidth
< sizeLine
.x
)
3681 maxWidth
= sizeLine
.x
;
3684 if (currentlyVisibleLines
> m_linesPerPage
)
3685 m_linesPerPage
= currentlyVisibleLines
;
3687 // assume that the size of the next one is the same... (FIXME)
3688 if ( y
+ sizeLine
.y
- 6 >= clientHeight
)
3690 currentlyVisibleLines
= 0;
3693 entireWidth
+= maxWidth
+6;
3696 if ( i
== count
- 1 )
3697 entireWidth
+= maxWidth
;
3698 if ((tries
== 0) && (entireWidth
> clientWidth
))
3700 clientHeight
-= 15; // scrollbar height
3702 currentlyVisibleLines
= 0;
3705 if ( i
== count
- 1 )
3706 tries
= 1; // everything fits, no second try required
3710 int scroll_pos
= GetScrollPos( wxHORIZONTAL
);
3711 SetScrollbars( m_xScroll
, m_yScroll
, (entireWidth
+SCROLL_UNIT_X
) / m_xScroll
, 0, scroll_pos
, 0, TRUE
);
3714 // FIXME: why should we call it from here?
3720 void wxListMainWindow::RefreshAll()
3725 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3728 headerWin
->m_dirty
= FALSE
;
3729 headerWin
->Refresh();
3733 void wxListMainWindow::UpdateCurrent()
3735 if ( !HasCurrent() && !IsEmpty() )
3740 if ( m_current
!= (size_t)-1 )
3742 OnFocusLine( m_current
);
3746 long wxListMainWindow::GetNextItem( long item
,
3747 int WXUNUSED(geometry
),
3751 max
= GetItemCount();
3752 wxCHECK_MSG( (ret
== -1) || (ret
< max
), -1,
3753 _T("invalid listctrl index in GetNextItem()") );
3755 // notice that we start with the next item (or the first one if item == -1)
3756 // and this is intentional to allow writing a simple loop to iterate over
3757 // all selected items
3761 // this is not an error because the index was ok initially, just no
3772 size_t count
= GetItemCount();
3773 for ( size_t line
= (size_t)ret
; line
< count
; line
++ )
3775 if ( (state
& wxLIST_STATE_FOCUSED
) && (line
== m_current
) )
3778 if ( (state
& wxLIST_STATE_SELECTED
) && IsHighlighted(line
) )
3785 // ----------------------------------------------------------------------------
3787 // ----------------------------------------------------------------------------
3789 void wxListMainWindow::DeleteItem( long lindex
)
3791 size_t count
= GetItemCount();
3793 wxCHECK_RET( (lindex
>= 0) && ((size_t)lindex
< count
),
3794 _T("invalid item index in DeleteItem") );
3796 size_t index
= (size_t)lindex
;
3800 // select the next item when the selected one is deleted
3801 if ( m_current
== index
)
3803 // the last valid index after deleting the item will be count-2
3804 if ( m_current
== count
- 1 )
3810 SendNotify( index
, wxEVT_COMMAND_LIST_DELETE_ITEM
);
3812 if ( InReportView() )
3814 ResetVisibleLinesRange();
3821 m_selStore
.OnItemDelete(index
);
3825 m_lines
.RemoveAt( index
);
3829 RefreshAfter(index
);
3832 void wxListMainWindow::DeleteColumn( int col
)
3834 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3836 wxCHECK_RET( node
, wxT("invalid column index in DeleteColumn()") );
3839 m_columns
.DeleteNode( node
);
3842 void wxListMainWindow::DeleteAllItems()
3846 // nothing to do - in particular, don't send the event
3852 // to make the deletion of all items faster, we don't send the
3853 // notifications for each item deletion in this case but only one event
3854 // for all of them: this is compatible with wxMSW and documented in
3855 // DeleteAllItems() description
3857 wxListEvent
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() );
3858 event
.SetEventObject( GetParent() );
3859 GetParent()->GetEventHandler()->ProcessEvent( event
);
3868 if ( InReportView() )
3870 ResetVisibleLinesRange();
3875 // NB: don't just set m_dirty to TRUE here as RecalculatePositions()
3876 // doesn't do anything if the control is empty and so we won't be
3881 void wxListMainWindow::DeleteEverything()
3888 // ----------------------------------------------------------------------------
3889 // scanning for an item
3890 // ----------------------------------------------------------------------------
3892 void wxListMainWindow::EnsureVisible( long index
)
3894 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3895 _T("invalid index in EnsureVisible") );
3897 // We have to call this here because the label in question might just have
3898 // been added and no screen update taken place.
3902 size_t oldCurrent
= m_current
;
3903 m_current
= (size_t)index
;
3905 m_current
= oldCurrent
;
3908 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) )
3915 size_t count
= GetItemCount();
3916 for ( size_t i
= (size_t)pos
; i
< count
; i
++ )
3918 wxListLineData
*line
= GetLine(i
);
3919 if ( line
->GetText(0) == tmp
)
3926 long wxListMainWindow::FindItem(long start
, long data
)
3932 size_t count
= GetItemCount();
3933 for (size_t i
= (size_t)pos
; i
< count
; i
++)
3935 wxListLineData
*line
= GetLine(i
);
3937 line
->GetItem( 0, item
);
3938 if (item
.m_data
== data
)
3945 long wxListMainWindow::HitTest( int x
, int y
, int &flags
)
3947 CalcUnscrolledPosition( x
, y
, &x
, &y
);
3949 if ( HasFlag(wxLC_REPORT
) )
3951 size_t current
= y
/ GetLineHeight();
3952 flags
= HitTestLine(current
, x
, y
);
3958 // TODO: optimize it too! this is less simple than for report view but
3959 // enumerating all items is still not a way to do it!!
3960 size_t count
= GetItemCount();
3961 for ( size_t current
= 0; current
< count
; current
++ )
3963 flags
= HitTestLine(current
, x
, y
);
3972 // ----------------------------------------------------------------------------
3974 // ----------------------------------------------------------------------------
3976 void wxListMainWindow::InsertItem( wxListItem
&item
)
3978 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") );
3980 size_t count
= GetItemCount();
3981 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
<= count
,
3982 _T("invalid item index") );
3984 size_t id
= item
.m_itemId
;
3989 if ( HasFlag(wxLC_REPORT
) )
3991 else if ( HasFlag(wxLC_LIST
) )
3993 else if ( HasFlag(wxLC_ICON
) )
3995 else if ( HasFlag(wxLC_SMALL_ICON
) )
3996 mode
= wxLC_ICON
; // no typo
3999 wxFAIL_MSG( _T("unknown mode") );
4002 wxListLineData
*line
= new wxListLineData(this);
4004 line
->SetItem( 0, item
);
4006 m_lines
.Insert( line
, id
);
4009 RefreshLines(id
, GetItemCount() - 1);
4012 void wxListMainWindow::InsertColumn( long col
, wxListItem
&item
)
4015 if ( HasFlag(wxLC_REPORT
) )
4017 if (item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
4018 item
.m_width
= GetTextLength( item
.m_text
);
4019 wxListHeaderData
*column
= new wxListHeaderData( item
);
4020 if ((col
>= 0) && (col
< (int)m_columns
.GetCount()))
4022 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
4023 m_columns
.Insert( node
, column
);
4027 m_columns
.Append( column
);
4032 // ----------------------------------------------------------------------------
4034 // ----------------------------------------------------------------------------
4036 wxListCtrlCompare list_ctrl_compare_func_2
;
4037 long list_ctrl_compare_data
;
4039 int LINKAGEMODE
list_ctrl_compare_func_1( wxListLineData
**arg1
, wxListLineData
**arg2
)
4041 wxListLineData
*line1
= *arg1
;
4042 wxListLineData
*line2
= *arg2
;
4044 line1
->GetItem( 0, item
);
4045 long data1
= item
.m_data
;
4046 line2
->GetItem( 0, item
);
4047 long data2
= item
.m_data
;
4048 return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data
);
4051 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data
)
4053 list_ctrl_compare_func_2
= fn
;
4054 list_ctrl_compare_data
= data
;
4055 m_lines
.Sort( list_ctrl_compare_func_1
);
4059 // ----------------------------------------------------------------------------
4061 // ----------------------------------------------------------------------------
4063 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
)
4065 // update our idea of which lines are shown when we redraw the window the
4067 ResetVisibleLinesRange();
4070 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
4071 wxScrolledWindow::OnScroll(event
);
4073 HandleOnScroll( event
);
4076 if ( event
.GetOrientation() == wxHORIZONTAL
&& HasHeader() )
4078 wxListCtrl
* lc
= GetListCtrl();
4079 wxCHECK_RET( lc
, _T("no listctrl window?") );
4081 lc
->m_headerWin
->Refresh() ;
4083 lc
->m_headerWin
->MacUpdateImmediately() ;
4088 int wxListMainWindow::GetCountPerPage() const
4090 if ( !m_linesPerPage
)
4092 wxConstCast(this, wxListMainWindow
)->
4093 m_linesPerPage
= GetClientSize().y
/ GetLineHeight();
4096 return m_linesPerPage
;
4099 void wxListMainWindow::GetVisibleLinesRange(size_t *from
, size_t *to
)
4101 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("this is for report mode only") );
4103 if ( m_lineFrom
== (size_t)-1 )
4105 size_t count
= GetItemCount();
4108 m_lineFrom
= GetScrollPos(wxVERTICAL
);
4110 // this may happen if SetScrollbars() hadn't been called yet
4111 if ( m_lineFrom
>= count
)
4112 m_lineFrom
= count
- 1;
4114 // we redraw one extra line but this is needed to make the redrawing
4115 // logic work when there is a fractional number of lines on screen
4116 m_lineTo
= m_lineFrom
+ m_linesPerPage
;
4117 if ( m_lineTo
>= count
)
4118 m_lineTo
= count
- 1;
4120 else // empty control
4123 m_lineTo
= (size_t)-1;
4127 wxASSERT_MSG( IsEmpty() ||
4128 (m_lineFrom
<= m_lineTo
&& m_lineTo
< GetItemCount()),
4129 _T("GetVisibleLinesRange() returns incorrect result") );
4137 // -------------------------------------------------------------------------------------
4139 // -------------------------------------------------------------------------------------
4141 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
)
4143 wxListItem::wxListItem()
4152 m_format
= wxLIST_FORMAT_CENTRE
;
4158 void wxListItem::Clear()
4167 m_format
= wxLIST_FORMAT_CENTRE
;
4174 void wxListItem::ClearAttributes()
4183 // -------------------------------------------------------------------------------------
4185 // -------------------------------------------------------------------------------------
4187 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
)
4189 wxListEvent::wxListEvent( wxEventType commandType
, int id
)
4190 : wxNotifyEvent( commandType
, id
)
4196 m_cancelled
= FALSE
;
4201 void wxListEvent::CopyObject(wxObject
& object_dest
) const
4203 wxListEvent
*obj
= (wxListEvent
*)&object_dest
;
4205 wxNotifyEvent::CopyObject(object_dest
);
4207 obj
->m_code
= m_code
;
4208 obj
->m_itemIndex
= m_itemIndex
;
4209 obj
->m_oldItemIndex
= m_oldItemIndex
;
4211 obj
->m_cancelled
= m_cancelled
;
4212 obj
->m_pointDrag
= m_pointDrag
;
4213 obj
->m_item
.m_mask
= m_item
.m_mask
;
4214 obj
->m_item
.m_itemId
= m_item
.m_itemId
;
4215 obj
->m_item
.m_col
= m_item
.m_col
;
4216 obj
->m_item
.m_state
= m_item
.m_state
;
4217 obj
->m_item
.m_stateMask
= m_item
.m_stateMask
;
4218 obj
->m_item
.m_text
= m_item
.m_text
;
4219 obj
->m_item
.m_image
= m_item
.m_image
;
4220 obj
->m_item
.m_data
= m_item
.m_data
;
4221 obj
->m_item
.m_format
= m_item
.m_format
;
4222 obj
->m_item
.m_width
= m_item
.m_width
;
4224 if ( m_item
.HasAttributes() )
4226 obj
->m_item
.SetTextColour(m_item
.GetTextColour());
4230 // -------------------------------------------------------------------------------------
4232 // -------------------------------------------------------------------------------------
4234 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
)
4236 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
)
4237 EVT_SIZE(wxListCtrl::OnSize
)
4238 EVT_IDLE(wxListCtrl::OnIdle
)
4241 wxListCtrl::wxListCtrl()
4243 m_imageListNormal
= (wxImageList
*) NULL
;
4244 m_imageListSmall
= (wxImageList
*) NULL
;
4245 m_imageListState
= (wxImageList
*) NULL
;
4247 m_ownsImageListNormal
=
4248 m_ownsImageListSmall
=
4249 m_ownsImageListState
= FALSE
;
4251 m_mainWin
= (wxListMainWindow
*) NULL
;
4252 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4255 wxListCtrl::~wxListCtrl()
4258 m_mainWin
->ResetCurrent();
4260 if (m_ownsImageListNormal
)
4261 delete m_imageListNormal
;
4262 if (m_ownsImageListSmall
)
4263 delete m_imageListSmall
;
4264 if (m_ownsImageListState
)
4265 delete m_imageListState
;
4268 void wxListCtrl::CreateHeaderWindow()
4270 m_headerWin
= new wxListHeaderWindow
4272 this, -1, m_mainWin
,
4274 wxSize(GetClientSize().x
, HEADER_HEIGHT
),
4279 bool wxListCtrl::Create(wxWindow
*parent
,
4284 const wxValidator
&validator
,
4285 const wxString
&name
)
4289 m_imageListState
= (wxImageList
*) NULL
;
4290 m_ownsImageListNormal
=
4291 m_ownsImageListSmall
=
4292 m_ownsImageListState
= FALSE
;
4294 m_mainWin
= (wxListMainWindow
*) NULL
;
4295 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4297 if ( !(style
& wxLC_MASK_TYPE
) )
4299 style
= style
| wxLC_LIST
;
4302 if ( !wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name
) )
4305 // don't create the inner window with the border
4306 style
&= ~wxSUNKEN_BORDER
;
4308 m_mainWin
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style
);
4310 if ( HasFlag(wxLC_REPORT
) )
4312 CreateHeaderWindow();
4314 if ( HasFlag(wxLC_NO_HEADER
) )
4316 // VZ: why do we create it at all then?
4317 m_headerWin
->Show( FALSE
);
4324 void wxListCtrl::SetSingleStyle( long style
, bool add
)
4326 wxASSERT_MSG( !(style
& wxLC_VIRTUAL
),
4327 _T("wxLC_VIRTUAL can't be [un]set") );
4329 long flag
= GetWindowStyle();
4333 if (style
& wxLC_MASK_TYPE
)
4334 flag
&= ~(wxLC_MASK_TYPE
| wxLC_VIRTUAL
);
4335 if (style
& wxLC_MASK_ALIGN
)
4336 flag
&= ~wxLC_MASK_ALIGN
;
4337 if (style
& wxLC_MASK_SORT
)
4338 flag
&= ~wxLC_MASK_SORT
;
4350 SetWindowStyleFlag( flag
);
4353 void wxListCtrl::SetWindowStyleFlag( long flag
)
4357 m_mainWin
->DeleteEverything();
4361 GetClientSize( &width
, &height
);
4363 if (flag
& wxLC_REPORT
)
4365 if (!HasFlag(wxLC_REPORT
))
4369 CreateHeaderWindow();
4371 if (HasFlag(wxLC_NO_HEADER
))
4372 m_headerWin
->Show( FALSE
);
4376 if (flag
& wxLC_NO_HEADER
)
4377 m_headerWin
->Show( FALSE
);
4379 m_headerWin
->Show( TRUE
);
4385 if ( m_mainWin
->HasHeader() )
4387 m_headerWin
->Show( FALSE
);
4392 wxWindow::SetWindowStyleFlag( flag
);
4395 bool wxListCtrl::GetColumn(int col
, wxListItem
&item
) const
4397 m_mainWin
->GetColumn( col
, item
);
4401 bool wxListCtrl::SetColumn( int col
, wxListItem
& item
)
4403 m_mainWin
->SetColumn( col
, item
);
4407 int wxListCtrl::GetColumnWidth( int col
) const
4409 return m_mainWin
->GetColumnWidth( col
);
4412 bool wxListCtrl::SetColumnWidth( int col
, int width
)
4414 m_mainWin
->SetColumnWidth( col
, width
);
4418 int wxListCtrl::GetCountPerPage() const
4420 return m_mainWin
->GetCountPerPage(); // different from Windows ?
4423 bool wxListCtrl::GetItem( wxListItem
&info
) const
4425 m_mainWin
->GetItem( info
);
4429 bool wxListCtrl::SetItem( wxListItem
&info
)
4431 m_mainWin
->SetItem( info
);
4435 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId
)
4438 info
.m_text
= label
;
4439 info
.m_mask
= wxLIST_MASK_TEXT
;
4440 info
.m_itemId
= index
;
4444 info
.m_image
= imageId
;
4445 info
.m_mask
|= wxLIST_MASK_IMAGE
;
4447 m_mainWin
->SetItem(info
);
4451 int wxListCtrl::GetItemState( long item
, long stateMask
) const
4453 return m_mainWin
->GetItemState( item
, stateMask
);
4456 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask
)
4458 m_mainWin
->SetItemState( item
, state
, stateMask
);
4462 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) )
4465 info
.m_image
= image
;
4466 info
.m_mask
= wxLIST_MASK_IMAGE
;
4467 info
.m_itemId
= item
;
4468 m_mainWin
->SetItem( info
);
4472 wxString
wxListCtrl::GetItemText( long item
) const
4475 info
.m_itemId
= item
;
4476 m_mainWin
->GetItem( info
);
4480 void wxListCtrl::SetItemText( long item
, const wxString
&str
)
4483 info
.m_mask
= wxLIST_MASK_TEXT
;
4484 info
.m_itemId
= item
;
4486 m_mainWin
->SetItem( info
);
4489 long wxListCtrl::GetItemData( long item
) const
4492 info
.m_itemId
= item
;
4493 m_mainWin
->GetItem( info
);
4497 bool wxListCtrl::SetItemData( long item
, long data
)
4500 info
.m_mask
= wxLIST_MASK_DATA
;
4501 info
.m_itemId
= item
;
4503 m_mainWin
->SetItem( info
);
4507 bool wxListCtrl::GetItemRect( long item
, wxRect
&rect
, int WXUNUSED(code
) ) const
4509 m_mainWin
->GetItemRect( item
, rect
);
4513 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos
) const
4515 m_mainWin
->GetItemPosition( item
, pos
);
4519 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) )
4524 int wxListCtrl::GetItemCount() const
4526 return m_mainWin
->GetItemCount();
4529 int wxListCtrl::GetColumnCount() const
4531 return m_mainWin
->GetColumnCount();
4534 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall
)
4536 m_mainWin
->SetItemSpacing( spacing
, isSmall
);
4539 int wxListCtrl::GetItemSpacing( bool isSmall
) const
4541 return m_mainWin
->GetItemSpacing( isSmall
);
4544 int wxListCtrl::GetSelectedItemCount() const
4546 return m_mainWin
->GetSelectedItemCount();
4549 wxColour
wxListCtrl::GetTextColour() const
4551 return GetForegroundColour();
4554 void wxListCtrl::SetTextColour(const wxColour
& col
)
4556 SetForegroundColour(col
);
4559 long wxListCtrl::GetTopItem() const
4564 long wxListCtrl::GetNextItem( long item
, int geom
, int state
) const
4566 return m_mainWin
->GetNextItem( item
, geom
, state
);
4569 wxImageList
*wxListCtrl::GetImageList(int which
) const
4571 if (which
== wxIMAGE_LIST_NORMAL
)
4573 return m_imageListNormal
;
4575 else if (which
== wxIMAGE_LIST_SMALL
)
4577 return m_imageListSmall
;
4579 else if (which
== wxIMAGE_LIST_STATE
)
4581 return m_imageListState
;
4583 return (wxImageList
*) NULL
;
4586 void wxListCtrl::SetImageList( wxImageList
*imageList
, int which
)
4588 if ( which
== wxIMAGE_LIST_NORMAL
)
4590 if (m_ownsImageListNormal
) delete m_imageListNormal
;
4591 m_imageListNormal
= imageList
;
4592 m_ownsImageListNormal
= FALSE
;
4594 else if ( which
== wxIMAGE_LIST_SMALL
)
4596 if (m_ownsImageListSmall
) delete m_imageListSmall
;
4597 m_imageListSmall
= imageList
;
4598 m_ownsImageListSmall
= FALSE
;
4600 else if ( which
== wxIMAGE_LIST_STATE
)
4602 if (m_ownsImageListState
) delete m_imageListState
;
4603 m_imageListState
= imageList
;
4604 m_ownsImageListState
= FALSE
;
4607 m_mainWin
->SetImageList( imageList
, which
);
4610 void wxListCtrl::AssignImageList(wxImageList
*imageList
, int which
)
4612 SetImageList(imageList
, which
);
4613 if ( which
== wxIMAGE_LIST_NORMAL
)
4614 m_ownsImageListNormal
= TRUE
;
4615 else if ( which
== wxIMAGE_LIST_SMALL
)
4616 m_ownsImageListSmall
= TRUE
;
4617 else if ( which
== wxIMAGE_LIST_STATE
)
4618 m_ownsImageListState
= TRUE
;
4621 bool wxListCtrl::Arrange( int WXUNUSED(flag
) )
4626 bool wxListCtrl::DeleteItem( long item
)
4628 m_mainWin
->DeleteItem( item
);
4632 bool wxListCtrl::DeleteAllItems()
4634 m_mainWin
->DeleteAllItems();
4638 bool wxListCtrl::DeleteAllColumns()
4640 size_t count
= m_mainWin
->m_columns
.GetCount();
4641 for ( size_t n
= 0; n
< count
; n
++ )
4647 void wxListCtrl::ClearAll()
4649 m_mainWin
->DeleteEverything();
4652 bool wxListCtrl::DeleteColumn( int col
)
4654 m_mainWin
->DeleteColumn( col
);
4658 void wxListCtrl::Edit( long item
)
4660 m_mainWin
->EditLabel( item
);
4663 bool wxListCtrl::EnsureVisible( long item
)
4665 m_mainWin
->EnsureVisible( item
);
4669 long wxListCtrl::FindItem( long start
, const wxString
& str
, bool partial
)
4671 return m_mainWin
->FindItem( start
, str
, partial
);
4674 long wxListCtrl::FindItem( long start
, long data
)
4676 return m_mainWin
->FindItem( start
, data
);
4679 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
),
4680 int WXUNUSED(direction
))
4685 long wxListCtrl::HitTest( const wxPoint
&point
, int &flags
)
4687 return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags
);
4690 long wxListCtrl::InsertItem( wxListItem
& info
)
4692 m_mainWin
->InsertItem( info
);
4693 return info
.m_itemId
;
4696 long wxListCtrl::InsertItem( long index
, const wxString
&label
)
4699 info
.m_text
= label
;
4700 info
.m_mask
= wxLIST_MASK_TEXT
;
4701 info
.m_itemId
= index
;
4702 return InsertItem( info
);
4705 long wxListCtrl::InsertItem( long index
, int imageIndex
)
4708 info
.m_mask
= wxLIST_MASK_IMAGE
;
4709 info
.m_image
= imageIndex
;
4710 info
.m_itemId
= index
;
4711 return InsertItem( info
);
4714 long wxListCtrl::InsertItem( long index
, const wxString
&label
, int imageIndex
)
4717 info
.m_text
= label
;
4718 info
.m_image
= imageIndex
;
4719 info
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_IMAGE
;
4720 info
.m_itemId
= index
;
4721 return InsertItem( info
);
4724 long wxListCtrl::InsertColumn( long col
, wxListItem
&item
)
4726 wxASSERT( m_headerWin
);
4727 m_mainWin
->InsertColumn( col
, item
);
4728 m_headerWin
->Refresh();
4733 long wxListCtrl::InsertColumn( long col
, const wxString
&heading
,
4734 int format
, int width
)
4737 item
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_FORMAT
;
4738 item
.m_text
= heading
;
4741 item
.m_mask
|= wxLIST_MASK_WIDTH
;
4742 item
.m_width
= width
;
4744 item
.m_format
= format
;
4746 return InsertColumn( col
, item
);
4749 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) )
4755 // fn is a function which takes 3 long arguments: item1, item2, data.
4756 // item1 is the long data associated with a first item (NOT the index).
4757 // item2 is the long data associated with a second item (NOT the index).
4758 // data is the same value as passed to SortItems.
4759 // The return value is a negative number if the first item should precede the second
4760 // item, a positive number of the second item should precede the first,
4761 // or zero if the two items are equivalent.
4762 // data is arbitrary data to be passed to the sort function.
4764 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data
)
4766 m_mainWin
->SortItems( fn
, data
);
4770 // ----------------------------------------------------------------------------
4772 // ----------------------------------------------------------------------------
4774 void wxListCtrl::OnSize(wxSizeEvent
& event
)
4780 GetClientSize( &cw
, &ch
);
4782 if ( m_mainWin
->HasHeader() )
4784 m_headerWin
->SetSize( 0, 0, cw
, HEADER_HEIGHT
);
4785 m_mainWin
->SetSize( 0, HEADER_HEIGHT
+ 1, cw
, ch
- HEADER_HEIGHT
- 1 );
4787 else // no header window
4789 m_mainWin
->SetSize( 0, 0, cw
, ch
);
4792 m_mainWin
->RecalculatePositions();
4795 void wxListCtrl::OnIdle( wxIdleEvent
& event
)
4799 // do it only if needed
4800 if ( !m_mainWin
->m_dirty
)
4803 m_mainWin
->RecalculatePositions();
4806 // ----------------------------------------------------------------------------
4808 // ----------------------------------------------------------------------------
4810 bool wxListCtrl::SetBackgroundColour( const wxColour
&colour
)
4814 m_mainWin
->SetBackgroundColour( colour
);
4815 m_mainWin
->m_dirty
= TRUE
;
4821 bool wxListCtrl::SetForegroundColour( const wxColour
&colour
)
4823 if ( !wxWindow::SetForegroundColour( colour
) )
4828 m_mainWin
->SetForegroundColour( colour
);
4829 m_mainWin
->m_dirty
= TRUE
;
4834 m_headerWin
->SetForegroundColour( colour
);
4840 bool wxListCtrl::SetFont( const wxFont
&font
)
4842 if ( !wxWindow::SetFont( font
) )
4847 m_mainWin
->SetFont( font
);
4848 m_mainWin
->m_dirty
= TRUE
;
4853 m_headerWin
->SetFont( font
);
4859 // ----------------------------------------------------------------------------
4860 // methods forwarded to m_mainWin
4861 // ----------------------------------------------------------------------------
4863 #if wxUSE_DRAG_AND_DROP
4865 void wxListCtrl::SetDropTarget( wxDropTarget
*dropTarget
)
4867 m_mainWin
->SetDropTarget( dropTarget
);
4870 wxDropTarget
*wxListCtrl::GetDropTarget() const
4872 return m_mainWin
->GetDropTarget();
4875 #endif // wxUSE_DRAG_AND_DROP
4877 bool wxListCtrl::SetCursor( const wxCursor
&cursor
)
4879 return m_mainWin
? m_mainWin
->wxWindow::SetCursor(cursor
) : FALSE
;
4882 wxColour
wxListCtrl::GetBackgroundColour() const
4884 return m_mainWin
? m_mainWin
->GetBackgroundColour() : wxColour();
4887 wxColour
wxListCtrl::GetForegroundColour() const
4889 return m_mainWin
? m_mainWin
->GetForegroundColour() : wxColour();
4892 bool wxListCtrl::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
4895 return m_mainWin
->PopupMenu( menu
, x
, y
);
4898 #endif // wxUSE_MENUS
4901 void wxListCtrl::SetFocus()
4903 /* The test in window.cpp fails as we are a composite
4904 window, so it checks against "this", but not m_mainWin. */
4905 if ( FindFocus() != this )
4906 m_mainWin
->SetFocus();
4909 // ----------------------------------------------------------------------------
4910 // virtual list control support
4911 // ----------------------------------------------------------------------------
4913 wxString
wxListCtrl::OnGetItemText(long item
, long col
) const
4915 // this is a pure virtual function, in fact - which is not really pure
4916 // because the controls which are not virtual don't need to implement it
4917 wxFAIL_MSG( _T("not supposed to be called") );
4919 return wxEmptyString
;
4922 int wxListCtrl::OnGetItemImage(long item
) const
4925 wxFAIL_MSG( _T("not supposed to be called") );
4930 wxListItemAttr
*wxListCtrl::OnGetItemAttr(long item
) const
4932 wxASSERT_MSG( item
>= 0 && item
< GetItemCount(),
4933 _T("invalid item index in OnGetItemAttr()") );
4935 // no attributes by default
4939 void wxListCtrl::SetItemCount(long count
)
4941 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4943 m_mainWin
->SetItemCount(count
);
4946 void wxListCtrl::RefreshItem(long item
)
4948 m_mainWin
->RefreshLine(item
);
4951 void wxListCtrl::RefreshItems(long itemFrom
, long itemTo
)
4953 m_mainWin
->RefreshLines(itemFrom
, itemTo
);
4956 #endif // wxUSE_LISTCTRL