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
)
104 // ----------------------------------------------------------------------------
106 // ----------------------------------------------------------------------------
108 // the height of the header window (FIXME: should depend on its font!)
109 static const int HEADER_HEIGHT
= 23;
111 // the scrollbar units
112 static const int SCROLL_UNIT_X
= 15;
113 static const int SCROLL_UNIT_Y
= 15;
115 // the spacing between the lines (in report mode)
116 static const int LINE_SPACING
= 0;
118 // extra margins around the text label
119 static const int EXTRA_WIDTH
= 3;
120 static const int EXTRA_HEIGHT
= 4;
122 // offset for the header window
123 static const int HEADER_OFFSET_X
= 1;
124 static const int HEADER_OFFSET_Y
= 1;
126 // when autosizing the columns, add some slack
127 static const int AUTOSIZE_COL_MARGIN
= 10;
129 // default and minimal widths for the header columns
130 static const int WIDTH_COL_DEFAULT
= 80;
131 static const int WIDTH_COL_MIN
= 10;
133 // ============================================================================
135 // ============================================================================
137 // ----------------------------------------------------------------------------
139 // ----------------------------------------------------------------------------
141 int CMPFUNC_CONV
wxSizeTCmpFn(size_t n1
, size_t n2
) { return n1
- n2
; }
143 WX_DEFINE_SORTED_EXPORTED_ARRAY(size_t, wxIndexArray
);
145 // this class is used to store the selected items in the virtual list control
146 // (but it is not tied to list control and so can be used with other controls
147 // such as wxListBox in wxUniv)
149 // the idea is to make it really smart later (i.e. store the selections as an
150 // array of ranes + individual items) but, as I don't have time to do it now
151 // (this would require writing code to merge/break ranges and much more) keep
152 // it simple but define a clean interface to it which allows it to be made
154 class WXDLLEXPORT wxSelectionStore
157 wxSelectionStore() : m_itemsSel(wxSizeTCmpFn
) { Init(); }
159 // set the total number of items we handle
160 void SetItemCount(size_t count
) { m_count
= count
; }
162 // special case of SetItemCount(0)
163 void Clear() { m_itemsSel
.Clear(); m_count
= 0; }
165 // must be called when a new item is inserted/added
166 void OnItemAdd(size_t item
) { wxFAIL_MSG( _T("TODO") ); }
168 // must be called when an item is deleted
169 void OnItemDelete(size_t item
);
171 // select one item, use SelectRange() insted if possible!
173 // returns true if the items selection really changed
174 bool SelectItem(size_t item
, bool select
= TRUE
);
176 // select the range of items
177 void SelectRange(size_t itemFrom
, size_t itemTo
, bool select
= TRUE
);
179 // return true if the given item is selected
180 bool IsSelected(size_t item
) const;
182 // return the total number of selected items
183 size_t GetSelectedCount() const
185 return m_defaultState
? m_count
- m_itemsSel
.GetCount()
186 : m_itemsSel
.GetCount();
191 void Init() { m_defaultState
= FALSE
; }
193 // the total number of items we handle
196 // the default state: normally, FALSE (i.e. off) but maybe set to TRUE if
197 // there are more selected items than non selected ones - this allows to
198 // handle selection of all items efficiently
201 // the array of items whose selection state is different from default
202 wxIndexArray m_itemsSel
;
204 DECLARE_NO_COPY_CLASS(wxSelectionStore
)
207 //-----------------------------------------------------------------------------
208 // wxListItemData (internal)
209 //-----------------------------------------------------------------------------
211 class WXDLLEXPORT wxListItemData
214 wxListItemData(wxListMainWindow
*owner
);
215 ~wxListItemData() { delete m_attr
; delete m_rect
; }
217 void SetItem( const wxListItem
&info
);
218 void SetImage( int image
) { m_image
= image
; }
219 void SetData( long data
) { m_data
= data
; }
220 void SetPosition( int x
, int y
);
221 void SetSize( int width
, int height
);
223 bool HasText() const { return !m_text
.empty(); }
224 const wxString
& GetText() const { return m_text
; }
225 void SetText(const wxString
& text
) { m_text
= text
; }
227 // we can't use empty string for measuring the string width/height, so
228 // always return something
229 wxString
GetTextForMeasuring() const
231 wxString s
= GetText();
238 bool IsHit( int x
, int y
) const;
242 int GetWidth() const;
243 int GetHeight() const;
245 int GetImage() const { return m_image
; }
246 bool HasImage() const { return GetImage() != -1; }
248 void GetItem( wxListItem
&info
) const;
250 void SetAttr(wxListItemAttr
*attr
) { m_attr
= attr
; }
251 wxListItemAttr
*GetAttr() const { return m_attr
; }
254 // the item image or -1
257 // user data associated with the item
260 // the item coordinates are not used in report mode, instead this pointer
261 // is NULL and the owner window is used to retrieve the item position and
265 // the list ctrl we are in
266 wxListMainWindow
*m_owner
;
268 // custom attributes or NULL
269 wxListItemAttr
*m_attr
;
272 // common part of all ctors
278 //-----------------------------------------------------------------------------
279 // wxListHeaderData (internal)
280 //-----------------------------------------------------------------------------
282 class WXDLLEXPORT wxListHeaderData
: public wxObject
296 wxListHeaderData( const wxListItem
&info
);
297 void SetItem( const wxListItem
&item
);
298 void SetPosition( int x
, int y
);
299 void SetWidth( int w
);
300 void SetFormat( int format
);
301 void SetHeight( int h
);
302 bool HasImage() const;
304 bool HasText() const { return !m_text
.empty(); }
305 const wxString
& GetText() const { return m_text
; }
306 void SetText(const wxString
& text
) { m_text
= text
; }
308 void GetItem( wxListItem
&item
);
310 bool IsHit( int x
, int y
) const;
311 int GetImage() const;
312 int GetWidth() const;
313 int GetFormat() const;
316 DECLARE_DYNAMIC_CLASS(wxListHeaderData
);
319 //-----------------------------------------------------------------------------
320 // wxListLineData (internal)
321 //-----------------------------------------------------------------------------
323 WX_DECLARE_LIST(wxListItemData
, wxListItemDataList
);
324 #include "wx/listimpl.cpp"
325 WX_DEFINE_LIST(wxListItemDataList
);
327 class WXDLLEXPORT wxListLineData
330 // the list of subitems: only may have more than one item in report mode
331 wxListItemDataList m_items
;
333 // this is not used in report view
345 // the part to be highlighted
346 wxRect m_rectHighlight
;
349 // is this item selected? [NB: not used in virtual mode]
352 // back pointer to the list ctrl
353 wxListMainWindow
*m_owner
;
356 wxListLineData(wxListMainWindow
*owner
);
358 ~wxListLineData() { delete m_gi
; }
360 // are we in report mode?
361 inline bool InReportView() const;
363 // are we in virtual report mode?
364 inline bool IsVirtual() const;
366 // these 2 methods shouldn't be called for report view controls, in that
367 // case we determine our position/size ourselves
369 // calculate the size of the line
370 void CalculateSize( wxDC
*dc
, int spacing
);
372 // remember the position this line appears at
373 void SetPosition( int x
, int y
, int window_width
, int spacing
);
377 void SetImage( int image
) { SetImage(0, image
); }
378 int GetImage() const { return GetImage(0); }
379 bool HasImage() const { return GetImage() != -1; }
380 bool HasText() const { return !GetText(0).empty(); }
382 void SetItem( int index
, const wxListItem
&info
);
383 void GetItem( int index
, wxListItem
&info
);
385 wxString
GetText(int index
) const;
386 void SetText( int index
, const wxString s
);
388 wxListItemAttr
*GetAttr() const;
389 void SetAttr(wxListItemAttr
*attr
);
391 // return true if the highlighting really changed
392 bool Highlight( bool on
);
394 void ReverseHighlight();
396 bool IsHighlighted() const
398 wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") );
400 return m_highlighted
;
403 // draw the line on the given DC in icon/list mode
404 void Draw( wxDC
*dc
);
406 // the same in report mode
407 void DrawInReportMode( wxDC
*dc
,
409 const wxRect
& rectHL
,
413 // set the line to contain num items (only can be > 1 in report mode)
414 void InitItems( int num
);
416 // get the mode (i.e. style) of the list control
417 inline int GetMode() const;
419 void SetAttributes(wxDC
*dc
,
420 const wxListItemAttr
*attr
,
421 const wxColour
& colText
,
425 // these are only used by GetImage/SetImage above, we don't support images
426 // with subitems at the public API level yet
427 void SetImage( int index
, int image
);
428 int GetImage( int index
) const;
431 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData
, wxListLineDataArray
);
432 #include "wx/arrimpl.cpp"
433 WX_DEFINE_OBJARRAY(wxListLineDataArray
);
435 //-----------------------------------------------------------------------------
436 // wxListHeaderWindow (internal)
437 //-----------------------------------------------------------------------------
439 class WXDLLEXPORT wxListHeaderWindow
: public wxWindow
442 wxListMainWindow
*m_owner
;
443 wxCursor
*m_currentCursor
;
444 wxCursor
*m_resizeCursor
;
447 // column being resized
450 // divider line position in logical (unscrolled) coords
453 // minimal position beyond which the divider line can't be dragged in
458 wxListHeaderWindow();
459 virtual ~wxListHeaderWindow();
461 wxListHeaderWindow( wxWindow
*win
,
463 wxListMainWindow
*owner
,
464 const wxPoint
&pos
= wxDefaultPosition
,
465 const wxSize
&size
= wxDefaultSize
,
467 const wxString
&name
= "wxlistctrlcolumntitles" );
469 void DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
);
471 void AdjustDC(wxDC
& dc
);
473 void OnPaint( wxPaintEvent
&event
);
474 void OnMouse( wxMouseEvent
&event
);
475 void OnSetFocus( wxFocusEvent
&event
);
481 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow
)
482 DECLARE_EVENT_TABLE()
485 //-----------------------------------------------------------------------------
486 // wxListRenameTimer (internal)
487 //-----------------------------------------------------------------------------
489 class WXDLLEXPORT wxListRenameTimer
: public wxTimer
492 wxListMainWindow
*m_owner
;
495 wxListRenameTimer( wxListMainWindow
*owner
);
499 //-----------------------------------------------------------------------------
500 // wxListTextCtrl (internal)
501 //-----------------------------------------------------------------------------
503 class WXDLLEXPORT wxListTextCtrl
: public wxTextCtrl
508 wxListMainWindow
*m_owner
;
509 wxString m_startValue
;
513 wxListTextCtrl( wxWindow
*parent
, const wxWindowID id
,
514 bool *accept
, wxString
*res
, wxListMainWindow
*owner
,
515 const wxString
&value
= "",
516 const wxPoint
&pos
= wxDefaultPosition
, const wxSize
&size
= wxDefaultSize
,
518 const wxValidator
& validator
= wxDefaultValidator
,
519 const wxString
&name
= "listctrltextctrl" );
520 void OnChar( wxKeyEvent
&event
);
521 void OnKeyUp( wxKeyEvent
&event
);
522 void OnKillFocus( wxFocusEvent
&event
);
525 DECLARE_DYNAMIC_CLASS(wxListTextCtrl
);
526 DECLARE_EVENT_TABLE()
529 //-----------------------------------------------------------------------------
530 // wxListMainWindow (internal)
531 //-----------------------------------------------------------------------------
533 WX_DECLARE_LIST(wxListHeaderData
, wxListHeaderDataList
);
534 #include "wx/listimpl.cpp"
535 WX_DEFINE_LIST(wxListHeaderDataList
);
537 class WXDLLEXPORT wxListMainWindow
: public wxScrolledWindow
541 wxListMainWindow( wxWindow
*parent
,
543 const wxPoint
& pos
= wxDefaultPosition
,
544 const wxSize
& size
= wxDefaultSize
,
546 const wxString
&name
= _T("listctrlmainwindow") );
548 virtual ~wxListMainWindow();
550 bool HasFlag(int flag
) const { return m_parent
->HasFlag(flag
); }
552 // return true if this is a virtual list control
553 bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL
); }
555 // return true if the control is in report mode
556 bool InReportView() const { return HasFlag(wxLC_REPORT
); }
558 // return true if we are in single selection mode, false if multi sel
559 bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL
); }
561 // do we have a header window?
562 bool HasHeader() const
563 { return HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
); }
565 void HighlightAll( bool on
);
567 // all these functions only do something if the line is currently visible
569 // change the line "selected" state, return TRUE if it really changed
570 bool HighlightLine( size_t line
, bool highlight
= TRUE
);
572 // as HighlightLine() but do it for the range of lines: this is incredibly
573 // more efficient for virtual list controls!
575 // NB: unlike HighlightLine() this one does refresh the lines on screen
576 void HighlightLines( size_t lineFrom
, size_t lineTo
, bool on
= TRUE
);
578 // toggle the line state and refresh it
579 void ReverseHighlight( size_t line
)
580 { HighlightLine(line
, !IsHighlighted(line
)); RefreshLine(line
); }
582 // return true if the line is highlighted
583 bool IsHighlighted(size_t line
) const;
585 // refresh one or several lines at once
586 void RefreshLine( size_t line
);
587 void RefreshLines( size_t lineFrom
, size_t lineTo
);
589 // refresh all lines below the given one: the difference with
590 // RefreshLines() is that the index here might not be a valid one (happens
591 // when the last line is deleted)
592 void RefreshAfter( size_t lineFrom
);
594 // the methods which are forwarded to wxListLineData itself in list/icon
595 // modes but are here because the lines don't store their positions in the
598 // get the bound rect for the entire line
599 wxRect
GetLineRect(size_t line
) const;
601 // get the bound rect of the label
602 wxRect
GetLineLabelRect(size_t line
) const;
604 // get the bound rect of the items icon (only may be called if we do have
606 wxRect
GetLineIconRect(size_t line
) const;
608 // get the rect to be highlighted when the item has focus
609 wxRect
GetLineHighlightRect(size_t line
) const;
611 // get the size of the total line rect
612 wxSize
GetLineSize(size_t line
) const
613 { return GetLineRect(line
).GetSize(); }
615 // return the hit code for the corresponding position (in this line)
616 long HitTestLine(size_t line
, int x
, int y
) const;
618 void EditLabel( long item
);
619 void OnRenameTimer();
620 void OnRenameAccept();
622 void OnMouse( wxMouseEvent
&event
);
625 // called to switch the selection from the current item to newCurrent,
626 void OnArrowChar( size_t newCurrent
, const wxKeyEvent
& event
);
628 void OnChar( wxKeyEvent
&event
);
629 void OnKeyDown( wxKeyEvent
&event
);
630 void OnSetFocus( wxFocusEvent
&event
);
631 void OnKillFocus( wxFocusEvent
&event
);
632 void OnScroll(wxScrollWinEvent
& event
) ;
634 void OnPaint( wxPaintEvent
&event
);
636 void DrawImage( int index
, wxDC
*dc
, int x
, int y
);
637 void GetImageSize( int index
, int &width
, int &height
) const;
638 int GetTextLength( const wxString
&s
) const;
640 void SetImageList( wxImageList
*imageList
, int which
);
641 void SetItemSpacing( int spacing
, bool isSmall
= FALSE
);
642 int GetItemSpacing( bool isSmall
= FALSE
);
644 void SetColumn( int col
, wxListItem
&item
);
645 void SetColumnWidth( int col
, int width
);
646 void GetColumn( int col
, wxListItem
&item
) const;
647 int GetColumnWidth( int col
) const;
648 int GetColumnCount() const { return m_columns
.GetCount(); }
650 // returns the sum of the heights of all columns
651 int GetHeaderWidth() const;
653 int GetCountPerPage() const;
655 void SetItem( wxListItem
&item
);
656 void GetItem( wxListItem
&item
);
657 void SetItemState( long item
, long state
, long stateMask
);
658 int GetItemState( long item
, long stateMask
);
659 void GetItemRect( long index
, wxRect
&rect
);
660 bool GetItemPosition( long item
, wxPoint
& pos
);
661 int GetSelectedItemCount();
663 // set the scrollbars and update the positions of the items
664 void RecalculatePositions();
666 // refresh the window and the header
669 long GetNextItem( long item
, int geometry
, int state
);
670 void DeleteItem( long index
);
671 void DeleteAllItems();
672 void DeleteColumn( int col
);
673 void DeleteEverything();
674 void EnsureVisible( long index
);
675 long FindItem( long start
, const wxString
& str
, bool partial
= FALSE
);
676 long FindItem( long start
, long data
);
677 long HitTest( int x
, int y
, int &flags
);
678 void InsertItem( wxListItem
&item
);
679 void InsertColumn( long col
, wxListItem
&item
);
680 void SortItems( wxListCtrlCompare fn
, long data
);
682 size_t GetItemCount() const;
683 bool IsEmpty() const { return GetItemCount() == 0; }
684 void SetItemCount(long count
);
686 void ResetCurrent() { m_current
= (size_t)-1; }
687 bool HasCurrent() const { return m_current
!= (size_t)-1; }
689 // send out a wxListEvent
690 void SendNotify( size_t line
,
692 wxPoint point
= wxDefaultPosition
);
694 // override base class virtual to reset m_lineHeight when the font changes
695 virtual bool SetFont(const wxFont
& font
)
697 if ( !wxScrolledWindow::SetFont(font
) )
705 // these are for wxListLineData usage only
707 // get the backpointer to the list ctrl
708 wxListCtrl
*GetListCtrl() const
710 return wxStaticCast(GetParent(), wxListCtrl
);
713 // get the height of all lines (assuming they all do have the same height)
714 wxCoord
GetLineHeight() const;
716 // get the y position of the given line (only for report view)
717 wxCoord
GetLineY(size_t line
) const;
720 // the array of all line objects for a non virtual list control
721 wxListLineDataArray m_lines
;
723 // the list of column objects
724 wxListHeaderDataList m_columns
;
726 // currently focused item or -1
729 // the item currently being edited or -1
730 size_t m_currentEdit
;
732 // the number of lines per page
735 // this flag is set when something which should result in the window
736 // redrawing happens (i.e. an item was added or deleted, or its appearance
737 // changed) and OnPaint() doesn't redraw the window while it is set which
738 // allows to minimize the number of repaintings when a lot of items are
739 // being added. The real repainting occurs only after the next OnIdle()
743 wxBrush
*m_highlightBrush
;
744 wxColour
*m_highlightColour
;
747 wxImageList
*m_small_image_list
;
748 wxImageList
*m_normal_image_list
;
750 int m_normal_spacing
;
754 wxTimer
*m_renameTimer
;
756 wxString m_renameRes
;
761 // for double click logic
762 size_t m_lineLastClicked
,
763 m_lineBeforeLastClicked
;
766 // the total count of items in a virtual list control
769 // the object maintaining the items selection state, only used in virtual
771 wxSelectionStore m_selStore
;
773 // common part of all ctors
776 // intiialize m_[xy]Scroll
777 void InitScrolling();
779 // get the line data for the given index
780 wxListLineData
*GetLine(size_t n
) const
782 wxASSERT_MSG( n
!= (size_t)-1, _T("invalid line index") );
786 wxConstCast(this, wxListMainWindow
)->CacheLineData(n
);
794 // get a dummy line which can be used for geometry calculations and such:
795 // you must use GetLine() if you want to really draw the line
796 wxListLineData
*GetDummyLine() const;
798 // cache the line data of the n-th line in m_lines[0]
799 void CacheLineData(size_t line
);
801 // get the range of visible lines
802 void GetVisibleLinesRange(size_t *from
, size_t *to
);
804 // force us to recalculate the range of visible lines
805 void ResetVisibleLinesRange() { m_lineFrom
= (size_t)-1; }
807 // get the colour to be used for drawing the rules
808 wxColour
GetRuleColour() const
813 return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT
);
818 // initialize the current item if needed
819 void UpdateCurrent();
821 // called when an item is [un]focuded, i.e. becomes [not] current
824 void OnFocusLine( size_t line
);
825 void OnUnfocusLine( size_t line
);
827 // the height of one line using the current font
828 wxCoord m_lineHeight
;
830 // the total header width or 0 if not calculated yet
831 wxCoord m_headerWidth
;
833 // the first and last lines being shown on screen right now (inclusive),
834 // both may be -1 if they must be calculated so never access them directly:
835 // use GetVisibleLinesRange() above instead
839 DECLARE_DYNAMIC_CLASS(wxListMainWindow
);
840 DECLARE_EVENT_TABLE()
843 // ============================================================================
845 // ============================================================================
847 // ----------------------------------------------------------------------------
849 // ----------------------------------------------------------------------------
851 bool wxSelectionStore::IsSelected(size_t item
) const
853 bool isSel
= m_itemsSel
.Index(item
) != wxNOT_FOUND
;
855 // if the default state is to be selected, being in m_itemsSel means that
856 // the item is not selected, so we have to inverse the logic
857 return m_defaultState
? !isSel
: isSel
;
860 bool wxSelectionStore::SelectItem(size_t item
, bool select
)
862 // search for the item ourselves as like this we get the index where to
863 // insert it later if needed, so we do only one search in the array instead
864 // of two (adding item to a sorted array requires a search)
865 size_t index
= m_itemsSel
.IndexForInsert(item
);
866 bool isSel
= index
< m_itemsSel
.GetCount() && m_itemsSel
[index
] == item
;
868 if ( select
!= m_defaultState
)
872 m_itemsSel
.AddAt(item
, index
);
877 else // reset to default state
881 m_itemsSel
.RemoveAt(index
);
889 void wxSelectionStore::SelectRange(size_t itemFrom
, size_t itemTo
, bool select
)
891 wxASSERT_MSG( itemFrom
<= itemTo
, _T("should be in order") );
893 // are we going to have more [un]selected items than the other ones?
894 if ( itemTo
- itemFrom
> m_count
/ 2 )
896 if ( select
!= m_defaultState
)
898 // the default state now becomes the same as 'select'
899 m_defaultState
= select
;
901 // so all the old selections (which had state select) shouldn't be
902 // selected any more, but all the other ones should
903 wxIndexArray selOld
= m_itemsSel
;
906 // TODO: it should be possible to optimize the searches a bit
907 // knowing the possible range
910 for ( item
= 0; item
< itemFrom
; item
++ )
912 if ( selOld
.Index(item
) == wxNOT_FOUND
)
913 m_itemsSel
.Add(item
);
916 for ( item
= itemTo
+ 1; item
< m_count
; item
++ )
918 if ( selOld
.Index(item
) == wxNOT_FOUND
)
919 m_itemsSel
.Add(item
);
922 else // select == m_defaultState
924 // get the inclusive range of items between itemFrom and itemTo
925 size_t count
= m_itemsSel
.GetCount(),
926 start
= m_itemsSel
.IndexForInsert(itemFrom
),
927 end
= m_itemsSel
.IndexForInsert(itemTo
);
929 if ( start
== count
|| m_itemsSel
[start
] < itemFrom
)
934 if ( end
== count
|| m_itemsSel
[end
] > itemTo
)
941 // delete all of them (from end to avoid changing indices)
942 for ( int i
= end
; i
>= (int)start
; i
-- )
944 m_itemsSel
.RemoveAt(i
);
949 else // "few" items change state
951 // just add the items to the selection
952 for ( size_t item
= itemFrom
; item
<= itemTo
; item
++ )
954 SelectItem(item
, select
);
959 void wxSelectionStore::OnItemDelete(size_t item
)
961 size_t count
= m_itemsSel
.GetCount(),
962 i
= m_itemsSel
.IndexForInsert(item
);
964 if ( i
< count
&& m_itemsSel
[i
] == item
)
966 // this item itself was in m_itemsSel, remove it from there
967 m_itemsSel
.RemoveAt(i
);
972 // and adjust the index of all which follow it
975 // all following elements must be greater than the one we deleted
976 wxASSERT_MSG( m_itemsSel
[i
] > item
, _T("logic error") );
982 //-----------------------------------------------------------------------------
984 //-----------------------------------------------------------------------------
986 void wxListItemData::Init()
994 wxListItemData::wxListItemData(wxListMainWindow
*owner
)
1000 if ( owner
->HasFlag(wxLC_REPORT
) )
1006 m_rect
= new wxRect
;
1010 void wxListItemData::SetItem( const wxListItem
&info
)
1012 if ( info
.m_mask
& wxLIST_MASK_TEXT
)
1013 SetText(info
.m_text
);
1014 if ( info
.m_mask
& wxLIST_MASK_IMAGE
)
1015 m_image
= info
.m_image
;
1016 if ( info
.m_mask
& wxLIST_MASK_DATA
)
1017 m_data
= info
.m_data
;
1019 if ( info
.HasAttributes() )
1022 *m_attr
= *info
.GetAttributes();
1024 m_attr
= new wxListItemAttr(*info
.GetAttributes());
1032 m_rect
->width
= info
.m_width
;
1036 void wxListItemData::SetPosition( int x
, int y
)
1038 wxCHECK_RET( m_rect
, _T("unexpected SetPosition() call") );
1044 void wxListItemData::SetSize( int width
, int height
)
1046 wxCHECK_RET( m_rect
, _T("unexpected SetSize() call") );
1049 m_rect
->width
= width
;
1051 m_rect
->height
= height
;
1054 bool wxListItemData::IsHit( int x
, int y
) const
1056 wxCHECK_MSG( m_rect
, FALSE
, _T("can't be called in this mode") );
1058 return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x
, y
);
1061 int wxListItemData::GetX() const
1063 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1068 int wxListItemData::GetY() const
1070 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1075 int wxListItemData::GetWidth() const
1077 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1079 return m_rect
->width
;
1082 int wxListItemData::GetHeight() const
1084 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1086 return m_rect
->height
;
1089 void wxListItemData::GetItem( wxListItem
&info
) const
1091 info
.m_text
= m_text
;
1092 info
.m_image
= m_image
;
1093 info
.m_data
= m_data
;
1097 if ( m_attr
->HasTextColour() )
1098 info
.SetTextColour(m_attr
->GetTextColour());
1099 if ( m_attr
->HasBackgroundColour() )
1100 info
.SetBackgroundColour(m_attr
->GetBackgroundColour());
1101 if ( m_attr
->HasFont() )
1102 info
.SetFont(m_attr
->GetFont());
1106 //-----------------------------------------------------------------------------
1108 //-----------------------------------------------------------------------------
1110 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData
,wxObject
);
1112 wxListHeaderData::wxListHeaderData()
1123 wxListHeaderData::wxListHeaderData( const wxListItem
&item
)
1131 void wxListHeaderData::SetItem( const wxListItem
&item
)
1133 m_mask
= item
.m_mask
;
1134 m_text
= item
.m_text
;
1135 m_image
= item
.m_image
;
1136 m_format
= item
.m_format
;
1138 SetWidth(item
.m_width
);
1141 void wxListHeaderData::SetPosition( int x
, int y
)
1147 void wxListHeaderData::SetHeight( int h
)
1152 void wxListHeaderData::SetWidth( int w
)
1156 m_width
= WIDTH_COL_DEFAULT
;
1157 if (m_width
< WIDTH_COL_MIN
)
1158 m_width
= WIDTH_COL_MIN
;
1161 void wxListHeaderData::SetFormat( int format
)
1166 bool wxListHeaderData::HasImage() const
1168 return (m_image
!= 0);
1171 bool wxListHeaderData::IsHit( int x
, int y
) const
1173 return ((x
>= m_xpos
) && (x
<= m_xpos
+m_width
) && (y
>= m_ypos
) && (y
<= m_ypos
+m_height
));
1176 void wxListHeaderData::GetItem( wxListItem
&item
)
1178 item
.m_mask
= m_mask
;
1179 item
.m_text
= m_text
;
1180 item
.m_image
= m_image
;
1181 item
.m_format
= m_format
;
1182 item
.m_width
= m_width
;
1185 int wxListHeaderData::GetImage() const
1190 int wxListHeaderData::GetWidth() const
1195 int wxListHeaderData::GetFormat() const
1200 //-----------------------------------------------------------------------------
1202 //-----------------------------------------------------------------------------
1204 inline int wxListLineData::GetMode() const
1206 return m_owner
->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE
;
1209 inline bool wxListLineData::InReportView() const
1211 return m_owner
->HasFlag(wxLC_REPORT
);
1214 inline bool wxListLineData::IsVirtual() const
1216 return m_owner
->IsVirtual();
1219 wxListLineData::wxListLineData( wxListMainWindow
*owner
)
1222 m_items
.DeleteContents( TRUE
);
1224 if ( InReportView() )
1230 m_gi
= new GeometryInfo
;
1233 m_highlighted
= FALSE
;
1235 InitItems( GetMode() == wxLC_REPORT
? m_owner
->GetColumnCount() : 1 );
1238 void wxListLineData::CalculateSize( wxDC
*dc
, int spacing
)
1240 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1241 wxCHECK_RET( node
, _T("no subitems at all??") );
1243 wxListItemData
*item
= node
->GetData();
1245 switch ( GetMode() )
1248 case wxLC_SMALL_ICON
:
1250 m_gi
->m_rectAll
.width
= spacing
;
1252 wxString s
= item
->GetText();
1258 m_gi
->m_rectLabel
.width
=
1259 m_gi
->m_rectLabel
.height
= 0;
1263 dc
->GetTextExtent( s
, &lw
, &lh
);
1264 if (lh
< SCROLL_UNIT_Y
)
1269 m_gi
->m_rectAll
.height
= spacing
+ lh
;
1271 m_gi
->m_rectAll
.width
= lw
;
1273 m_gi
->m_rectLabel
.width
= lw
;
1274 m_gi
->m_rectLabel
.height
= lh
;
1277 if (item
->HasImage())
1280 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1281 m_gi
->m_rectIcon
.width
= w
+ 8;
1282 m_gi
->m_rectIcon
.height
= h
+ 8;
1284 if ( m_gi
->m_rectIcon
.width
> m_gi
->m_rectAll
.width
)
1285 m_gi
->m_rectAll
.width
= m_gi
->m_rectIcon
.width
;
1286 if ( m_gi
->m_rectIcon
.height
+ lh
> m_gi
->m_rectAll
.height
- 4 )
1287 m_gi
->m_rectAll
.height
= m_gi
->m_rectIcon
.height
+ lh
+ 4;
1290 if ( item
->HasText() )
1292 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectLabel
.width
;
1293 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectLabel
.height
;
1295 else // no text, highlight the icon
1297 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectIcon
.width
;
1298 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectIcon
.height
;
1305 wxString s
= item
->GetTextForMeasuring();
1308 dc
->GetTextExtent( s
, &lw
, &lh
);
1309 if (lh
< SCROLL_UNIT_Y
)
1314 m_gi
->m_rectLabel
.width
= lw
;
1315 m_gi
->m_rectLabel
.height
= lh
;
1317 m_gi
->m_rectAll
.width
= lw
;
1318 m_gi
->m_rectAll
.height
= lh
;
1320 if (item
->HasImage())
1323 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1324 m_gi
->m_rectIcon
.width
= w
;
1325 m_gi
->m_rectIcon
.height
= h
;
1327 m_gi
->m_rectAll
.width
+= 4 + w
;
1328 if (h
> m_gi
->m_rectAll
.height
)
1329 m_gi
->m_rectAll
.height
= h
;
1332 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectAll
.width
;
1333 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectAll
.height
;
1338 wxFAIL_MSG( _T("unexpected call to SetSize") );
1342 wxFAIL_MSG( _T("unknown mode") );
1346 void wxListLineData::SetPosition( int x
, int y
,
1350 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1351 wxCHECK_RET( node
, _T("no subitems at all??") );
1353 wxListItemData
*item
= node
->GetData();
1355 switch ( GetMode() )
1358 case wxLC_SMALL_ICON
:
1359 m_gi
->m_rectAll
.x
= x
;
1360 m_gi
->m_rectAll
.y
= y
;
1362 if ( item
->HasImage() )
1364 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 4
1365 + (spacing
- m_gi
->m_rectIcon
.width
)/2;
1366 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 4;
1369 if ( item
->HasText() )
1371 if (m_gi
->m_rectAll
.width
> spacing
)
1372 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1374 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2 + (spacing
/2) - (m_gi
->m_rectLabel
.width
/2);
1375 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ m_gi
->m_rectAll
.height
+ 2 - m_gi
->m_rectLabel
.height
;
1376 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectLabel
.x
- 2;
1377 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectLabel
.y
- 2;
1379 else // no text, highlight the icon
1381 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectIcon
.x
- 4;
1382 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectIcon
.y
- 4;
1387 m_gi
->m_rectAll
.x
= x
;
1388 m_gi
->m_rectAll
.y
= y
;
1390 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectAll
.x
;
1391 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectAll
.y
;
1392 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ 2;
1394 if (item
->HasImage())
1396 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 2;
1397 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 2;
1398 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 6 + m_gi
->m_rectIcon
.width
;
1402 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1407 wxFAIL_MSG( _T("unexpected call to SetPosition") );
1411 wxFAIL_MSG( _T("unknown mode") );
1415 void wxListLineData::InitItems( int num
)
1417 for (int i
= 0; i
< num
; i
++)
1418 m_items
.Append( new wxListItemData(m_owner
) );
1421 void wxListLineData::SetItem( int index
, const wxListItem
&info
)
1423 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1424 wxCHECK_RET( node
, _T("invalid column index in SetItem") );
1426 wxListItemData
*item
= node
->GetData();
1427 item
->SetItem( info
);
1430 void wxListLineData::GetItem( int index
, wxListItem
&info
)
1432 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1435 wxListItemData
*item
= node
->GetData();
1436 item
->GetItem( info
);
1440 wxString
wxListLineData::GetText(int index
) const
1444 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1447 wxListItemData
*item
= node
->GetData();
1448 s
= item
->GetText();
1454 void wxListLineData::SetText( int index
, const wxString s
)
1456 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1459 wxListItemData
*item
= node
->GetData();
1464 void wxListLineData::SetImage( int index
, int image
)
1466 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1467 wxCHECK_RET( node
, _T("invalid column index in SetImage()") );
1469 wxListItemData
*item
= node
->GetData();
1470 item
->SetImage(image
);
1473 int wxListLineData::GetImage( int index
) const
1475 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1476 wxCHECK_MSG( node
, -1, _T("invalid column index in GetImage()") );
1478 wxListItemData
*item
= node
->GetData();
1479 return item
->GetImage();
1482 wxListItemAttr
*wxListLineData::GetAttr() const
1484 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1485 wxCHECK_MSG( node
, NULL
, _T("invalid column index in GetAttr()") );
1487 wxListItemData
*item
= node
->GetData();
1488 return item
->GetAttr();
1491 void wxListLineData::SetAttr(wxListItemAttr
*attr
)
1493 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1494 wxCHECK_RET( node
, _T("invalid column index in SetAttr()") );
1496 wxListItemData
*item
= node
->GetData();
1497 item
->SetAttr(attr
);
1500 void wxListLineData::SetAttributes(wxDC
*dc
,
1501 const wxListItemAttr
*attr
,
1502 const wxColour
& colText
,
1506 // don't use foregroud colour for drawing highlighted items - this might
1507 // make them completely invisible (and there is no way to do bit
1508 // arithmetics on wxColour, unfortunately)
1509 if ( !highlight
&& attr
&& attr
->HasTextColour() )
1511 dc
->SetTextForeground(attr
->GetTextColour());
1515 dc
->SetTextForeground(colText
);
1518 if ( attr
&& attr
->HasFont() )
1520 dc
->SetFont(attr
->GetFont());
1528 void wxListLineData::Draw( wxDC
*dc
)
1530 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1531 wxCHECK_RET( node
, _T("no subitems at all??") );
1533 wxListItemData
*item
= node
->GetData();
1534 if (item
->HasImage())
1536 wxRect rectIcon
= m_gi
->m_rectIcon
;
1537 m_owner
->DrawImage( item
->GetImage(), dc
,
1538 rectIcon
.x
, rectIcon
.y
);
1541 if (item
->HasText())
1543 wxRect rectLabel
= m_gi
->m_rectLabel
;
1544 dc
->DrawText( item
->GetText(), rectLabel
.x
, rectLabel
.y
);
1548 void wxListLineData::DrawInReportMode( wxDC
*dc
,
1550 const wxRect
& rectHL
,
1553 // use our own flag if we maintain it
1555 highlighted
= m_highlighted
;
1557 // default foreground colour
1558 wxWindow
*listctrl
= m_owner
->GetParent();
1562 colText
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT
);
1566 colText
= listctrl
->GetForegroundColour();
1570 wxFont font
= listctrl
->GetFont();
1572 // TODO: later we should support setting different attributes for
1573 // different columns - to do it, just add "col" argument to
1574 // GetAttr() and move this code into the loop below
1575 wxListItemAttr
*attr
= GetAttr();
1576 SetAttributes(dc
, attr
, colText
, font
, highlighted
);
1578 bool hasBgCol
= attr
&& attr
->HasBackgroundColour();
1579 if ( highlighted
|| hasBgCol
)
1583 dc
->SetBrush( *m_owner
->m_highlightBrush
);
1588 dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
));
1590 dc
->SetBrush( * wxWHITE_BRUSH
);
1593 dc
->SetPen( * wxTRANSPARENT_PEN
);
1594 dc
->DrawRectangle( rectHL
);
1597 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1598 wxCHECK_RET( node
, _T("no subitems at all??") );
1601 wxCoord x
= rect
.x
+ HEADER_OFFSET_X
,
1602 y
= rect
.y
+ (LINE_SPACING
+ EXTRA_HEIGHT
) / 2;
1606 wxListItemData
*item
= node
->GetData();
1610 if ( item
->HasImage() )
1613 m_owner
->DrawImage( item
->GetImage(), dc
, x
, y
);
1614 m_owner
->GetImageSize( item
->GetImage(), ix
, iy
);
1615 x
+= ix
+ 5; // FIXME: what is "5"?
1618 int width
= m_owner
->GetColumnWidth(col
++);
1620 wxDCClipper
clipper(*dc
, x
, y
, width
, rect
.height
);
1622 if ( item
->HasText() )
1624 dc
->DrawText( item
->GetText(), x
, y
);
1629 node
= node
->GetNext();
1633 bool wxListLineData::Highlight( bool on
)
1635 wxCHECK_MSG( !m_owner
->IsVirtual(), FALSE
, _T("unexpected call to Highlight") );
1637 if ( on
== m_highlighted
)
1645 void wxListLineData::ReverseHighlight( void )
1647 Highlight(!IsHighlighted());
1650 //-----------------------------------------------------------------------------
1651 // wxListHeaderWindow
1652 //-----------------------------------------------------------------------------
1654 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
);
1656 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
)
1657 EVT_PAINT (wxListHeaderWindow::OnPaint
)
1658 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse
)
1659 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus
)
1662 wxListHeaderWindow::wxListHeaderWindow( void )
1664 m_owner
= (wxListMainWindow
*) NULL
;
1665 m_currentCursor
= (wxCursor
*) NULL
;
1666 m_resizeCursor
= (wxCursor
*) NULL
;
1667 m_isDragging
= FALSE
;
1670 wxListHeaderWindow::wxListHeaderWindow( wxWindow
*win
, wxWindowID id
, wxListMainWindow
*owner
,
1671 const wxPoint
&pos
, const wxSize
&size
,
1672 long style
, const wxString
&name
) :
1673 wxWindow( win
, id
, pos
, size
, style
, name
)
1676 // m_currentCursor = wxSTANDARD_CURSOR;
1677 m_currentCursor
= (wxCursor
*) NULL
;
1678 m_resizeCursor
= new wxCursor( wxCURSOR_SIZEWE
);
1679 m_isDragging
= FALSE
;
1682 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
) );
1685 wxListHeaderWindow::~wxListHeaderWindow( void )
1687 delete m_resizeCursor
;
1690 void wxListHeaderWindow::DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
)
1693 GtkStateType state
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
1694 : GTK_STATE_INSENSITIVE
;
1696 x
= dc
->XLOG2DEV( x
);
1698 gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
,
1699 state
, GTK_SHADOW_OUT
,
1700 (GdkRectangle
*) NULL
, m_wxwindow
, "button",
1701 x
-1, y
-1, w
+2, h
+2);
1702 #elif defined( __WXMAC__ )
1703 const int m_corner
= 1;
1705 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1707 dc
->SetPen( wxPen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
) , 1 , wxSOLID
) );
1708 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1709 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1711 wxPen
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID
);
1714 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1715 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1717 dc
->SetPen( *wxWHITE_PEN
);
1718 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1719 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1720 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1721 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1723 const int m_corner
= 1;
1725 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1727 dc
->SetPen( *wxBLACK_PEN
);
1728 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1729 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1731 wxPen
pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
), 1, wxSOLID
);
1734 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1735 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1737 dc
->SetPen( *wxWHITE_PEN
);
1738 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1739 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1740 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1741 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1745 // shift the DC origin to match the position of the main window horz
1746 // scrollbar: this allows us to always use logical coords
1747 void wxListHeaderWindow::AdjustDC(wxDC
& dc
)
1750 m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL
);
1753 m_owner
->GetViewStart( &x
, NULL
);
1755 // account for the horz scrollbar offset
1756 dc
.SetDeviceOrigin( -x
* xpix
, 0 );
1759 void wxListHeaderWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
1762 wxClientDC
dc( this );
1764 wxPaintDC
dc( this );
1772 dc
.SetFont( GetFont() );
1774 // width and height of the entire header window
1776 GetClientSize( &w
, &h
);
1777 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1779 dc
.SetBackgroundMode(wxTRANSPARENT
);
1781 // do *not* use the listctrl colour for headers - one day we will have a
1782 // function to set it separately
1783 //dc.SetTextForeground( *wxBLACK );
1784 dc
.SetTextForeground(wxSystemSettings::
1785 GetSystemColour( wxSYS_COLOUR_WINDOWTEXT
));
1787 int x
= HEADER_OFFSET_X
;
1789 int numColumns
= m_owner
->GetColumnCount();
1791 for (int i
= 0; i
< numColumns
; i
++)
1793 m_owner
->GetColumn( i
, item
);
1794 int wCol
= item
.m_width
;
1795 int cw
= wCol
- 2; // the width of the rect to draw
1797 int xEnd
= x
+ wCol
;
1799 dc
.SetPen( *wxWHITE_PEN
);
1801 DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 );
1802 dc
.SetClippingRegion( x
, HEADER_OFFSET_Y
, cw
-5, h
-4 );
1803 dc
.DrawText( item
.GetText(), x
+ EXTRA_WIDTH
, HEADER_OFFSET_Y
+ EXTRA_HEIGHT
);
1804 dc
.DestroyClippingRegion();
1813 void wxListHeaderWindow::DrawCurrent()
1815 int x1
= m_currentX
;
1817 ClientToScreen( &x1
, &y1
);
1819 int x2
= m_currentX
-1;
1821 m_owner
->GetClientSize( NULL
, &y2
);
1822 m_owner
->ClientToScreen( &x2
, &y2
);
1825 dc
.SetLogicalFunction( wxINVERT
);
1826 dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID
) );
1827 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1831 dc
.DrawLine( x1
, y1
, x2
, y2
);
1833 dc
.SetLogicalFunction( wxCOPY
);
1835 dc
.SetPen( wxNullPen
);
1836 dc
.SetBrush( wxNullBrush
);
1839 void wxListHeaderWindow::OnMouse( wxMouseEvent
&event
)
1841 // we want to work with logical coords
1843 m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
);
1844 int y
= event
.GetY();
1848 // we don't draw the line beyond our window, but we allow dragging it
1851 GetClientSize( &w
, NULL
);
1852 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1855 // erase the line if it was drawn
1856 if ( m_currentX
< w
)
1859 if (event
.ButtonUp())
1862 m_isDragging
= FALSE
;
1864 m_owner
->SetColumnWidth( m_column
, m_currentX
- m_minX
);
1871 m_currentX
= m_minX
+ 7;
1873 // draw in the new location
1874 if ( m_currentX
< w
)
1878 else // not dragging
1881 bool hit_border
= FALSE
;
1883 // end of the current column
1886 // find the column where this event occured
1887 int countCol
= m_owner
->GetColumnCount();
1888 for (int col
= 0; col
< countCol
; col
++)
1890 xpos
+= m_owner
->GetColumnWidth( col
);
1893 if ( (abs(x
-xpos
) < 3) && (y
< 22) )
1895 // near the column border
1902 // inside the column
1909 if (event
.LeftDown())
1913 m_isDragging
= TRUE
;
1920 wxWindow
*parent
= GetParent();
1921 wxListEvent
le( wxEVT_COMMAND_LIST_COL_CLICK
, parent
->GetId() );
1922 le
.SetEventObject( parent
);
1923 le
.m_col
= m_column
;
1924 parent
->GetEventHandler()->ProcessEvent( le
);
1927 else if (event
.Moving())
1932 setCursor
= m_currentCursor
== wxSTANDARD_CURSOR
;
1933 m_currentCursor
= m_resizeCursor
;
1937 setCursor
= m_currentCursor
!= wxSTANDARD_CURSOR
;
1938 m_currentCursor
= wxSTANDARD_CURSOR
;
1942 SetCursor(*m_currentCursor
);
1947 void wxListHeaderWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
1949 m_owner
->SetFocus();
1952 //-----------------------------------------------------------------------------
1953 // wxListRenameTimer (internal)
1954 //-----------------------------------------------------------------------------
1956 wxListRenameTimer::wxListRenameTimer( wxListMainWindow
*owner
)
1961 void wxListRenameTimer::Notify()
1963 m_owner
->OnRenameTimer();
1966 //-----------------------------------------------------------------------------
1967 // wxListTextCtrl (internal)
1968 //-----------------------------------------------------------------------------
1970 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl
,wxTextCtrl
);
1972 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
)
1973 EVT_CHAR (wxListTextCtrl::OnChar
)
1974 EVT_KEY_UP (wxListTextCtrl::OnKeyUp
)
1975 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus
)
1978 wxListTextCtrl::wxListTextCtrl( wxWindow
*parent
,
1979 const wxWindowID id
,
1982 wxListMainWindow
*owner
,
1983 const wxString
&value
,
1987 const wxValidator
& validator
,
1988 const wxString
&name
)
1989 : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name
)
1994 (*m_accept
) = FALSE
;
1996 m_startValue
= value
;
1999 void wxListTextCtrl::OnChar( wxKeyEvent
&event
)
2001 if (event
.m_keyCode
== WXK_RETURN
)
2004 (*m_res
) = GetValue();
2006 if (!wxPendingDelete
.Member(this))
2007 wxPendingDelete
.Append(this);
2009 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2010 m_owner
->OnRenameAccept();
2014 if (event
.m_keyCode
== WXK_ESCAPE
)
2016 (*m_accept
) = FALSE
;
2019 if (!wxPendingDelete
.Member(this))
2020 wxPendingDelete
.Append(this);
2028 void wxListTextCtrl::OnKeyUp( wxKeyEvent
&event
)
2030 // auto-grow the textctrl:
2031 wxSize parentSize
= m_owner
->GetSize();
2032 wxPoint myPos
= GetPosition();
2033 wxSize mySize
= GetSize();
2035 GetTextExtent(GetValue() + _T("MM"), &sx
, &sy
); // FIXME: MM??
2036 if (myPos
.x
+ sx
> parentSize
.x
)
2037 sx
= parentSize
.x
- myPos
.x
;
2045 void wxListTextCtrl::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
2047 if (!wxPendingDelete
.Member(this))
2048 wxPendingDelete
.Append(this);
2050 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2051 m_owner
->OnRenameAccept();
2054 //-----------------------------------------------------------------------------
2056 //-----------------------------------------------------------------------------
2058 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
);
2060 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
)
2061 EVT_PAINT (wxListMainWindow::OnPaint
)
2062 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse
)
2063 EVT_CHAR (wxListMainWindow::OnChar
)
2064 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown
)
2065 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus
)
2066 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus
)
2067 EVT_SCROLLWIN (wxListMainWindow::OnScroll
)
2070 void wxListMainWindow::Init()
2072 m_columns
.DeleteContents( TRUE
);
2076 m_lineTo
= (size_t)-1;
2082 m_small_image_list
= (wxImageList
*) NULL
;
2083 m_normal_image_list
= (wxImageList
*) NULL
;
2085 m_small_spacing
= 30;
2086 m_normal_spacing
= 40;
2090 m_isCreated
= FALSE
;
2092 m_lastOnSame
= FALSE
;
2093 m_renameTimer
= new wxListRenameTimer( this );
2094 m_renameAccept
= FALSE
;
2099 m_lineBeforeLastClicked
= (size_t)-1;
2102 void wxListMainWindow::InitScrolling()
2104 if ( HasFlag(wxLC_REPORT
) )
2106 m_xScroll
= SCROLL_UNIT_X
;
2107 m_yScroll
= SCROLL_UNIT_Y
;
2111 m_xScroll
= SCROLL_UNIT_Y
;
2116 wxListMainWindow::wxListMainWindow()
2120 m_highlightBrush
= (wxBrush
*) NULL
;
2126 wxListMainWindow::wxListMainWindow( wxWindow
*parent
,
2131 const wxString
&name
)
2132 : wxScrolledWindow( parent
, id
, pos
, size
,
2133 style
| wxHSCROLL
| wxVSCROLL
, name
)
2137 m_highlightBrush
= new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
), wxSOLID
);
2142 SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 );
2144 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX
) );
2147 wxListMainWindow::~wxListMainWindow()
2151 delete m_highlightBrush
;
2153 delete m_renameTimer
;
2156 void wxListMainWindow::CacheLineData(size_t line
)
2158 wxListCtrl
*listctrl
= GetListCtrl();
2160 wxListLineData
*ld
= GetDummyLine();
2162 size_t countCol
= GetColumnCount();
2163 for ( size_t col
= 0; col
< countCol
; col
++ )
2165 ld
->SetText(col
, listctrl
->OnGetItemText(line
, col
));
2168 ld
->SetImage(listctrl
->OnGetItemImage(line
));
2169 ld
->SetAttr(listctrl
->OnGetItemAttr(line
));
2172 wxListLineData
*wxListMainWindow::GetDummyLine() const
2174 wxASSERT_MSG( !IsEmpty(), _T("invalid line index") );
2176 if ( m_lines
.IsEmpty() )
2178 // normal controls are supposed to have something in m_lines
2179 // already if it's not empty
2180 wxASSERT_MSG( IsVirtual(), _T("logic error") );
2182 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2183 wxListLineData
*line
= new wxListLineData(self
);
2184 self
->m_lines
.Add(line
);
2190 // ----------------------------------------------------------------------------
2191 // line geometry (report mode only)
2192 // ----------------------------------------------------------------------------
2194 wxCoord
wxListMainWindow::GetLineHeight() const
2196 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2198 // we cache the line height as calling GetTextExtent() is slow
2199 if ( !m_lineHeight
)
2201 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2203 wxClientDC
dc( self
);
2204 dc
.SetFont( GetFont() );
2207 dc
.GetTextExtent(_T("H"), NULL
, &y
);
2209 if ( y
< SCROLL_UNIT_Y
)
2213 self
->m_lineHeight
= y
+ LINE_SPACING
;
2216 return m_lineHeight
;
2219 wxCoord
wxListMainWindow::GetLineY(size_t line
) const
2221 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2223 return LINE_SPACING
+ line
*GetLineHeight();
2226 wxRect
wxListMainWindow::GetLineRect(size_t line
) const
2228 if ( !InReportView() )
2229 return GetLine(line
)->m_gi
->m_rectAll
;
2232 rect
.x
= HEADER_OFFSET_X
;
2233 rect
.y
= GetLineY(line
);
2234 rect
.width
= GetHeaderWidth();
2235 rect
.height
= GetLineHeight();
2240 wxRect
wxListMainWindow::GetLineLabelRect(size_t line
) const
2242 if ( !InReportView() )
2243 return GetLine(line
)->m_gi
->m_rectLabel
;
2246 rect
.x
= HEADER_OFFSET_X
;
2247 rect
.y
= GetLineY(line
);
2248 rect
.width
= GetColumnWidth(0);
2249 rect
.height
= GetLineHeight();
2254 wxRect
wxListMainWindow::GetLineIconRect(size_t line
) const
2256 if ( !InReportView() )
2257 return GetLine(line
)->m_gi
->m_rectIcon
;
2259 wxListLineData
*ld
= GetLine(line
);
2260 wxASSERT_MSG( ld
->HasImage(), _T("should have an image") );
2263 rect
.x
= HEADER_OFFSET_X
;
2264 rect
.y
= GetLineY(line
);
2265 GetImageSize(ld
->GetImage(), rect
.width
, rect
.height
);
2270 wxRect
wxListMainWindow::GetLineHighlightRect(size_t line
) const
2272 return InReportView() ? GetLineRect(line
)
2273 : GetLine(line
)->m_gi
->m_rectHighlight
;
2276 long wxListMainWindow::HitTestLine(size_t line
, int x
, int y
) const
2278 wxListLineData
*ld
= GetLine(line
);
2280 if ( ld
->HasImage() && GetLineIconRect(line
).Inside(x
, y
) )
2281 return wxLIST_HITTEST_ONITEMICON
;
2283 if ( ld
->HasText() )
2285 wxRect rect
= InReportView() ? GetLineRect(line
)
2286 : GetLineLabelRect(line
);
2288 if ( rect
.Inside(x
, y
) )
2289 return wxLIST_HITTEST_ONITEMLABEL
;
2295 // ----------------------------------------------------------------------------
2296 // highlight (selection) handling
2297 // ----------------------------------------------------------------------------
2299 bool wxListMainWindow::IsHighlighted(size_t line
) const
2303 return m_selStore
.IsSelected(line
);
2307 wxListLineData
*ld
= GetLine(line
);
2308 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2310 return ld
->IsHighlighted();
2314 void wxListMainWindow::HighlightLines( size_t lineFrom
, size_t lineTo
, bool highlight
)
2318 m_selStore
.SelectRange(lineFrom
, lineTo
, highlight
);
2319 RefreshLines(lineFrom
, lineTo
);
2323 // do it the dumb way
2324 bool needsRefresh
= FALSE
;
2325 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2327 if ( HighlightLine(line
, highlight
) )
2328 needsRefresh
= TRUE
;
2332 RefreshLines(lineFrom
, lineTo
);
2336 bool wxListMainWindow::HighlightLine( size_t line
, bool highlight
)
2342 changed
= m_selStore
.SelectItem(line
, highlight
);
2346 wxListLineData
*ld
= GetLine(line
);
2347 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2349 changed
= ld
->Highlight(highlight
);
2354 SendNotify( line
, highlight
? wxEVT_COMMAND_LIST_ITEM_SELECTED
2355 : wxEVT_COMMAND_LIST_ITEM_DESELECTED
);
2361 void wxListMainWindow::RefreshLine( size_t line
)
2363 wxRect rect
= GetLineRect(line
);
2365 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2366 RefreshRect( rect
);
2369 void wxListMainWindow::RefreshLines( size_t lineFrom
, size_t lineTo
)
2371 // we suppose that they are ordered by caller
2372 wxASSERT_MSG( lineFrom
<= lineTo
, _T("indices in disorder") );
2374 wxASSERT_MSG( lineTo
< GetItemCount(), _T("invalid line range") );
2376 if ( HasFlag(wxLC_REPORT
) )
2378 size_t visibleFrom
, visibleTo
;
2379 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2381 if ( lineFrom
< visibleFrom
)
2382 lineFrom
= visibleFrom
;
2383 if ( lineTo
> visibleTo
)
2388 rect
.y
= GetLineY(lineFrom
);
2389 rect
.width
= GetClientSize().x
;
2390 rect
.height
= GetLineY(lineTo
) - rect
.y
;
2392 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2393 RefreshRect( rect
);
2397 // TODO: this should be optimized...
2398 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2405 void wxListMainWindow::RefreshAfter( size_t lineFrom
)
2407 if ( HasFlag(wxLC_REPORT
) )
2410 GetVisibleLinesRange(&visibleFrom
, NULL
);
2412 if ( lineFrom
< visibleFrom
)
2413 lineFrom
= visibleFrom
;
2417 rect
.y
= GetLineY(lineFrom
);
2419 wxSize size
= GetClientSize();
2420 rect
.width
= size
.x
;
2421 // refresh till the bottom of the window
2422 rect
.height
= size
.y
- rect
.y
;
2424 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2425 RefreshRect( rect
);
2429 // TODO: how to do it more efficiently?
2434 void wxListMainWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
2436 // Note: a wxPaintDC must be constructed even if no drawing is
2437 // done (a Windows requirement).
2438 wxPaintDC
dc( this );
2442 // empty control. nothing to draw
2448 // delay the repainting until we calculate all the items positions
2455 CalcScrolledPosition( 0, 0, &dev_x
, &dev_y
);
2459 dc
.SetFont( GetFont() );
2461 if ( HasFlag(wxLC_REPORT
) )
2463 int lineHeight
= GetLineHeight();
2465 size_t visibleFrom
, visibleTo
;
2466 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2469 wxCoord xOrig
, yOrig
;
2470 CalcUnscrolledPosition(0, 0, &xOrig
, &yOrig
);
2472 for ( size_t line
= visibleFrom
; line
<= visibleTo
; line
++ )
2474 rectLine
= GetLineRect(line
);
2476 if ( !IsExposed(rectLine
.x
- xOrig
, rectLine
.y
- yOrig
,
2477 rectLine
.width
, rectLine
.height
) )
2479 // don't redraw unaffected lines to avoid flicker
2483 GetLine(line
)->DrawInReportMode( &dc
,
2485 GetLineHighlightRect(line
),
2486 IsHighlighted(line
) );
2489 if ( HasFlag(wxLC_HRULES
) )
2491 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2492 wxSize clientSize
= GetClientSize();
2494 for ( size_t i
= visibleFrom
; i
<= visibleTo
; i
++ )
2497 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2498 dc
.DrawLine(0 - dev_x
, i
*lineHeight
,
2499 clientSize
.x
- dev_x
, i
*lineHeight
);
2502 // Draw last horizontal rule
2503 if ( visibleTo
> visibleFrom
)
2506 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2507 dc
.DrawLine(0 - dev_x
, m_lineTo
*lineHeight
,
2508 clientSize
.x
- dev_x
, m_lineTo
*lineHeight
);
2512 // Draw vertical rules if required
2513 if ( HasFlag(wxLC_VRULES
) && !IsEmpty() )
2515 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2518 wxRect firstItemRect
;
2519 wxRect lastItemRect
;
2520 GetItemRect(0, firstItemRect
);
2521 GetItemRect(GetItemCount() - 1, lastItemRect
);
2522 int x
= firstItemRect
.GetX();
2524 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
2525 for (col
= 0; col
< GetColumnCount(); col
++)
2527 int colWidth
= GetColumnWidth(col
);
2529 dc
.DrawLine(x
- dev_x
, firstItemRect
.GetY() - 1 - dev_y
,
2530 x
- dev_x
, lastItemRect
.GetBottom() + 1 - dev_y
);
2536 size_t count
= GetItemCount();
2537 for ( size_t i
= 0; i
< count
; i
++ )
2539 GetLine(i
)->Draw( &dc
);
2543 if ( HasCurrent() && m_hasFocus
)
2546 // no rect outline, we already have the background color
2548 dc
.SetPen( *wxBLACK_PEN
);
2549 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2550 dc
.DrawRectangle( GetLineHighlightRect(m_current
) );
2557 void wxListMainWindow::HighlightAll( bool on
)
2559 if ( IsSingleSel() )
2561 wxASSERT_MSG( !on
, _T("can't do this in a single sel control") );
2563 // we just have one item to turn off
2564 if ( HasCurrent() && IsHighlighted(m_current
) )
2566 HighlightLine(m_current
, FALSE
);
2567 RefreshLine(m_current
);
2572 HighlightLines(0, GetItemCount() - 1, on
);
2576 void wxListMainWindow::SendNotify( size_t line
,
2577 wxEventType command
,
2580 wxListEvent
le( command
, GetParent()->GetId() );
2581 le
.SetEventObject( GetParent() );
2582 le
.m_itemIndex
= line
;
2584 // set only for events which have position
2585 if ( point
!= wxDefaultPosition
)
2586 le
.m_pointDrag
= point
;
2588 GetLine(line
)->GetItem( 0, le
.m_item
);
2589 GetParent()->GetEventHandler()->ProcessEvent( le
);
2592 void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line
) )
2594 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
2597 void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line
) )
2599 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
2602 void wxListMainWindow::EditLabel( long item
)
2604 wxCHECK_RET( (item
>= 0) && ((size_t)item
< GetItemCount()),
2605 wxT("wrong index in wxListCtrl::EditLabel()") );
2607 m_currentEdit
= (size_t)item
;
2609 wxListEvent
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() );
2610 le
.SetEventObject( GetParent() );
2611 le
.m_itemIndex
= item
;
2612 wxListLineData
*data
= GetLine(m_currentEdit
);
2613 wxCHECK_RET( data
, _T("invalid index in EditLabel()") );
2614 data
->GetItem( 0, le
.m_item
);
2615 GetParent()->GetEventHandler()->ProcessEvent( le
);
2617 if (!le
.IsAllowed())
2620 // We have to call this here because the label in question might just have
2621 // been added and no screen update taken place.
2625 wxClientDC
dc(this);
2628 wxString s
= data
->GetText(0);
2629 wxRect rectLabel
= GetLineLabelRect(m_currentEdit
);
2631 rectLabel
.x
= dc
.LogicalToDeviceX( rectLabel
.x
);
2632 rectLabel
.y
= dc
.LogicalToDeviceY( rectLabel
.y
);
2634 wxListTextCtrl
*text
= new wxListTextCtrl
2641 wxPoint(rectLabel
.x
-4,rectLabel
.y
-4),
2642 wxSize(rectLabel
.width
+11,rectLabel
.height
+8)
2647 void wxListMainWindow::OnRenameTimer()
2649 wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") );
2651 EditLabel( m_current
);
2654 void wxListMainWindow::OnRenameAccept()
2656 wxListEvent
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() );
2657 le
.SetEventObject( GetParent() );
2658 le
.m_itemIndex
= m_currentEdit
;
2660 wxListLineData
*data
= GetLine(m_currentEdit
);
2661 wxCHECK_RET( data
, _T("invalid index in OnRenameAccept()") );
2663 data
->GetItem( 0, le
.m_item
);
2664 le
.m_item
.m_text
= m_renameRes
;
2665 GetParent()->GetEventHandler()->ProcessEvent( le
);
2667 if (!le
.IsAllowed()) return;
2670 info
.m_mask
= wxLIST_MASK_TEXT
;
2671 info
.m_itemId
= le
.m_itemIndex
;
2672 info
.m_text
= m_renameRes
;
2673 info
.SetTextColour(le
.m_item
.GetTextColour());
2677 void wxListMainWindow::OnMouse( wxMouseEvent
&event
)
2679 event
.SetEventObject( GetParent() );
2680 if ( GetParent()->GetEventHandler()->ProcessEvent( event
) )
2683 if ( !HasCurrent() || IsEmpty() )
2689 if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() ||
2690 event
.ButtonDClick()) )
2693 int x
= event
.GetX();
2694 int y
= event
.GetY();
2695 CalcUnscrolledPosition( x
, y
, &x
, &y
);
2697 // where did we hit it (if we did)?
2700 size_t count
= GetItemCount(),
2703 if ( HasFlag(wxLC_REPORT
) )
2705 current
= y
/ GetLineHeight();
2706 if ( current
< count
)
2707 hitResult
= HitTestLine(current
, x
, y
);
2711 // TODO: optimize it too! this is less simple than for report view but
2712 // enumerating all items is still not a way to do it!!
2713 for ( current
= 0; current
< count
; current
++ )
2715 hitResult
= HitTestLine(current
, x
, y
);
2721 if (event
.Dragging())
2723 if (m_dragCount
== 0)
2724 m_dragStart
= wxPoint(x
,y
);
2728 if (m_dragCount
!= 3)
2731 int command
= event
.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2732 : wxEVT_COMMAND_LIST_BEGIN_DRAG
;
2734 wxListEvent
le( command
, GetParent()->GetId() );
2735 le
.SetEventObject( GetParent() );
2736 le
.m_pointDrag
= m_dragStart
;
2737 GetParent()->GetEventHandler()->ProcessEvent( le
);
2748 // outside of any item
2752 bool forceClick
= FALSE
;
2753 if (event
.ButtonDClick())
2755 m_renameTimer
->Stop();
2756 m_lastOnSame
= FALSE
;
2758 if ( current
== m_lineBeforeLastClicked
)
2760 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
);
2766 // the first click was on another item, so don't interpret this as
2767 // a double click, but as a simple click instead
2772 if (event
.LeftUp() && m_lastOnSame
)
2774 if ((current
== m_current
) &&
2775 (hitResult
== wxLIST_HITTEST_ONITEMLABEL
) &&
2776 HasFlag(wxLC_EDIT_LABELS
) )
2778 m_renameTimer
->Start( 100, TRUE
);
2780 m_lastOnSame
= FALSE
;
2782 else if (event
.RightDown())
2784 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
,
2785 event
.GetPosition() );
2787 else if (event
.MiddleDown())
2789 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
);
2791 else if ( event
.LeftDown() || forceClick
)
2793 m_lineBeforeLastClicked
= m_lineLastClicked
;
2794 m_lineLastClicked
= current
;
2796 size_t oldCurrent
= m_current
;
2798 if ( IsSingleSel() || !(event
.ControlDown() || event
.ShiftDown()) )
2800 HighlightAll( FALSE
);
2801 m_current
= current
;
2803 ReverseHighlight(m_current
);
2805 else // multi sel & either ctrl or shift is down
2807 if (event
.ControlDown())
2809 m_current
= current
;
2811 ReverseHighlight(m_current
);
2813 else if (event
.ShiftDown())
2815 m_current
= current
;
2817 size_t lineFrom
= oldCurrent
,
2820 if ( lineTo
< lineFrom
)
2823 lineFrom
= m_current
;
2826 HighlightLines(lineFrom
, lineTo
);
2828 else // !ctrl, !shift
2830 // test in the enclosing if should make it impossible
2831 wxFAIL_MSG( _T("how did we get here?") );
2835 if (m_current
!= oldCurrent
)
2837 RefreshLine( oldCurrent
);
2838 OnUnfocusLine( oldCurrent
);
2839 OnFocusLine( m_current
);
2842 // forceClick is only set if the previous click was on another item
2843 m_lastOnSame
= !forceClick
&& (m_current
== oldCurrent
);
2847 void wxListMainWindow::MoveToFocus()
2849 if ( !HasCurrent() )
2852 wxRect rect
= GetLineRect(m_current
);
2854 int client_w
, client_h
;
2855 GetClientSize( &client_w
, &client_h
);
2857 int view_x
= m_xScroll
*GetScrollPos( wxHORIZONTAL
);
2858 int view_y
= m_yScroll
*GetScrollPos( wxVERTICAL
);
2860 if ( HasFlag(wxLC_REPORT
) )
2862 // the next we need the range of lines shown it might be different, so
2864 ResetVisibleLinesRange();
2866 if (rect
.y
< view_y
)
2867 Scroll( -1, rect
.y
/m_yScroll
);
2868 if (rect
.y
+rect
.height
+5 > view_y
+client_h
)
2869 Scroll( -1, (rect
.y
+rect
.height
-client_h
+SCROLL_UNIT_Y
)/m_yScroll
);
2873 if (rect
.x
-view_x
< 5)
2874 Scroll( (rect
.x
-5)/m_xScroll
, -1 );
2875 if (rect
.x
+rect
.width
-5 > view_x
+client_w
)
2876 Scroll( (rect
.x
+rect
.width
-client_w
+SCROLL_UNIT_X
)/m_xScroll
, -1 );
2880 // ----------------------------------------------------------------------------
2881 // keyboard handling
2882 // ----------------------------------------------------------------------------
2884 void wxListMainWindow::OnArrowChar(size_t newCurrent
, const wxKeyEvent
& event
)
2886 wxCHECK_RET( newCurrent
< (size_t)GetItemCount(),
2887 _T("invalid item index in OnArrowChar()") );
2889 size_t oldCurrent
= m_current
;
2891 // in single selection we just ignore Shift as we can't select several
2893 if ( event
.ShiftDown() && !IsSingleSel() )
2895 m_current
= newCurrent
;
2897 // select all the items between the old and the new one
2898 if ( oldCurrent
> newCurrent
)
2900 newCurrent
= oldCurrent
;
2901 oldCurrent
= m_current
;
2904 HighlightLines(oldCurrent
, newCurrent
);
2908 // all previously selected items are unselected unless ctrl is held
2909 if ( !event
.ControlDown() )
2910 HighlightAll(FALSE
);
2912 m_current
= newCurrent
;
2914 HighlightLine( oldCurrent
, FALSE
);
2915 RefreshLine( oldCurrent
);
2917 if ( !event
.ControlDown() )
2919 HighlightLine( m_current
, TRUE
);
2923 OnUnfocusLine( oldCurrent
);
2924 OnFocusLine( m_current
);
2925 RefreshLine( m_current
);
2930 void wxListMainWindow::OnKeyDown( wxKeyEvent
&event
)
2932 wxWindow
*parent
= GetParent();
2934 /* we propagate the key event up */
2935 wxKeyEvent
ke( wxEVT_KEY_DOWN
);
2936 ke
.m_shiftDown
= event
.m_shiftDown
;
2937 ke
.m_controlDown
= event
.m_controlDown
;
2938 ke
.m_altDown
= event
.m_altDown
;
2939 ke
.m_metaDown
= event
.m_metaDown
;
2940 ke
.m_keyCode
= event
.m_keyCode
;
2943 ke
.SetEventObject( parent
);
2944 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2949 void wxListMainWindow::OnChar( wxKeyEvent
&event
)
2951 wxWindow
*parent
= GetParent();
2953 /* we send a list_key event up */
2956 wxListEvent
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() );
2957 le
.m_itemIndex
= m_current
;
2958 GetLine(m_current
)->GetItem( 0, le
.m_item
);
2959 le
.m_code
= (int)event
.KeyCode();
2960 le
.SetEventObject( parent
);
2961 parent
->GetEventHandler()->ProcessEvent( le
);
2964 /* we propagate the char event up */
2965 wxKeyEvent
ke( wxEVT_CHAR
);
2966 ke
.m_shiftDown
= event
.m_shiftDown
;
2967 ke
.m_controlDown
= event
.m_controlDown
;
2968 ke
.m_altDown
= event
.m_altDown
;
2969 ke
.m_metaDown
= event
.m_metaDown
;
2970 ke
.m_keyCode
= event
.m_keyCode
;
2973 ke
.SetEventObject( parent
);
2974 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2976 if (event
.KeyCode() == WXK_TAB
)
2978 wxNavigationKeyEvent nevent
;
2979 nevent
.SetWindowChange( event
.ControlDown() );
2980 nevent
.SetDirection( !event
.ShiftDown() );
2981 nevent
.SetEventObject( GetParent()->GetParent() );
2982 nevent
.SetCurrentFocus( m_parent
);
2983 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent
)) return;
2986 /* no item -> nothing to do */
2993 switch (event
.KeyCode())
2996 if ( m_current
> 0 )
2997 OnArrowChar( m_current
- 1, event
);
3001 if ( m_current
< (size_t)GetItemCount() - 1 )
3002 OnArrowChar( m_current
+ 1, event
);
3007 OnArrowChar( GetItemCount() - 1, event
);
3012 OnArrowChar( 0, event
);
3018 if ( HasFlag(wxLC_REPORT
) )
3020 steps
= m_linesPerPage
- 1;
3024 steps
= m_current
% m_linesPerPage
;
3027 int index
= m_current
- steps
;
3031 OnArrowChar( index
, event
);
3038 if ( HasFlag(wxLC_REPORT
) )
3040 steps
= m_linesPerPage
- 1;
3044 steps
= m_linesPerPage
- (m_current
% m_linesPerPage
) - 1;
3047 size_t index
= m_current
+ steps
;
3048 size_t count
= GetItemCount();
3049 if ( index
>= count
)
3052 OnArrowChar( index
, event
);
3057 if ( !HasFlag(wxLC_REPORT
) )
3059 int index
= m_current
- m_linesPerPage
;
3063 OnArrowChar( index
, event
);
3068 if ( !HasFlag(wxLC_REPORT
) )
3070 size_t index
= m_current
+ m_linesPerPage
;
3072 size_t count
= GetItemCount();
3073 if ( index
>= count
)
3076 OnArrowChar( index
, event
);
3081 if ( IsSingleSel() )
3083 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3084 GetParent()->GetId() );
3085 le
.SetEventObject( GetParent() );
3086 le
.m_itemIndex
= m_current
;
3087 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3088 GetParent()->GetEventHandler()->ProcessEvent( le
);
3092 ReverseHighlight(m_current
);
3099 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3100 GetParent()->GetId() );
3101 le
.SetEventObject( GetParent() );
3102 le
.m_itemIndex
= m_current
;
3103 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3104 GetParent()->GetEventHandler()->ProcessEvent( le
);
3113 // ----------------------------------------------------------------------------
3115 // ----------------------------------------------------------------------------
3118 extern wxWindow
*g_focusWindow
;
3121 void wxListMainWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
3126 RefreshLine( m_current
);
3132 g_focusWindow
= GetParent();
3135 wxFocusEvent
event( wxEVT_SET_FOCUS
, GetParent()->GetId() );
3136 event
.SetEventObject( GetParent() );
3137 GetParent()->GetEventHandler()->ProcessEvent( event
);
3140 void wxListMainWindow::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
3145 RefreshLine( m_current
);
3148 void wxListMainWindow::DrawImage( int index
, wxDC
*dc
, int x
, int y
)
3150 if ( HasFlag(wxLC_ICON
) && (m_normal_image_list
))
3152 m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3154 else if ( HasFlag(wxLC_SMALL_ICON
) && (m_small_image_list
))
3156 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3158 else if ( HasFlag(wxLC_LIST
) && (m_small_image_list
))
3160 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3162 else if ( HasFlag(wxLC_REPORT
) && (m_small_image_list
))
3164 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3168 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height
) const
3170 if ( HasFlag(wxLC_ICON
) && m_normal_image_list
)
3172 m_normal_image_list
->GetSize( index
, width
, height
);
3174 else if ( HasFlag(wxLC_SMALL_ICON
) && m_small_image_list
)
3176 m_small_image_list
->GetSize( index
, width
, height
);
3178 else if ( HasFlag(wxLC_LIST
) && m_small_image_list
)
3180 m_small_image_list
->GetSize( index
, width
, height
);
3182 else if ( HasFlag(wxLC_REPORT
) && m_small_image_list
)
3184 m_small_image_list
->GetSize( index
, width
, height
);
3193 int wxListMainWindow::GetTextLength( const wxString
&s
) const
3195 wxClientDC
dc( wxConstCast(this, wxListMainWindow
) );
3196 dc
.SetFont( GetFont() );
3199 dc
.GetTextExtent( s
, &lw
, NULL
);
3201 return lw
+ AUTOSIZE_COL_MARGIN
;
3204 void wxListMainWindow::SetImageList( wxImageList
*imageList
, int which
)
3208 // calc the spacing from the icon size
3211 if ((imageList
) && (imageList
->GetImageCount()) )
3213 imageList
->GetSize(0, width
, height
);
3216 if (which
== wxIMAGE_LIST_NORMAL
)
3218 m_normal_image_list
= imageList
;
3219 m_normal_spacing
= width
+ 8;
3222 if (which
== wxIMAGE_LIST_SMALL
)
3224 m_small_image_list
= imageList
;
3225 m_small_spacing
= width
+ 14;
3229 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall
)
3234 m_small_spacing
= spacing
;
3238 m_normal_spacing
= spacing
;
3242 int wxListMainWindow::GetItemSpacing( bool isSmall
)
3244 return isSmall
? m_small_spacing
: m_normal_spacing
;
3247 // ----------------------------------------------------------------------------
3249 // ----------------------------------------------------------------------------
3251 void wxListMainWindow::SetColumn( int col
, wxListItem
&item
)
3253 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3255 wxCHECK_RET( node
, _T("invalid column index in SetColumn") );
3257 if ( item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3258 item
.m_width
= GetTextLength( item
.m_text
);
3260 wxListHeaderData
*column
= node
->GetData();
3261 column
->SetItem( item
);
3263 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3265 headerWin
->m_dirty
= TRUE
;
3269 // invalidate it as it has to be recalculated
3273 void wxListMainWindow::SetColumnWidth( int col
, int width
)
3275 wxCHECK_RET( col
>= 0 && col
< GetColumnCount(),
3276 _T("invalid column index") );
3278 wxCHECK_RET( HasFlag(wxLC_REPORT
),
3279 _T("SetColumnWidth() can only be called in report mode.") );
3283 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3284 wxCHECK_RET( node
, _T("no column?") );
3286 wxListHeaderData
*column
= node
->GetData();
3288 size_t count
= GetItemCount();
3290 if (width
== wxLIST_AUTOSIZE_USEHEADER
)
3292 width
= GetTextLength(column
->GetText());
3294 else if ( width
== wxLIST_AUTOSIZE
)
3298 // TODO: determine the max width somehow...
3299 width
= WIDTH_COL_DEFAULT
;
3303 wxClientDC
dc(this);
3304 dc
.SetFont( GetFont() );
3306 int max
= AUTOSIZE_COL_MARGIN
;
3308 for ( size_t i
= 0; i
< count
; i
++ )
3310 wxListLineData
*line
= GetLine(i
);
3311 wxListItemDataList::Node
*n
= line
->m_items
.Item( col
);
3313 wxCHECK_RET( n
, _T("no subitem?") );
3315 wxListItemData
*item
= n
->GetData();
3318 if (item
->HasImage())
3321 GetImageSize( item
->GetImage(), ix
, iy
);
3325 if (item
->HasText())
3328 dc
.GetTextExtent( item
->GetText(), &w
, NULL
);
3336 width
= max
+ AUTOSIZE_COL_MARGIN
;
3340 column
->SetWidth( width
);
3342 // invalidate it as it has to be recalculated
3346 int wxListMainWindow::GetHeaderWidth() const
3348 if ( !m_headerWidth
)
3350 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
3352 size_t count
= GetColumnCount();
3353 for ( size_t col
= 0; col
< count
; col
++ )
3355 self
->m_headerWidth
+= GetColumnWidth(col
);
3359 return m_headerWidth
;
3362 void wxListMainWindow::GetColumn( int col
, wxListItem
&item
) const
3364 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3365 wxCHECK_RET( node
, _T("invalid column index in GetColumn") );
3367 wxListHeaderData
*column
= node
->GetData();
3368 column
->GetItem( item
);
3371 int wxListMainWindow::GetColumnWidth( int col
) const
3373 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3374 wxCHECK_MSG( node
, 0, _T("invalid column index") );
3376 wxListHeaderData
*column
= node
->GetData();
3377 return column
->GetWidth();
3380 // ----------------------------------------------------------------------------
3382 // ----------------------------------------------------------------------------
3384 void wxListMainWindow::SetItem( wxListItem
&item
)
3386 long id
= item
.m_itemId
;
3387 wxCHECK_RET( id
>= 0 && (size_t)id
< GetItemCount(),
3388 _T("invalid item index in SetItem") );
3392 wxListLineData
*line
= GetLine((size_t)id
);
3393 line
->SetItem( item
.m_col
, item
);
3396 if ( InReportView() )
3398 // just refresh the line to show the new value of the text/image
3399 RefreshLine((size_t)id
);
3403 // refresh everything (resulting in horrible flicker - FIXME!)
3408 void wxListMainWindow::SetItemState( long litem
, long state
, long stateMask
)
3410 wxCHECK_RET( litem
>= 0 && (size_t)litem
< GetItemCount(),
3411 _T("invalid list ctrl item index in SetItem") );
3413 size_t oldCurrent
= m_current
;
3414 size_t item
= (size_t)litem
; // sdafe because of the check above
3416 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3418 if ( state
& wxLIST_STATE_FOCUSED
)
3420 // don't do anything if this item is already focused
3421 if ( item
!= m_current
)
3423 OnUnfocusLine( m_current
);
3425 OnFocusLine( m_current
);
3427 if ( IsSingleSel() && (oldCurrent
!= (size_t)-1) )
3429 HighlightLine(oldCurrent
, FALSE
);
3430 RefreshLine(oldCurrent
);
3433 RefreshLine( m_current
);
3438 // don't do anything if this item is not focused
3439 if ( item
== m_current
)
3441 OnUnfocusLine( m_current
);
3442 m_current
= (size_t)-1;
3447 if ( stateMask
& wxLIST_STATE_SELECTED
)
3449 bool on
= (state
& wxLIST_STATE_SELECTED
) != 0;
3451 if ( IsSingleSel() )
3455 // selecting the item also makes it the focused one in the
3457 if ( m_current
!= item
)
3459 OnUnfocusLine( m_current
);
3461 OnFocusLine( m_current
);
3463 if ( oldCurrent
!= (size_t)-1 )
3465 HighlightLine( oldCurrent
, FALSE
);
3466 RefreshLine( oldCurrent
);
3472 // only the current item may be selected anyhow
3473 if ( item
!= m_current
)
3478 if ( HighlightLine(item
, on
) )
3485 int wxListMainWindow::GetItemState( long item
, long stateMask
)
3487 wxCHECK_MSG( item
>= 0 && (size_t)item
< GetItemCount(), 0,
3488 _T("invalid list ctrl item index in GetItemState()") );
3490 int ret
= wxLIST_STATE_DONTCARE
;
3492 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3494 if ( (size_t)item
== m_current
)
3495 ret
|= wxLIST_STATE_FOCUSED
;
3498 if ( stateMask
& wxLIST_STATE_SELECTED
)
3500 if ( IsHighlighted(item
) )
3501 ret
|= wxLIST_STATE_SELECTED
;
3507 void wxListMainWindow::GetItem( wxListItem
&item
)
3509 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
< GetItemCount(),
3510 _T("invalid item index in GetItem") );
3512 wxListLineData
*line
= GetLine((size_t)item
.m_itemId
);
3513 line
->GetItem( item
.m_col
, item
);
3516 // ----------------------------------------------------------------------------
3518 // ----------------------------------------------------------------------------
3520 size_t wxListMainWindow::GetItemCount() const
3522 return IsVirtual() ? m_countVirt
: m_lines
.GetCount();
3525 void wxListMainWindow::SetItemCount(long count
)
3527 m_selStore
.SetItemCount(count
);
3528 m_countVirt
= count
;
3533 int wxListMainWindow::GetSelectedItemCount()
3535 // deal with the quick case first
3536 if ( IsSingleSel() )
3538 return HasCurrent() ? IsHighlighted(m_current
) : FALSE
;
3541 // virtual controls remmebers all its selections itself
3543 return m_selStore
.GetSelectedCount();
3545 // TODO: we probably should maintain the number of items selected even for
3546 // non virtual controls as enumerating all lines is really slow...
3547 size_t countSel
= 0;
3548 size_t count
= GetItemCount();
3549 for ( size_t line
= 0; line
< count
; line
++ )
3551 if ( GetLine(line
)->IsHighlighted() )
3558 // ----------------------------------------------------------------------------
3559 // item position/size
3560 // ----------------------------------------------------------------------------
3562 void wxListMainWindow::GetItemRect( long index
, wxRect
&rect
)
3564 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3565 _T("invalid index in GetItemRect") );
3567 rect
= GetLineRect((size_t)index
);
3569 CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
3572 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
)
3575 GetItemRect(item
, rect
);
3583 // ----------------------------------------------------------------------------
3584 // geometry calculation
3585 // ----------------------------------------------------------------------------
3587 void wxListMainWindow::RecalculatePositions()
3592 wxClientDC
dc( this );
3593 dc
.SetFont( GetFont() );
3596 if ( HasFlag(wxLC_ICON
) )
3597 iconSpacing
= m_normal_spacing
;
3598 else if ( HasFlag(wxLC_SMALL_ICON
) )
3599 iconSpacing
= m_small_spacing
;
3605 GetClientSize( &clientWidth
, &clientHeight
);
3607 if ( HasFlag(wxLC_REPORT
) )
3609 // all lines have the same height
3610 int lineHeight
= GetLineHeight();
3612 // scroll one line per step
3613 m_yScroll
= lineHeight
;
3615 size_t lineCount
= GetItemCount();
3616 int entireHeight
= lineCount
*lineHeight
+ LINE_SPACING
;
3618 m_linesPerPage
= clientHeight
/ lineHeight
;
3620 ResetVisibleLinesRange();
3622 SetScrollbars( m_xScroll
, m_yScroll
,
3623 (GetHeaderWidth() + m_xScroll
- 1)/m_xScroll
,
3624 (entireHeight
+ m_yScroll
- 1)/m_yScroll
,
3625 GetScrollPos(wxHORIZONTAL
),
3626 GetScrollPos(wxVERTICAL
),
3631 // at first we try without any scrollbar. if the items don't
3632 // fit into the window, we recalculate after subtracting an
3633 // approximated 15 pt for the horizontal scrollbar
3635 clientHeight
-= 4; // sunken frame
3637 int entireWidth
= 0;
3639 for (int tries
= 0; tries
< 2; tries
++)
3646 int currentlyVisibleLines
= 0;
3648 size_t count
= GetItemCount();
3649 for (size_t i
= 0; i
< count
; i
++)
3651 currentlyVisibleLines
++;
3652 wxListLineData
*line
= GetLine(i
);
3653 line
->CalculateSize( &dc
, iconSpacing
);
3654 line
->SetPosition( x
, y
, clientWidth
, iconSpacing
);
3656 wxSize sizeLine
= GetLineSize(i
);
3658 if ( maxWidth
< sizeLine
.x
)
3659 maxWidth
= sizeLine
.x
;
3662 if (currentlyVisibleLines
> m_linesPerPage
)
3663 m_linesPerPage
= currentlyVisibleLines
;
3665 // assume that the size of the next one is the same... (FIXME)
3666 if ( y
+ sizeLine
.y
- 6 >= clientHeight
)
3668 currentlyVisibleLines
= 0;
3671 entireWidth
+= maxWidth
+6;
3674 if ( i
== count
- 1 )
3675 entireWidth
+= maxWidth
;
3676 if ((tries
== 0) && (entireWidth
> clientWidth
))
3678 clientHeight
-= 15; // scrollbar height
3680 currentlyVisibleLines
= 0;
3683 if ( i
== count
- 1 )
3684 tries
= 1; // everything fits, no second try required
3688 int scroll_pos
= GetScrollPos( wxHORIZONTAL
);
3689 SetScrollbars( m_xScroll
, m_yScroll
, (entireWidth
+SCROLL_UNIT_X
) / m_xScroll
, 0, scroll_pos
, 0, TRUE
);
3692 // FIXME: why should we call it from here?
3698 void wxListMainWindow::RefreshAll()
3703 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3706 headerWin
->m_dirty
= FALSE
;
3707 headerWin
->Refresh();
3711 void wxListMainWindow::UpdateCurrent()
3713 if ( !HasCurrent() && !IsEmpty() )
3718 if ( m_current
!= (size_t)-1 )
3720 OnFocusLine( m_current
);
3724 long wxListMainWindow::GetNextItem( long item
,
3725 int WXUNUSED(geometry
),
3729 max
= GetItemCount();
3730 wxCHECK_MSG( (ret
== -1) || (ret
< max
), -1,
3731 _T("invalid listctrl index in GetNextItem()") );
3733 // notice that we start with the next item (or the first one if item == -1)
3734 // and this is intentional to allow writing a simple loop to iterate over
3735 // all selected items
3739 // this is not an error because the index was ok initially, just no
3750 size_t count
= GetItemCount();
3751 for ( size_t line
= (size_t)ret
; line
< count
; line
++ )
3753 if ( (state
& wxLIST_STATE_FOCUSED
) && (line
== m_current
) )
3756 if ( (state
& wxLIST_STATE_SELECTED
) && IsHighlighted(line
) )
3763 // ----------------------------------------------------------------------------
3765 // ----------------------------------------------------------------------------
3767 void wxListMainWindow::DeleteItem( long lindex
)
3769 size_t count
= GetItemCount();
3771 wxCHECK_RET( (lindex
>= 0) && ((size_t)lindex
< count
),
3772 _T("invalid item index in DeleteItem") );
3774 size_t index
= (size_t)lindex
;
3778 // select the next item when the selected one is deleted
3779 if ( m_current
== index
)
3781 // the last valid index after deleting the item will be count-2
3782 if ( m_current
== count
- 1 )
3788 SendNotify( index
, wxEVT_COMMAND_LIST_DELETE_ITEM
);
3790 if ( InReportView() )
3792 ResetVisibleLinesRange();
3799 m_selStore
.OnItemDelete(index
);
3803 m_lines
.RemoveAt( index
);
3807 RefreshAfter(index
);
3810 void wxListMainWindow::DeleteColumn( int col
)
3812 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3814 wxCHECK_RET( node
, wxT("invalid column index in DeleteColumn()") );
3817 m_columns
.DeleteNode( node
);
3820 void wxListMainWindow::DeleteAllItems()
3824 // nothing to do - in particular, don't send the event
3832 // to make the deletion of all items faster, we don't send the
3833 // notifications for each item deletion in this case but only one event
3834 // for all of them: this is compatible with wxMSW and documented in
3835 // DeleteAllItems() description
3837 wxListEvent
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() );
3838 event
.SetEventObject( GetParent() );
3839 GetParent()->GetEventHandler()->ProcessEvent( event
);
3845 ResetVisibleLinesRange();
3848 if ( InReportView() )
3850 ResetVisibleLinesRange();
3858 void wxListMainWindow::DeleteEverything()
3865 // ----------------------------------------------------------------------------
3866 // scanning for an item
3867 // ----------------------------------------------------------------------------
3869 void wxListMainWindow::EnsureVisible( long index
)
3871 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3872 _T("invalid index in EnsureVisible") );
3874 // We have to call this here because the label in question might just have
3875 // been added and no screen update taken place.
3879 size_t oldCurrent
= m_current
;
3880 m_current
= (size_t)index
;
3882 m_current
= oldCurrent
;
3885 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) )
3892 size_t count
= GetItemCount();
3893 for ( size_t i
= (size_t)pos
; i
< count
; i
++ )
3895 wxListLineData
*line
= GetLine(i
);
3896 if ( line
->GetText(0) == tmp
)
3903 long wxListMainWindow::FindItem(long start
, long data
)
3909 size_t count
= GetItemCount();
3910 for (size_t i
= (size_t)pos
; i
< count
; i
++)
3912 wxListLineData
*line
= GetLine(i
);
3914 line
->GetItem( 0, item
);
3915 if (item
.m_data
== data
)
3922 long wxListMainWindow::HitTest( int x
, int y
, int &flags
)
3924 CalcUnscrolledPosition( x
, y
, &x
, &y
);
3926 if ( HasFlag(wxLC_REPORT
) )
3928 size_t current
= y
/ GetLineHeight();
3929 flags
= HitTestLine(current
, x
, y
);
3935 // TODO: optimize it too! this is less simple than for report view but
3936 // enumerating all items is still not a way to do it!!
3937 size_t count
= GetItemCount();
3938 for ( size_t current
= 0; current
< count
; current
++ )
3940 flags
= HitTestLine(current
, x
, y
);
3949 // ----------------------------------------------------------------------------
3951 // ----------------------------------------------------------------------------
3953 void wxListMainWindow::InsertItem( wxListItem
&item
)
3955 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") );
3957 size_t count
= GetItemCount();
3958 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
<= count
,
3959 _T("invalid item index") );
3961 size_t id
= item
.m_itemId
;
3966 if ( HasFlag(wxLC_REPORT
) )
3968 else if ( HasFlag(wxLC_LIST
) )
3970 else if ( HasFlag(wxLC_ICON
) )
3972 else if ( HasFlag(wxLC_SMALL_ICON
) )
3973 mode
= wxLC_ICON
; // no typo
3976 wxFAIL_MSG( _T("unknown mode") );
3979 wxListLineData
*line
= new wxListLineData(this);
3981 line
->SetItem( 0, item
);
3983 m_lines
.Insert( line
, id
);
3986 RefreshLines(id
, GetItemCount() - 1);
3989 void wxListMainWindow::InsertColumn( long col
, wxListItem
&item
)
3992 if ( HasFlag(wxLC_REPORT
) )
3994 if (item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3995 item
.m_width
= GetTextLength( item
.m_text
);
3996 wxListHeaderData
*column
= new wxListHeaderData( item
);
3997 if ((col
>= 0) && (col
< (int)m_columns
.GetCount()))
3999 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
4000 m_columns
.Insert( node
, column
);
4004 m_columns
.Append( column
);
4009 // ----------------------------------------------------------------------------
4011 // ----------------------------------------------------------------------------
4013 wxListCtrlCompare list_ctrl_compare_func_2
;
4014 long list_ctrl_compare_data
;
4016 int LINKAGEMODE
list_ctrl_compare_func_1( wxListLineData
**arg1
, wxListLineData
**arg2
)
4018 wxListLineData
*line1
= *arg1
;
4019 wxListLineData
*line2
= *arg2
;
4021 line1
->GetItem( 0, item
);
4022 long data1
= item
.m_data
;
4023 line2
->GetItem( 0, item
);
4024 long data2
= item
.m_data
;
4025 return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data
);
4028 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data
)
4030 list_ctrl_compare_func_2
= fn
;
4031 list_ctrl_compare_data
= data
;
4032 m_lines
.Sort( list_ctrl_compare_func_1
);
4036 // ----------------------------------------------------------------------------
4038 // ----------------------------------------------------------------------------
4040 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
)
4042 // update our idea of which lines are shown when we redraw the window the
4044 ResetVisibleLinesRange();
4047 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
4048 wxScrolledWindow::OnScroll(event
);
4050 HandleOnScroll( event
);
4053 if ( event
.GetOrientation() == wxHORIZONTAL
&& HasHeader() )
4055 wxListCtrl
* lc
= GetListCtrl();
4056 wxCHECK_RET( lc
, _T("no listctrl window?") );
4058 lc
->m_headerWin
->Refresh() ;
4060 lc
->m_headerWin
->MacUpdateImmediately() ;
4065 int wxListMainWindow::GetCountPerPage() const
4067 if ( !m_linesPerPage
)
4069 wxConstCast(this, wxListMainWindow
)->
4070 m_linesPerPage
= GetClientSize().y
/ GetLineHeight();
4073 return m_linesPerPage
;
4076 void wxListMainWindow::GetVisibleLinesRange(size_t *from
, size_t *to
)
4078 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("this is for report mode only") );
4080 if ( m_lineFrom
== (size_t)-1 )
4082 size_t count
= GetItemCount();
4085 m_lineFrom
= GetScrollPos(wxVERTICAL
);
4087 // this may happen if SetScrollbars() hadn't been called yet
4088 if ( m_lineFrom
>= count
)
4089 m_lineFrom
= count
- 1;
4091 // we redraw one extra line but this is needed to make the redrawing
4092 // logic work when there is a fractional number of lines on screen
4093 m_lineTo
= m_lineFrom
+ m_linesPerPage
;
4094 if ( m_lineTo
>= count
)
4095 m_lineTo
= count
- 1;
4097 else // empty control
4100 m_lineTo
= (size_t)-1;
4104 wxASSERT_MSG( IsEmpty() ||
4105 (m_lineFrom
<= m_lineTo
&& m_lineTo
< GetItemCount()),
4106 _T("GetVisibleLinesRange() returns incorrect result") );
4114 // -------------------------------------------------------------------------------------
4116 // -------------------------------------------------------------------------------------
4118 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
)
4120 wxListItem::wxListItem()
4129 m_format
= wxLIST_FORMAT_CENTRE
;
4135 void wxListItem::Clear()
4144 m_format
= wxLIST_FORMAT_CENTRE
;
4151 void wxListItem::ClearAttributes()
4160 // -------------------------------------------------------------------------------------
4162 // -------------------------------------------------------------------------------------
4164 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
)
4166 wxListEvent::wxListEvent( wxEventType commandType
, int id
)
4167 : wxNotifyEvent( commandType
, id
)
4173 m_cancelled
= FALSE
;
4178 void wxListEvent::CopyObject(wxObject
& object_dest
) const
4180 wxListEvent
*obj
= (wxListEvent
*)&object_dest
;
4182 wxNotifyEvent::CopyObject(object_dest
);
4184 obj
->m_code
= m_code
;
4185 obj
->m_itemIndex
= m_itemIndex
;
4186 obj
->m_oldItemIndex
= m_oldItemIndex
;
4188 obj
->m_cancelled
= m_cancelled
;
4189 obj
->m_pointDrag
= m_pointDrag
;
4190 obj
->m_item
.m_mask
= m_item
.m_mask
;
4191 obj
->m_item
.m_itemId
= m_item
.m_itemId
;
4192 obj
->m_item
.m_col
= m_item
.m_col
;
4193 obj
->m_item
.m_state
= m_item
.m_state
;
4194 obj
->m_item
.m_stateMask
= m_item
.m_stateMask
;
4195 obj
->m_item
.m_text
= m_item
.m_text
;
4196 obj
->m_item
.m_image
= m_item
.m_image
;
4197 obj
->m_item
.m_data
= m_item
.m_data
;
4198 obj
->m_item
.m_format
= m_item
.m_format
;
4199 obj
->m_item
.m_width
= m_item
.m_width
;
4201 if ( m_item
.HasAttributes() )
4203 obj
->m_item
.SetTextColour(m_item
.GetTextColour());
4207 // -------------------------------------------------------------------------------------
4209 // -------------------------------------------------------------------------------------
4211 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
)
4213 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
)
4214 EVT_SIZE(wxListCtrl::OnSize
)
4215 EVT_IDLE(wxListCtrl::OnIdle
)
4218 wxListCtrl::wxListCtrl()
4220 m_imageListNormal
= (wxImageList
*) NULL
;
4221 m_imageListSmall
= (wxImageList
*) NULL
;
4222 m_imageListState
= (wxImageList
*) NULL
;
4224 m_ownsImageListNormal
=
4225 m_ownsImageListSmall
=
4226 m_ownsImageListState
= FALSE
;
4228 m_mainWin
= (wxListMainWindow
*) NULL
;
4229 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4232 wxListCtrl::~wxListCtrl()
4235 m_mainWin
->ResetCurrent();
4237 if (m_ownsImageListNormal
)
4238 delete m_imageListNormal
;
4239 if (m_ownsImageListSmall
)
4240 delete m_imageListSmall
;
4241 if (m_ownsImageListState
)
4242 delete m_imageListState
;
4245 void wxListCtrl::CreateHeaderWindow()
4247 m_headerWin
= new wxListHeaderWindow
4249 this, -1, m_mainWin
,
4251 wxSize(GetClientSize().x
, HEADER_HEIGHT
),
4256 bool wxListCtrl::Create(wxWindow
*parent
,
4261 const wxValidator
&validator
,
4262 const wxString
&name
)
4266 m_imageListState
= (wxImageList
*) NULL
;
4267 m_ownsImageListNormal
=
4268 m_ownsImageListSmall
=
4269 m_ownsImageListState
= FALSE
;
4271 m_mainWin
= (wxListMainWindow
*) NULL
;
4272 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4274 if ( !(style
& wxLC_MASK_TYPE
) )
4276 style
= style
| wxLC_LIST
;
4279 if ( !wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name
) )
4282 // don't create the inner window with the border
4283 style
&= ~wxSUNKEN_BORDER
;
4285 m_mainWin
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style
);
4287 if ( HasFlag(wxLC_REPORT
) )
4289 CreateHeaderWindow();
4291 if ( HasFlag(wxLC_NO_HEADER
) )
4293 // VZ: why do we create it at all then?
4294 m_headerWin
->Show( FALSE
);
4301 void wxListCtrl::SetSingleStyle( long style
, bool add
)
4303 wxASSERT_MSG( !(style
& wxLC_VIRTUAL
),
4304 _T("wxLC_VIRTUAL can't be [un]set") );
4306 long flag
= GetWindowStyle();
4310 if (style
& wxLC_MASK_TYPE
)
4311 flag
&= ~(wxLC_MASK_TYPE
| wxLC_VIRTUAL
);
4312 if (style
& wxLC_MASK_ALIGN
)
4313 flag
&= ~wxLC_MASK_ALIGN
;
4314 if (style
& wxLC_MASK_SORT
)
4315 flag
&= ~wxLC_MASK_SORT
;
4327 SetWindowStyleFlag( flag
);
4330 void wxListCtrl::SetWindowStyleFlag( long flag
)
4334 m_mainWin
->DeleteEverything();
4338 GetClientSize( &width
, &height
);
4340 if (flag
& wxLC_REPORT
)
4342 if (!HasFlag(wxLC_REPORT
))
4346 CreateHeaderWindow();
4348 if (HasFlag(wxLC_NO_HEADER
))
4349 m_headerWin
->Show( FALSE
);
4353 if (flag
& wxLC_NO_HEADER
)
4354 m_headerWin
->Show( FALSE
);
4356 m_headerWin
->Show( TRUE
);
4362 if ( m_mainWin
->HasHeader() )
4364 m_headerWin
->Show( FALSE
);
4369 wxWindow::SetWindowStyleFlag( flag
);
4372 bool wxListCtrl::GetColumn(int col
, wxListItem
&item
) const
4374 m_mainWin
->GetColumn( col
, item
);
4378 bool wxListCtrl::SetColumn( int col
, wxListItem
& item
)
4380 m_mainWin
->SetColumn( col
, item
);
4384 int wxListCtrl::GetColumnWidth( int col
) const
4386 return m_mainWin
->GetColumnWidth( col
);
4389 bool wxListCtrl::SetColumnWidth( int col
, int width
)
4391 m_mainWin
->SetColumnWidth( col
, width
);
4395 int wxListCtrl::GetCountPerPage() const
4397 return m_mainWin
->GetCountPerPage(); // different from Windows ?
4400 bool wxListCtrl::GetItem( wxListItem
&info
) const
4402 m_mainWin
->GetItem( info
);
4406 bool wxListCtrl::SetItem( wxListItem
&info
)
4408 m_mainWin
->SetItem( info
);
4412 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId
)
4415 info
.m_text
= label
;
4416 info
.m_mask
= wxLIST_MASK_TEXT
;
4417 info
.m_itemId
= index
;
4421 info
.m_image
= imageId
;
4422 info
.m_mask
|= wxLIST_MASK_IMAGE
;
4424 m_mainWin
->SetItem(info
);
4428 int wxListCtrl::GetItemState( long item
, long stateMask
) const
4430 return m_mainWin
->GetItemState( item
, stateMask
);
4433 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask
)
4435 m_mainWin
->SetItemState( item
, state
, stateMask
);
4439 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) )
4442 info
.m_image
= image
;
4443 info
.m_mask
= wxLIST_MASK_IMAGE
;
4444 info
.m_itemId
= item
;
4445 m_mainWin
->SetItem( info
);
4449 wxString
wxListCtrl::GetItemText( long item
) const
4452 info
.m_itemId
= item
;
4453 m_mainWin
->GetItem( info
);
4457 void wxListCtrl::SetItemText( long item
, const wxString
&str
)
4460 info
.m_mask
= wxLIST_MASK_TEXT
;
4461 info
.m_itemId
= item
;
4463 m_mainWin
->SetItem( info
);
4466 long wxListCtrl::GetItemData( long item
) const
4469 info
.m_itemId
= item
;
4470 m_mainWin
->GetItem( info
);
4474 bool wxListCtrl::SetItemData( long item
, long data
)
4477 info
.m_mask
= wxLIST_MASK_DATA
;
4478 info
.m_itemId
= item
;
4480 m_mainWin
->SetItem( info
);
4484 bool wxListCtrl::GetItemRect( long item
, wxRect
&rect
, int WXUNUSED(code
) ) const
4486 m_mainWin
->GetItemRect( item
, rect
);
4490 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos
) const
4492 m_mainWin
->GetItemPosition( item
, pos
);
4496 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) )
4501 int wxListCtrl::GetItemCount() const
4503 return m_mainWin
->GetItemCount();
4506 int wxListCtrl::GetColumnCount() const
4508 return m_mainWin
->GetColumnCount();
4511 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall
)
4513 m_mainWin
->SetItemSpacing( spacing
, isSmall
);
4516 int wxListCtrl::GetItemSpacing( bool isSmall
) const
4518 return m_mainWin
->GetItemSpacing( isSmall
);
4521 int wxListCtrl::GetSelectedItemCount() const
4523 return m_mainWin
->GetSelectedItemCount();
4526 wxColour
wxListCtrl::GetTextColour() const
4528 return GetForegroundColour();
4531 void wxListCtrl::SetTextColour(const wxColour
& col
)
4533 SetForegroundColour(col
);
4536 long wxListCtrl::GetTopItem() const
4541 long wxListCtrl::GetNextItem( long item
, int geom
, int state
) const
4543 return m_mainWin
->GetNextItem( item
, geom
, state
);
4546 wxImageList
*wxListCtrl::GetImageList(int which
) const
4548 if (which
== wxIMAGE_LIST_NORMAL
)
4550 return m_imageListNormal
;
4552 else if (which
== wxIMAGE_LIST_SMALL
)
4554 return m_imageListSmall
;
4556 else if (which
== wxIMAGE_LIST_STATE
)
4558 return m_imageListState
;
4560 return (wxImageList
*) NULL
;
4563 void wxListCtrl::SetImageList( wxImageList
*imageList
, int which
)
4565 if ( which
== wxIMAGE_LIST_NORMAL
)
4567 if (m_ownsImageListNormal
) delete m_imageListNormal
;
4568 m_imageListNormal
= imageList
;
4569 m_ownsImageListNormal
= FALSE
;
4571 else if ( which
== wxIMAGE_LIST_SMALL
)
4573 if (m_ownsImageListSmall
) delete m_imageListSmall
;
4574 m_imageListSmall
= imageList
;
4575 m_ownsImageListSmall
= FALSE
;
4577 else if ( which
== wxIMAGE_LIST_STATE
)
4579 if (m_ownsImageListState
) delete m_imageListState
;
4580 m_imageListState
= imageList
;
4581 m_ownsImageListState
= FALSE
;
4584 m_mainWin
->SetImageList( imageList
, which
);
4587 void wxListCtrl::AssignImageList(wxImageList
*imageList
, int which
)
4589 SetImageList(imageList
, which
);
4590 if ( which
== wxIMAGE_LIST_NORMAL
)
4591 m_ownsImageListNormal
= TRUE
;
4592 else if ( which
== wxIMAGE_LIST_SMALL
)
4593 m_ownsImageListSmall
= TRUE
;
4594 else if ( which
== wxIMAGE_LIST_STATE
)
4595 m_ownsImageListState
= TRUE
;
4598 bool wxListCtrl::Arrange( int WXUNUSED(flag
) )
4603 bool wxListCtrl::DeleteItem( long item
)
4605 m_mainWin
->DeleteItem( item
);
4609 bool wxListCtrl::DeleteAllItems()
4611 m_mainWin
->DeleteAllItems();
4615 bool wxListCtrl::DeleteAllColumns()
4617 size_t count
= m_mainWin
->m_columns
.GetCount();
4618 for ( size_t n
= 0; n
< count
; n
++ )
4624 void wxListCtrl::ClearAll()
4626 m_mainWin
->DeleteEverything();
4629 bool wxListCtrl::DeleteColumn( int col
)
4631 m_mainWin
->DeleteColumn( col
);
4635 void wxListCtrl::Edit( long item
)
4637 m_mainWin
->EditLabel( item
);
4640 bool wxListCtrl::EnsureVisible( long item
)
4642 m_mainWin
->EnsureVisible( item
);
4646 long wxListCtrl::FindItem( long start
, const wxString
& str
, bool partial
)
4648 return m_mainWin
->FindItem( start
, str
, partial
);
4651 long wxListCtrl::FindItem( long start
, long data
)
4653 return m_mainWin
->FindItem( start
, data
);
4656 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
),
4657 int WXUNUSED(direction
))
4662 long wxListCtrl::HitTest( const wxPoint
&point
, int &flags
)
4664 return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags
);
4667 long wxListCtrl::InsertItem( wxListItem
& info
)
4669 m_mainWin
->InsertItem( info
);
4670 return info
.m_itemId
;
4673 long wxListCtrl::InsertItem( long index
, const wxString
&label
)
4676 info
.m_text
= label
;
4677 info
.m_mask
= wxLIST_MASK_TEXT
;
4678 info
.m_itemId
= index
;
4679 return InsertItem( info
);
4682 long wxListCtrl::InsertItem( long index
, int imageIndex
)
4685 info
.m_mask
= wxLIST_MASK_IMAGE
;
4686 info
.m_image
= imageIndex
;
4687 info
.m_itemId
= index
;
4688 return InsertItem( info
);
4691 long wxListCtrl::InsertItem( long index
, const wxString
&label
, int imageIndex
)
4694 info
.m_text
= label
;
4695 info
.m_image
= imageIndex
;
4696 info
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_IMAGE
;
4697 info
.m_itemId
= index
;
4698 return InsertItem( info
);
4701 long wxListCtrl::InsertColumn( long col
, wxListItem
&item
)
4703 wxASSERT( m_headerWin
);
4704 m_mainWin
->InsertColumn( col
, item
);
4705 m_headerWin
->Refresh();
4710 long wxListCtrl::InsertColumn( long col
, const wxString
&heading
,
4711 int format
, int width
)
4714 item
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_FORMAT
;
4715 item
.m_text
= heading
;
4718 item
.m_mask
|= wxLIST_MASK_WIDTH
;
4719 item
.m_width
= width
;
4721 item
.m_format
= format
;
4723 return InsertColumn( col
, item
);
4726 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) )
4732 // fn is a function which takes 3 long arguments: item1, item2, data.
4733 // item1 is the long data associated with a first item (NOT the index).
4734 // item2 is the long data associated with a second item (NOT the index).
4735 // data is the same value as passed to SortItems.
4736 // The return value is a negative number if the first item should precede the second
4737 // item, a positive number of the second item should precede the first,
4738 // or zero if the two items are equivalent.
4739 // data is arbitrary data to be passed to the sort function.
4741 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data
)
4743 m_mainWin
->SortItems( fn
, data
);
4747 // ----------------------------------------------------------------------------
4749 // ----------------------------------------------------------------------------
4751 void wxListCtrl::OnSize(wxSizeEvent
& event
)
4757 GetClientSize( &cw
, &ch
);
4759 if ( m_mainWin
->HasHeader() )
4761 m_headerWin
->SetSize( 0, 0, cw
, HEADER_HEIGHT
);
4762 m_mainWin
->SetSize( 0, HEADER_HEIGHT
+ 1, cw
, ch
- HEADER_HEIGHT
- 1 );
4764 else // no header window
4766 m_mainWin
->SetSize( 0, 0, cw
, ch
);
4769 m_mainWin
->RecalculatePositions();
4772 void wxListCtrl::OnIdle( wxIdleEvent
& event
)
4776 // do it only if needed
4777 if ( !m_mainWin
->m_dirty
)
4780 m_mainWin
->RecalculatePositions();
4783 // ----------------------------------------------------------------------------
4785 // ----------------------------------------------------------------------------
4787 bool wxListCtrl::SetBackgroundColour( const wxColour
&colour
)
4791 m_mainWin
->SetBackgroundColour( colour
);
4792 m_mainWin
->m_dirty
= TRUE
;
4798 bool wxListCtrl::SetForegroundColour( const wxColour
&colour
)
4800 if ( !wxWindow::SetForegroundColour( colour
) )
4805 m_mainWin
->SetForegroundColour( colour
);
4806 m_mainWin
->m_dirty
= TRUE
;
4811 m_headerWin
->SetForegroundColour( colour
);
4817 bool wxListCtrl::SetFont( const wxFont
&font
)
4819 if ( !wxWindow::SetFont( font
) )
4824 m_mainWin
->SetFont( font
);
4825 m_mainWin
->m_dirty
= TRUE
;
4830 m_headerWin
->SetFont( font
);
4836 // ----------------------------------------------------------------------------
4837 // methods forwarded to m_mainWin
4838 // ----------------------------------------------------------------------------
4840 #if wxUSE_DRAG_AND_DROP
4842 void wxListCtrl::SetDropTarget( wxDropTarget
*dropTarget
)
4844 m_mainWin
->SetDropTarget( dropTarget
);
4847 wxDropTarget
*wxListCtrl::GetDropTarget() const
4849 return m_mainWin
->GetDropTarget();
4852 #endif // wxUSE_DRAG_AND_DROP
4854 bool wxListCtrl::SetCursor( const wxCursor
&cursor
)
4856 return m_mainWin
? m_mainWin
->wxWindow::SetCursor(cursor
) : FALSE
;
4859 wxColour
wxListCtrl::GetBackgroundColour() const
4861 return m_mainWin
? m_mainWin
->GetBackgroundColour() : wxColour();
4864 wxColour
wxListCtrl::GetForegroundColour() const
4866 return m_mainWin
? m_mainWin
->GetForegroundColour() : wxColour();
4869 bool wxListCtrl::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
4872 return m_mainWin
->PopupMenu( menu
, x
, y
);
4875 #endif // wxUSE_MENUS
4878 void wxListCtrl::SetFocus()
4880 /* The test in window.cpp fails as we are a composite
4881 window, so it checks against "this", but not m_mainWin. */
4882 if ( FindFocus() != this )
4883 m_mainWin
->SetFocus();
4886 // ----------------------------------------------------------------------------
4887 // virtual list control support
4888 // ----------------------------------------------------------------------------
4890 wxString
wxListCtrl::OnGetItemText(long item
, long col
) const
4892 // this is a pure virtual function, in fact - which is not really pure
4893 // because the controls which are not virtual don't need to implement it
4894 wxFAIL_MSG( _T("not supposed to be called") );
4896 return wxEmptyString
;
4899 int wxListCtrl::OnGetItemImage(long item
) const
4902 wxFAIL_MSG( _T("not supposed to be called") );
4907 wxListItemAttr
*wxListCtrl::OnGetItemAttr(long item
) const
4909 wxASSERT_MSG( item
>= 0 && item
< GetItemCount(),
4910 _T("invalid item index in OnGetItemAttr()") );
4912 // no attributes by default
4916 void wxListCtrl::SetItemCount(long count
)
4918 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4920 m_mainWin
->SetItemCount(count
);
4923 #endif // wxUSE_LISTCTRL