1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/listctrl.cpp
3 // Purpose: generic implementation of wxListCtrl
4 // Author: Robert Roebling
5 // Vadim Zeitlin (virtual list control support)
7 // Copyright: (c) 1998 Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 FIXME for virtual list controls
14 +1. clicking on the item with a mouse is awfully slow, what is going on?
15 note that selecting with keyboard seems to be much faster
16 => fixed HighlightAll() - iterating over 1000000 items *is* slow
18 2. background colour is wrong?
22 TODO for better virtual list control support:
24 1. less dumb line caching, we should cache at least all those visible
25 in the control itself and probably twice as many (we might also need to
26 cache the first one always for geometry calculations?)
28 +2. storing selections: we can't use an array to store the selected indices
29 like right now as selecting all in a control with 1000000 items is not
30 doable like this - instead, store selections as collection of individual
35 3. we need to implement searching/sorting somehow
37 4. the idea of storing the line index in the line itself is really stupid,
38 we shouldn't need it - but for this we have to get rid of all calles to
39 wxListLineData::GetFoo() and replace them with something like
41 ... we have it ourselves ...
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
55 #pragma implementation "listctrl.h"
56 #pragma implementation "listctrlbase.h"
60 #include "listctrl.old.cpp"
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 wxListItemAttr
*GetAttributes() const { return m_attr
; }
253 // the item image or -1
256 // user data associated with the item
259 // the item coordinates are not used in report mode, instead this pointer
260 // is NULL and the owner window is used to retrieve the item position and
264 // the list ctrl we are in
265 wxListMainWindow
*m_owner
;
267 // custom attributes or NULL
268 wxListItemAttr
*m_attr
;
271 // common part of all ctors
277 //-----------------------------------------------------------------------------
278 // wxListHeaderData (internal)
279 //-----------------------------------------------------------------------------
281 class WXDLLEXPORT wxListHeaderData
: public wxObject
295 wxListHeaderData( const wxListItem
&info
);
296 void SetItem( const wxListItem
&item
);
297 void SetPosition( int x
, int y
);
298 void SetWidth( int w
);
299 void SetFormat( int format
);
300 void SetHeight( int h
);
301 bool HasImage() const;
303 bool HasText() const { return !m_text
.empty(); }
304 const wxString
& GetText() const { return m_text
; }
305 void SetText(const wxString
& text
) { m_text
= text
; }
307 void GetItem( wxListItem
&item
);
309 bool IsHit( int x
, int y
) const;
310 int GetImage() const;
311 int GetWidth() const;
312 int GetFormat() const;
315 DECLARE_DYNAMIC_CLASS(wxListHeaderData
);
318 //-----------------------------------------------------------------------------
319 // wxListLineData (internal)
320 //-----------------------------------------------------------------------------
322 WX_DECLARE_LIST(wxListItemData
, wxListItemDataList
);
323 #include "wx/listimpl.cpp"
324 WX_DEFINE_LIST(wxListItemDataList
);
326 class WXDLLEXPORT wxListLineData
329 // the list of subitems: only may have more than one item in report mode
330 wxListItemDataList m_items
;
332 // this is not used in report view
344 // the part to be highlighted
345 wxRect m_rectHighlight
;
348 // is this item selected? [NB: not used in virtual mode]
351 // back pointer to the list ctrl
352 wxListMainWindow
*m_owner
;
355 wxListLineData(wxListMainWindow
*owner
);
357 ~wxListLineData() { delete m_gi
; }
359 // are we in report mode?
360 inline bool InReportView() const;
362 // are we in virtual report mode?
363 inline bool IsVirtual() const;
365 // these 2 methods shouldn't be called for report view controls, in that
366 // case we determine our position/size ourselves
368 // calculate the size of the line
369 void CalculateSize( wxDC
*dc
, int spacing
);
371 // remember the position this line appears at
372 void SetPosition( int x
, int y
, int window_width
, int spacing
);
376 void SetImage( int image
) { SetImage(0, image
); }
377 int GetImage() const { return GetImage(0); }
378 bool HasImage() const { return GetImage() != -1; }
379 bool HasText() const { return !GetText(0).empty(); }
381 void SetItem( int index
, const wxListItem
&info
);
382 void GetItem( int index
, wxListItem
&info
);
384 wxString
GetText(int index
) const;
385 void SetText( int index
, const wxString s
);
387 // return true if the highlighting really changed
388 bool Highlight( bool on
);
390 void ReverseHighlight();
392 bool IsHighlighted() const
394 wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") );
396 return m_highlighted
;
399 // draw the line on the given DC in icon/list mode
400 void Draw( wxDC
*dc
);
402 // the same in report mode
403 void DrawInReportMode( wxDC
*dc
,
405 const wxRect
& rectHL
,
409 // set the line to contain num items (only can be > 1 in report mode)
410 void InitItems( int num
);
412 // get the mode (i.e. style) of the list control
413 inline int GetMode() const;
415 void SetAttributes(wxDC
*dc
,
416 const wxListItemAttr
*attr
,
417 const wxColour
& colText
,
421 // these are only used by GetImage/SetImage above, we don't support images
422 // with subitems at the public API level yet
423 void SetImage( int index
, int image
);
424 int GetImage( int index
) const;
427 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData
, wxListLineDataArray
);
428 #include "wx/arrimpl.cpp"
429 WX_DEFINE_OBJARRAY(wxListLineDataArray
);
431 //-----------------------------------------------------------------------------
432 // wxListHeaderWindow (internal)
433 //-----------------------------------------------------------------------------
435 class WXDLLEXPORT wxListHeaderWindow
: public wxWindow
438 wxListMainWindow
*m_owner
;
439 wxCursor
*m_currentCursor
;
440 wxCursor
*m_resizeCursor
;
443 // column being resized
446 // divider line position in logical (unscrolled) coords
449 // minimal position beyond which the divider line can't be dragged in
454 wxListHeaderWindow();
455 virtual ~wxListHeaderWindow();
457 wxListHeaderWindow( wxWindow
*win
,
459 wxListMainWindow
*owner
,
460 const wxPoint
&pos
= wxDefaultPosition
,
461 const wxSize
&size
= wxDefaultSize
,
463 const wxString
&name
= "wxlistctrlcolumntitles" );
465 void DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
);
467 void AdjustDC(wxDC
& dc
);
469 void OnPaint( wxPaintEvent
&event
);
470 void OnMouse( wxMouseEvent
&event
);
471 void OnSetFocus( wxFocusEvent
&event
);
477 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow
)
478 DECLARE_EVENT_TABLE()
481 //-----------------------------------------------------------------------------
482 // wxListRenameTimer (internal)
483 //-----------------------------------------------------------------------------
485 class WXDLLEXPORT wxListRenameTimer
: public wxTimer
488 wxListMainWindow
*m_owner
;
491 wxListRenameTimer( wxListMainWindow
*owner
);
495 //-----------------------------------------------------------------------------
496 // wxListTextCtrl (internal)
497 //-----------------------------------------------------------------------------
499 class WXDLLEXPORT wxListTextCtrl
: public wxTextCtrl
504 wxListMainWindow
*m_owner
;
505 wxString m_startValue
;
509 wxListTextCtrl( wxWindow
*parent
, const wxWindowID id
,
510 bool *accept
, wxString
*res
, wxListMainWindow
*owner
,
511 const wxString
&value
= "",
512 const wxPoint
&pos
= wxDefaultPosition
, const wxSize
&size
= wxDefaultSize
,
514 const wxValidator
& validator
= wxDefaultValidator
,
515 const wxString
&name
= "listctrltextctrl" );
516 void OnChar( wxKeyEvent
&event
);
517 void OnKeyUp( wxKeyEvent
&event
);
518 void OnKillFocus( wxFocusEvent
&event
);
521 DECLARE_DYNAMIC_CLASS(wxListTextCtrl
);
522 DECLARE_EVENT_TABLE()
525 //-----------------------------------------------------------------------------
526 // wxListMainWindow (internal)
527 //-----------------------------------------------------------------------------
529 WX_DECLARE_LIST(wxListHeaderData
, wxListHeaderDataList
);
530 #include "wx/listimpl.cpp"
531 WX_DEFINE_LIST(wxListHeaderDataList
);
533 class WXDLLEXPORT wxListMainWindow
: public wxScrolledWindow
537 wxListMainWindow( wxWindow
*parent
,
539 const wxPoint
& pos
= wxDefaultPosition
,
540 const wxSize
& size
= wxDefaultSize
,
542 const wxString
&name
= _T("listctrlmainwindow") );
544 virtual ~wxListMainWindow();
546 bool HasFlag(int flag
) const { return m_parent
->HasFlag(flag
); }
548 // return true if this is a virtual list control
549 bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL
); }
551 // return true if the control is in report mode
552 bool InReportView() const { return HasFlag(wxLC_REPORT
); }
554 // return true if we are in single selection mode, false if multi sel
555 bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL
); }
557 // do we have a header window?
558 bool HasHeader() const
559 { return HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
); }
561 void HighlightAll( bool on
);
563 // all these functions only do something if the line is currently visible
565 // change the line "selected" state, return TRUE if it really changed
566 bool HighlightLine( size_t line
, bool highlight
= TRUE
);
568 // as HighlightLine() but do it for the range of lines: this is incredibly
569 // more efficient for virtual list controls!
571 // NB: unlike HighlightLine() this one does refresh the lines on screen
572 void HighlightLines( size_t lineFrom
, size_t lineTo
, bool on
= TRUE
);
574 // toggle the line state and refresh it
575 void ReverseHighlight( size_t line
)
576 { HighlightLine(line
, !IsHighlighted(line
)); RefreshLine(line
); }
578 // refresh one or several lines at once
579 void RefreshLine( size_t line
);
580 void RefreshLines( size_t lineFrom
, size_t lineTo
);
582 // return true if the line is highlighted
583 bool IsHighlighted(size_t line
) const;
585 // the methods which are forwarded to wxListLineData itself in list/icon
586 // modes but are here because the lines don't store their positions in the
589 // get the bound rect for the entire line
590 wxRect
GetLineRect(size_t line
) const;
592 // get the bound rect of the label
593 wxRect
GetLineLabelRect(size_t line
) const;
595 // get the bound rect of the items icon (only may be called if we do have
597 wxRect
GetLineIconRect(size_t line
) const;
599 // get the rect to be highlighted when the item has focus
600 wxRect
GetLineHighlightRect(size_t line
) const;
602 // get the size of the total line rect
603 wxSize
GetLineSize(size_t line
) const
604 { return GetLineRect(line
).GetSize(); }
606 // return the hit code for the corresponding position (in this line)
607 long HitTestLine(size_t line
, int x
, int y
) const;
609 void EditLabel( long item
);
610 void OnRenameTimer();
611 void OnRenameAccept();
613 void OnMouse( wxMouseEvent
&event
);
616 // called to switch the selection from the current item to newCurrent,
617 void OnArrowChar( size_t newCurrent
, const wxKeyEvent
& event
);
619 void OnChar( wxKeyEvent
&event
);
620 void OnKeyDown( wxKeyEvent
&event
);
621 void OnSetFocus( wxFocusEvent
&event
);
622 void OnKillFocus( wxFocusEvent
&event
);
623 void OnScroll(wxScrollWinEvent
& event
) ;
625 void OnPaint( wxPaintEvent
&event
);
627 void DrawImage( int index
, wxDC
*dc
, int x
, int y
);
628 void GetImageSize( int index
, int &width
, int &height
) const;
629 int GetTextLength( const wxString
&s
) const;
631 void SetImageList( wxImageList
*imageList
, int which
);
632 void SetItemSpacing( int spacing
, bool isSmall
= FALSE
);
633 int GetItemSpacing( bool isSmall
= FALSE
);
635 void SetColumn( int col
, wxListItem
&item
);
636 void SetColumnWidth( int col
, int width
);
637 void GetColumn( int col
, wxListItem
&item
) const;
638 int GetColumnWidth( int col
) const;
639 int GetColumnCount() const { return m_columns
.GetCount(); }
641 // returns the sum of the heights of all columns
642 int GetHeaderWidth() const;
644 int GetCountPerPage() const;
646 void SetItem( wxListItem
&item
);
647 void GetItem( wxListItem
&item
);
648 void SetItemState( long item
, long state
, long stateMask
);
649 int GetItemState( long item
, long stateMask
);
650 void GetItemRect( long index
, wxRect
&rect
);
651 bool GetItemPosition( long item
, wxPoint
& pos
);
652 int GetSelectedItemCount();
654 // set the scrollbars and update the positions of the items
655 void RecalculatePositions();
657 // refresh the window and the header
660 long GetNextItem( long item
, int geometry
, int state
);
661 void DeleteItem( long index
);
662 void DeleteAllItems();
663 void DeleteColumn( int col
);
664 void DeleteEverything();
665 void EnsureVisible( long index
);
666 long FindItem( long start
, const wxString
& str
, bool partial
= FALSE
);
667 long FindItem( long start
, long data
);
668 long HitTest( int x
, int y
, int &flags
);
669 void InsertItem( wxListItem
&item
);
670 void InsertColumn( long col
, wxListItem
&item
);
671 void SortItems( wxListCtrlCompare fn
, long data
);
673 size_t GetItemCount() const;
674 bool IsEmpty() const { return GetItemCount() == 0; }
675 void SetItemCount(long count
);
677 void ResetCurrent() { m_current
= (size_t)-1; }
678 bool HasCurrent() const { return m_current
!= (size_t)-1; }
680 // send out a wxListEvent
681 void SendNotify( size_t line
,
683 wxPoint point
= wxDefaultPosition
);
685 // override base class virtual to reset m_lineHeight when the font changes
686 virtual bool SetFont(const wxFont
& font
)
688 if ( !wxScrolledWindow::SetFont(font
) )
696 // these are for wxListLineData usage only
698 // get the backpointer to the list ctrl
699 wxListCtrl
*GetListCtrl() const
701 return wxStaticCast(GetParent(), wxListCtrl
);
704 // get the height of all lines (assuming they all do have the same height)
705 wxCoord
GetLineHeight() const;
707 // get the y position of the given line (only for report view)
708 wxCoord
GetLineY(size_t line
) const;
711 // the array of all line objects for a non virtual list control
712 wxListLineDataArray m_lines
;
714 // the list of column objects
715 wxListHeaderDataList m_columns
;
717 // currently focused item or -1
720 // the item currently being edited or -1
721 size_t m_currentEdit
;
723 // the number of lines per page
726 // this flag is set when something which should result in the window
727 // redrawing happens (i.e. an item was added or deleted, or its appearance
728 // changed) and OnPaint() doesn't redraw the window while it is set which
729 // allows to minimize the number of repaintings when a lot of items are
730 // being added. The real repainting occurs only after the next OnIdle()
734 wxBrush
*m_highlightBrush
;
735 wxColour
*m_highlightColour
;
738 wxImageList
*m_small_image_list
;
739 wxImageList
*m_normal_image_list
;
741 int m_normal_spacing
;
745 wxTimer
*m_renameTimer
;
747 wxString m_renameRes
;
752 // for double click logic
753 size_t m_lineLastClicked
,
754 m_lineBeforeLastClicked
;
757 // the total count of items in a virtual list control
760 // the object maintaining the items selection state, only used in virtual
762 wxSelectionStore m_selStore
;
764 // common part of all ctors
767 // intiialize m_[xy]Scroll
768 void InitScrolling();
770 // get the line data for the given index
771 wxListLineData
*GetLine(size_t n
) const
773 wxASSERT_MSG( n
!= (size_t)-1, _T("invalid line index") );
777 wxConstCast(this, wxListMainWindow
)->CacheLineData(n
);
785 // get a dummy line which can be used for geometry calculations and such:
786 // you must use GetLine() if you want to really draw the line
787 wxListLineData
*GetDummyLine() const;
789 // cache the line data of the n-th line in m_lines[0]
790 void CacheLineData(size_t line
);
792 // get the range of visible lines
793 void GetVisibleLinesRange(size_t *from
, size_t *to
);
795 // force us to recalculate the range of visible lines
796 void ResetVisibleLinesRange() { m_lineFrom
= (size_t)-1; }
798 // get the colour to be used for drawing the rules
799 wxColour
GetRuleColour() const
804 return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT
);
809 // initialize the current item if needed
810 void UpdateCurrent();
812 // called when an item is [un]focuded, i.e. becomes [not] current
815 void OnFocusLine( size_t line
);
816 void OnUnfocusLine( size_t line
);
818 // the height of one line using the current font
819 wxCoord m_lineHeight
;
821 // the total header width or 0 if not calculated yet
822 wxCoord m_headerWidth
;
824 // the first and last lines being shown on screen right now (inclusive),
825 // both may be -1 if they must be calculated so never access them directly:
826 // use GetVisibleLinesRange() above instead
830 DECLARE_DYNAMIC_CLASS(wxListMainWindow
);
831 DECLARE_EVENT_TABLE()
834 // ============================================================================
836 // ============================================================================
838 // ----------------------------------------------------------------------------
840 // ----------------------------------------------------------------------------
842 bool wxSelectionStore::IsSelected(size_t item
) const
844 bool isSel
= m_itemsSel
.Index(item
) != wxNOT_FOUND
;
846 // if the default state is to be selected, being in m_itemsSel means that
847 // the item is not selected, so we have to inverse the logic
848 return m_defaultState
? !isSel
: isSel
;
851 bool wxSelectionStore::SelectItem(size_t item
, bool select
)
853 // search for the item ourselves as like this we get the index where to
854 // insert it later if needed, so we do only one search in the array instead
855 // of two (adding item to a sorted array requires a search)
856 size_t index
= m_itemsSel
.IndexForInsert(item
);
857 bool isSel
= index
< m_itemsSel
.GetCount() && m_itemsSel
[index
] == item
;
859 if ( select
!= m_defaultState
)
863 m_itemsSel
.AddAt(item
, index
);
868 else // reset to default state
872 m_itemsSel
.RemoveAt(index
);
880 void wxSelectionStore::SelectRange(size_t itemFrom
, size_t itemTo
, bool select
)
882 wxASSERT_MSG( itemFrom
<= itemTo
, _T("should be in order") );
884 // are we going to have more [un]selected items than the other ones?
885 if ( itemTo
- itemFrom
> m_count
/ 2 )
887 if ( select
!= m_defaultState
)
889 // the default state now becomes the same as 'select'
890 m_defaultState
= select
;
892 // so all the old selections (which had state select) shouldn't be
893 // selected any more, but all the other ones should
894 wxIndexArray selOld
= m_itemsSel
;
897 // TODO: it should be possible to optimize the searches a bit
898 // knowing the possible range
901 for ( item
= 0; item
< itemFrom
; item
++ )
903 if ( selOld
.Index(item
) == wxNOT_FOUND
)
904 m_itemsSel
.Add(item
);
907 for ( item
= itemTo
+ 1; item
< m_count
; item
++ )
909 if ( selOld
.Index(item
) == wxNOT_FOUND
)
910 m_itemsSel
.Add(item
);
913 else // select == m_defaultState
915 // get the inclusive range of items between itemFrom and itemTo
916 size_t count
= m_itemsSel
.GetCount(),
917 start
= m_itemsSel
.IndexForInsert(itemFrom
),
918 end
= m_itemsSel
.IndexForInsert(itemTo
);
920 if ( start
== count
|| m_itemsSel
[start
] < itemFrom
)
925 if ( end
== count
|| m_itemsSel
[end
] > itemTo
)
932 // delete all of them (from end to avoid changing indices)
933 for ( int i
= end
; i
>= (int)start
; i
-- )
935 m_itemsSel
.RemoveAt(i
);
940 else // "few" items change state
942 // just add the items to the selection
943 for ( size_t item
= itemFrom
; item
<= itemTo
; item
++ )
945 SelectItem(item
, select
);
950 void wxSelectionStore::OnItemDelete(size_t item
)
952 size_t count
= m_itemsSel
.GetCount(),
953 i
= m_itemsSel
.IndexForInsert(item
);
955 if ( i
< count
&& m_itemsSel
[i
] == item
)
957 // this item itself was in m_itemsSel, remove it from there
958 m_itemsSel
.RemoveAt(i
);
961 // and adjust the index of all which follow it
964 // all following elements must be greater than the one we deleted
965 wxASSERT_MSG( m_itemsSel
[i
] > item
, _T("logic error") );
971 //-----------------------------------------------------------------------------
973 //-----------------------------------------------------------------------------
975 void wxListItemData::Init()
983 wxListItemData::wxListItemData(wxListMainWindow
*owner
)
989 if ( owner
->HasFlag(wxLC_REPORT
) )
999 void wxListItemData::SetItem( const wxListItem
&info
)
1001 if ( info
.m_mask
& wxLIST_MASK_TEXT
)
1002 SetText(info
.m_text
);
1003 if ( info
.m_mask
& wxLIST_MASK_IMAGE
)
1004 m_image
= info
.m_image
;
1005 if ( info
.m_mask
& wxLIST_MASK_DATA
)
1006 m_data
= info
.m_data
;
1008 if ( info
.HasAttributes() )
1011 *m_attr
= *info
.GetAttributes();
1013 m_attr
= new wxListItemAttr(*info
.GetAttributes());
1021 m_rect
->width
= info
.m_width
;
1025 void wxListItemData::SetPosition( int x
, int y
)
1027 wxCHECK_RET( m_rect
, _T("unexpected SetPosition() call") );
1033 void wxListItemData::SetSize( int width
, int height
)
1035 wxCHECK_RET( m_rect
, _T("unexpected SetSize() call") );
1038 m_rect
->width
= width
;
1040 m_rect
->height
= height
;
1043 bool wxListItemData::IsHit( int x
, int y
) const
1045 wxCHECK_MSG( m_rect
, FALSE
, _T("can't be called in this mode") );
1047 return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x
, y
);
1050 int wxListItemData::GetX() const
1052 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1057 int wxListItemData::GetY() const
1059 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1064 int wxListItemData::GetWidth() const
1066 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1068 return m_rect
->width
;
1071 int wxListItemData::GetHeight() const
1073 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1075 return m_rect
->height
;
1078 void wxListItemData::GetItem( wxListItem
&info
) const
1080 info
.m_text
= m_text
;
1081 info
.m_image
= m_image
;
1082 info
.m_data
= m_data
;
1086 if ( m_attr
->HasTextColour() )
1087 info
.SetTextColour(m_attr
->GetTextColour());
1088 if ( m_attr
->HasBackgroundColour() )
1089 info
.SetBackgroundColour(m_attr
->GetBackgroundColour());
1090 if ( m_attr
->HasFont() )
1091 info
.SetFont(m_attr
->GetFont());
1095 //-----------------------------------------------------------------------------
1097 //-----------------------------------------------------------------------------
1099 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData
,wxObject
);
1101 wxListHeaderData::wxListHeaderData()
1112 wxListHeaderData::wxListHeaderData( const wxListItem
&item
)
1120 void wxListHeaderData::SetItem( const wxListItem
&item
)
1122 m_mask
= item
.m_mask
;
1123 m_text
= item
.m_text
;
1124 m_image
= item
.m_image
;
1125 m_format
= item
.m_format
;
1127 SetWidth(item
.m_width
);
1130 void wxListHeaderData::SetPosition( int x
, int y
)
1136 void wxListHeaderData::SetHeight( int h
)
1141 void wxListHeaderData::SetWidth( int w
)
1145 m_width
= WIDTH_COL_DEFAULT
;
1146 if (m_width
< WIDTH_COL_MIN
)
1147 m_width
= WIDTH_COL_MIN
;
1150 void wxListHeaderData::SetFormat( int format
)
1155 bool wxListHeaderData::HasImage() const
1157 return (m_image
!= 0);
1160 bool wxListHeaderData::IsHit( int x
, int y
) const
1162 return ((x
>= m_xpos
) && (x
<= m_xpos
+m_width
) && (y
>= m_ypos
) && (y
<= m_ypos
+m_height
));
1165 void wxListHeaderData::GetItem( wxListItem
&item
)
1167 item
.m_mask
= m_mask
;
1168 item
.m_text
= m_text
;
1169 item
.m_image
= m_image
;
1170 item
.m_format
= m_format
;
1171 item
.m_width
= m_width
;
1174 int wxListHeaderData::GetImage() const
1179 int wxListHeaderData::GetWidth() const
1184 int wxListHeaderData::GetFormat() const
1189 //-----------------------------------------------------------------------------
1191 //-----------------------------------------------------------------------------
1193 inline int wxListLineData::GetMode() const
1195 return m_owner
->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE
;
1198 inline bool wxListLineData::InReportView() const
1200 return m_owner
->HasFlag(wxLC_REPORT
);
1203 inline bool wxListLineData::IsVirtual() const
1205 return m_owner
->IsVirtual();
1208 wxListLineData::wxListLineData( wxListMainWindow
*owner
)
1211 m_items
.DeleteContents( TRUE
);
1213 if ( InReportView() )
1219 m_gi
= new GeometryInfo
;
1222 m_highlighted
= FALSE
;
1224 InitItems( GetMode() == wxLC_REPORT
? m_owner
->GetColumnCount() : 1 );
1227 void wxListLineData::CalculateSize( wxDC
*dc
, int spacing
)
1229 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1230 wxCHECK_RET( node
, _T("no subitems at all??") );
1232 wxListItemData
*item
= node
->GetData();
1234 switch ( GetMode() )
1237 case wxLC_SMALL_ICON
:
1239 m_gi
->m_rectAll
.width
= spacing
;
1241 wxString s
= item
->GetText();
1247 m_gi
->m_rectLabel
.width
=
1248 m_gi
->m_rectLabel
.height
= 0;
1252 dc
->GetTextExtent( s
, &lw
, &lh
);
1253 if (lh
< SCROLL_UNIT_Y
)
1258 m_gi
->m_rectAll
.height
= spacing
+ lh
;
1260 m_gi
->m_rectAll
.width
= lw
;
1262 m_gi
->m_rectLabel
.width
= lw
;
1263 m_gi
->m_rectLabel
.height
= lh
;
1266 if (item
->HasImage())
1269 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1270 m_gi
->m_rectIcon
.width
= w
+ 8;
1271 m_gi
->m_rectIcon
.height
= h
+ 8;
1273 if ( m_gi
->m_rectIcon
.width
> m_gi
->m_rectAll
.width
)
1274 m_gi
->m_rectAll
.width
= m_gi
->m_rectIcon
.width
;
1275 if ( m_gi
->m_rectIcon
.height
+ lh
> m_gi
->m_rectAll
.height
- 4 )
1276 m_gi
->m_rectAll
.height
= m_gi
->m_rectIcon
.height
+ lh
+ 4;
1279 if ( item
->HasText() )
1281 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectLabel
.width
;
1282 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectLabel
.height
;
1284 else // no text, highlight the icon
1286 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectIcon
.width
;
1287 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectIcon
.height
;
1294 wxString s
= item
->GetTextForMeasuring();
1297 dc
->GetTextExtent( s
, &lw
, &lh
);
1298 if (lh
< SCROLL_UNIT_Y
)
1303 m_gi
->m_rectLabel
.width
= lw
;
1304 m_gi
->m_rectLabel
.height
= lh
;
1306 m_gi
->m_rectAll
.width
= lw
;
1307 m_gi
->m_rectAll
.height
= lh
;
1309 if (item
->HasImage())
1312 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1313 m_gi
->m_rectIcon
.width
= w
;
1314 m_gi
->m_rectIcon
.height
= h
;
1316 m_gi
->m_rectAll
.width
+= 4 + w
;
1317 if (h
> m_gi
->m_rectAll
.height
)
1318 m_gi
->m_rectAll
.height
= h
;
1321 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectAll
.width
;
1322 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectAll
.height
;
1327 wxFAIL_MSG( _T("unexpected call to SetSize") );
1331 wxFAIL_MSG( _T("unknown mode") );
1335 void wxListLineData::SetPosition( int x
, int y
,
1339 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1340 wxCHECK_RET( node
, _T("no subitems at all??") );
1342 wxListItemData
*item
= node
->GetData();
1344 switch ( GetMode() )
1347 case wxLC_SMALL_ICON
:
1348 m_gi
->m_rectAll
.x
= x
;
1349 m_gi
->m_rectAll
.y
= y
;
1351 if ( item
->HasImage() )
1353 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 4
1354 + (spacing
- m_gi
->m_rectIcon
.width
)/2;
1355 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 4;
1358 if ( item
->HasText() )
1360 if (m_gi
->m_rectAll
.width
> spacing
)
1361 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1363 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2 + (spacing
/2) - (m_gi
->m_rectLabel
.width
/2);
1364 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ m_gi
->m_rectAll
.height
+ 2 - m_gi
->m_rectLabel
.height
;
1365 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectLabel
.x
- 2;
1366 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectLabel
.y
- 2;
1368 else // no text, highlight the icon
1370 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectIcon
.x
- 4;
1371 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectIcon
.y
- 4;
1376 m_gi
->m_rectAll
.x
= x
;
1377 m_gi
->m_rectAll
.y
= y
;
1379 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectAll
.x
;
1380 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectAll
.y
;
1381 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ 2;
1383 if (item
->HasImage())
1385 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 2;
1386 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 2;
1387 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 6 + m_gi
->m_rectIcon
.width
;
1391 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1396 wxFAIL_MSG( _T("unexpected call to SetPosition") );
1400 wxFAIL_MSG( _T("unknown mode") );
1404 void wxListLineData::InitItems( int num
)
1406 for (int i
= 0; i
< num
; i
++)
1407 m_items
.Append( new wxListItemData(m_owner
) );
1410 void wxListLineData::SetItem( int index
, const wxListItem
&info
)
1412 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1413 wxCHECK_RET( node
, _T("invalid column index in SetItem") );
1415 wxListItemData
*item
= node
->GetData();
1416 item
->SetItem( info
);
1419 void wxListLineData::GetItem( int index
, wxListItem
&info
)
1421 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1424 wxListItemData
*item
= node
->GetData();
1425 item
->GetItem( info
);
1429 wxString
wxListLineData::GetText(int index
) const
1433 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1436 wxListItemData
*item
= node
->GetData();
1437 s
= item
->GetText();
1443 void wxListLineData::SetText( int index
, const wxString s
)
1445 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1448 wxListItemData
*item
= node
->GetData();
1453 void wxListLineData::SetImage( int index
, int image
)
1455 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1456 wxCHECK_RET( node
, _T("invalid column index in SetImage()") );
1458 wxListItemData
*item
= node
->GetData();
1459 item
->SetImage(image
);
1462 int wxListLineData::GetImage( int index
) const
1464 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1465 wxCHECK_MSG( node
, -1, _T("invalid column index in GetImage()") );
1467 wxListItemData
*item
= node
->GetData();
1468 return item
->GetImage();
1471 void wxListLineData::SetAttributes(wxDC
*dc
,
1472 const wxListItemAttr
*attr
,
1473 const wxColour
& colText
,
1477 // don't use foregroud colour for drawing highlighted items - this might
1478 // make them completely invisible (and there is no way to do bit
1479 // arithmetics on wxColour, unfortunately)
1480 if ( !highlight
&& attr
&& attr
->HasTextColour() )
1482 dc
->SetTextForeground(attr
->GetTextColour());
1486 dc
->SetTextForeground(colText
);
1489 if ( attr
&& attr
->HasFont() )
1491 dc
->SetFont(attr
->GetFont());
1499 void wxListLineData::Draw( wxDC
*dc
)
1501 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1502 wxCHECK_RET( node
, _T("no subitems at all??") );
1504 wxListItemData
*item
= node
->GetData();
1505 if (item
->HasImage())
1507 wxRect rectIcon
= m_gi
->m_rectIcon
;
1508 m_owner
->DrawImage( item
->GetImage(), dc
,
1509 rectIcon
.x
, rectIcon
.y
);
1512 if (item
->HasText())
1514 wxRect rectLabel
= m_gi
->m_rectLabel
;
1515 dc
->DrawText( item
->GetText(), rectLabel
.x
, rectLabel
.y
);
1519 void wxListLineData::DrawInReportMode( wxDC
*dc
,
1521 const wxRect
& rectHL
,
1525 //m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
1527 if ( !m_owner
->IsExposed( rect
) )
1530 // use our own flag if we maintain it
1532 highlighted
= m_highlighted
;
1534 // default foreground colour
1535 wxWindow
*listctrl
= m_owner
->GetParent();
1539 colText
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT
);
1543 colText
= listctrl
->GetForegroundColour();
1547 wxFont font
= listctrl
->GetFont();
1549 // VZ: currently we set the colours/fonts only once, but like this (i.e.
1550 // using SetAttributes() inside the loop), it will be trivial to
1551 // customize the subitems (in report mode) too.
1552 wxListItemData
*item
= m_items
.GetFirst()->GetData();
1553 wxListItemAttr
*attr
= item
->GetAttributes();
1554 SetAttributes(dc
, attr
, colText
, font
, highlighted
);
1556 bool hasBgCol
= attr
&& attr
->HasBackgroundColour();
1557 if ( highlighted
|| hasBgCol
)
1561 dc
->SetBrush( *m_owner
->m_highlightBrush
);
1566 dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
));
1568 dc
->SetBrush( * wxWHITE_BRUSH
);
1571 dc
->SetPen( * wxTRANSPARENT_PEN
);
1572 dc
->DrawRectangle( rectHL
);
1575 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1576 wxCHECK_RET( node
, _T("no subitems at all??") );
1579 int x
= rect
.x
+ HEADER_OFFSET_X
;
1581 rect
.y
+= (LINE_SPACING
+ EXTRA_HEIGHT
) / 2;
1585 wxListItemData
*item
= node
->GetData();
1589 if ( item
->HasImage() )
1592 m_owner
->DrawImage( item
->GetImage(), dc
, x
, rect
.y
);
1593 m_owner
->GetImageSize( item
->GetImage(), ix
, iy
);
1594 x
+= ix
+ 5; // FIXME: what is "5"?
1597 int width
= m_owner
->GetColumnWidth(col
++);
1599 dc
->SetClippingRegion(x
, rect
.y
, width
, rect
.height
);
1601 if ( item
->HasText() )
1603 dc
->DrawText( item
->GetText(), x
, rect
.y
);
1606 dc
->DestroyClippingRegion();
1610 node
= node
->GetNext();
1614 bool wxListLineData::Highlight( bool on
)
1616 wxCHECK_MSG( !m_owner
->IsVirtual(), FALSE
, _T("unexpected call to Highlight") );
1618 if ( on
== m_highlighted
)
1626 void wxListLineData::ReverseHighlight( void )
1628 Highlight(!IsHighlighted());
1631 //-----------------------------------------------------------------------------
1632 // wxListHeaderWindow
1633 //-----------------------------------------------------------------------------
1635 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
);
1637 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
)
1638 EVT_PAINT (wxListHeaderWindow::OnPaint
)
1639 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse
)
1640 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus
)
1643 wxListHeaderWindow::wxListHeaderWindow( void )
1645 m_owner
= (wxListMainWindow
*) NULL
;
1646 m_currentCursor
= (wxCursor
*) NULL
;
1647 m_resizeCursor
= (wxCursor
*) NULL
;
1648 m_isDragging
= FALSE
;
1651 wxListHeaderWindow::wxListHeaderWindow( wxWindow
*win
, wxWindowID id
, wxListMainWindow
*owner
,
1652 const wxPoint
&pos
, const wxSize
&size
,
1653 long style
, const wxString
&name
) :
1654 wxWindow( win
, id
, pos
, size
, style
, name
)
1657 // m_currentCursor = wxSTANDARD_CURSOR;
1658 m_currentCursor
= (wxCursor
*) NULL
;
1659 m_resizeCursor
= new wxCursor( wxCURSOR_SIZEWE
);
1660 m_isDragging
= FALSE
;
1663 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
) );
1666 wxListHeaderWindow::~wxListHeaderWindow( void )
1668 delete m_resizeCursor
;
1671 void wxListHeaderWindow::DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
)
1674 GtkStateType state
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
1675 : GTK_STATE_INSENSITIVE
;
1677 x
= dc
->XLOG2DEV( x
);
1679 gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
,
1680 state
, GTK_SHADOW_OUT
,
1681 (GdkRectangle
*) NULL
, m_wxwindow
, "button",
1682 x
-1, y
-1, w
+2, h
+2);
1683 #elif defined( __WXMAC__ )
1684 const int m_corner
= 1;
1686 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1688 dc
->SetPen( wxPen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
) , 1 , wxSOLID
) );
1689 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1690 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1692 wxPen
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID
);
1695 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1696 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1698 dc
->SetPen( *wxWHITE_PEN
);
1699 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1700 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1701 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1702 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1704 const int m_corner
= 1;
1706 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1708 dc
->SetPen( *wxBLACK_PEN
);
1709 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1710 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1712 wxPen
pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
), 1, wxSOLID
);
1715 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1716 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1718 dc
->SetPen( *wxWHITE_PEN
);
1719 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1720 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1721 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1722 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1726 // shift the DC origin to match the position of the main window horz
1727 // scrollbar: this allows us to always use logical coords
1728 void wxListHeaderWindow::AdjustDC(wxDC
& dc
)
1731 m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL
);
1734 m_owner
->GetViewStart( &x
, NULL
);
1736 // account for the horz scrollbar offset
1737 dc
.SetDeviceOrigin( -x
* xpix
, 0 );
1740 void wxListHeaderWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
1743 wxClientDC
dc( this );
1745 wxPaintDC
dc( this );
1753 dc
.SetFont( GetFont() );
1755 // width and height of the entire header window
1757 GetClientSize( &w
, &h
);
1758 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1760 dc
.SetBackgroundMode(wxTRANSPARENT
);
1762 // do *not* use the listctrl colour for headers - one day we will have a
1763 // function to set it separately
1764 //dc.SetTextForeground( *wxBLACK );
1765 dc
.SetTextForeground(wxSystemSettings::
1766 GetSystemColour( wxSYS_COLOUR_WINDOWTEXT
));
1768 int x
= HEADER_OFFSET_X
;
1770 int numColumns
= m_owner
->GetColumnCount();
1772 for (int i
= 0; i
< numColumns
; i
++)
1774 m_owner
->GetColumn( i
, item
);
1775 int wCol
= item
.m_width
;
1776 int cw
= wCol
- 2; // the width of the rect to draw
1778 int xEnd
= x
+ wCol
;
1780 dc
.SetPen( *wxWHITE_PEN
);
1782 DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 );
1783 dc
.SetClippingRegion( x
, HEADER_OFFSET_Y
, cw
-5, h
-4 );
1784 dc
.DrawText( item
.GetText(), x
+ EXTRA_WIDTH
, HEADER_OFFSET_Y
+ EXTRA_HEIGHT
);
1785 dc
.DestroyClippingRegion();
1794 void wxListHeaderWindow::DrawCurrent()
1796 int x1
= m_currentX
;
1798 ClientToScreen( &x1
, &y1
);
1800 int x2
= m_currentX
-1;
1802 m_owner
->GetClientSize( NULL
, &y2
);
1803 m_owner
->ClientToScreen( &x2
, &y2
);
1806 dc
.SetLogicalFunction( wxINVERT
);
1807 dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID
) );
1808 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1812 dc
.DrawLine( x1
, y1
, x2
, y2
);
1814 dc
.SetLogicalFunction( wxCOPY
);
1816 dc
.SetPen( wxNullPen
);
1817 dc
.SetBrush( wxNullBrush
);
1820 void wxListHeaderWindow::OnMouse( wxMouseEvent
&event
)
1822 // we want to work with logical coords
1824 m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
);
1825 int y
= event
.GetY();
1829 // we don't draw the line beyond our window, but we allow dragging it
1832 GetClientSize( &w
, NULL
);
1833 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1836 // erase the line if it was drawn
1837 if ( m_currentX
< w
)
1840 if (event
.ButtonUp())
1843 m_isDragging
= FALSE
;
1845 m_owner
->SetColumnWidth( m_column
, m_currentX
- m_minX
);
1852 m_currentX
= m_minX
+ 7;
1854 // draw in the new location
1855 if ( m_currentX
< w
)
1859 else // not dragging
1862 bool hit_border
= FALSE
;
1864 // end of the current column
1867 // find the column where this event occured
1868 int countCol
= m_owner
->GetColumnCount();
1869 for (int col
= 0; col
< countCol
; col
++)
1871 xpos
+= m_owner
->GetColumnWidth( col
);
1874 if ( (abs(x
-xpos
) < 3) && (y
< 22) )
1876 // near the column border
1883 // inside the column
1890 if (event
.LeftDown())
1894 m_isDragging
= TRUE
;
1901 wxWindow
*parent
= GetParent();
1902 wxListEvent
le( wxEVT_COMMAND_LIST_COL_CLICK
, parent
->GetId() );
1903 le
.SetEventObject( parent
);
1904 le
.m_col
= m_column
;
1905 parent
->GetEventHandler()->ProcessEvent( le
);
1908 else if (event
.Moving())
1913 setCursor
= m_currentCursor
== wxSTANDARD_CURSOR
;
1914 m_currentCursor
= m_resizeCursor
;
1918 setCursor
= m_currentCursor
!= wxSTANDARD_CURSOR
;
1919 m_currentCursor
= wxSTANDARD_CURSOR
;
1923 SetCursor(*m_currentCursor
);
1928 void wxListHeaderWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
1930 m_owner
->SetFocus();
1933 //-----------------------------------------------------------------------------
1934 // wxListRenameTimer (internal)
1935 //-----------------------------------------------------------------------------
1937 wxListRenameTimer::wxListRenameTimer( wxListMainWindow
*owner
)
1942 void wxListRenameTimer::Notify()
1944 m_owner
->OnRenameTimer();
1947 //-----------------------------------------------------------------------------
1948 // wxListTextCtrl (internal)
1949 //-----------------------------------------------------------------------------
1951 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl
,wxTextCtrl
);
1953 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
)
1954 EVT_CHAR (wxListTextCtrl::OnChar
)
1955 EVT_KEY_UP (wxListTextCtrl::OnKeyUp
)
1956 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus
)
1959 wxListTextCtrl::wxListTextCtrl( wxWindow
*parent
,
1960 const wxWindowID id
,
1963 wxListMainWindow
*owner
,
1964 const wxString
&value
,
1968 const wxValidator
& validator
,
1969 const wxString
&name
)
1970 : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name
)
1975 (*m_accept
) = FALSE
;
1977 m_startValue
= value
;
1980 void wxListTextCtrl::OnChar( wxKeyEvent
&event
)
1982 if (event
.m_keyCode
== WXK_RETURN
)
1985 (*m_res
) = GetValue();
1987 if (!wxPendingDelete
.Member(this))
1988 wxPendingDelete
.Append(this);
1990 if ((*m_accept
) && ((*m_res
) != m_startValue
))
1991 m_owner
->OnRenameAccept();
1995 if (event
.m_keyCode
== WXK_ESCAPE
)
1997 (*m_accept
) = FALSE
;
2000 if (!wxPendingDelete
.Member(this))
2001 wxPendingDelete
.Append(this);
2009 void wxListTextCtrl::OnKeyUp( wxKeyEvent
&event
)
2011 // auto-grow the textctrl:
2012 wxSize parentSize
= m_owner
->GetSize();
2013 wxPoint myPos
= GetPosition();
2014 wxSize mySize
= GetSize();
2016 GetTextExtent(GetValue() + _T("MM"), &sx
, &sy
); // FIXME: MM??
2017 if (myPos
.x
+ sx
> parentSize
.x
)
2018 sx
= parentSize
.x
- myPos
.x
;
2026 void wxListTextCtrl::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
2028 if (!wxPendingDelete
.Member(this))
2029 wxPendingDelete
.Append(this);
2031 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2032 m_owner
->OnRenameAccept();
2035 //-----------------------------------------------------------------------------
2037 //-----------------------------------------------------------------------------
2039 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
);
2041 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
)
2042 EVT_PAINT (wxListMainWindow::OnPaint
)
2043 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse
)
2044 EVT_CHAR (wxListMainWindow::OnChar
)
2045 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown
)
2046 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus
)
2047 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus
)
2048 EVT_SCROLLWIN (wxListMainWindow::OnScroll
)
2051 void wxListMainWindow::Init()
2053 m_columns
.DeleteContents( TRUE
);
2057 m_lineTo
= (size_t)-1;
2063 m_small_image_list
= (wxImageList
*) NULL
;
2064 m_normal_image_list
= (wxImageList
*) NULL
;
2066 m_small_spacing
= 30;
2067 m_normal_spacing
= 40;
2071 m_isCreated
= FALSE
;
2073 m_lastOnSame
= FALSE
;
2074 m_renameTimer
= new wxListRenameTimer( this );
2075 m_renameAccept
= FALSE
;
2080 m_lineBeforeLastClicked
= (size_t)-1;
2083 void wxListMainWindow::InitScrolling()
2085 if ( HasFlag(wxLC_REPORT
) )
2087 m_xScroll
= SCROLL_UNIT_X
;
2088 m_yScroll
= SCROLL_UNIT_Y
;
2092 m_xScroll
= SCROLL_UNIT_Y
;
2097 wxListMainWindow::wxListMainWindow()
2101 m_highlightBrush
= (wxBrush
*) NULL
;
2107 wxListMainWindow::wxListMainWindow( wxWindow
*parent
,
2112 const wxString
&name
)
2113 : wxScrolledWindow( parent
, id
, pos
, size
,
2114 style
| wxHSCROLL
| wxVSCROLL
, name
)
2118 m_highlightBrush
= new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
), wxSOLID
);
2123 SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 );
2125 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX
) );
2128 wxListMainWindow::~wxListMainWindow()
2132 delete m_highlightBrush
;
2134 delete m_renameTimer
;
2137 void wxListMainWindow::CacheLineData(size_t line
)
2139 wxListCtrl
*listctrl
= GetListCtrl();
2141 wxListLineData
*ld
= GetDummyLine();
2143 size_t countCol
= GetColumnCount();
2144 for ( size_t col
= 0; col
< countCol
; col
++ )
2146 ld
->SetText(col
, listctrl
->OnGetItemText(line
, col
));
2149 ld
->SetImage(listctrl
->OnGetItemImage(line
));
2152 wxListLineData
*wxListMainWindow::GetDummyLine() const
2154 wxASSERT_MSG( !IsEmpty(), _T("invalid line index") );
2156 if ( m_lines
.IsEmpty() )
2158 // normal controls are supposed to have something in m_lines
2159 // already if it's not empty
2160 wxASSERT_MSG( IsVirtual(), _T("logic error") );
2162 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2163 wxListLineData
*line
= new wxListLineData(self
);
2164 self
->m_lines
.Add(line
);
2170 // ----------------------------------------------------------------------------
2171 // line geometry (report mode only)
2172 // ----------------------------------------------------------------------------
2174 wxCoord
wxListMainWindow::GetLineHeight() const
2176 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2178 // we cache the line height as calling GetTextExtent() is slow
2179 if ( !m_lineHeight
)
2181 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2183 wxClientDC
dc( self
);
2184 dc
.SetFont( GetFont() );
2187 dc
.GetTextExtent(_T("H"), NULL
, &y
);
2189 if ( y
< SCROLL_UNIT_Y
)
2193 self
->m_lineHeight
= y
+ LINE_SPACING
;
2196 return m_lineHeight
;
2199 wxCoord
wxListMainWindow::GetLineY(size_t line
) const
2201 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2203 return LINE_SPACING
+ line
*GetLineHeight();
2206 wxRect
wxListMainWindow::GetLineRect(size_t line
) const
2208 if ( !InReportView() )
2209 return GetLine(line
)->m_gi
->m_rectAll
;
2212 rect
.x
= HEADER_OFFSET_X
;
2213 rect
.y
= GetLineY(line
);
2214 rect
.width
= GetHeaderWidth();
2215 rect
.height
= GetLineHeight();
2220 wxRect
wxListMainWindow::GetLineLabelRect(size_t line
) const
2222 if ( !InReportView() )
2223 return GetLine(line
)->m_gi
->m_rectLabel
;
2226 rect
.x
= HEADER_OFFSET_X
;
2227 rect
.y
= GetLineY(line
);
2228 rect
.width
= GetColumnWidth(0);
2229 rect
.height
= GetLineHeight();
2234 wxRect
wxListMainWindow::GetLineIconRect(size_t line
) const
2236 if ( !InReportView() )
2237 return GetLine(line
)->m_gi
->m_rectIcon
;
2239 wxListLineData
*ld
= GetLine(line
);
2240 wxASSERT_MSG( ld
->HasImage(), _T("should have an image") );
2243 rect
.x
= HEADER_OFFSET_X
;
2244 rect
.y
= GetLineY(line
);
2245 GetImageSize(ld
->GetImage(), rect
.width
, rect
.height
);
2250 wxRect
wxListMainWindow::GetLineHighlightRect(size_t line
) const
2252 return InReportView() ? GetLineRect(line
)
2253 : GetLine(line
)->m_gi
->m_rectHighlight
;
2256 long wxListMainWindow::HitTestLine(size_t line
, int x
, int y
) const
2258 wxListLineData
*ld
= GetLine(line
);
2260 if ( ld
->HasImage() && GetLineIconRect(line
).Inside(x
, y
) )
2261 return wxLIST_HITTEST_ONITEMICON
;
2263 if ( ld
->HasText() )
2265 wxRect rect
= InReportView() ? GetLineRect(line
)
2266 : GetLineLabelRect(line
);
2268 if ( rect
.Inside(x
, y
) )
2269 return wxLIST_HITTEST_ONITEMLABEL
;
2275 // ----------------------------------------------------------------------------
2276 // highlight (selection) handling
2277 // ----------------------------------------------------------------------------
2279 bool wxListMainWindow::IsHighlighted(size_t line
) const
2283 return m_selStore
.IsSelected(line
);
2287 wxListLineData
*ld
= GetLine(line
);
2288 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2290 return ld
->IsHighlighted();
2294 void wxListMainWindow::HighlightLines( size_t lineFrom
, size_t lineTo
, bool highlight
)
2298 m_selStore
.SelectRange(lineFrom
, lineTo
, highlight
);
2299 RefreshLines(lineFrom
, lineTo
);
2303 // do it the dumb way
2304 bool needsRefresh
= FALSE
;
2305 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2307 if ( HighlightLine(line
, highlight
) )
2308 needsRefresh
= TRUE
;
2312 RefreshLines(lineFrom
, lineTo
);
2316 bool wxListMainWindow::HighlightLine( size_t line
, bool highlight
)
2322 changed
= m_selStore
.SelectItem(line
, highlight
);
2326 wxListLineData
*ld
= GetLine(line
);
2327 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2329 changed
= ld
->Highlight(highlight
);
2334 SendNotify( line
, highlight
? wxEVT_COMMAND_LIST_ITEM_SELECTED
2335 : wxEVT_COMMAND_LIST_ITEM_DESELECTED
);
2341 void wxListMainWindow::RefreshLine( size_t line
)
2343 wxRect rect
= GetLineRect(line
);
2345 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2346 RefreshRect( rect
);
2349 void wxListMainWindow::RefreshLines( size_t lineFrom
, size_t lineTo
)
2351 // we suppose that they are ordered by caller
2352 wxASSERT_MSG( lineFrom
<= lineTo
, _T("indices in disorder") );
2354 if ( HasFlag(wxLC_REPORT
) )
2356 size_t visibleFrom
, visibleTo
;
2357 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2359 if ( lineFrom
< visibleFrom
)
2360 lineFrom
= visibleFrom
;
2361 if ( lineTo
> visibleTo
)
2366 rect
.y
= GetLineY(lineFrom
);
2367 rect
.width
= GetClientSize().x
;
2368 rect
.height
= GetLineY(lineTo
) - rect
.y
;
2370 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2371 RefreshRect( rect
);
2375 // TODO: this should be optimized...
2376 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2383 void wxListMainWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
2385 // Note: a wxPaintDC must be constructed even if no drawing is
2386 // done (a Windows requirement).
2387 wxPaintDC
dc( this );
2391 // empty control. nothing to draw
2398 CalcScrolledPosition( 0, 0, &dev_x
, &dev_y
);
2402 dc
.SetFont( GetFont() );
2404 if ( HasFlag(wxLC_REPORT
) )
2406 int lineHeight
= GetLineHeight();
2408 size_t visibleFrom
, visibleTo
;
2409 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2410 for ( size_t line
= visibleFrom
; line
<= visibleTo
; line
++ )
2412 GetLine(line
)->DrawInReportMode( &dc
,
2414 GetLineHighlightRect(line
),
2415 IsHighlighted(line
) );
2418 if ( HasFlag(wxLC_HRULES
) )
2420 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2421 wxSize clientSize
= GetClientSize();
2423 for ( size_t i
= visibleFrom
; i
<= visibleTo
; i
++ )
2426 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2427 dc
.DrawLine(0 - dev_x
, i
*lineHeight
,
2428 clientSize
.x
- dev_x
, i
*lineHeight
);
2431 // Draw last horizontal rule
2432 if ( visibleTo
> visibleFrom
)
2435 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2436 dc
.DrawLine(0 - dev_x
, m_lineTo
*lineHeight
,
2437 clientSize
.x
- dev_x
, m_lineTo
*lineHeight
);
2441 // Draw vertical rules if required
2442 if ( HasFlag(wxLC_VRULES
) && !IsEmpty() )
2444 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2447 wxRect firstItemRect
;
2448 wxRect lastItemRect
;
2449 GetItemRect(0, firstItemRect
);
2450 GetItemRect(GetItemCount() - 1, lastItemRect
);
2451 int x
= firstItemRect
.GetX();
2453 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
2454 for (col
= 0; col
< GetColumnCount(); col
++)
2456 int colWidth
= GetColumnWidth(col
);
2458 dc
.DrawLine(x
- dev_x
, firstItemRect
.GetY() - 1 - dev_y
,
2459 x
- dev_x
, lastItemRect
.GetBottom() + 1 - dev_y
);
2465 size_t count
= GetItemCount();
2466 for ( size_t i
= 0; i
< count
; i
++ )
2468 GetLine(i
)->Draw( &dc
);
2472 if ( HasCurrent() && m_hasFocus
)
2475 // no rect outline, we already have the background color
2477 dc
.SetPen( *wxBLACK_PEN
);
2478 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2479 dc
.DrawRectangle( GetLineHighlightRect(m_current
) );
2486 void wxListMainWindow::HighlightAll( bool on
)
2488 if ( IsSingleSel() )
2490 wxASSERT_MSG( !on
, _T("can't do this in a single sel control") );
2492 // we just have one item to turn off
2493 if ( HasCurrent() && IsHighlighted(m_current
) )
2495 HighlightLine(m_current
, FALSE
);
2496 RefreshLine(m_current
);
2501 HighlightLines(0, GetItemCount() - 1, on
);
2505 void wxListMainWindow::SendNotify( size_t line
,
2506 wxEventType command
,
2509 wxListEvent
le( command
, GetParent()->GetId() );
2510 le
.SetEventObject( GetParent() );
2511 le
.m_itemIndex
= line
;
2513 // set only for events which have position
2514 if ( point
!= wxDefaultPosition
)
2515 le
.m_pointDrag
= point
;
2517 GetLine(line
)->GetItem( 0, le
.m_item
);
2518 GetParent()->GetEventHandler()->ProcessEvent( le
);
2521 void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line
) )
2523 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
2526 void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line
) )
2528 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
2531 void wxListMainWindow::EditLabel( long item
)
2533 wxCHECK_RET( (item
>= 0) && ((size_t)item
< GetItemCount()),
2534 wxT("wrong index in wxListCtrl::EditLabel()") );
2536 m_currentEdit
= (size_t)item
;
2538 wxListEvent
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() );
2539 le
.SetEventObject( GetParent() );
2540 le
.m_itemIndex
= item
;
2541 wxListLineData
*data
= GetLine(m_currentEdit
);
2542 wxCHECK_RET( data
, _T("invalid index in EditLabel()") );
2543 data
->GetItem( 0, le
.m_item
);
2544 GetParent()->GetEventHandler()->ProcessEvent( le
);
2546 if (!le
.IsAllowed())
2549 // We have to call this here because the label in question might just have
2550 // been added and no screen update taken place.
2554 wxClientDC
dc(this);
2557 wxString s
= data
->GetText(0);
2558 wxRect rectLabel
= GetLineLabelRect(m_currentEdit
);
2560 rectLabel
.x
= dc
.LogicalToDeviceX( rectLabel
.x
);
2561 rectLabel
.y
= dc
.LogicalToDeviceY( rectLabel
.y
);
2563 wxListTextCtrl
*text
= new wxListTextCtrl
2570 wxPoint(rectLabel
.x
-4,rectLabel
.y
-4),
2571 wxSize(rectLabel
.width
+11,rectLabel
.height
+8)
2576 void wxListMainWindow::OnRenameTimer()
2578 wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") );
2580 EditLabel( m_current
);
2583 void wxListMainWindow::OnRenameAccept()
2585 wxListEvent
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() );
2586 le
.SetEventObject( GetParent() );
2587 le
.m_itemIndex
= m_currentEdit
;
2589 wxListLineData
*data
= GetLine(m_currentEdit
);
2590 wxCHECK_RET( data
, _T("invalid index in OnRenameAccept()") );
2592 data
->GetItem( 0, le
.m_item
);
2593 le
.m_item
.m_text
= m_renameRes
;
2594 GetParent()->GetEventHandler()->ProcessEvent( le
);
2596 if (!le
.IsAllowed()) return;
2599 info
.m_mask
= wxLIST_MASK_TEXT
;
2600 info
.m_itemId
= le
.m_itemIndex
;
2601 info
.m_text
= m_renameRes
;
2602 info
.SetTextColour(le
.m_item
.GetTextColour());
2606 void wxListMainWindow::OnMouse( wxMouseEvent
&event
)
2608 event
.SetEventObject( GetParent() );
2609 if ( GetParent()->GetEventHandler()->ProcessEvent( event
) )
2612 if ( !HasCurrent() || IsEmpty() )
2618 if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() ||
2619 event
.ButtonDClick()) )
2622 int x
= event
.GetX();
2623 int y
= event
.GetY();
2624 CalcUnscrolledPosition( x
, y
, &x
, &y
);
2626 /* Did we actually hit an item ? */
2629 size_t count
= GetItemCount(),
2632 if ( HasFlag(wxLC_REPORT
) )
2634 current
= y
/ GetLineHeight();
2635 hitResult
= HitTestLine(current
, x
, y
);
2639 // TODO: optimize it too! this is less simple than for report view but
2640 // enumerating all items is still not a way to do it!!
2641 for ( current
= 0; current
< count
&& !hitResult
; current
++ )
2643 hitResult
= HitTestLine(current
, x
, y
);
2647 if (event
.Dragging())
2649 if (m_dragCount
== 0)
2650 m_dragStart
= wxPoint(x
,y
);
2654 if (m_dragCount
!= 3)
2657 int command
= event
.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2658 : wxEVT_COMMAND_LIST_BEGIN_DRAG
;
2660 wxListEvent
le( command
, GetParent()->GetId() );
2661 le
.SetEventObject( GetParent() );
2662 le
.m_pointDrag
= m_dragStart
;
2663 GetParent()->GetEventHandler()->ProcessEvent( le
);
2674 // outside of any item
2678 bool forceClick
= FALSE
;
2679 if (event
.ButtonDClick())
2681 m_renameTimer
->Stop();
2682 m_lastOnSame
= FALSE
;
2684 if ( current
== m_lineBeforeLastClicked
)
2686 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
);
2692 // the first click was on another item, so don't interpret this as
2693 // a double click, but as a simple click instead
2698 if (event
.LeftUp() && m_lastOnSame
)
2700 if ((current
== m_current
) &&
2701 (hitResult
== wxLIST_HITTEST_ONITEMLABEL
) &&
2702 HasFlag(wxLC_EDIT_LABELS
) )
2704 m_renameTimer
->Start( 100, TRUE
);
2706 m_lastOnSame
= FALSE
;
2708 else if (event
.RightDown())
2710 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
,
2711 event
.GetPosition() );
2713 else if (event
.MiddleDown())
2715 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
);
2717 else if ( event
.LeftDown() || forceClick
)
2719 m_lineBeforeLastClicked
= m_lineLastClicked
;
2720 m_lineLastClicked
= current
;
2722 size_t oldCurrent
= m_current
;
2724 if ( IsSingleSel() || !(event
.ControlDown() || event
.ShiftDown()) )
2726 HighlightAll( FALSE
);
2727 m_current
= current
;
2729 ReverseHighlight(m_current
);
2731 else // multi sel & either ctrl or shift is down
2733 if (event
.ControlDown())
2735 m_current
= current
;
2737 ReverseHighlight(m_current
);
2739 else if (event
.ShiftDown())
2741 m_current
= current
;
2743 size_t lineFrom
= oldCurrent
,
2746 if ( lineTo
< lineFrom
)
2749 lineFrom
= m_current
;
2752 HighlightLines(lineFrom
, lineTo
);
2754 else // !ctrl, !shift
2756 // test in the enclosing if should make it impossible
2757 wxFAIL_MSG( _T("how did we get here?") );
2761 if (m_current
!= oldCurrent
)
2763 RefreshLine( oldCurrent
);
2764 OnUnfocusLine( oldCurrent
);
2765 OnFocusLine( m_current
);
2768 // forceClick is only set if the previous click was on another item
2769 m_lastOnSame
= !forceClick
&& (m_current
== oldCurrent
);
2773 void wxListMainWindow::MoveToFocus()
2775 if ( !HasCurrent() )
2778 wxRect rect
= GetLineRect(m_current
);
2780 int client_w
, client_h
;
2781 GetClientSize( &client_w
, &client_h
);
2783 int view_x
= m_xScroll
*GetScrollPos( wxHORIZONTAL
);
2784 int view_y
= m_yScroll
*GetScrollPos( wxVERTICAL
);
2786 if ( HasFlag(wxLC_REPORT
) )
2788 // the next we need the range of lines shown it might be different, so
2790 ResetVisibleLinesRange();
2792 if (rect
.y
< view_y
)
2793 Scroll( -1, rect
.y
/m_yScroll
);
2794 if (rect
.y
+rect
.height
+5 > view_y
+client_h
)
2795 Scroll( -1, (rect
.y
+rect
.height
-client_h
+SCROLL_UNIT_Y
)/m_yScroll
);
2799 if (rect
.x
-view_x
< 5)
2800 Scroll( (rect
.x
-5)/m_xScroll
, -1 );
2801 if (rect
.x
+rect
.width
-5 > view_x
+client_w
)
2802 Scroll( (rect
.x
+rect
.width
-client_w
+SCROLL_UNIT_X
)/m_xScroll
, -1 );
2806 // ----------------------------------------------------------------------------
2807 // keyboard handling
2808 // ----------------------------------------------------------------------------
2810 void wxListMainWindow::OnArrowChar(size_t newCurrent
, const wxKeyEvent
& event
)
2812 wxCHECK_RET( newCurrent
< (size_t)GetItemCount(),
2813 _T("invalid item index in OnArrowChar()") );
2815 size_t oldCurrent
= m_current
;
2817 // in single selection we just ignore Shift as we can't select several
2819 if ( event
.ShiftDown() && !IsSingleSel() )
2821 m_current
= newCurrent
;
2823 // select all the items between the old and the new one
2824 if ( oldCurrent
> newCurrent
)
2826 newCurrent
= oldCurrent
;
2827 oldCurrent
= m_current
;
2830 HighlightLines(oldCurrent
, newCurrent
);
2834 // all previously selected items are unselected unless ctrl is held
2835 if ( !event
.ControlDown() )
2836 HighlightAll(FALSE
);
2838 m_current
= newCurrent
;
2840 HighlightLine( oldCurrent
, FALSE
);
2841 RefreshLine( oldCurrent
);
2843 if ( !event
.ControlDown() )
2845 HighlightLine( m_current
, TRUE
);
2849 OnUnfocusLine( oldCurrent
);
2850 OnFocusLine( m_current
);
2851 RefreshLine( m_current
);
2856 void wxListMainWindow::OnKeyDown( wxKeyEvent
&event
)
2858 wxWindow
*parent
= GetParent();
2860 /* we propagate the key event up */
2861 wxKeyEvent
ke( wxEVT_KEY_DOWN
);
2862 ke
.m_shiftDown
= event
.m_shiftDown
;
2863 ke
.m_controlDown
= event
.m_controlDown
;
2864 ke
.m_altDown
= event
.m_altDown
;
2865 ke
.m_metaDown
= event
.m_metaDown
;
2866 ke
.m_keyCode
= event
.m_keyCode
;
2869 ke
.SetEventObject( parent
);
2870 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2875 void wxListMainWindow::OnChar( wxKeyEvent
&event
)
2877 wxWindow
*parent
= GetParent();
2879 /* we send a list_key event up */
2882 wxListEvent
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() );
2883 le
.m_itemIndex
= m_current
;
2884 GetLine(m_current
)->GetItem( 0, le
.m_item
);
2885 le
.m_code
= (int)event
.KeyCode();
2886 le
.SetEventObject( parent
);
2887 parent
->GetEventHandler()->ProcessEvent( le
);
2890 /* we propagate the char event up */
2891 wxKeyEvent
ke( wxEVT_CHAR
);
2892 ke
.m_shiftDown
= event
.m_shiftDown
;
2893 ke
.m_controlDown
= event
.m_controlDown
;
2894 ke
.m_altDown
= event
.m_altDown
;
2895 ke
.m_metaDown
= event
.m_metaDown
;
2896 ke
.m_keyCode
= event
.m_keyCode
;
2899 ke
.SetEventObject( parent
);
2900 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2902 if (event
.KeyCode() == WXK_TAB
)
2904 wxNavigationKeyEvent nevent
;
2905 nevent
.SetWindowChange( event
.ControlDown() );
2906 nevent
.SetDirection( !event
.ShiftDown() );
2907 nevent
.SetEventObject( GetParent()->GetParent() );
2908 nevent
.SetCurrentFocus( m_parent
);
2909 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent
)) return;
2912 /* no item -> nothing to do */
2919 switch (event
.KeyCode())
2922 if ( m_current
> 0 )
2923 OnArrowChar( m_current
- 1, event
);
2927 if ( m_current
< (size_t)GetItemCount() - 1 )
2928 OnArrowChar( m_current
+ 1, event
);
2933 OnArrowChar( GetItemCount() - 1, event
);
2938 OnArrowChar( 0, event
);
2944 if ( HasFlag(wxLC_REPORT
) )
2946 steps
= m_linesPerPage
- 1;
2950 steps
= m_current
% m_linesPerPage
;
2953 int index
= m_current
- steps
;
2957 OnArrowChar( index
, event
);
2964 if ( HasFlag(wxLC_REPORT
) )
2966 steps
= m_linesPerPage
- 1;
2970 steps
= m_linesPerPage
- (m_current
% m_linesPerPage
) - 1;
2973 size_t index
= m_current
+ steps
;
2974 size_t count
= GetItemCount();
2975 if ( index
>= count
)
2978 OnArrowChar( index
, event
);
2983 if ( !HasFlag(wxLC_REPORT
) )
2985 int index
= m_current
- m_linesPerPage
;
2989 OnArrowChar( index
, event
);
2994 if ( !HasFlag(wxLC_REPORT
) )
2996 size_t index
= m_current
+ m_linesPerPage
;
2998 size_t count
= GetItemCount();
2999 if ( index
>= count
)
3002 OnArrowChar( index
, event
);
3007 if ( IsSingleSel() )
3009 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3010 GetParent()->GetId() );
3011 le
.SetEventObject( GetParent() );
3012 le
.m_itemIndex
= m_current
;
3013 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3014 GetParent()->GetEventHandler()->ProcessEvent( le
);
3018 ReverseHighlight(m_current
);
3025 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3026 GetParent()->GetId() );
3027 le
.SetEventObject( GetParent() );
3028 le
.m_itemIndex
= m_current
;
3029 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3030 GetParent()->GetEventHandler()->ProcessEvent( le
);
3039 // ----------------------------------------------------------------------------
3041 // ----------------------------------------------------------------------------
3044 extern wxWindow
*g_focusWindow
;
3047 void wxListMainWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
3052 RefreshLine( m_current
);
3058 g_focusWindow
= GetParent();
3061 wxFocusEvent
event( wxEVT_SET_FOCUS
, GetParent()->GetId() );
3062 event
.SetEventObject( GetParent() );
3063 GetParent()->GetEventHandler()->ProcessEvent( event
);
3066 void wxListMainWindow::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
3071 RefreshLine( m_current
);
3074 void wxListMainWindow::DrawImage( int index
, wxDC
*dc
, int x
, int y
)
3076 if ( HasFlag(wxLC_ICON
) && (m_normal_image_list
))
3078 m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3080 else if ( HasFlag(wxLC_SMALL_ICON
) && (m_small_image_list
))
3082 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3084 else if ( HasFlag(wxLC_LIST
) && (m_small_image_list
))
3086 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3088 else if ( HasFlag(wxLC_REPORT
) && (m_small_image_list
))
3090 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3094 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height
) const
3096 if ( HasFlag(wxLC_ICON
) && m_normal_image_list
)
3098 m_normal_image_list
->GetSize( index
, width
, height
);
3100 else if ( HasFlag(wxLC_SMALL_ICON
) && m_small_image_list
)
3102 m_small_image_list
->GetSize( index
, width
, height
);
3104 else if ( HasFlag(wxLC_LIST
) && m_small_image_list
)
3106 m_small_image_list
->GetSize( index
, width
, height
);
3108 else if ( HasFlag(wxLC_REPORT
) && m_small_image_list
)
3110 m_small_image_list
->GetSize( index
, width
, height
);
3119 int wxListMainWindow::GetTextLength( const wxString
&s
) const
3121 wxClientDC
dc( wxConstCast(this, wxListMainWindow
) );
3122 dc
.SetFont( GetFont() );
3125 dc
.GetTextExtent( s
, &lw
, NULL
);
3127 return lw
+ AUTOSIZE_COL_MARGIN
;
3130 void wxListMainWindow::SetImageList( wxImageList
*imageList
, int which
)
3134 // calc the spacing from the icon size
3137 if ((imageList
) && (imageList
->GetImageCount()) )
3139 imageList
->GetSize(0, width
, height
);
3142 if (which
== wxIMAGE_LIST_NORMAL
)
3144 m_normal_image_list
= imageList
;
3145 m_normal_spacing
= width
+ 8;
3148 if (which
== wxIMAGE_LIST_SMALL
)
3150 m_small_image_list
= imageList
;
3151 m_small_spacing
= width
+ 14;
3155 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall
)
3160 m_small_spacing
= spacing
;
3164 m_normal_spacing
= spacing
;
3168 int wxListMainWindow::GetItemSpacing( bool isSmall
)
3170 return isSmall
? m_small_spacing
: m_normal_spacing
;
3173 // ----------------------------------------------------------------------------
3175 // ----------------------------------------------------------------------------
3177 void wxListMainWindow::SetColumn( int col
, wxListItem
&item
)
3179 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3181 wxCHECK_RET( node
, _T("invalid column index in SetColumn") );
3183 if ( item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3184 item
.m_width
= GetTextLength( item
.m_text
);
3186 wxListHeaderData
*column
= node
->GetData();
3187 column
->SetItem( item
);
3189 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3191 headerWin
->m_dirty
= TRUE
;
3195 // invalidate it as it has to be recalculated
3199 void wxListMainWindow::SetColumnWidth( int col
, int width
)
3201 wxCHECK_RET( col
>= 0 && col
< GetColumnCount(),
3202 _T("invalid column index") );
3204 wxCHECK_RET( HasFlag(wxLC_REPORT
),
3205 _T("SetColumnWidth() can only be called in report mode.") );
3209 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3210 wxCHECK_RET( node
, _T("no column?") );
3212 wxListHeaderData
*column
= node
->GetData();
3214 size_t count
= GetItemCount();
3216 if (width
== wxLIST_AUTOSIZE_USEHEADER
)
3218 width
= GetTextLength(column
->GetText());
3220 else if ( width
== wxLIST_AUTOSIZE
)
3224 // TODO: determine the max width somehow...
3225 width
= WIDTH_COL_DEFAULT
;
3229 wxClientDC
dc(this);
3230 dc
.SetFont( GetFont() );
3232 int max
= AUTOSIZE_COL_MARGIN
;
3234 for ( size_t i
= 0; i
< count
; i
++ )
3236 wxListLineData
*line
= GetLine(i
);
3237 wxListItemDataList::Node
*n
= line
->m_items
.Item( col
);
3239 wxCHECK_RET( n
, _T("no subitem?") );
3241 wxListItemData
*item
= n
->GetData();
3244 if (item
->HasImage())
3247 GetImageSize( item
->GetImage(), ix
, iy
);
3251 if (item
->HasText())
3254 dc
.GetTextExtent( item
->GetText(), &w
, NULL
);
3262 width
= max
+ AUTOSIZE_COL_MARGIN
;
3266 column
->SetWidth( width
);
3268 // invalidate it as it has to be recalculated
3272 int wxListMainWindow::GetHeaderWidth() const
3274 if ( !m_headerWidth
)
3276 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
3278 size_t count
= GetColumnCount();
3279 for ( size_t col
= 0; col
< count
; col
++ )
3281 self
->m_headerWidth
+= GetColumnWidth(col
);
3285 return m_headerWidth
;
3288 void wxListMainWindow::GetColumn( int col
, wxListItem
&item
) const
3290 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3291 wxCHECK_RET( node
, _T("invalid column index in GetColumn") );
3293 wxListHeaderData
*column
= node
->GetData();
3294 column
->GetItem( item
);
3297 int wxListMainWindow::GetColumnWidth( int col
) const
3299 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3300 wxCHECK_MSG( node
, 0, _T("invalid column index") );
3302 wxListHeaderData
*column
= node
->GetData();
3303 return column
->GetWidth();
3306 // ----------------------------------------------------------------------------
3308 // ----------------------------------------------------------------------------
3310 void wxListMainWindow::SetItem( wxListItem
&item
)
3312 long id
= item
.m_itemId
;
3313 wxCHECK_RET( id
>= 0 && (size_t)id
< GetItemCount(),
3314 _T("invalid item index in SetItem") );
3318 // just refresh the line to show the new value of the text/image
3319 RefreshLine((size_t)id
);
3325 wxListLineData
*line
= GetLine((size_t)id
);
3326 if ( HasFlag(wxLC_REPORT
) )
3327 item
.m_width
= GetColumnWidth( item
.m_col
);
3328 line
->SetItem( item
.m_col
, item
);
3332 void wxListMainWindow::SetItemState( long litem
, long state
, long stateMask
)
3334 wxCHECK_RET( litem
>= 0 && (size_t)litem
< GetItemCount(),
3335 _T("invalid list ctrl item index in SetItem") );
3337 size_t oldCurrent
= m_current
;
3338 size_t item
= (size_t)litem
; // sdafe because of the check above
3340 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3342 if ( state
& wxLIST_STATE_FOCUSED
)
3344 // don't do anything if this item is already focused
3345 if ( item
!= m_current
)
3347 OnUnfocusLine( m_current
);
3349 OnFocusLine( m_current
);
3351 if ( IsSingleSel() && (oldCurrent
!= (size_t)-1) )
3353 HighlightLine(oldCurrent
, FALSE
);
3354 RefreshLine(oldCurrent
);
3357 RefreshLine( m_current
);
3362 // don't do anything if this item is not focused
3363 if ( item
== m_current
)
3365 OnUnfocusLine( m_current
);
3366 m_current
= (size_t)-1;
3371 if ( stateMask
& wxLIST_STATE_SELECTED
)
3373 bool on
= (state
& wxLIST_STATE_SELECTED
) != 0;
3375 if ( IsSingleSel() )
3379 // selecting the item also makes it the focused one in the
3381 if ( m_current
!= item
)
3383 OnUnfocusLine( m_current
);
3385 OnFocusLine( m_current
);
3387 if ( oldCurrent
!= (size_t)-1 )
3389 HighlightLine( oldCurrent
, FALSE
);
3390 RefreshLine( oldCurrent
);
3396 // only the current item may be selected anyhow
3397 if ( item
!= m_current
)
3402 if ( HighlightLine(item
, on
) )
3409 int wxListMainWindow::GetItemState( long item
, long stateMask
)
3411 wxCHECK_MSG( item
>= 0 && (size_t)item
< GetItemCount(), 0,
3412 _T("invalid list ctrl item index in GetItemState()") );
3414 int ret
= wxLIST_STATE_DONTCARE
;
3416 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3418 if ( (size_t)item
== m_current
)
3419 ret
|= wxLIST_STATE_FOCUSED
;
3422 if ( stateMask
& wxLIST_STATE_SELECTED
)
3424 if ( IsHighlighted(item
) )
3425 ret
|= wxLIST_STATE_SELECTED
;
3431 void wxListMainWindow::GetItem( wxListItem
&item
)
3433 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
< GetItemCount(),
3434 _T("invalid item index in GetItem") );
3436 wxListLineData
*line
= GetLine((size_t)item
.m_itemId
);
3437 line
->GetItem( item
.m_col
, item
);
3440 // ----------------------------------------------------------------------------
3442 // ----------------------------------------------------------------------------
3444 size_t wxListMainWindow::GetItemCount() const
3446 return IsVirtual() ? m_countVirt
: m_lines
.GetCount();
3449 void wxListMainWindow::SetItemCount(long count
)
3451 m_selStore
.SetItemCount(count
);
3452 m_countVirt
= count
;
3457 int wxListMainWindow::GetSelectedItemCount()
3459 // deal with the quick case first
3460 if ( IsSingleSel() )
3462 return HasCurrent() ? IsHighlighted(m_current
) : FALSE
;
3465 // virtual controls remmebers all its selections itself
3467 return m_selStore
.GetSelectedCount();
3469 // TODO: we probably should maintain the number of items selected even for
3470 // non virtual controls as enumerating all lines is really slow...
3471 size_t countSel
= 0;
3472 size_t count
= GetItemCount();
3473 for ( size_t line
= 0; line
< count
; line
++ )
3475 if ( GetLine(line
)->IsHighlighted() )
3482 // ----------------------------------------------------------------------------
3483 // item position/size
3484 // ----------------------------------------------------------------------------
3486 void wxListMainWindow::GetItemRect( long index
, wxRect
&rect
)
3488 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3489 _T("invalid index in GetItemRect") );
3491 rect
= GetLineRect((size_t)index
);
3493 CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
3496 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
)
3499 GetItemRect(item
, rect
);
3507 // ----------------------------------------------------------------------------
3508 // geometry calculation
3509 // ----------------------------------------------------------------------------
3511 void wxListMainWindow::RecalculatePositions()
3516 wxClientDC
dc( this );
3517 dc
.SetFont( GetFont() );
3520 if ( HasFlag(wxLC_ICON
) )
3521 iconSpacing
= m_normal_spacing
;
3522 else if ( HasFlag(wxLC_SMALL_ICON
) )
3523 iconSpacing
= m_small_spacing
;
3529 GetClientSize( &clientWidth
, &clientHeight
);
3531 if ( HasFlag(wxLC_REPORT
) )
3533 // all lines have the same height
3534 int lineHeight
= GetLineHeight();
3536 // scroll one line per step
3537 m_yScroll
= lineHeight
;
3539 size_t lineCount
= GetItemCount();
3540 int entireHeight
= lineCount
*lineHeight
+ LINE_SPACING
;
3542 m_linesPerPage
= clientHeight
/ lineHeight
;
3544 ResetVisibleLinesRange();
3546 SetScrollbars( m_xScroll
, m_yScroll
,
3547 (GetHeaderWidth() + m_xScroll
- 1)/m_xScroll
,
3548 (entireHeight
+ m_yScroll
- 1)/m_yScroll
,
3549 GetScrollPos(wxHORIZONTAL
),
3550 GetScrollPos(wxVERTICAL
),
3553 // FIXME: wxGTK::wxScrolledWindow doesn't have SetTargetRect()
3554 #if !defined(__WXGTK__) || defined(__WXUNIVERSAL__)
3555 // we must have an integer number of lines on screen and so we fit
3556 // the real control size to the line height
3559 rect
.y
= LINE_SPACING
;
3560 rect
.width
= clientWidth
;
3561 rect
.height
= ((clientHeight
- LINE_SPACING
) / lineHeight
)*lineHeight
;
3562 SetTargetRect(rect
);
3567 // at first we try without any scrollbar. if the items don't
3568 // fit into the window, we recalculate after subtracting an
3569 // approximated 15 pt for the horizontal scrollbar
3571 clientHeight
-= 4; // sunken frame
3573 int entireWidth
= 0;
3575 for (int tries
= 0; tries
< 2; tries
++)
3582 int currentlyVisibleLines
= 0;
3584 size_t count
= GetItemCount();
3585 for (size_t i
= 0; i
< count
; i
++)
3587 currentlyVisibleLines
++;
3588 wxListLineData
*line
= GetLine(i
);
3589 line
->CalculateSize( &dc
, iconSpacing
);
3590 line
->SetPosition( x
, y
, clientWidth
, iconSpacing
);
3592 wxSize sizeLine
= GetLineSize(i
);
3594 if ( maxWidth
< sizeLine
.x
)
3595 maxWidth
= sizeLine
.x
;
3598 if (currentlyVisibleLines
> m_linesPerPage
)
3599 m_linesPerPage
= currentlyVisibleLines
;
3601 // assume that the size of the next one is the same... (FIXME)
3602 if ( y
+ sizeLine
.y
- 6 >= clientHeight
)
3604 currentlyVisibleLines
= 0;
3607 entireWidth
+= maxWidth
+6;
3610 if ( i
== count
- 1 )
3611 entireWidth
+= maxWidth
;
3612 if ((tries
== 0) && (entireWidth
> clientWidth
))
3614 clientHeight
-= 15; // scrollbar height
3616 currentlyVisibleLines
= 0;
3619 if ( i
== count
- 1 )
3620 tries
= 1; // everything fits, no second try required
3624 int scroll_pos
= GetScrollPos( wxHORIZONTAL
);
3625 SetScrollbars( m_xScroll
, m_yScroll
, (entireWidth
+SCROLL_UNIT_X
) / m_xScroll
, 0, scroll_pos
, 0, TRUE
);
3628 // FIXME: why should we call it from here?
3634 void wxListMainWindow::RefreshAll()
3639 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3642 headerWin
->m_dirty
= FALSE
;
3643 headerWin
->Refresh();
3647 void wxListMainWindow::UpdateCurrent()
3649 if ( !HasCurrent() && !IsEmpty() )
3654 if ( m_current
!= (size_t)-1 )
3656 OnFocusLine( m_current
);
3660 long wxListMainWindow::GetNextItem( long item
,
3661 int WXUNUSED(geometry
),
3665 max
= GetItemCount();
3666 wxCHECK_MSG( (ret
== -1) || (ret
< max
), -1,
3667 _T("invalid listctrl index in GetNextItem()") );
3669 // notice that we start with the next item (or the first one if item == -1)
3670 // and this is intentional to allow writing a simple loop to iterate over
3671 // all selected items
3675 // this is not an error because the index was ok initially, just no
3686 size_t count
= GetItemCount();
3687 for ( size_t line
= (size_t)ret
; line
< count
; line
++ )
3689 if ( (state
& wxLIST_STATE_FOCUSED
) && (line
== m_current
) )
3692 if ( (state
& wxLIST_STATE_SELECTED
) && IsHighlighted(line
) )
3699 // ----------------------------------------------------------------------------
3701 // ----------------------------------------------------------------------------
3703 void wxListMainWindow::DeleteItem( long lindex
)
3705 size_t count
= GetItemCount();
3707 wxCHECK_RET( (lindex
>= 0) && ((size_t)lindex
< count
),
3708 _T("invalid item index in DeleteItem") );
3710 size_t index
= (size_t)lindex
;
3714 // select the next item when the selected one is deleted
3715 if ( m_current
== index
)
3717 // the last valid index after deleting the item will be count-2
3718 if ( m_current
== count
- 1 )
3724 SendNotify( index
, wxEVT_COMMAND_LIST_DELETE_ITEM
);
3728 if ( m_lineTo
== --m_countVirt
)
3733 m_selStore
.OnItemDelete(index
);
3737 m_lines
.RemoveAt( index
);
3740 RefreshLines(index
, GetItemCount() - 1);
3743 void wxListMainWindow::DeleteColumn( int col
)
3745 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3747 wxCHECK_RET( node
, wxT("invalid column index in DeleteColumn()") );
3750 m_columns
.DeleteNode( node
);
3753 void wxListMainWindow::DeleteAllItems()
3757 // nothing to do - in particular, don't send the event
3765 // to make the deletion of all items faster, we don't send the
3766 // notifications for each item deletion in this case but only one event
3767 // for all of them: this is compatible with wxMSW and documented in
3768 // DeleteAllItems() description
3770 wxListEvent
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() );
3771 event
.SetEventObject( GetParent() );
3772 GetParent()->GetEventHandler()->ProcessEvent( event
);
3778 ResetVisibleLinesRange();
3786 void wxListMainWindow::DeleteEverything()
3793 // ----------------------------------------------------------------------------
3794 // scanning for an item
3795 // ----------------------------------------------------------------------------
3797 void wxListMainWindow::EnsureVisible( long index
)
3799 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3800 _T("invalid index in EnsureVisible") );
3802 // We have to call this here because the label in question might just have
3803 // been added and no screen update taken place.
3807 size_t oldCurrent
= m_current
;
3808 m_current
= (size_t)index
;
3810 m_current
= oldCurrent
;
3813 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) )
3820 size_t count
= GetItemCount();
3821 for ( size_t i
= (size_t)pos
; i
< count
; i
++ )
3823 wxListLineData
*line
= GetLine(i
);
3824 if ( line
->GetText(0) == tmp
)
3831 long wxListMainWindow::FindItem(long start
, long data
)
3837 size_t count
= GetItemCount();
3838 for (size_t i
= (size_t)pos
; i
< count
; i
++)
3840 wxListLineData
*line
= GetLine(i
);
3842 line
->GetItem( 0, item
);
3843 if (item
.m_data
== data
)
3850 long wxListMainWindow::HitTest( int x
, int y
, int &flags
)
3852 CalcUnscrolledPosition( x
, y
, &x
, &y
);
3854 if ( HasFlag(wxLC_REPORT
) )
3856 size_t current
= y
/ GetLineHeight();
3857 flags
= HitTestLine(current
, x
, y
);
3863 // TODO: optimize it too! this is less simple than for report view but
3864 // enumerating all items is still not a way to do it!!
3865 size_t count
= GetItemCount();
3866 for ( size_t current
= 0; current
< count
; current
++ )
3868 flags
= HitTestLine(current
, x
, y
);
3877 // ----------------------------------------------------------------------------
3879 // ----------------------------------------------------------------------------
3881 void wxListMainWindow::InsertItem( wxListItem
&item
)
3883 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") );
3885 size_t count
= GetItemCount();
3886 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
<= count
,
3887 _T("invalid item index") );
3889 size_t id
= item
.m_itemId
;
3894 if ( HasFlag(wxLC_REPORT
) )
3896 else if ( HasFlag(wxLC_LIST
) )
3898 else if ( HasFlag(wxLC_ICON
) )
3900 else if ( HasFlag(wxLC_SMALL_ICON
) )
3901 mode
= wxLC_ICON
; // no typo
3904 wxFAIL_MSG( _T("unknown mode") );
3907 wxListLineData
*line
= new wxListLineData(this);
3909 line
->SetItem( 0, item
);
3911 m_lines
.Insert( line
, id
);
3913 RefreshLines(id
, GetItemCount() - 1);
3916 void wxListMainWindow::InsertColumn( long col
, wxListItem
&item
)
3919 if ( HasFlag(wxLC_REPORT
) )
3921 if (item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3922 item
.m_width
= GetTextLength( item
.m_text
);
3923 wxListHeaderData
*column
= new wxListHeaderData( item
);
3924 if ((col
>= 0) && (col
< (int)m_columns
.GetCount()))
3926 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3927 m_columns
.Insert( node
, column
);
3931 m_columns
.Append( column
);
3936 // ----------------------------------------------------------------------------
3938 // ----------------------------------------------------------------------------
3940 wxListCtrlCompare list_ctrl_compare_func_2
;
3941 long list_ctrl_compare_data
;
3943 int LINKAGEMODE
list_ctrl_compare_func_1( wxListLineData
**arg1
, wxListLineData
**arg2
)
3945 wxListLineData
*line1
= *arg1
;
3946 wxListLineData
*line2
= *arg2
;
3948 line1
->GetItem( 0, item
);
3949 long data1
= item
.m_data
;
3950 line2
->GetItem( 0, item
);
3951 long data2
= item
.m_data
;
3952 return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data
);
3955 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data
)
3957 list_ctrl_compare_func_2
= fn
;
3958 list_ctrl_compare_data
= data
;
3959 m_lines
.Sort( list_ctrl_compare_func_1
);
3963 // ----------------------------------------------------------------------------
3965 // ----------------------------------------------------------------------------
3967 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
)
3969 // update our idea of which lines are shown when we redraw the window the
3971 ResetVisibleLinesRange();
3974 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
3975 wxScrolledWindow::OnScroll(event
);
3977 HandleOnScroll( event
);
3980 if ( event
.GetOrientation() == wxHORIZONTAL
&& HasHeader() )
3982 wxListCtrl
* lc
= GetListCtrl();
3983 wxCHECK_RET( lc
, _T("no listctrl window?") );
3985 lc
->m_headerWin
->Refresh() ;
3987 lc
->m_headerWin
->MacUpdateImmediately() ;
3992 int wxListMainWindow::GetCountPerPage() const
3994 if ( !m_linesPerPage
)
3996 wxConstCast(this, wxListMainWindow
)->
3997 m_linesPerPage
= GetClientSize().y
/ GetLineHeight();
4000 return m_linesPerPage
;
4003 void wxListMainWindow::GetVisibleLinesRange(size_t *from
, size_t *to
)
4005 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("this is for report mode only") );
4007 if ( m_lineFrom
== (size_t)-1 )
4009 m_lineFrom
= GetScrollPos(wxVERTICAL
);
4011 size_t count
= GetItemCount();
4013 wxASSERT_MSG( m_lineFrom
< count
, _T("invalid scroll position?") );
4015 m_lineTo
= m_lineFrom
+ m_linesPerPage
- 1;
4016 if ( m_lineTo
>= count
)
4017 m_lineTo
= count
- 1;
4026 // -------------------------------------------------------------------------------------
4028 // -------------------------------------------------------------------------------------
4030 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
)
4032 wxListItem::wxListItem()
4041 m_format
= wxLIST_FORMAT_CENTRE
;
4047 void wxListItem::Clear()
4056 m_format
= wxLIST_FORMAT_CENTRE
;
4063 void wxListItem::ClearAttributes()
4072 // -------------------------------------------------------------------------------------
4074 // -------------------------------------------------------------------------------------
4076 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
)
4078 wxListEvent::wxListEvent( wxEventType commandType
, int id
)
4079 : wxNotifyEvent( commandType
, id
)
4085 m_cancelled
= FALSE
;
4090 void wxListEvent::CopyObject(wxObject
& object_dest
) const
4092 wxListEvent
*obj
= (wxListEvent
*)&object_dest
;
4094 wxNotifyEvent::CopyObject(object_dest
);
4096 obj
->m_code
= m_code
;
4097 obj
->m_itemIndex
= m_itemIndex
;
4098 obj
->m_oldItemIndex
= m_oldItemIndex
;
4100 obj
->m_cancelled
= m_cancelled
;
4101 obj
->m_pointDrag
= m_pointDrag
;
4102 obj
->m_item
.m_mask
= m_item
.m_mask
;
4103 obj
->m_item
.m_itemId
= m_item
.m_itemId
;
4104 obj
->m_item
.m_col
= m_item
.m_col
;
4105 obj
->m_item
.m_state
= m_item
.m_state
;
4106 obj
->m_item
.m_stateMask
= m_item
.m_stateMask
;
4107 obj
->m_item
.m_text
= m_item
.m_text
;
4108 obj
->m_item
.m_image
= m_item
.m_image
;
4109 obj
->m_item
.m_data
= m_item
.m_data
;
4110 obj
->m_item
.m_format
= m_item
.m_format
;
4111 obj
->m_item
.m_width
= m_item
.m_width
;
4113 if ( m_item
.HasAttributes() )
4115 obj
->m_item
.SetTextColour(m_item
.GetTextColour());
4119 // -------------------------------------------------------------------------------------
4121 // -------------------------------------------------------------------------------------
4123 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
)
4125 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
)
4126 EVT_SIZE(wxListCtrl::OnSize
)
4127 EVT_IDLE(wxListCtrl::OnIdle
)
4130 wxListCtrl::wxListCtrl()
4132 m_imageListNormal
= (wxImageList
*) NULL
;
4133 m_imageListSmall
= (wxImageList
*) NULL
;
4134 m_imageListState
= (wxImageList
*) NULL
;
4136 m_ownsImageListNormal
=
4137 m_ownsImageListSmall
=
4138 m_ownsImageListState
= FALSE
;
4140 m_mainWin
= (wxListMainWindow
*) NULL
;
4141 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4144 wxListCtrl::~wxListCtrl()
4147 m_mainWin
->ResetCurrent();
4149 if (m_ownsImageListNormal
)
4150 delete m_imageListNormal
;
4151 if (m_ownsImageListSmall
)
4152 delete m_imageListSmall
;
4153 if (m_ownsImageListState
)
4154 delete m_imageListState
;
4157 void wxListCtrl::CreateHeaderWindow()
4159 m_headerWin
= new wxListHeaderWindow
4161 this, -1, m_mainWin
,
4163 wxSize(GetClientSize().x
, HEADER_HEIGHT
),
4168 bool wxListCtrl::Create(wxWindow
*parent
,
4173 const wxValidator
&validator
,
4174 const wxString
&name
)
4178 m_imageListState
= (wxImageList
*) NULL
;
4179 m_ownsImageListNormal
=
4180 m_ownsImageListSmall
=
4181 m_ownsImageListState
= FALSE
;
4183 m_mainWin
= (wxListMainWindow
*) NULL
;
4184 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4186 if ( !(style
& wxLC_MASK_TYPE
) )
4188 style
= style
| wxLC_LIST
;
4191 if ( !wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name
) )
4194 // don't create the inner window with the border
4195 style
&= ~wxSUNKEN_BORDER
;
4197 m_mainWin
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style
);
4199 if ( HasFlag(wxLC_REPORT
) )
4201 CreateHeaderWindow();
4203 if ( HasFlag(wxLC_NO_HEADER
) )
4205 // VZ: why do we create it at all then?
4206 m_headerWin
->Show( FALSE
);
4213 void wxListCtrl::SetSingleStyle( long style
, bool add
)
4215 wxASSERT_MSG( !(style
& wxLC_VIRTUAL
),
4216 _T("wxLC_VIRTUAL can't be [un]set") );
4218 long flag
= GetWindowStyle();
4222 if (style
& wxLC_MASK_TYPE
)
4223 flag
&= ~(wxLC_MASK_TYPE
| wxLC_VIRTUAL
);
4224 if (style
& wxLC_MASK_ALIGN
)
4225 flag
&= ~wxLC_MASK_ALIGN
;
4226 if (style
& wxLC_MASK_SORT
)
4227 flag
&= ~wxLC_MASK_SORT
;
4239 SetWindowStyleFlag( flag
);
4242 void wxListCtrl::SetWindowStyleFlag( long flag
)
4246 m_mainWin
->DeleteEverything();
4250 GetClientSize( &width
, &height
);
4252 if (flag
& wxLC_REPORT
)
4254 if (!HasFlag(wxLC_REPORT
))
4258 CreateHeaderWindow();
4260 if (HasFlag(wxLC_NO_HEADER
))
4261 m_headerWin
->Show( FALSE
);
4265 if (flag
& wxLC_NO_HEADER
)
4266 m_headerWin
->Show( FALSE
);
4268 m_headerWin
->Show( TRUE
);
4274 if ( m_mainWin
->HasHeader() )
4276 m_headerWin
->Show( FALSE
);
4281 wxWindow::SetWindowStyleFlag( flag
);
4284 bool wxListCtrl::GetColumn(int col
, wxListItem
&item
) const
4286 m_mainWin
->GetColumn( col
, item
);
4290 bool wxListCtrl::SetColumn( int col
, wxListItem
& item
)
4292 m_mainWin
->SetColumn( col
, item
);
4296 int wxListCtrl::GetColumnWidth( int col
) const
4298 return m_mainWin
->GetColumnWidth( col
);
4301 bool wxListCtrl::SetColumnWidth( int col
, int width
)
4303 m_mainWin
->SetColumnWidth( col
, width
);
4307 int wxListCtrl::GetCountPerPage() const
4309 return m_mainWin
->GetCountPerPage(); // different from Windows ?
4312 bool wxListCtrl::GetItem( wxListItem
&info
) const
4314 m_mainWin
->GetItem( info
);
4318 bool wxListCtrl::SetItem( wxListItem
&info
)
4320 m_mainWin
->SetItem( info
);
4324 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId
)
4327 info
.m_text
= label
;
4328 info
.m_mask
= wxLIST_MASK_TEXT
;
4329 info
.m_itemId
= index
;
4333 info
.m_image
= imageId
;
4334 info
.m_mask
|= wxLIST_MASK_IMAGE
;
4336 m_mainWin
->SetItem(info
);
4340 int wxListCtrl::GetItemState( long item
, long stateMask
) const
4342 return m_mainWin
->GetItemState( item
, stateMask
);
4345 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask
)
4347 m_mainWin
->SetItemState( item
, state
, stateMask
);
4351 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) )
4354 info
.m_image
= image
;
4355 info
.m_mask
= wxLIST_MASK_IMAGE
;
4356 info
.m_itemId
= item
;
4357 m_mainWin
->SetItem( info
);
4361 wxString
wxListCtrl::GetItemText( long item
) const
4364 info
.m_itemId
= item
;
4365 m_mainWin
->GetItem( info
);
4369 void wxListCtrl::SetItemText( long item
, const wxString
&str
)
4372 info
.m_mask
= wxLIST_MASK_TEXT
;
4373 info
.m_itemId
= item
;
4375 m_mainWin
->SetItem( info
);
4378 long wxListCtrl::GetItemData( long item
) const
4381 info
.m_itemId
= item
;
4382 m_mainWin
->GetItem( info
);
4386 bool wxListCtrl::SetItemData( long item
, long data
)
4389 info
.m_mask
= wxLIST_MASK_DATA
;
4390 info
.m_itemId
= item
;
4392 m_mainWin
->SetItem( info
);
4396 bool wxListCtrl::GetItemRect( long item
, wxRect
&rect
, int WXUNUSED(code
) ) const
4398 m_mainWin
->GetItemRect( item
, rect
);
4402 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos
) const
4404 m_mainWin
->GetItemPosition( item
, pos
);
4408 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) )
4413 int wxListCtrl::GetItemCount() const
4415 return m_mainWin
->GetItemCount();
4418 int wxListCtrl::GetColumnCount() const
4420 return m_mainWin
->GetColumnCount();
4423 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall
)
4425 m_mainWin
->SetItemSpacing( spacing
, isSmall
);
4428 int wxListCtrl::GetItemSpacing( bool isSmall
) const
4430 return m_mainWin
->GetItemSpacing( isSmall
);
4433 int wxListCtrl::GetSelectedItemCount() const
4435 return m_mainWin
->GetSelectedItemCount();
4438 wxColour
wxListCtrl::GetTextColour() const
4440 return GetForegroundColour();
4443 void wxListCtrl::SetTextColour(const wxColour
& col
)
4445 SetForegroundColour(col
);
4448 long wxListCtrl::GetTopItem() const
4453 long wxListCtrl::GetNextItem( long item
, int geom
, int state
) const
4455 return m_mainWin
->GetNextItem( item
, geom
, state
);
4458 wxImageList
*wxListCtrl::GetImageList(int which
) const
4460 if (which
== wxIMAGE_LIST_NORMAL
)
4462 return m_imageListNormal
;
4464 else if (which
== wxIMAGE_LIST_SMALL
)
4466 return m_imageListSmall
;
4468 else if (which
== wxIMAGE_LIST_STATE
)
4470 return m_imageListState
;
4472 return (wxImageList
*) NULL
;
4475 void wxListCtrl::SetImageList( wxImageList
*imageList
, int which
)
4477 if ( which
== wxIMAGE_LIST_NORMAL
)
4479 if (m_ownsImageListNormal
) delete m_imageListNormal
;
4480 m_imageListNormal
= imageList
;
4481 m_ownsImageListNormal
= FALSE
;
4483 else if ( which
== wxIMAGE_LIST_SMALL
)
4485 if (m_ownsImageListSmall
) delete m_imageListSmall
;
4486 m_imageListSmall
= imageList
;
4487 m_ownsImageListSmall
= FALSE
;
4489 else if ( which
== wxIMAGE_LIST_STATE
)
4491 if (m_ownsImageListState
) delete m_imageListState
;
4492 m_imageListState
= imageList
;
4493 m_ownsImageListState
= FALSE
;
4496 m_mainWin
->SetImageList( imageList
, which
);
4499 void wxListCtrl::AssignImageList(wxImageList
*imageList
, int which
)
4501 SetImageList(imageList
, which
);
4502 if ( which
== wxIMAGE_LIST_NORMAL
)
4503 m_ownsImageListNormal
= TRUE
;
4504 else if ( which
== wxIMAGE_LIST_SMALL
)
4505 m_ownsImageListSmall
= TRUE
;
4506 else if ( which
== wxIMAGE_LIST_STATE
)
4507 m_ownsImageListState
= TRUE
;
4510 bool wxListCtrl::Arrange( int WXUNUSED(flag
) )
4515 bool wxListCtrl::DeleteItem( long item
)
4517 m_mainWin
->DeleteItem( item
);
4521 bool wxListCtrl::DeleteAllItems()
4523 m_mainWin
->DeleteAllItems();
4527 bool wxListCtrl::DeleteAllColumns()
4529 size_t count
= m_mainWin
->m_columns
.GetCount();
4530 for ( size_t n
= 0; n
< count
; n
++ )
4536 void wxListCtrl::ClearAll()
4538 m_mainWin
->DeleteEverything();
4541 bool wxListCtrl::DeleteColumn( int col
)
4543 m_mainWin
->DeleteColumn( col
);
4547 void wxListCtrl::Edit( long item
)
4549 m_mainWin
->EditLabel( item
);
4552 bool wxListCtrl::EnsureVisible( long item
)
4554 m_mainWin
->EnsureVisible( item
);
4558 long wxListCtrl::FindItem( long start
, const wxString
& str
, bool partial
)
4560 return m_mainWin
->FindItem( start
, str
, partial
);
4563 long wxListCtrl::FindItem( long start
, long data
)
4565 return m_mainWin
->FindItem( start
, data
);
4568 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
),
4569 int WXUNUSED(direction
))
4574 long wxListCtrl::HitTest( const wxPoint
&point
, int &flags
)
4576 return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags
);
4579 long wxListCtrl::InsertItem( wxListItem
& info
)
4581 m_mainWin
->InsertItem( info
);
4582 return info
.m_itemId
;
4585 long wxListCtrl::InsertItem( long index
, const wxString
&label
)
4588 info
.m_text
= label
;
4589 info
.m_mask
= wxLIST_MASK_TEXT
;
4590 info
.m_itemId
= index
;
4591 return InsertItem( info
);
4594 long wxListCtrl::InsertItem( long index
, int imageIndex
)
4597 info
.m_mask
= wxLIST_MASK_IMAGE
;
4598 info
.m_image
= imageIndex
;
4599 info
.m_itemId
= index
;
4600 return InsertItem( info
);
4603 long wxListCtrl::InsertItem( long index
, const wxString
&label
, int imageIndex
)
4606 info
.m_text
= label
;
4607 info
.m_image
= imageIndex
;
4608 info
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_IMAGE
;
4609 info
.m_itemId
= index
;
4610 return InsertItem( info
);
4613 long wxListCtrl::InsertColumn( long col
, wxListItem
&item
)
4615 wxASSERT( m_headerWin
);
4616 m_mainWin
->InsertColumn( col
, item
);
4617 m_headerWin
->Refresh();
4622 long wxListCtrl::InsertColumn( long col
, const wxString
&heading
,
4623 int format
, int width
)
4626 item
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_FORMAT
;
4627 item
.m_text
= heading
;
4630 item
.m_mask
|= wxLIST_MASK_WIDTH
;
4631 item
.m_width
= width
;
4633 item
.m_format
= format
;
4635 return InsertColumn( col
, item
);
4638 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) )
4644 // fn is a function which takes 3 long arguments: item1, item2, data.
4645 // item1 is the long data associated with a first item (NOT the index).
4646 // item2 is the long data associated with a second item (NOT the index).
4647 // data is the same value as passed to SortItems.
4648 // The return value is a negative number if the first item should precede the second
4649 // item, a positive number of the second item should precede the first,
4650 // or zero if the two items are equivalent.
4651 // data is arbitrary data to be passed to the sort function.
4653 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data
)
4655 m_mainWin
->SortItems( fn
, data
);
4659 // ----------------------------------------------------------------------------
4661 // ----------------------------------------------------------------------------
4663 void wxListCtrl::OnSize(wxSizeEvent
& event
)
4669 GetClientSize( &cw
, &ch
);
4671 if ( m_mainWin
->HasHeader() )
4673 m_headerWin
->SetSize( 0, 0, cw
, HEADER_HEIGHT
);
4674 m_mainWin
->SetSize( 0, HEADER_HEIGHT
+ 1, cw
, ch
- HEADER_HEIGHT
- 1 );
4676 else // no header window
4678 m_mainWin
->SetSize( 0, 0, cw
, ch
);
4681 m_mainWin
->RecalculatePositions();
4684 void wxListCtrl::OnIdle( wxIdleEvent
& event
)
4688 // do it only if needed
4689 if ( !m_mainWin
->m_dirty
)
4692 m_mainWin
->RecalculatePositions();
4695 // ----------------------------------------------------------------------------
4697 // ----------------------------------------------------------------------------
4699 bool wxListCtrl::SetBackgroundColour( const wxColour
&colour
)
4703 m_mainWin
->SetBackgroundColour( colour
);
4704 m_mainWin
->m_dirty
= TRUE
;
4710 bool wxListCtrl::SetForegroundColour( const wxColour
&colour
)
4712 if ( !wxWindow::SetForegroundColour( colour
) )
4717 m_mainWin
->SetForegroundColour( colour
);
4718 m_mainWin
->m_dirty
= TRUE
;
4723 m_headerWin
->SetForegroundColour( colour
);
4729 bool wxListCtrl::SetFont( const wxFont
&font
)
4731 if ( !wxWindow::SetFont( font
) )
4736 m_mainWin
->SetFont( font
);
4737 m_mainWin
->m_dirty
= TRUE
;
4742 m_headerWin
->SetFont( font
);
4748 // ----------------------------------------------------------------------------
4749 // methods forwarded to m_mainWin
4750 // ----------------------------------------------------------------------------
4752 #if wxUSE_DRAG_AND_DROP
4754 void wxListCtrl::SetDropTarget( wxDropTarget
*dropTarget
)
4756 m_mainWin
->SetDropTarget( dropTarget
);
4759 wxDropTarget
*wxListCtrl::GetDropTarget() const
4761 return m_mainWin
->GetDropTarget();
4764 #endif // wxUSE_DRAG_AND_DROP
4766 bool wxListCtrl::SetCursor( const wxCursor
&cursor
)
4768 return m_mainWin
? m_mainWin
->wxWindow::SetCursor(cursor
) : FALSE
;
4771 wxColour
wxListCtrl::GetBackgroundColour() const
4773 return m_mainWin
? m_mainWin
->GetBackgroundColour() : wxColour();
4776 wxColour
wxListCtrl::GetForegroundColour() const
4778 return m_mainWin
? m_mainWin
->GetForegroundColour() : wxColour();
4781 bool wxListCtrl::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
4784 return m_mainWin
->PopupMenu( menu
, x
, y
);
4787 #endif // wxUSE_MENUS
4790 void wxListCtrl::SetFocus()
4792 /* The test in window.cpp fails as we are a composite
4793 window, so it checks against "this", but not m_mainWin. */
4794 if ( FindFocus() != this )
4795 m_mainWin
->SetFocus();
4798 // ----------------------------------------------------------------------------
4799 // virtual list control support
4800 // ----------------------------------------------------------------------------
4802 wxString
wxListCtrl::OnGetItemText(long item
, long col
) const
4804 // this is a pure virtual function, in fact - which is not really pure
4805 // because the controls which are not virtual don't need to implement it
4806 wxFAIL_MSG( _T("not supposed to be called") );
4808 return wxEmptyString
;
4811 int wxListCtrl::OnGetItemImage(long item
) const
4814 wxFAIL_MSG( _T("not supposed to be called") );
4819 void wxListCtrl::SetItemCount(long count
)
4821 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4823 m_mainWin
->SetItemCount(count
);
4826 #endif // wxUSE_LISTCTRL