1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/listctrl.cpp
3 // Purpose: generic implementation of wxListCtrl
4 // Author: Robert Roebling
5 // Vadim Zeitlin (virtual list control support)
7 // Copyright: (c) 1998 Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 FIXME for virtual list controls
14 +1. clicking on the item with a mouse is awfully slow, what is going on?
15 note that selecting with keyboard seems to be much faster
16 => fixed HighlightAll() - iterating over 1000000 items *is* slow
18 2. background colour is wrong?
22 TODO for better virtual list control support:
24 1. less dumb line caching, we should cache at least all those visible
25 in the control itself and probably twice as many (we might also need to
26 cache the first one always for geometry calculations?)
28 +2. storing selections: we can't use an array to store the selected indices
29 like right now as selecting all in a control with 1000000 items is not
30 doable like this - instead, store selections as collection of individual
35 3. we need to implement searching/sorting somehow
37 4. the idea of storing the line index in the line itself is really stupid,
38 we shouldn't need it - but for this we have to get rid of all calles to
39 wxListLineData::GetFoo() and replace them with something like
41 ... we have it ourselves ...
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
55 #pragma implementation "listctrl.h"
56 #pragma implementation "listctrlbase.h"
59 // For compilers that support precompilation, includes "wx.h".
60 #include "wx/wxprec.h"
68 #include "wx/dcscreen.h"
70 #include "wx/listctrl.h"
71 #include "wx/imaglist.h"
72 #include "wx/dynarray.h"
76 #include "wx/gtk/win_gtk.h"
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG
)
84 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG
)
85 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
)
86 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT
)
87 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM
)
88 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
)
89 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO
)
90 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO
)
91 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED
)
92 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED
)
93 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN
)
94 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM
)
95 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK
)
96 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
)
97 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
)
98 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED
)
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 // the height of the header window (FIXME: should depend on its font!)
105 static const int HEADER_HEIGHT
= 23;
107 // the scrollbar units
108 static const int SCROLL_UNIT_X
= 15;
109 static const int SCROLL_UNIT_Y
= 15;
111 // the spacing between the lines (in report mode)
112 static const int LINE_SPACING
= 0;
114 // extra margins around the text label
115 static const int EXTRA_WIDTH
= 3;
116 static const int EXTRA_HEIGHT
= 4;
118 // offset for the header window
119 static const int HEADER_OFFSET_X
= 1;
120 static const int HEADER_OFFSET_Y
= 1;
122 // when autosizing the columns, add some slack
123 static const int AUTOSIZE_COL_MARGIN
= 10;
125 // default and minimal widths for the header columns
126 static const int WIDTH_COL_DEFAULT
= 80;
127 static const int WIDTH_COL_MIN
= 10;
129 // ============================================================================
131 // ============================================================================
133 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
137 int CMPFUNC_CONV
wxSizeTCmpFn(size_t n1
, size_t n2
) { return n1
- n2
; }
139 WX_DEFINE_SORTED_EXPORTED_ARRAY(size_t, wxIndexArray
);
141 // this class is used to store the selected items in the virtual list control
142 // (but it is not tied to list control and so can be used with other controls
143 // such as wxListBox in wxUniv)
145 // the idea is to make it really smart later (i.e. store the selections as an
146 // array of ranes + individual items) but, as I don't have time to do it now
147 // (this would require writing code to merge/break ranges and much more) keep
148 // it simple but define a clean interface to it which allows it to be made
150 class WXDLLEXPORT wxSelectionStore
153 wxSelectionStore() : m_itemsSel(wxSizeTCmpFn
) { Init(); }
155 // set the total number of items we handle
156 void SetItemCount(size_t count
) { m_count
= count
; }
158 // special case of SetItemCount(0)
159 void Clear() { m_itemsSel
.Clear(); m_count
= 0; }
161 // must be called when a new item is inserted/added
162 void OnItemAdd(size_t item
) { wxFAIL_MSG( _T("TODO") ); }
164 // must be called when an item is deleted
165 void OnItemDelete(size_t item
);
167 // select one item, use SelectRange() insted if possible!
169 // returns true if the items selection really changed
170 bool SelectItem(size_t item
, bool select
= TRUE
);
172 // select the range of items
173 void SelectRange(size_t itemFrom
, size_t itemTo
, bool select
= TRUE
);
175 // return true if the given item is selected
176 bool IsSelected(size_t item
) const;
178 // return the total number of selected items
179 size_t GetSelectedCount() const
181 return m_defaultState
? m_count
- m_itemsSel
.GetCount()
182 : m_itemsSel
.GetCount();
187 void Init() { m_defaultState
= FALSE
; }
189 // the total number of items we handle
192 // the default state: normally, FALSE (i.e. off) but maybe set to TRUE if
193 // there are more selected items than non selected ones - this allows to
194 // handle selection of all items efficiently
197 // the array of items whose selection state is different from default
198 wxIndexArray m_itemsSel
;
200 DECLARE_NO_COPY_CLASS(wxSelectionStore
)
203 //-----------------------------------------------------------------------------
204 // wxListItemData (internal)
205 //-----------------------------------------------------------------------------
207 class WXDLLEXPORT wxListItemData
210 wxListItemData(wxListMainWindow
*owner
);
211 ~wxListItemData() { delete m_attr
; delete m_rect
; }
213 void SetItem( const wxListItem
&info
);
214 void SetImage( int image
) { m_image
= image
; }
215 void SetData( long data
) { m_data
= data
; }
216 void SetPosition( int x
, int y
);
217 void SetSize( int width
, int height
);
219 bool HasText() const { return !m_text
.empty(); }
220 const wxString
& GetText() const { return m_text
; }
221 void SetText(const wxString
& text
) { m_text
= text
; }
223 // we can't use empty string for measuring the string width/height, so
224 // always return something
225 wxString
GetTextForMeasuring() const
227 wxString s
= GetText();
234 bool IsHit( int x
, int y
) const;
238 int GetWidth() const;
239 int GetHeight() const;
241 int GetImage() const { return m_image
; }
242 bool HasImage() const { return GetImage() != -1; }
244 void GetItem( wxListItem
&info
) const;
246 wxListItemAttr
*GetAttributes() const { return m_attr
; }
249 // the item image or -1
252 // user data associated with the item
255 // the item coordinates are not used in report mode, instead this pointer
256 // is NULL and the owner window is used to retrieve the item position and
260 // the list ctrl we are in
261 wxListMainWindow
*m_owner
;
263 // custom attributes or NULL
264 wxListItemAttr
*m_attr
;
267 // common part of all ctors
273 //-----------------------------------------------------------------------------
274 // wxListHeaderData (internal)
275 //-----------------------------------------------------------------------------
277 class WXDLLEXPORT wxListHeaderData
: public wxObject
291 wxListHeaderData( const wxListItem
&info
);
292 void SetItem( const wxListItem
&item
);
293 void SetPosition( int x
, int y
);
294 void SetWidth( int w
);
295 void SetFormat( int format
);
296 void SetHeight( int h
);
297 bool HasImage() const;
299 bool HasText() const { return !m_text
.empty(); }
300 const wxString
& GetText() const { return m_text
; }
301 void SetText(const wxString
& text
) { m_text
= text
; }
303 void GetItem( wxListItem
&item
);
305 bool IsHit( int x
, int y
) const;
306 int GetImage() const;
307 int GetWidth() const;
308 int GetFormat() const;
311 DECLARE_DYNAMIC_CLASS(wxListHeaderData
);
314 //-----------------------------------------------------------------------------
315 // wxListLineData (internal)
316 //-----------------------------------------------------------------------------
318 WX_DECLARE_LIST(wxListItemData
, wxListItemDataList
);
319 #include "wx/listimpl.cpp"
320 WX_DEFINE_LIST(wxListItemDataList
);
322 class WXDLLEXPORT wxListLineData
325 // the list of subitems: only may have more than one item in report mode
326 wxListItemDataList m_items
;
328 // this is not used in report view
340 // the part to be highlighted
341 wxRect m_rectHighlight
;
344 // is this item selected? [NB: not used in virtual mode]
347 // back pointer to the list ctrl
348 wxListMainWindow
*m_owner
;
351 wxListLineData(wxListMainWindow
*owner
);
353 ~wxListLineData() { delete m_gi
; }
355 // are we in report mode?
356 inline bool InReportView() const;
358 // are we in virtual report mode?
359 inline bool IsVirtual() const;
361 // these 2 methods shouldn't be called for report view controls, in that
362 // case we determine our position/size ourselves
364 // calculate the size of the line
365 void CalculateSize( wxDC
*dc
, int spacing
);
367 // remember the position this line appears at
368 void SetPosition( int x
, int y
, int window_width
, int spacing
);
372 void SetImage( int image
) { SetImage(0, image
); }
373 int GetImage() const { return GetImage(0); }
374 bool HasImage() const { return GetImage() != -1; }
375 bool HasText() const { return !GetText(0).empty(); }
377 void SetItem( int index
, const wxListItem
&info
);
378 void GetItem( int index
, wxListItem
&info
);
380 wxString
GetText(int index
) const;
381 void SetText( int index
, const wxString s
);
383 // return true if the highlighting really changed
384 bool Highlight( bool on
);
386 void ReverseHighlight();
388 bool IsHighlighted() const
390 wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") );
392 return m_highlighted
;
395 // draw the line on the given DC in icon/list mode
396 void Draw( wxDC
*dc
);
398 // the same in report mode
399 void DrawInReportMode( wxDC
*dc
,
401 const wxRect
& rectHL
,
405 // set the line to contain num items (only can be > 1 in report mode)
406 void InitItems( int num
);
408 // get the mode (i.e. style) of the list control
409 inline int GetMode() const;
411 void SetAttributes(wxDC
*dc
,
412 const wxListItemAttr
*attr
,
413 const wxColour
& colText
,
417 // these are only used by GetImage/SetImage above, we don't support images
418 // with subitems at the public API level yet
419 void SetImage( int index
, int image
);
420 int GetImage( int index
) const;
423 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData
, wxListLineDataArray
);
424 #include "wx/arrimpl.cpp"
425 WX_DEFINE_OBJARRAY(wxListLineDataArray
);
427 //-----------------------------------------------------------------------------
428 // wxListHeaderWindow (internal)
429 //-----------------------------------------------------------------------------
431 class WXDLLEXPORT wxListHeaderWindow
: public wxWindow
434 wxListMainWindow
*m_owner
;
435 wxCursor
*m_currentCursor
;
436 wxCursor
*m_resizeCursor
;
439 // column being resized
442 // divider line position in logical (unscrolled) coords
445 // minimal position beyond which the divider line can't be dragged in
450 wxListHeaderWindow();
451 virtual ~wxListHeaderWindow();
453 wxListHeaderWindow( wxWindow
*win
,
455 wxListMainWindow
*owner
,
456 const wxPoint
&pos
= wxDefaultPosition
,
457 const wxSize
&size
= wxDefaultSize
,
459 const wxString
&name
= "wxlistctrlcolumntitles" );
461 void DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
);
463 void AdjustDC(wxDC
& dc
);
465 void OnPaint( wxPaintEvent
&event
);
466 void OnMouse( wxMouseEvent
&event
);
467 void OnSetFocus( wxFocusEvent
&event
);
473 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow
)
474 DECLARE_EVENT_TABLE()
477 //-----------------------------------------------------------------------------
478 // wxListRenameTimer (internal)
479 //-----------------------------------------------------------------------------
481 class WXDLLEXPORT wxListRenameTimer
: public wxTimer
484 wxListMainWindow
*m_owner
;
487 wxListRenameTimer( wxListMainWindow
*owner
);
491 //-----------------------------------------------------------------------------
492 // wxListTextCtrl (internal)
493 //-----------------------------------------------------------------------------
495 class WXDLLEXPORT wxListTextCtrl
: public wxTextCtrl
500 wxListMainWindow
*m_owner
;
501 wxString m_startValue
;
505 wxListTextCtrl( wxWindow
*parent
, const wxWindowID id
,
506 bool *accept
, wxString
*res
, wxListMainWindow
*owner
,
507 const wxString
&value
= "",
508 const wxPoint
&pos
= wxDefaultPosition
, const wxSize
&size
= wxDefaultSize
,
510 const wxValidator
& validator
= wxDefaultValidator
,
511 const wxString
&name
= "listctrltextctrl" );
512 void OnChar( wxKeyEvent
&event
);
513 void OnKeyUp( wxKeyEvent
&event
);
514 void OnKillFocus( wxFocusEvent
&event
);
517 DECLARE_DYNAMIC_CLASS(wxListTextCtrl
);
518 DECLARE_EVENT_TABLE()
521 //-----------------------------------------------------------------------------
522 // wxListMainWindow (internal)
523 //-----------------------------------------------------------------------------
525 WX_DECLARE_LIST(wxListHeaderData
, wxListHeaderDataList
);
526 #include "wx/listimpl.cpp"
527 WX_DEFINE_LIST(wxListHeaderDataList
);
529 class WXDLLEXPORT wxListMainWindow
: public wxScrolledWindow
533 wxListMainWindow( wxWindow
*parent
,
535 const wxPoint
& pos
= wxDefaultPosition
,
536 const wxSize
& size
= wxDefaultSize
,
538 const wxString
&name
= _T("listctrlmainwindow") );
540 virtual ~wxListMainWindow();
542 bool HasFlag(int flag
) const { return m_parent
->HasFlag(flag
); }
544 // return true if this is a virtual list control
545 bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL
); }
547 // return true if the control is in report mode
548 bool InReportView() const { return HasFlag(wxLC_REPORT
); }
550 // return true if we are in single selection mode, false if multi sel
551 bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL
); }
553 // do we have a header window?
554 bool HasHeader() const
555 { return HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
); }
557 void HighlightAll( bool on
);
559 // all these functions only do something if the line is currently visible
561 // change the line "selected" state, return TRUE if it really changed
562 bool HighlightLine( size_t line
, bool highlight
= TRUE
);
564 // as HighlightLine() but do it for the range of lines: this is incredibly
565 // more efficient for virtual list controls!
567 // NB: unlike HighlightLine() this one does refresh the lines on screen
568 void HighlightLines( size_t lineFrom
, size_t lineTo
, bool on
= TRUE
);
570 // toggle the line state and refresh it
571 void ReverseHighlight( size_t line
)
572 { HighlightLine(line
, !IsHighlighted(line
)); RefreshLine(line
); }
574 // refresh one or several lines at once
575 void RefreshLine( size_t line
);
576 void RefreshLines( size_t lineFrom
, size_t lineTo
);
578 // return true if the line is highlighted
579 bool IsHighlighted(size_t line
) const;
581 // the methods which are forwarded to wxListLineData itself in list/icon
582 // modes but are here because the lines don't store their positions in the
585 // get the bound rect for the entire line
586 wxRect
GetLineRect(size_t line
) const;
588 // get the bound rect of the label
589 wxRect
GetLineLabelRect(size_t line
) const;
591 // get the bound rect of the items icon (only may be called if we do have
593 wxRect
GetLineIconRect(size_t line
) const;
595 // get the rect to be highlighted when the item has focus
596 wxRect
GetLineHighlightRect(size_t line
) const;
598 // get the size of the total line rect
599 wxSize
GetLineSize(size_t line
) const
600 { return GetLineRect(line
).GetSize(); }
602 // return the hit code for the corresponding position (in this line)
603 long HitTestLine(size_t line
, int x
, int y
) const;
605 void EditLabel( long item
);
606 void OnRenameTimer();
607 void OnRenameAccept();
609 void OnMouse( wxMouseEvent
&event
);
612 // called to switch the selection from the current item to newCurrent,
613 void OnArrowChar( size_t newCurrent
, const wxKeyEvent
& event
);
615 void OnChar( wxKeyEvent
&event
);
616 void OnKeyDown( wxKeyEvent
&event
);
617 void OnSetFocus( wxFocusEvent
&event
);
618 void OnKillFocus( wxFocusEvent
&event
);
619 void OnScroll(wxScrollWinEvent
& event
) ;
621 void OnPaint( wxPaintEvent
&event
);
623 void DrawImage( int index
, wxDC
*dc
, int x
, int y
);
624 void GetImageSize( int index
, int &width
, int &height
) const;
625 int GetTextLength( const wxString
&s
) const;
627 void SetImageList( wxImageList
*imageList
, int which
);
628 void SetItemSpacing( int spacing
, bool isSmall
= FALSE
);
629 int GetItemSpacing( bool isSmall
= FALSE
);
631 void SetColumn( int col
, wxListItem
&item
);
632 void SetColumnWidth( int col
, int width
);
633 void GetColumn( int col
, wxListItem
&item
) const;
634 int GetColumnWidth( int col
) const;
635 int GetColumnCount() const { return m_columns
.GetCount(); }
637 // returns the sum of the heights of all columns
638 int GetHeaderWidth() const;
640 int GetCountPerPage() const;
642 void SetItem( wxListItem
&item
);
643 void GetItem( wxListItem
&item
);
644 void SetItemState( long item
, long state
, long stateMask
);
645 int GetItemState( long item
, long stateMask
);
646 void GetItemRect( long index
, wxRect
&rect
);
647 bool GetItemPosition( long item
, wxPoint
& pos
);
648 int GetSelectedItemCount();
650 // set the scrollbars and update the positions of the items
651 void RecalculatePositions();
653 // refresh the window and the header
656 long GetNextItem( long item
, int geometry
, int state
);
657 void DeleteItem( long index
);
658 void DeleteAllItems();
659 void DeleteColumn( int col
);
660 void DeleteEverything();
661 void EnsureVisible( long index
);
662 long FindItem( long start
, const wxString
& str
, bool partial
= FALSE
);
663 long FindItem( long start
, long data
);
664 long HitTest( int x
, int y
, int &flags
);
665 void InsertItem( wxListItem
&item
);
666 void InsertColumn( long col
, wxListItem
&item
);
667 void SortItems( wxListCtrlCompare fn
, long data
);
669 size_t GetItemCount() const;
670 bool IsEmpty() const { return GetItemCount() == 0; }
671 void SetItemCount(long count
);
673 void ResetCurrent() { m_current
= (size_t)-1; }
674 bool HasCurrent() const { return m_current
!= (size_t)-1; }
676 // send out a wxListEvent
677 void SendNotify( size_t line
,
679 wxPoint point
= wxDefaultPosition
);
681 // override base class virtual to reset m_lineHeight when the font changes
682 virtual bool SetFont(const wxFont
& font
)
684 if ( !wxScrolledWindow::SetFont(font
) )
692 // these are for wxListLineData usage only
694 // get the backpointer to the list ctrl
695 wxListCtrl
*GetListCtrl() const
697 return wxStaticCast(GetParent(), wxListCtrl
);
700 // get the height of all lines (assuming they all do have the same height)
701 wxCoord
GetLineHeight() const;
703 // get the y position of the given line (only for report view)
704 wxCoord
GetLineY(size_t line
) const;
707 // the array of all line objects for a non virtual list control
708 wxListLineDataArray m_lines
;
710 // the list of column objects
711 wxListHeaderDataList m_columns
;
713 // currently focused item or -1
716 // the item currently being edited or -1
717 size_t m_currentEdit
;
719 // the number of lines per page
722 // this flag is set when something which should result in the window
723 // redrawing happens (i.e. an item was added or deleted, or its appearance
724 // changed) and OnPaint() doesn't redraw the window while it is set which
725 // allows to minimize the number of repaintings when a lot of items are
726 // being added. The real repainting occurs only after the next OnIdle()
730 wxBrush
*m_highlightBrush
;
731 wxColour
*m_highlightColour
;
734 wxImageList
*m_small_image_list
;
735 wxImageList
*m_normal_image_list
;
737 int m_normal_spacing
;
741 wxTimer
*m_renameTimer
;
743 wxString m_renameRes
;
748 // for double click logic
749 size_t m_lineLastClicked
,
750 m_lineBeforeLastClicked
;
753 // the total count of items in a virtual list control
756 // the object maintaining the items selection state, only used in virtual
758 wxSelectionStore m_selStore
;
760 // common part of all ctors
763 // intiialize m_[xy]Scroll
764 void InitScrolling();
766 // get the line data for the given index
767 wxListLineData
*GetLine(size_t n
) const
769 wxASSERT_MSG( n
!= (size_t)-1, _T("invalid line index") );
773 wxConstCast(this, wxListMainWindow
)->CacheLineData(n
);
781 // get a dummy line which can be used for geometry calculations and such:
782 // you must use GetLine() if you want to really draw the line
783 wxListLineData
*GetDummyLine() const;
785 // cache the line data of the n-th line in m_lines[0]
786 void CacheLineData(size_t line
);
788 // get the range of visible lines
789 void GetVisibleLinesRange(size_t *from
, size_t *to
);
791 // force us to recalculate the range of visible lines
792 void ResetVisibleLinesRange() { m_lineFrom
= (size_t)-1; }
794 // get the colour to be used for drawing the rules
795 wxColour
GetRuleColour() const
800 return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT
);
805 // initialize the current item if needed
806 void UpdateCurrent();
808 // called when an item is [un]focuded, i.e. becomes [not] current
811 void OnFocusLine( size_t line
);
812 void OnUnfocusLine( size_t line
);
814 // the height of one line using the current font
815 wxCoord m_lineHeight
;
817 // the total header width or 0 if not calculated yet
818 wxCoord m_headerWidth
;
820 // the first and last lines being shown on screen right now (inclusive),
821 // both may be -1 if they must be calculated so never access them directly:
822 // use GetVisibleLinesRange() above instead
826 DECLARE_DYNAMIC_CLASS(wxListMainWindow
);
827 DECLARE_EVENT_TABLE()
830 // ============================================================================
832 // ============================================================================
834 // ----------------------------------------------------------------------------
836 // ----------------------------------------------------------------------------
838 bool wxSelectionStore::IsSelected(size_t item
) const
840 bool isSel
= m_itemsSel
.Index(item
) != wxNOT_FOUND
;
842 // if the default state is to be selected, being in m_itemsSel means that
843 // the item is not selected, so we have to inverse the logic
844 return m_defaultState
? !isSel
: isSel
;
847 bool wxSelectionStore::SelectItem(size_t item
, bool select
)
849 // search for the item ourselves as like this we get the index where to
850 // insert it later if needed, so we do only one search in the array instead
851 // of two (adding item to a sorted array requires a search)
852 size_t index
= m_itemsSel
.IndexForInsert(item
);
853 bool isSel
= index
< m_itemsSel
.GetCount() && m_itemsSel
[index
] == item
;
855 if ( select
!= m_defaultState
)
859 m_itemsSel
.AddAt(item
, index
);
864 else // reset to default state
868 m_itemsSel
.RemoveAt(index
);
876 void wxSelectionStore::SelectRange(size_t itemFrom
, size_t itemTo
, bool select
)
878 wxASSERT_MSG( itemFrom
<= itemTo
, _T("should be in order") );
880 // are we going to have more [un]selected items than the other ones?
881 if ( itemTo
- itemFrom
> m_count
/ 2 )
883 if ( select
!= m_defaultState
)
885 // the default state now becomes the same as 'select'
886 m_defaultState
= select
;
888 // so all the old selections (which had state select) shouldn't be
889 // selected any more, but all the other ones should
890 wxIndexArray selOld
= m_itemsSel
;
893 // TODO: it should be possible to optimize the searches a bit
894 // knowing the possible range
897 for ( item
= 0; item
< itemFrom
; item
++ )
899 if ( selOld
.Index(item
) == wxNOT_FOUND
)
900 m_itemsSel
.Add(item
);
903 for ( item
= itemTo
+ 1; item
< m_count
; item
++ )
905 if ( selOld
.Index(item
) == wxNOT_FOUND
)
906 m_itemsSel
.Add(item
);
909 else // select == m_defaultState
911 // get the inclusive range of items between itemFrom and itemTo
912 size_t count
= m_itemsSel
.GetCount(),
913 start
= m_itemsSel
.IndexForInsert(itemFrom
),
914 end
= m_itemsSel
.IndexForInsert(itemTo
);
916 if ( start
== count
|| m_itemsSel
[start
] < itemFrom
)
921 if ( end
== count
|| m_itemsSel
[end
] > itemTo
)
928 // delete all of them (from end to avoid changing indices)
929 for ( int i
= end
; i
>= (int)start
; i
-- )
931 m_itemsSel
.RemoveAt(i
);
936 else // "few" items change state
938 // just add the items to the selection
939 for ( size_t item
= itemFrom
; item
<= itemTo
; item
++ )
941 SelectItem(item
, select
);
946 void wxSelectionStore::OnItemDelete(size_t item
)
948 size_t count
= m_itemsSel
.GetCount(),
949 i
= m_itemsSel
.IndexForInsert(item
);
951 if ( i
< count
&& m_itemsSel
[i
] == item
)
953 // this item itself was in m_itemsSel, remove it from there
954 m_itemsSel
.RemoveAt(i
);
959 // and adjust the index of all which follow it
962 // all following elements must be greater than the one we deleted
963 wxASSERT_MSG( m_itemsSel
[i
] > item
, _T("logic error") );
969 //-----------------------------------------------------------------------------
971 //-----------------------------------------------------------------------------
973 void wxListItemData::Init()
981 wxListItemData::wxListItemData(wxListMainWindow
*owner
)
987 if ( owner
->HasFlag(wxLC_REPORT
) )
997 void wxListItemData::SetItem( const wxListItem
&info
)
999 if ( info
.m_mask
& wxLIST_MASK_TEXT
)
1000 SetText(info
.m_text
);
1001 if ( info
.m_mask
& wxLIST_MASK_IMAGE
)
1002 m_image
= info
.m_image
;
1003 if ( info
.m_mask
& wxLIST_MASK_DATA
)
1004 m_data
= info
.m_data
;
1006 if ( info
.HasAttributes() )
1009 *m_attr
= *info
.GetAttributes();
1011 m_attr
= new wxListItemAttr(*info
.GetAttributes());
1019 m_rect
->width
= info
.m_width
;
1023 void wxListItemData::SetPosition( int x
, int y
)
1025 wxCHECK_RET( m_rect
, _T("unexpected SetPosition() call") );
1031 void wxListItemData::SetSize( int width
, int height
)
1033 wxCHECK_RET( m_rect
, _T("unexpected SetSize() call") );
1036 m_rect
->width
= width
;
1038 m_rect
->height
= height
;
1041 bool wxListItemData::IsHit( int x
, int y
) const
1043 wxCHECK_MSG( m_rect
, FALSE
, _T("can't be called in this mode") );
1045 return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x
, y
);
1048 int wxListItemData::GetX() const
1050 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1055 int wxListItemData::GetY() const
1057 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1062 int wxListItemData::GetWidth() const
1064 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1066 return m_rect
->width
;
1069 int wxListItemData::GetHeight() const
1071 wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") );
1073 return m_rect
->height
;
1076 void wxListItemData::GetItem( wxListItem
&info
) const
1078 info
.m_text
= m_text
;
1079 info
.m_image
= m_image
;
1080 info
.m_data
= m_data
;
1084 if ( m_attr
->HasTextColour() )
1085 info
.SetTextColour(m_attr
->GetTextColour());
1086 if ( m_attr
->HasBackgroundColour() )
1087 info
.SetBackgroundColour(m_attr
->GetBackgroundColour());
1088 if ( m_attr
->HasFont() )
1089 info
.SetFont(m_attr
->GetFont());
1093 //-----------------------------------------------------------------------------
1095 //-----------------------------------------------------------------------------
1097 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData
,wxObject
);
1099 wxListHeaderData::wxListHeaderData()
1110 wxListHeaderData::wxListHeaderData( const wxListItem
&item
)
1118 void wxListHeaderData::SetItem( const wxListItem
&item
)
1120 m_mask
= item
.m_mask
;
1121 m_text
= item
.m_text
;
1122 m_image
= item
.m_image
;
1123 m_format
= item
.m_format
;
1125 SetWidth(item
.m_width
);
1128 void wxListHeaderData::SetPosition( int x
, int y
)
1134 void wxListHeaderData::SetHeight( int h
)
1139 void wxListHeaderData::SetWidth( int w
)
1143 m_width
= WIDTH_COL_DEFAULT
;
1144 if (m_width
< WIDTH_COL_MIN
)
1145 m_width
= WIDTH_COL_MIN
;
1148 void wxListHeaderData::SetFormat( int format
)
1153 bool wxListHeaderData::HasImage() const
1155 return (m_image
!= 0);
1158 bool wxListHeaderData::IsHit( int x
, int y
) const
1160 return ((x
>= m_xpos
) && (x
<= m_xpos
+m_width
) && (y
>= m_ypos
) && (y
<= m_ypos
+m_height
));
1163 void wxListHeaderData::GetItem( wxListItem
&item
)
1165 item
.m_mask
= m_mask
;
1166 item
.m_text
= m_text
;
1167 item
.m_image
= m_image
;
1168 item
.m_format
= m_format
;
1169 item
.m_width
= m_width
;
1172 int wxListHeaderData::GetImage() const
1177 int wxListHeaderData::GetWidth() const
1182 int wxListHeaderData::GetFormat() const
1187 //-----------------------------------------------------------------------------
1189 //-----------------------------------------------------------------------------
1191 inline int wxListLineData::GetMode() const
1193 return m_owner
->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE
;
1196 inline bool wxListLineData::InReportView() const
1198 return m_owner
->HasFlag(wxLC_REPORT
);
1201 inline bool wxListLineData::IsVirtual() const
1203 return m_owner
->IsVirtual();
1206 wxListLineData::wxListLineData( wxListMainWindow
*owner
)
1209 m_items
.DeleteContents( TRUE
);
1211 if ( InReportView() )
1217 m_gi
= new GeometryInfo
;
1220 m_highlighted
= FALSE
;
1222 InitItems( GetMode() == wxLC_REPORT
? m_owner
->GetColumnCount() : 1 );
1225 void wxListLineData::CalculateSize( wxDC
*dc
, int spacing
)
1227 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1228 wxCHECK_RET( node
, _T("no subitems at all??") );
1230 wxListItemData
*item
= node
->GetData();
1232 switch ( GetMode() )
1235 case wxLC_SMALL_ICON
:
1237 m_gi
->m_rectAll
.width
= spacing
;
1239 wxString s
= item
->GetText();
1245 m_gi
->m_rectLabel
.width
=
1246 m_gi
->m_rectLabel
.height
= 0;
1250 dc
->GetTextExtent( s
, &lw
, &lh
);
1251 if (lh
< SCROLL_UNIT_Y
)
1256 m_gi
->m_rectAll
.height
= spacing
+ lh
;
1258 m_gi
->m_rectAll
.width
= lw
;
1260 m_gi
->m_rectLabel
.width
= lw
;
1261 m_gi
->m_rectLabel
.height
= lh
;
1264 if (item
->HasImage())
1267 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1268 m_gi
->m_rectIcon
.width
= w
+ 8;
1269 m_gi
->m_rectIcon
.height
= h
+ 8;
1271 if ( m_gi
->m_rectIcon
.width
> m_gi
->m_rectAll
.width
)
1272 m_gi
->m_rectAll
.width
= m_gi
->m_rectIcon
.width
;
1273 if ( m_gi
->m_rectIcon
.height
+ lh
> m_gi
->m_rectAll
.height
- 4 )
1274 m_gi
->m_rectAll
.height
= m_gi
->m_rectIcon
.height
+ lh
+ 4;
1277 if ( item
->HasText() )
1279 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectLabel
.width
;
1280 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectLabel
.height
;
1282 else // no text, highlight the icon
1284 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectIcon
.width
;
1285 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectIcon
.height
;
1292 wxString s
= item
->GetTextForMeasuring();
1295 dc
->GetTextExtent( s
, &lw
, &lh
);
1296 if (lh
< SCROLL_UNIT_Y
)
1301 m_gi
->m_rectLabel
.width
= lw
;
1302 m_gi
->m_rectLabel
.height
= lh
;
1304 m_gi
->m_rectAll
.width
= lw
;
1305 m_gi
->m_rectAll
.height
= lh
;
1307 if (item
->HasImage())
1310 m_owner
->GetImageSize( item
->GetImage(), w
, h
);
1311 m_gi
->m_rectIcon
.width
= w
;
1312 m_gi
->m_rectIcon
.height
= h
;
1314 m_gi
->m_rectAll
.width
+= 4 + w
;
1315 if (h
> m_gi
->m_rectAll
.height
)
1316 m_gi
->m_rectAll
.height
= h
;
1319 m_gi
->m_rectHighlight
.width
= m_gi
->m_rectAll
.width
;
1320 m_gi
->m_rectHighlight
.height
= m_gi
->m_rectAll
.height
;
1325 wxFAIL_MSG( _T("unexpected call to SetSize") );
1329 wxFAIL_MSG( _T("unknown mode") );
1333 void wxListLineData::SetPosition( int x
, int y
,
1337 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1338 wxCHECK_RET( node
, _T("no subitems at all??") );
1340 wxListItemData
*item
= node
->GetData();
1342 switch ( GetMode() )
1345 case wxLC_SMALL_ICON
:
1346 m_gi
->m_rectAll
.x
= x
;
1347 m_gi
->m_rectAll
.y
= y
;
1349 if ( item
->HasImage() )
1351 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 4
1352 + (spacing
- m_gi
->m_rectIcon
.width
)/2;
1353 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 4;
1356 if ( item
->HasText() )
1358 if (m_gi
->m_rectAll
.width
> spacing
)
1359 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1361 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2 + (spacing
/2) - (m_gi
->m_rectLabel
.width
/2);
1362 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ m_gi
->m_rectAll
.height
+ 2 - m_gi
->m_rectLabel
.height
;
1363 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectLabel
.x
- 2;
1364 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectLabel
.y
- 2;
1366 else // no text, highlight the icon
1368 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectIcon
.x
- 4;
1369 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectIcon
.y
- 4;
1374 m_gi
->m_rectAll
.x
= x
;
1375 m_gi
->m_rectAll
.y
= y
;
1377 m_gi
->m_rectHighlight
.x
= m_gi
->m_rectAll
.x
;
1378 m_gi
->m_rectHighlight
.y
= m_gi
->m_rectAll
.y
;
1379 m_gi
->m_rectLabel
.y
= m_gi
->m_rectAll
.y
+ 2;
1381 if (item
->HasImage())
1383 m_gi
->m_rectIcon
.x
= m_gi
->m_rectAll
.x
+ 2;
1384 m_gi
->m_rectIcon
.y
= m_gi
->m_rectAll
.y
+ 2;
1385 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 6 + m_gi
->m_rectIcon
.width
;
1389 m_gi
->m_rectLabel
.x
= m_gi
->m_rectAll
.x
+ 2;
1394 wxFAIL_MSG( _T("unexpected call to SetPosition") );
1398 wxFAIL_MSG( _T("unknown mode") );
1402 void wxListLineData::InitItems( int num
)
1404 for (int i
= 0; i
< num
; i
++)
1405 m_items
.Append( new wxListItemData(m_owner
) );
1408 void wxListLineData::SetItem( int index
, const wxListItem
&info
)
1410 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1411 wxCHECK_RET( node
, _T("invalid column index in SetItem") );
1413 wxListItemData
*item
= node
->GetData();
1414 item
->SetItem( info
);
1417 void wxListLineData::GetItem( int index
, wxListItem
&info
)
1419 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1422 wxListItemData
*item
= node
->GetData();
1423 item
->GetItem( info
);
1427 wxString
wxListLineData::GetText(int index
) const
1431 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1434 wxListItemData
*item
= node
->GetData();
1435 s
= item
->GetText();
1441 void wxListLineData::SetText( int index
, const wxString s
)
1443 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1446 wxListItemData
*item
= node
->GetData();
1451 void wxListLineData::SetImage( int index
, int image
)
1453 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1454 wxCHECK_RET( node
, _T("invalid column index in SetImage()") );
1456 wxListItemData
*item
= node
->GetData();
1457 item
->SetImage(image
);
1460 int wxListLineData::GetImage( int index
) const
1462 wxListItemDataList::Node
*node
= m_items
.Item( index
);
1463 wxCHECK_MSG( node
, -1, _T("invalid column index in GetImage()") );
1465 wxListItemData
*item
= node
->GetData();
1466 return item
->GetImage();
1469 void wxListLineData::SetAttributes(wxDC
*dc
,
1470 const wxListItemAttr
*attr
,
1471 const wxColour
& colText
,
1475 // don't use foregroud colour for drawing highlighted items - this might
1476 // make them completely invisible (and there is no way to do bit
1477 // arithmetics on wxColour, unfortunately)
1478 if ( !highlight
&& attr
&& attr
->HasTextColour() )
1480 dc
->SetTextForeground(attr
->GetTextColour());
1484 dc
->SetTextForeground(colText
);
1487 if ( attr
&& attr
->HasFont() )
1489 dc
->SetFont(attr
->GetFont());
1497 void wxListLineData::Draw( wxDC
*dc
)
1499 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1500 wxCHECK_RET( node
, _T("no subitems at all??") );
1502 wxListItemData
*item
= node
->GetData();
1503 if (item
->HasImage())
1505 wxRect rectIcon
= m_gi
->m_rectIcon
;
1506 m_owner
->DrawImage( item
->GetImage(), dc
,
1507 rectIcon
.x
, rectIcon
.y
);
1510 if (item
->HasText())
1512 wxRect rectLabel
= m_gi
->m_rectLabel
;
1513 dc
->DrawText( item
->GetText(), rectLabel
.x
, rectLabel
.y
);
1517 void wxListLineData::DrawInReportMode( wxDC
*dc
,
1519 const wxRect
& rectHL
,
1522 // use our own flag if we maintain it
1524 highlighted
= m_highlighted
;
1526 // default foreground colour
1527 wxWindow
*listctrl
= m_owner
->GetParent();
1531 colText
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT
);
1535 colText
= listctrl
->GetForegroundColour();
1539 wxFont font
= listctrl
->GetFont();
1541 // VZ: currently we set the colours/fonts only once, but like this (i.e.
1542 // using SetAttributes() inside the loop), it will be trivial to
1543 // customize the subitems (in report mode) too.
1544 wxListItemData
*item
= m_items
.GetFirst()->GetData();
1545 wxListItemAttr
*attr
= item
->GetAttributes();
1546 SetAttributes(dc
, attr
, colText
, font
, highlighted
);
1548 bool hasBgCol
= attr
&& attr
->HasBackgroundColour();
1549 if ( highlighted
|| hasBgCol
)
1553 dc
->SetBrush( *m_owner
->m_highlightBrush
);
1558 dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
));
1560 dc
->SetBrush( * wxWHITE_BRUSH
);
1563 dc
->SetPen( * wxTRANSPARENT_PEN
);
1564 dc
->DrawRectangle( rectHL
);
1567 wxListItemDataList::Node
*node
= m_items
.GetFirst();
1568 wxCHECK_RET( node
, _T("no subitems at all??") );
1571 wxCoord x
= rect
.x
+ HEADER_OFFSET_X
,
1572 y
= rect
.y
+ (LINE_SPACING
+ EXTRA_HEIGHT
) / 2;
1576 wxListItemData
*item
= node
->GetData();
1580 if ( item
->HasImage() )
1583 m_owner
->DrawImage( item
->GetImage(), dc
, x
, y
);
1584 m_owner
->GetImageSize( item
->GetImage(), ix
, iy
);
1585 x
+= ix
+ 5; // FIXME: what is "5"?
1588 int width
= m_owner
->GetColumnWidth(col
++);
1590 wxDCClipper
clipper(*dc
, x
, y
, width
, rect
.height
);
1592 if ( item
->HasText() )
1594 dc
->DrawText( item
->GetText(), x
, y
);
1599 node
= node
->GetNext();
1603 bool wxListLineData::Highlight( bool on
)
1605 wxCHECK_MSG( !m_owner
->IsVirtual(), FALSE
, _T("unexpected call to Highlight") );
1607 if ( on
== m_highlighted
)
1615 void wxListLineData::ReverseHighlight( void )
1617 Highlight(!IsHighlighted());
1620 //-----------------------------------------------------------------------------
1621 // wxListHeaderWindow
1622 //-----------------------------------------------------------------------------
1624 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
);
1626 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
)
1627 EVT_PAINT (wxListHeaderWindow::OnPaint
)
1628 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse
)
1629 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus
)
1632 wxListHeaderWindow::wxListHeaderWindow( void )
1634 m_owner
= (wxListMainWindow
*) NULL
;
1635 m_currentCursor
= (wxCursor
*) NULL
;
1636 m_resizeCursor
= (wxCursor
*) NULL
;
1637 m_isDragging
= FALSE
;
1640 wxListHeaderWindow::wxListHeaderWindow( wxWindow
*win
, wxWindowID id
, wxListMainWindow
*owner
,
1641 const wxPoint
&pos
, const wxSize
&size
,
1642 long style
, const wxString
&name
) :
1643 wxWindow( win
, id
, pos
, size
, style
, name
)
1646 // m_currentCursor = wxSTANDARD_CURSOR;
1647 m_currentCursor
= (wxCursor
*) NULL
;
1648 m_resizeCursor
= new wxCursor( wxCURSOR_SIZEWE
);
1649 m_isDragging
= FALSE
;
1652 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
) );
1655 wxListHeaderWindow::~wxListHeaderWindow( void )
1657 delete m_resizeCursor
;
1660 void wxListHeaderWindow::DoDrawRect( wxDC
*dc
, int x
, int y
, int w
, int h
)
1663 GtkStateType state
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
1664 : GTK_STATE_INSENSITIVE
;
1666 x
= dc
->XLOG2DEV( x
);
1668 gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
,
1669 state
, GTK_SHADOW_OUT
,
1670 (GdkRectangle
*) NULL
, m_wxwindow
, "button",
1671 x
-1, y
-1, w
+2, h
+2);
1672 #elif defined( __WXMAC__ )
1673 const int m_corner
= 1;
1675 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1677 dc
->SetPen( wxPen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
) , 1 , wxSOLID
) );
1678 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1679 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1681 wxPen
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID
);
1684 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1685 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1687 dc
->SetPen( *wxWHITE_PEN
);
1688 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1689 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1690 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1691 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1693 const int m_corner
= 1;
1695 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
1697 dc
->SetPen( *wxBLACK_PEN
);
1698 dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h
); // right (outer)
1699 dc
->DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
1701 wxPen
pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW
), 1, wxSOLID
);
1704 dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h
); // right (inner)
1705 dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
1707 dc
->SetPen( *wxWHITE_PEN
);
1708 dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 ); // top (outer)
1709 dc
->DrawRectangle( x
, y
, 1, h
); // left (outer)
1710 dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
1711 dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
1715 // shift the DC origin to match the position of the main window horz
1716 // scrollbar: this allows us to always use logical coords
1717 void wxListHeaderWindow::AdjustDC(wxDC
& dc
)
1720 m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL
);
1723 m_owner
->GetViewStart( &x
, NULL
);
1725 // account for the horz scrollbar offset
1726 dc
.SetDeviceOrigin( -x
* xpix
, 0 );
1729 void wxListHeaderWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
1732 wxClientDC
dc( this );
1734 wxPaintDC
dc( this );
1742 dc
.SetFont( GetFont() );
1744 // width and height of the entire header window
1746 GetClientSize( &w
, &h
);
1747 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1749 dc
.SetBackgroundMode(wxTRANSPARENT
);
1751 // do *not* use the listctrl colour for headers - one day we will have a
1752 // function to set it separately
1753 //dc.SetTextForeground( *wxBLACK );
1754 dc
.SetTextForeground(wxSystemSettings::
1755 GetSystemColour( wxSYS_COLOUR_WINDOWTEXT
));
1757 int x
= HEADER_OFFSET_X
;
1759 int numColumns
= m_owner
->GetColumnCount();
1761 for (int i
= 0; i
< numColumns
; i
++)
1763 m_owner
->GetColumn( i
, item
);
1764 int wCol
= item
.m_width
;
1765 int cw
= wCol
- 2; // the width of the rect to draw
1767 int xEnd
= x
+ wCol
;
1769 dc
.SetPen( *wxWHITE_PEN
);
1771 DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 );
1772 dc
.SetClippingRegion( x
, HEADER_OFFSET_Y
, cw
-5, h
-4 );
1773 dc
.DrawText( item
.GetText(), x
+ EXTRA_WIDTH
, HEADER_OFFSET_Y
+ EXTRA_HEIGHT
);
1774 dc
.DestroyClippingRegion();
1783 void wxListHeaderWindow::DrawCurrent()
1785 int x1
= m_currentX
;
1787 ClientToScreen( &x1
, &y1
);
1789 int x2
= m_currentX
-1;
1791 m_owner
->GetClientSize( NULL
, &y2
);
1792 m_owner
->ClientToScreen( &x2
, &y2
);
1795 dc
.SetLogicalFunction( wxINVERT
);
1796 dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID
) );
1797 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1801 dc
.DrawLine( x1
, y1
, x2
, y2
);
1803 dc
.SetLogicalFunction( wxCOPY
);
1805 dc
.SetPen( wxNullPen
);
1806 dc
.SetBrush( wxNullBrush
);
1809 void wxListHeaderWindow::OnMouse( wxMouseEvent
&event
)
1811 // we want to work with logical coords
1813 m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
);
1814 int y
= event
.GetY();
1818 // we don't draw the line beyond our window, but we allow dragging it
1821 GetClientSize( &w
, NULL
);
1822 m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
);
1825 // erase the line if it was drawn
1826 if ( m_currentX
< w
)
1829 if (event
.ButtonUp())
1832 m_isDragging
= FALSE
;
1834 m_owner
->SetColumnWidth( m_column
, m_currentX
- m_minX
);
1841 m_currentX
= m_minX
+ 7;
1843 // draw in the new location
1844 if ( m_currentX
< w
)
1848 else // not dragging
1851 bool hit_border
= FALSE
;
1853 // end of the current column
1856 // find the column where this event occured
1857 int countCol
= m_owner
->GetColumnCount();
1858 for (int col
= 0; col
< countCol
; col
++)
1860 xpos
+= m_owner
->GetColumnWidth( col
);
1863 if ( (abs(x
-xpos
) < 3) && (y
< 22) )
1865 // near the column border
1872 // inside the column
1879 if (event
.LeftDown())
1883 m_isDragging
= TRUE
;
1890 wxWindow
*parent
= GetParent();
1891 wxListEvent
le( wxEVT_COMMAND_LIST_COL_CLICK
, parent
->GetId() );
1892 le
.SetEventObject( parent
);
1893 le
.m_col
= m_column
;
1894 parent
->GetEventHandler()->ProcessEvent( le
);
1897 else if (event
.Moving())
1902 setCursor
= m_currentCursor
== wxSTANDARD_CURSOR
;
1903 m_currentCursor
= m_resizeCursor
;
1907 setCursor
= m_currentCursor
!= wxSTANDARD_CURSOR
;
1908 m_currentCursor
= wxSTANDARD_CURSOR
;
1912 SetCursor(*m_currentCursor
);
1917 void wxListHeaderWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
1919 m_owner
->SetFocus();
1922 //-----------------------------------------------------------------------------
1923 // wxListRenameTimer (internal)
1924 //-----------------------------------------------------------------------------
1926 wxListRenameTimer::wxListRenameTimer( wxListMainWindow
*owner
)
1931 void wxListRenameTimer::Notify()
1933 m_owner
->OnRenameTimer();
1936 //-----------------------------------------------------------------------------
1937 // wxListTextCtrl (internal)
1938 //-----------------------------------------------------------------------------
1940 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl
,wxTextCtrl
);
1942 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
)
1943 EVT_CHAR (wxListTextCtrl::OnChar
)
1944 EVT_KEY_UP (wxListTextCtrl::OnKeyUp
)
1945 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus
)
1948 wxListTextCtrl::wxListTextCtrl( wxWindow
*parent
,
1949 const wxWindowID id
,
1952 wxListMainWindow
*owner
,
1953 const wxString
&value
,
1957 const wxValidator
& validator
,
1958 const wxString
&name
)
1959 : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name
)
1964 (*m_accept
) = FALSE
;
1966 m_startValue
= value
;
1969 void wxListTextCtrl::OnChar( wxKeyEvent
&event
)
1971 if (event
.m_keyCode
== WXK_RETURN
)
1974 (*m_res
) = GetValue();
1976 if (!wxPendingDelete
.Member(this))
1977 wxPendingDelete
.Append(this);
1979 if ((*m_accept
) && ((*m_res
) != m_startValue
))
1980 m_owner
->OnRenameAccept();
1984 if (event
.m_keyCode
== WXK_ESCAPE
)
1986 (*m_accept
) = FALSE
;
1989 if (!wxPendingDelete
.Member(this))
1990 wxPendingDelete
.Append(this);
1998 void wxListTextCtrl::OnKeyUp( wxKeyEvent
&event
)
2000 // auto-grow the textctrl:
2001 wxSize parentSize
= m_owner
->GetSize();
2002 wxPoint myPos
= GetPosition();
2003 wxSize mySize
= GetSize();
2005 GetTextExtent(GetValue() + _T("MM"), &sx
, &sy
); // FIXME: MM??
2006 if (myPos
.x
+ sx
> parentSize
.x
)
2007 sx
= parentSize
.x
- myPos
.x
;
2015 void wxListTextCtrl::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
2017 if (!wxPendingDelete
.Member(this))
2018 wxPendingDelete
.Append(this);
2020 if ((*m_accept
) && ((*m_res
) != m_startValue
))
2021 m_owner
->OnRenameAccept();
2024 //-----------------------------------------------------------------------------
2026 //-----------------------------------------------------------------------------
2028 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
);
2030 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
)
2031 EVT_PAINT (wxListMainWindow::OnPaint
)
2032 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse
)
2033 EVT_CHAR (wxListMainWindow::OnChar
)
2034 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown
)
2035 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus
)
2036 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus
)
2037 EVT_SCROLLWIN (wxListMainWindow::OnScroll
)
2040 void wxListMainWindow::Init()
2042 m_columns
.DeleteContents( TRUE
);
2046 m_lineTo
= (size_t)-1;
2052 m_small_image_list
= (wxImageList
*) NULL
;
2053 m_normal_image_list
= (wxImageList
*) NULL
;
2055 m_small_spacing
= 30;
2056 m_normal_spacing
= 40;
2060 m_isCreated
= FALSE
;
2062 m_lastOnSame
= FALSE
;
2063 m_renameTimer
= new wxListRenameTimer( this );
2064 m_renameAccept
= FALSE
;
2069 m_lineBeforeLastClicked
= (size_t)-1;
2072 void wxListMainWindow::InitScrolling()
2074 if ( HasFlag(wxLC_REPORT
) )
2076 m_xScroll
= SCROLL_UNIT_X
;
2077 m_yScroll
= SCROLL_UNIT_Y
;
2081 m_xScroll
= SCROLL_UNIT_Y
;
2086 wxListMainWindow::wxListMainWindow()
2090 m_highlightBrush
= (wxBrush
*) NULL
;
2096 wxListMainWindow::wxListMainWindow( wxWindow
*parent
,
2101 const wxString
&name
)
2102 : wxScrolledWindow( parent
, id
, pos
, size
,
2103 style
| wxHSCROLL
| wxVSCROLL
, name
)
2107 m_highlightBrush
= new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
), wxSOLID
);
2112 SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 );
2114 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX
) );
2117 wxListMainWindow::~wxListMainWindow()
2121 delete m_highlightBrush
;
2123 delete m_renameTimer
;
2126 void wxListMainWindow::CacheLineData(size_t line
)
2128 wxListCtrl
*listctrl
= GetListCtrl();
2130 wxListLineData
*ld
= GetDummyLine();
2132 size_t countCol
= GetColumnCount();
2133 for ( size_t col
= 0; col
< countCol
; col
++ )
2135 ld
->SetText(col
, listctrl
->OnGetItemText(line
, col
));
2138 ld
->SetImage(listctrl
->OnGetItemImage(line
));
2141 wxListLineData
*wxListMainWindow::GetDummyLine() const
2143 wxASSERT_MSG( !IsEmpty(), _T("invalid line index") );
2145 if ( m_lines
.IsEmpty() )
2147 // normal controls are supposed to have something in m_lines
2148 // already if it's not empty
2149 wxASSERT_MSG( IsVirtual(), _T("logic error") );
2151 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2152 wxListLineData
*line
= new wxListLineData(self
);
2153 self
->m_lines
.Add(line
);
2159 // ----------------------------------------------------------------------------
2160 // line geometry (report mode only)
2161 // ----------------------------------------------------------------------------
2163 wxCoord
wxListMainWindow::GetLineHeight() const
2165 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2167 // we cache the line height as calling GetTextExtent() is slow
2168 if ( !m_lineHeight
)
2170 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
2172 wxClientDC
dc( self
);
2173 dc
.SetFont( GetFont() );
2176 dc
.GetTextExtent(_T("H"), NULL
, &y
);
2178 if ( y
< SCROLL_UNIT_Y
)
2182 self
->m_lineHeight
= y
+ LINE_SPACING
;
2185 return m_lineHeight
;
2188 wxCoord
wxListMainWindow::GetLineY(size_t line
) const
2190 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") );
2192 return LINE_SPACING
+ line
*GetLineHeight();
2195 wxRect
wxListMainWindow::GetLineRect(size_t line
) const
2197 if ( !InReportView() )
2198 return GetLine(line
)->m_gi
->m_rectAll
;
2201 rect
.x
= HEADER_OFFSET_X
;
2202 rect
.y
= GetLineY(line
);
2203 rect
.width
= GetHeaderWidth();
2204 rect
.height
= GetLineHeight();
2209 wxRect
wxListMainWindow::GetLineLabelRect(size_t line
) const
2211 if ( !InReportView() )
2212 return GetLine(line
)->m_gi
->m_rectLabel
;
2215 rect
.x
= HEADER_OFFSET_X
;
2216 rect
.y
= GetLineY(line
);
2217 rect
.width
= GetColumnWidth(0);
2218 rect
.height
= GetLineHeight();
2223 wxRect
wxListMainWindow::GetLineIconRect(size_t line
) const
2225 if ( !InReportView() )
2226 return GetLine(line
)->m_gi
->m_rectIcon
;
2228 wxListLineData
*ld
= GetLine(line
);
2229 wxASSERT_MSG( ld
->HasImage(), _T("should have an image") );
2232 rect
.x
= HEADER_OFFSET_X
;
2233 rect
.y
= GetLineY(line
);
2234 GetImageSize(ld
->GetImage(), rect
.width
, rect
.height
);
2239 wxRect
wxListMainWindow::GetLineHighlightRect(size_t line
) const
2241 return InReportView() ? GetLineRect(line
)
2242 : GetLine(line
)->m_gi
->m_rectHighlight
;
2245 long wxListMainWindow::HitTestLine(size_t line
, int x
, int y
) const
2247 wxListLineData
*ld
= GetLine(line
);
2249 if ( ld
->HasImage() && GetLineIconRect(line
).Inside(x
, y
) )
2250 return wxLIST_HITTEST_ONITEMICON
;
2252 if ( ld
->HasText() )
2254 wxRect rect
= InReportView() ? GetLineRect(line
)
2255 : GetLineLabelRect(line
);
2257 if ( rect
.Inside(x
, y
) )
2258 return wxLIST_HITTEST_ONITEMLABEL
;
2264 // ----------------------------------------------------------------------------
2265 // highlight (selection) handling
2266 // ----------------------------------------------------------------------------
2268 bool wxListMainWindow::IsHighlighted(size_t line
) const
2272 return m_selStore
.IsSelected(line
);
2276 wxListLineData
*ld
= GetLine(line
);
2277 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2279 return ld
->IsHighlighted();
2283 void wxListMainWindow::HighlightLines( size_t lineFrom
, size_t lineTo
, bool highlight
)
2287 m_selStore
.SelectRange(lineFrom
, lineTo
, highlight
);
2288 RefreshLines(lineFrom
, lineTo
);
2292 // do it the dumb way
2293 bool needsRefresh
= FALSE
;
2294 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2296 if ( HighlightLine(line
, highlight
) )
2297 needsRefresh
= TRUE
;
2301 RefreshLines(lineFrom
, lineTo
);
2305 bool wxListMainWindow::HighlightLine( size_t line
, bool highlight
)
2311 changed
= m_selStore
.SelectItem(line
, highlight
);
2315 wxListLineData
*ld
= GetLine(line
);
2316 wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") );
2318 changed
= ld
->Highlight(highlight
);
2323 SendNotify( line
, highlight
? wxEVT_COMMAND_LIST_ITEM_SELECTED
2324 : wxEVT_COMMAND_LIST_ITEM_DESELECTED
);
2330 void wxListMainWindow::RefreshLine( size_t line
)
2332 wxRect rect
= GetLineRect(line
);
2334 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2335 RefreshRect( rect
);
2338 void wxListMainWindow::RefreshLines( size_t lineFrom
, size_t lineTo
)
2340 // we suppose that they are ordered by caller
2341 wxASSERT_MSG( lineFrom
<= lineTo
, _T("indices in disorder") );
2343 if ( HasFlag(wxLC_REPORT
) )
2345 size_t visibleFrom
, visibleTo
;
2346 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2348 if ( lineFrom
< visibleFrom
)
2349 lineFrom
= visibleFrom
;
2350 if ( lineTo
> visibleTo
)
2355 rect
.y
= GetLineY(lineFrom
);
2356 rect
.width
= GetClientSize().x
;
2357 rect
.height
= GetLineY(lineTo
) - rect
.y
;
2359 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
2360 RefreshRect( rect
);
2364 // TODO: this should be optimized...
2365 for ( size_t line
= lineFrom
; line
<= lineTo
; line
++ )
2372 void wxListMainWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
2374 // Note: a wxPaintDC must be constructed even if no drawing is
2375 // done (a Windows requirement).
2376 wxPaintDC
dc( this );
2380 // empty control. nothing to draw
2387 CalcScrolledPosition( 0, 0, &dev_x
, &dev_y
);
2391 dc
.SetFont( GetFont() );
2393 if ( HasFlag(wxLC_REPORT
) )
2395 int lineHeight
= GetLineHeight();
2397 size_t visibleFrom
, visibleTo
;
2398 GetVisibleLinesRange(&visibleFrom
, &visibleTo
);
2399 for ( size_t line
= visibleFrom
; line
<= visibleTo
; line
++ )
2401 GetLine(line
)->DrawInReportMode( &dc
,
2403 GetLineHighlightRect(line
),
2404 IsHighlighted(line
) );
2407 if ( HasFlag(wxLC_HRULES
) )
2409 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2410 wxSize clientSize
= GetClientSize();
2412 for ( size_t i
= visibleFrom
; i
<= visibleTo
; i
++ )
2415 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2416 dc
.DrawLine(0 - dev_x
, i
*lineHeight
,
2417 clientSize
.x
- dev_x
, i
*lineHeight
);
2420 // Draw last horizontal rule
2421 if ( visibleTo
> visibleFrom
)
2424 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2425 dc
.DrawLine(0 - dev_x
, m_lineTo
*lineHeight
,
2426 clientSize
.x
- dev_x
, m_lineTo
*lineHeight
);
2430 // Draw vertical rules if required
2431 if ( HasFlag(wxLC_VRULES
) && !IsEmpty() )
2433 wxPen
pen(GetRuleColour(), 1, wxSOLID
);
2436 wxRect firstItemRect
;
2437 wxRect lastItemRect
;
2438 GetItemRect(0, firstItemRect
);
2439 GetItemRect(GetItemCount() - 1, lastItemRect
);
2440 int x
= firstItemRect
.GetX();
2442 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
2443 for (col
= 0; col
< GetColumnCount(); col
++)
2445 int colWidth
= GetColumnWidth(col
);
2447 dc
.DrawLine(x
- dev_x
, firstItemRect
.GetY() - 1 - dev_y
,
2448 x
- dev_x
, lastItemRect
.GetBottom() + 1 - dev_y
);
2454 size_t count
= GetItemCount();
2455 for ( size_t i
= 0; i
< count
; i
++ )
2457 GetLine(i
)->Draw( &dc
);
2461 if ( HasCurrent() && m_hasFocus
)
2464 // no rect outline, we already have the background color
2466 dc
.SetPen( *wxBLACK_PEN
);
2467 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
2468 dc
.DrawRectangle( GetLineHighlightRect(m_current
) );
2475 void wxListMainWindow::HighlightAll( bool on
)
2477 if ( IsSingleSel() )
2479 wxASSERT_MSG( !on
, _T("can't do this in a single sel control") );
2481 // we just have one item to turn off
2482 if ( HasCurrent() && IsHighlighted(m_current
) )
2484 HighlightLine(m_current
, FALSE
);
2485 RefreshLine(m_current
);
2490 HighlightLines(0, GetItemCount() - 1, on
);
2494 void wxListMainWindow::SendNotify( size_t line
,
2495 wxEventType command
,
2498 wxListEvent
le( command
, GetParent()->GetId() );
2499 le
.SetEventObject( GetParent() );
2500 le
.m_itemIndex
= line
;
2502 // set only for events which have position
2503 if ( point
!= wxDefaultPosition
)
2504 le
.m_pointDrag
= point
;
2506 GetLine(line
)->GetItem( 0, le
.m_item
);
2507 GetParent()->GetEventHandler()->ProcessEvent( le
);
2510 void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line
) )
2512 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
2515 void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line
) )
2517 // SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
2520 void wxListMainWindow::EditLabel( long item
)
2522 wxCHECK_RET( (item
>= 0) && ((size_t)item
< GetItemCount()),
2523 wxT("wrong index in wxListCtrl::EditLabel()") );
2525 m_currentEdit
= (size_t)item
;
2527 wxListEvent
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() );
2528 le
.SetEventObject( GetParent() );
2529 le
.m_itemIndex
= item
;
2530 wxListLineData
*data
= GetLine(m_currentEdit
);
2531 wxCHECK_RET( data
, _T("invalid index in EditLabel()") );
2532 data
->GetItem( 0, le
.m_item
);
2533 GetParent()->GetEventHandler()->ProcessEvent( le
);
2535 if (!le
.IsAllowed())
2538 // We have to call this here because the label in question might just have
2539 // been added and no screen update taken place.
2543 wxClientDC
dc(this);
2546 wxString s
= data
->GetText(0);
2547 wxRect rectLabel
= GetLineLabelRect(m_currentEdit
);
2549 rectLabel
.x
= dc
.LogicalToDeviceX( rectLabel
.x
);
2550 rectLabel
.y
= dc
.LogicalToDeviceY( rectLabel
.y
);
2552 wxListTextCtrl
*text
= new wxListTextCtrl
2559 wxPoint(rectLabel
.x
-4,rectLabel
.y
-4),
2560 wxSize(rectLabel
.width
+11,rectLabel
.height
+8)
2565 void wxListMainWindow::OnRenameTimer()
2567 wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") );
2569 EditLabel( m_current
);
2572 void wxListMainWindow::OnRenameAccept()
2574 wxListEvent
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() );
2575 le
.SetEventObject( GetParent() );
2576 le
.m_itemIndex
= m_currentEdit
;
2578 wxListLineData
*data
= GetLine(m_currentEdit
);
2579 wxCHECK_RET( data
, _T("invalid index in OnRenameAccept()") );
2581 data
->GetItem( 0, le
.m_item
);
2582 le
.m_item
.m_text
= m_renameRes
;
2583 GetParent()->GetEventHandler()->ProcessEvent( le
);
2585 if (!le
.IsAllowed()) return;
2588 info
.m_mask
= wxLIST_MASK_TEXT
;
2589 info
.m_itemId
= le
.m_itemIndex
;
2590 info
.m_text
= m_renameRes
;
2591 info
.SetTextColour(le
.m_item
.GetTextColour());
2595 void wxListMainWindow::OnMouse( wxMouseEvent
&event
)
2597 event
.SetEventObject( GetParent() );
2598 if ( GetParent()->GetEventHandler()->ProcessEvent( event
) )
2601 if ( !HasCurrent() || IsEmpty() )
2607 if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() ||
2608 event
.ButtonDClick()) )
2611 int x
= event
.GetX();
2612 int y
= event
.GetY();
2613 CalcUnscrolledPosition( x
, y
, &x
, &y
);
2615 /* Did we actually hit an item ? */
2618 size_t count
= GetItemCount(),
2621 if ( HasFlag(wxLC_REPORT
) )
2623 current
= y
/ GetLineHeight();
2624 hitResult
= HitTestLine(current
, x
, y
);
2628 // TODO: optimize it too! this is less simple than for report view but
2629 // enumerating all items is still not a way to do it!!
2630 for ( current
= 0; current
< count
&& !hitResult
; current
++ )
2632 hitResult
= HitTestLine(current
, x
, y
);
2636 if (event
.Dragging())
2638 if (m_dragCount
== 0)
2639 m_dragStart
= wxPoint(x
,y
);
2643 if (m_dragCount
!= 3)
2646 int command
= event
.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2647 : wxEVT_COMMAND_LIST_BEGIN_DRAG
;
2649 wxListEvent
le( command
, GetParent()->GetId() );
2650 le
.SetEventObject( GetParent() );
2651 le
.m_pointDrag
= m_dragStart
;
2652 GetParent()->GetEventHandler()->ProcessEvent( le
);
2663 // outside of any item
2667 bool forceClick
= FALSE
;
2668 if (event
.ButtonDClick())
2670 m_renameTimer
->Stop();
2671 m_lastOnSame
= FALSE
;
2673 if ( current
== m_lineBeforeLastClicked
)
2675 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
);
2681 // the first click was on another item, so don't interpret this as
2682 // a double click, but as a simple click instead
2687 if (event
.LeftUp() && m_lastOnSame
)
2689 if ((current
== m_current
) &&
2690 (hitResult
== wxLIST_HITTEST_ONITEMLABEL
) &&
2691 HasFlag(wxLC_EDIT_LABELS
) )
2693 m_renameTimer
->Start( 100, TRUE
);
2695 m_lastOnSame
= FALSE
;
2697 else if (event
.RightDown())
2699 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
,
2700 event
.GetPosition() );
2702 else if (event
.MiddleDown())
2704 SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
);
2706 else if ( event
.LeftDown() || forceClick
)
2708 m_lineBeforeLastClicked
= m_lineLastClicked
;
2709 m_lineLastClicked
= current
;
2711 size_t oldCurrent
= m_current
;
2713 if ( IsSingleSel() || !(event
.ControlDown() || event
.ShiftDown()) )
2715 HighlightAll( FALSE
);
2716 m_current
= current
;
2718 ReverseHighlight(m_current
);
2720 else // multi sel & either ctrl or shift is down
2722 if (event
.ControlDown())
2724 m_current
= current
;
2726 ReverseHighlight(m_current
);
2728 else if (event
.ShiftDown())
2730 m_current
= current
;
2732 size_t lineFrom
= oldCurrent
,
2735 if ( lineTo
< lineFrom
)
2738 lineFrom
= m_current
;
2741 HighlightLines(lineFrom
, lineTo
);
2743 else // !ctrl, !shift
2745 // test in the enclosing if should make it impossible
2746 wxFAIL_MSG( _T("how did we get here?") );
2750 if (m_current
!= oldCurrent
)
2752 RefreshLine( oldCurrent
);
2753 OnUnfocusLine( oldCurrent
);
2754 OnFocusLine( m_current
);
2757 // forceClick is only set if the previous click was on another item
2758 m_lastOnSame
= !forceClick
&& (m_current
== oldCurrent
);
2762 void wxListMainWindow::MoveToFocus()
2764 if ( !HasCurrent() )
2767 wxRect rect
= GetLineRect(m_current
);
2769 int client_w
, client_h
;
2770 GetClientSize( &client_w
, &client_h
);
2772 int view_x
= m_xScroll
*GetScrollPos( wxHORIZONTAL
);
2773 int view_y
= m_yScroll
*GetScrollPos( wxVERTICAL
);
2775 if ( HasFlag(wxLC_REPORT
) )
2777 // the next we need the range of lines shown it might be different, so
2779 ResetVisibleLinesRange();
2781 if (rect
.y
< view_y
)
2782 Scroll( -1, rect
.y
/m_yScroll
);
2783 if (rect
.y
+rect
.height
+5 > view_y
+client_h
)
2784 Scroll( -1, (rect
.y
+rect
.height
-client_h
+SCROLL_UNIT_Y
)/m_yScroll
);
2788 if (rect
.x
-view_x
< 5)
2789 Scroll( (rect
.x
-5)/m_xScroll
, -1 );
2790 if (rect
.x
+rect
.width
-5 > view_x
+client_w
)
2791 Scroll( (rect
.x
+rect
.width
-client_w
+SCROLL_UNIT_X
)/m_xScroll
, -1 );
2795 // ----------------------------------------------------------------------------
2796 // keyboard handling
2797 // ----------------------------------------------------------------------------
2799 void wxListMainWindow::OnArrowChar(size_t newCurrent
, const wxKeyEvent
& event
)
2801 wxCHECK_RET( newCurrent
< (size_t)GetItemCount(),
2802 _T("invalid item index in OnArrowChar()") );
2804 size_t oldCurrent
= m_current
;
2806 // in single selection we just ignore Shift as we can't select several
2808 if ( event
.ShiftDown() && !IsSingleSel() )
2810 m_current
= newCurrent
;
2812 // select all the items between the old and the new one
2813 if ( oldCurrent
> newCurrent
)
2815 newCurrent
= oldCurrent
;
2816 oldCurrent
= m_current
;
2819 HighlightLines(oldCurrent
, newCurrent
);
2823 // all previously selected items are unselected unless ctrl is held
2824 if ( !event
.ControlDown() )
2825 HighlightAll(FALSE
);
2827 m_current
= newCurrent
;
2829 HighlightLine( oldCurrent
, FALSE
);
2830 RefreshLine( oldCurrent
);
2832 if ( !event
.ControlDown() )
2834 HighlightLine( m_current
, TRUE
);
2838 OnUnfocusLine( oldCurrent
);
2839 OnFocusLine( m_current
);
2840 RefreshLine( m_current
);
2845 void wxListMainWindow::OnKeyDown( wxKeyEvent
&event
)
2847 wxWindow
*parent
= GetParent();
2849 /* we propagate the key event up */
2850 wxKeyEvent
ke( wxEVT_KEY_DOWN
);
2851 ke
.m_shiftDown
= event
.m_shiftDown
;
2852 ke
.m_controlDown
= event
.m_controlDown
;
2853 ke
.m_altDown
= event
.m_altDown
;
2854 ke
.m_metaDown
= event
.m_metaDown
;
2855 ke
.m_keyCode
= event
.m_keyCode
;
2858 ke
.SetEventObject( parent
);
2859 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2864 void wxListMainWindow::OnChar( wxKeyEvent
&event
)
2866 wxWindow
*parent
= GetParent();
2868 /* we send a list_key event up */
2871 wxListEvent
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() );
2872 le
.m_itemIndex
= m_current
;
2873 GetLine(m_current
)->GetItem( 0, le
.m_item
);
2874 le
.m_code
= (int)event
.KeyCode();
2875 le
.SetEventObject( parent
);
2876 parent
->GetEventHandler()->ProcessEvent( le
);
2879 /* we propagate the char event up */
2880 wxKeyEvent
ke( wxEVT_CHAR
);
2881 ke
.m_shiftDown
= event
.m_shiftDown
;
2882 ke
.m_controlDown
= event
.m_controlDown
;
2883 ke
.m_altDown
= event
.m_altDown
;
2884 ke
.m_metaDown
= event
.m_metaDown
;
2885 ke
.m_keyCode
= event
.m_keyCode
;
2888 ke
.SetEventObject( parent
);
2889 if (parent
->GetEventHandler()->ProcessEvent( ke
)) return;
2891 if (event
.KeyCode() == WXK_TAB
)
2893 wxNavigationKeyEvent nevent
;
2894 nevent
.SetWindowChange( event
.ControlDown() );
2895 nevent
.SetDirection( !event
.ShiftDown() );
2896 nevent
.SetEventObject( GetParent()->GetParent() );
2897 nevent
.SetCurrentFocus( m_parent
);
2898 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent
)) return;
2901 /* no item -> nothing to do */
2908 switch (event
.KeyCode())
2911 if ( m_current
> 0 )
2912 OnArrowChar( m_current
- 1, event
);
2916 if ( m_current
< (size_t)GetItemCount() - 1 )
2917 OnArrowChar( m_current
+ 1, event
);
2922 OnArrowChar( GetItemCount() - 1, event
);
2927 OnArrowChar( 0, event
);
2933 if ( HasFlag(wxLC_REPORT
) )
2935 steps
= m_linesPerPage
- 1;
2939 steps
= m_current
% m_linesPerPage
;
2942 int index
= m_current
- steps
;
2946 OnArrowChar( index
, event
);
2953 if ( HasFlag(wxLC_REPORT
) )
2955 steps
= m_linesPerPage
- 1;
2959 steps
= m_linesPerPage
- (m_current
% m_linesPerPage
) - 1;
2962 size_t index
= m_current
+ steps
;
2963 size_t count
= GetItemCount();
2964 if ( index
>= count
)
2967 OnArrowChar( index
, event
);
2972 if ( !HasFlag(wxLC_REPORT
) )
2974 int index
= m_current
- m_linesPerPage
;
2978 OnArrowChar( index
, event
);
2983 if ( !HasFlag(wxLC_REPORT
) )
2985 size_t index
= m_current
+ m_linesPerPage
;
2987 size_t count
= GetItemCount();
2988 if ( index
>= count
)
2991 OnArrowChar( index
, event
);
2996 if ( IsSingleSel() )
2998 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
2999 GetParent()->GetId() );
3000 le
.SetEventObject( GetParent() );
3001 le
.m_itemIndex
= m_current
;
3002 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3003 GetParent()->GetEventHandler()->ProcessEvent( le
);
3007 ReverseHighlight(m_current
);
3014 wxListEvent
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
3015 GetParent()->GetId() );
3016 le
.SetEventObject( GetParent() );
3017 le
.m_itemIndex
= m_current
;
3018 GetLine(m_current
)->GetItem( 0, le
.m_item
);
3019 GetParent()->GetEventHandler()->ProcessEvent( le
);
3028 // ----------------------------------------------------------------------------
3030 // ----------------------------------------------------------------------------
3033 extern wxWindow
*g_focusWindow
;
3036 void wxListMainWindow::OnSetFocus( wxFocusEvent
&WXUNUSED(event
) )
3041 RefreshLine( m_current
);
3047 g_focusWindow
= GetParent();
3050 wxFocusEvent
event( wxEVT_SET_FOCUS
, GetParent()->GetId() );
3051 event
.SetEventObject( GetParent() );
3052 GetParent()->GetEventHandler()->ProcessEvent( event
);
3055 void wxListMainWindow::OnKillFocus( wxFocusEvent
&WXUNUSED(event
) )
3060 RefreshLine( m_current
);
3063 void wxListMainWindow::DrawImage( int index
, wxDC
*dc
, int x
, int y
)
3065 if ( HasFlag(wxLC_ICON
) && (m_normal_image_list
))
3067 m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3069 else if ( HasFlag(wxLC_SMALL_ICON
) && (m_small_image_list
))
3071 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3073 else if ( HasFlag(wxLC_LIST
) && (m_small_image_list
))
3075 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3077 else if ( HasFlag(wxLC_REPORT
) && (m_small_image_list
))
3079 m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT
);
3083 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height
) const
3085 if ( HasFlag(wxLC_ICON
) && m_normal_image_list
)
3087 m_normal_image_list
->GetSize( index
, width
, height
);
3089 else if ( HasFlag(wxLC_SMALL_ICON
) && m_small_image_list
)
3091 m_small_image_list
->GetSize( index
, width
, height
);
3093 else if ( HasFlag(wxLC_LIST
) && m_small_image_list
)
3095 m_small_image_list
->GetSize( index
, width
, height
);
3097 else if ( HasFlag(wxLC_REPORT
) && m_small_image_list
)
3099 m_small_image_list
->GetSize( index
, width
, height
);
3108 int wxListMainWindow::GetTextLength( const wxString
&s
) const
3110 wxClientDC
dc( wxConstCast(this, wxListMainWindow
) );
3111 dc
.SetFont( GetFont() );
3114 dc
.GetTextExtent( s
, &lw
, NULL
);
3116 return lw
+ AUTOSIZE_COL_MARGIN
;
3119 void wxListMainWindow::SetImageList( wxImageList
*imageList
, int which
)
3123 // calc the spacing from the icon size
3126 if ((imageList
) && (imageList
->GetImageCount()) )
3128 imageList
->GetSize(0, width
, height
);
3131 if (which
== wxIMAGE_LIST_NORMAL
)
3133 m_normal_image_list
= imageList
;
3134 m_normal_spacing
= width
+ 8;
3137 if (which
== wxIMAGE_LIST_SMALL
)
3139 m_small_image_list
= imageList
;
3140 m_small_spacing
= width
+ 14;
3144 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall
)
3149 m_small_spacing
= spacing
;
3153 m_normal_spacing
= spacing
;
3157 int wxListMainWindow::GetItemSpacing( bool isSmall
)
3159 return isSmall
? m_small_spacing
: m_normal_spacing
;
3162 // ----------------------------------------------------------------------------
3164 // ----------------------------------------------------------------------------
3166 void wxListMainWindow::SetColumn( int col
, wxListItem
&item
)
3168 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3170 wxCHECK_RET( node
, _T("invalid column index in SetColumn") );
3172 if ( item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3173 item
.m_width
= GetTextLength( item
.m_text
);
3175 wxListHeaderData
*column
= node
->GetData();
3176 column
->SetItem( item
);
3178 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3180 headerWin
->m_dirty
= TRUE
;
3184 // invalidate it as it has to be recalculated
3188 void wxListMainWindow::SetColumnWidth( int col
, int width
)
3190 wxCHECK_RET( col
>= 0 && col
< GetColumnCount(),
3191 _T("invalid column index") );
3193 wxCHECK_RET( HasFlag(wxLC_REPORT
),
3194 _T("SetColumnWidth() can only be called in report mode.") );
3198 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3199 wxCHECK_RET( node
, _T("no column?") );
3201 wxListHeaderData
*column
= node
->GetData();
3203 size_t count
= GetItemCount();
3205 if (width
== wxLIST_AUTOSIZE_USEHEADER
)
3207 width
= GetTextLength(column
->GetText());
3209 else if ( width
== wxLIST_AUTOSIZE
)
3213 // TODO: determine the max width somehow...
3214 width
= WIDTH_COL_DEFAULT
;
3218 wxClientDC
dc(this);
3219 dc
.SetFont( GetFont() );
3221 int max
= AUTOSIZE_COL_MARGIN
;
3223 for ( size_t i
= 0; i
< count
; i
++ )
3225 wxListLineData
*line
= GetLine(i
);
3226 wxListItemDataList::Node
*n
= line
->m_items
.Item( col
);
3228 wxCHECK_RET( n
, _T("no subitem?") );
3230 wxListItemData
*item
= n
->GetData();
3233 if (item
->HasImage())
3236 GetImageSize( item
->GetImage(), ix
, iy
);
3240 if (item
->HasText())
3243 dc
.GetTextExtent( item
->GetText(), &w
, NULL
);
3251 width
= max
+ AUTOSIZE_COL_MARGIN
;
3255 column
->SetWidth( width
);
3257 // invalidate it as it has to be recalculated
3261 int wxListMainWindow::GetHeaderWidth() const
3263 if ( !m_headerWidth
)
3265 wxListMainWindow
*self
= wxConstCast(this, wxListMainWindow
);
3267 size_t count
= GetColumnCount();
3268 for ( size_t col
= 0; col
< count
; col
++ )
3270 self
->m_headerWidth
+= GetColumnWidth(col
);
3274 return m_headerWidth
;
3277 void wxListMainWindow::GetColumn( int col
, wxListItem
&item
) const
3279 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3280 wxCHECK_RET( node
, _T("invalid column index in GetColumn") );
3282 wxListHeaderData
*column
= node
->GetData();
3283 column
->GetItem( item
);
3286 int wxListMainWindow::GetColumnWidth( int col
) const
3288 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3289 wxCHECK_MSG( node
, 0, _T("invalid column index") );
3291 wxListHeaderData
*column
= node
->GetData();
3292 return column
->GetWidth();
3295 // ----------------------------------------------------------------------------
3297 // ----------------------------------------------------------------------------
3299 void wxListMainWindow::SetItem( wxListItem
&item
)
3301 long id
= item
.m_itemId
;
3302 wxCHECK_RET( id
>= 0 && (size_t)id
< GetItemCount(),
3303 _T("invalid item index in SetItem") );
3307 // just refresh the line to show the new value of the text/image
3308 RefreshLine((size_t)id
);
3314 wxListLineData
*line
= GetLine((size_t)id
);
3315 if ( HasFlag(wxLC_REPORT
) )
3316 item
.m_width
= GetColumnWidth( item
.m_col
);
3317 line
->SetItem( item
.m_col
, item
);
3321 void wxListMainWindow::SetItemState( long litem
, long state
, long stateMask
)
3323 wxCHECK_RET( litem
>= 0 && (size_t)litem
< GetItemCount(),
3324 _T("invalid list ctrl item index in SetItem") );
3326 size_t oldCurrent
= m_current
;
3327 size_t item
= (size_t)litem
; // sdafe because of the check above
3329 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3331 if ( state
& wxLIST_STATE_FOCUSED
)
3333 // don't do anything if this item is already focused
3334 if ( item
!= m_current
)
3336 OnUnfocusLine( m_current
);
3338 OnFocusLine( m_current
);
3340 if ( IsSingleSel() && (oldCurrent
!= (size_t)-1) )
3342 HighlightLine(oldCurrent
, FALSE
);
3343 RefreshLine(oldCurrent
);
3346 RefreshLine( m_current
);
3351 // don't do anything if this item is not focused
3352 if ( item
== m_current
)
3354 OnUnfocusLine( m_current
);
3355 m_current
= (size_t)-1;
3360 if ( stateMask
& wxLIST_STATE_SELECTED
)
3362 bool on
= (state
& wxLIST_STATE_SELECTED
) != 0;
3364 if ( IsSingleSel() )
3368 // selecting the item also makes it the focused one in the
3370 if ( m_current
!= item
)
3372 OnUnfocusLine( m_current
);
3374 OnFocusLine( m_current
);
3376 if ( oldCurrent
!= (size_t)-1 )
3378 HighlightLine( oldCurrent
, FALSE
);
3379 RefreshLine( oldCurrent
);
3385 // only the current item may be selected anyhow
3386 if ( item
!= m_current
)
3391 if ( HighlightLine(item
, on
) )
3398 int wxListMainWindow::GetItemState( long item
, long stateMask
)
3400 wxCHECK_MSG( item
>= 0 && (size_t)item
< GetItemCount(), 0,
3401 _T("invalid list ctrl item index in GetItemState()") );
3403 int ret
= wxLIST_STATE_DONTCARE
;
3405 if ( stateMask
& wxLIST_STATE_FOCUSED
)
3407 if ( (size_t)item
== m_current
)
3408 ret
|= wxLIST_STATE_FOCUSED
;
3411 if ( stateMask
& wxLIST_STATE_SELECTED
)
3413 if ( IsHighlighted(item
) )
3414 ret
|= wxLIST_STATE_SELECTED
;
3420 void wxListMainWindow::GetItem( wxListItem
&item
)
3422 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
< GetItemCount(),
3423 _T("invalid item index in GetItem") );
3425 wxListLineData
*line
= GetLine((size_t)item
.m_itemId
);
3426 line
->GetItem( item
.m_col
, item
);
3429 // ----------------------------------------------------------------------------
3431 // ----------------------------------------------------------------------------
3433 size_t wxListMainWindow::GetItemCount() const
3435 return IsVirtual() ? m_countVirt
: m_lines
.GetCount();
3438 void wxListMainWindow::SetItemCount(long count
)
3440 m_selStore
.SetItemCount(count
);
3441 m_countVirt
= count
;
3446 int wxListMainWindow::GetSelectedItemCount()
3448 // deal with the quick case first
3449 if ( IsSingleSel() )
3451 return HasCurrent() ? IsHighlighted(m_current
) : FALSE
;
3454 // virtual controls remmebers all its selections itself
3456 return m_selStore
.GetSelectedCount();
3458 // TODO: we probably should maintain the number of items selected even for
3459 // non virtual controls as enumerating all lines is really slow...
3460 size_t countSel
= 0;
3461 size_t count
= GetItemCount();
3462 for ( size_t line
= 0; line
< count
; line
++ )
3464 if ( GetLine(line
)->IsHighlighted() )
3471 // ----------------------------------------------------------------------------
3472 // item position/size
3473 // ----------------------------------------------------------------------------
3475 void wxListMainWindow::GetItemRect( long index
, wxRect
&rect
)
3477 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3478 _T("invalid index in GetItemRect") );
3480 rect
= GetLineRect((size_t)index
);
3482 CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
3485 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
)
3488 GetItemRect(item
, rect
);
3496 // ----------------------------------------------------------------------------
3497 // geometry calculation
3498 // ----------------------------------------------------------------------------
3500 void wxListMainWindow::RecalculatePositions()
3505 wxClientDC
dc( this );
3506 dc
.SetFont( GetFont() );
3509 if ( HasFlag(wxLC_ICON
) )
3510 iconSpacing
= m_normal_spacing
;
3511 else if ( HasFlag(wxLC_SMALL_ICON
) )
3512 iconSpacing
= m_small_spacing
;
3518 GetClientSize( &clientWidth
, &clientHeight
);
3520 if ( HasFlag(wxLC_REPORT
) )
3522 // all lines have the same height
3523 int lineHeight
= GetLineHeight();
3525 // scroll one line per step
3526 m_yScroll
= lineHeight
;
3528 size_t lineCount
= GetItemCount();
3529 int entireHeight
= lineCount
*lineHeight
+ LINE_SPACING
;
3531 m_linesPerPage
= clientHeight
/ lineHeight
;
3533 ResetVisibleLinesRange();
3535 SetScrollbars( m_xScroll
, m_yScroll
,
3536 (GetHeaderWidth() + m_xScroll
- 1)/m_xScroll
,
3537 (entireHeight
+ m_yScroll
- 1)/m_yScroll
,
3538 GetScrollPos(wxHORIZONTAL
),
3539 GetScrollPos(wxVERTICAL
),
3544 // at first we try without any scrollbar. if the items don't
3545 // fit into the window, we recalculate after subtracting an
3546 // approximated 15 pt for the horizontal scrollbar
3548 clientHeight
-= 4; // sunken frame
3550 int entireWidth
= 0;
3552 for (int tries
= 0; tries
< 2; tries
++)
3559 int currentlyVisibleLines
= 0;
3561 size_t count
= GetItemCount();
3562 for (size_t i
= 0; i
< count
; i
++)
3564 currentlyVisibleLines
++;
3565 wxListLineData
*line
= GetLine(i
);
3566 line
->CalculateSize( &dc
, iconSpacing
);
3567 line
->SetPosition( x
, y
, clientWidth
, iconSpacing
);
3569 wxSize sizeLine
= GetLineSize(i
);
3571 if ( maxWidth
< sizeLine
.x
)
3572 maxWidth
= sizeLine
.x
;
3575 if (currentlyVisibleLines
> m_linesPerPage
)
3576 m_linesPerPage
= currentlyVisibleLines
;
3578 // assume that the size of the next one is the same... (FIXME)
3579 if ( y
+ sizeLine
.y
- 6 >= clientHeight
)
3581 currentlyVisibleLines
= 0;
3584 entireWidth
+= maxWidth
+6;
3587 if ( i
== count
- 1 )
3588 entireWidth
+= maxWidth
;
3589 if ((tries
== 0) && (entireWidth
> clientWidth
))
3591 clientHeight
-= 15; // scrollbar height
3593 currentlyVisibleLines
= 0;
3596 if ( i
== count
- 1 )
3597 tries
= 1; // everything fits, no second try required
3601 int scroll_pos
= GetScrollPos( wxHORIZONTAL
);
3602 SetScrollbars( m_xScroll
, m_yScroll
, (entireWidth
+SCROLL_UNIT_X
) / m_xScroll
, 0, scroll_pos
, 0, TRUE
);
3605 // FIXME: why should we call it from here?
3611 void wxListMainWindow::RefreshAll()
3616 wxListHeaderWindow
*headerWin
= GetListCtrl()->m_headerWin
;
3619 headerWin
->m_dirty
= FALSE
;
3620 headerWin
->Refresh();
3624 void wxListMainWindow::UpdateCurrent()
3626 if ( !HasCurrent() && !IsEmpty() )
3631 if ( m_current
!= (size_t)-1 )
3633 OnFocusLine( m_current
);
3637 long wxListMainWindow::GetNextItem( long item
,
3638 int WXUNUSED(geometry
),
3642 max
= GetItemCount();
3643 wxCHECK_MSG( (ret
== -1) || (ret
< max
), -1,
3644 _T("invalid listctrl index in GetNextItem()") );
3646 // notice that we start with the next item (or the first one if item == -1)
3647 // and this is intentional to allow writing a simple loop to iterate over
3648 // all selected items
3652 // this is not an error because the index was ok initially, just no
3663 size_t count
= GetItemCount();
3664 for ( size_t line
= (size_t)ret
; line
< count
; line
++ )
3666 if ( (state
& wxLIST_STATE_FOCUSED
) && (line
== m_current
) )
3669 if ( (state
& wxLIST_STATE_SELECTED
) && IsHighlighted(line
) )
3676 // ----------------------------------------------------------------------------
3678 // ----------------------------------------------------------------------------
3680 void wxListMainWindow::DeleteItem( long lindex
)
3682 size_t count
= GetItemCount();
3684 wxCHECK_RET( (lindex
>= 0) && ((size_t)lindex
< count
),
3685 _T("invalid item index in DeleteItem") );
3687 size_t index
= (size_t)lindex
;
3691 // select the next item when the selected one is deleted
3692 if ( m_current
== index
)
3694 // the last valid index after deleting the item will be count-2
3695 if ( m_current
== count
- 1 )
3701 SendNotify( index
, wxEVT_COMMAND_LIST_DELETE_ITEM
);
3703 if ( InReportView() )
3705 if ( m_lineTo
== GetItemCount() - 1 )
3711 // refresh before removing the line
3712 RefreshLines(index
, GetItemCount() - 1);
3718 m_selStore
.OnItemDelete(index
);
3722 m_lines
.RemoveAt( index
);
3726 void wxListMainWindow::DeleteColumn( int col
)
3728 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3730 wxCHECK_RET( node
, wxT("invalid column index in DeleteColumn()") );
3733 m_columns
.DeleteNode( node
);
3736 void wxListMainWindow::DeleteAllItems()
3740 // nothing to do - in particular, don't send the event
3748 // to make the deletion of all items faster, we don't send the
3749 // notifications for each item deletion in this case but only one event
3750 // for all of them: this is compatible with wxMSW and documented in
3751 // DeleteAllItems() description
3753 wxListEvent
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() );
3754 event
.SetEventObject( GetParent() );
3755 GetParent()->GetEventHandler()->ProcessEvent( event
);
3761 ResetVisibleLinesRange();
3769 void wxListMainWindow::DeleteEverything()
3776 // ----------------------------------------------------------------------------
3777 // scanning for an item
3778 // ----------------------------------------------------------------------------
3780 void wxListMainWindow::EnsureVisible( long index
)
3782 wxCHECK_RET( index
>= 0 && (size_t)index
< GetItemCount(),
3783 _T("invalid index in EnsureVisible") );
3785 // We have to call this here because the label in question might just have
3786 // been added and no screen update taken place.
3790 size_t oldCurrent
= m_current
;
3791 m_current
= (size_t)index
;
3793 m_current
= oldCurrent
;
3796 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) )
3803 size_t count
= GetItemCount();
3804 for ( size_t i
= (size_t)pos
; i
< count
; i
++ )
3806 wxListLineData
*line
= GetLine(i
);
3807 if ( line
->GetText(0) == tmp
)
3814 long wxListMainWindow::FindItem(long start
, long data
)
3820 size_t count
= GetItemCount();
3821 for (size_t i
= (size_t)pos
; i
< count
; i
++)
3823 wxListLineData
*line
= GetLine(i
);
3825 line
->GetItem( 0, item
);
3826 if (item
.m_data
== data
)
3833 long wxListMainWindow::HitTest( int x
, int y
, int &flags
)
3835 CalcUnscrolledPosition( x
, y
, &x
, &y
);
3837 if ( HasFlag(wxLC_REPORT
) )
3839 size_t current
= y
/ GetLineHeight();
3840 flags
= HitTestLine(current
, x
, y
);
3846 // TODO: optimize it too! this is less simple than for report view but
3847 // enumerating all items is still not a way to do it!!
3848 size_t count
= GetItemCount();
3849 for ( size_t current
= 0; current
< count
; current
++ )
3851 flags
= HitTestLine(current
, x
, y
);
3860 // ----------------------------------------------------------------------------
3862 // ----------------------------------------------------------------------------
3864 void wxListMainWindow::InsertItem( wxListItem
&item
)
3866 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") );
3868 size_t count
= GetItemCount();
3869 wxCHECK_RET( item
.m_itemId
>= 0 && (size_t)item
.m_itemId
<= count
,
3870 _T("invalid item index") );
3872 size_t id
= item
.m_itemId
;
3877 if ( HasFlag(wxLC_REPORT
) )
3879 else if ( HasFlag(wxLC_LIST
) )
3881 else if ( HasFlag(wxLC_ICON
) )
3883 else if ( HasFlag(wxLC_SMALL_ICON
) )
3884 mode
= wxLC_ICON
; // no typo
3887 wxFAIL_MSG( _T("unknown mode") );
3890 wxListLineData
*line
= new wxListLineData(this);
3892 line
->SetItem( 0, item
);
3894 m_lines
.Insert( line
, id
);
3896 RefreshLines(id
, GetItemCount() - 1);
3899 void wxListMainWindow::InsertColumn( long col
, wxListItem
&item
)
3902 if ( HasFlag(wxLC_REPORT
) )
3904 if (item
.m_width
== wxLIST_AUTOSIZE_USEHEADER
)
3905 item
.m_width
= GetTextLength( item
.m_text
);
3906 wxListHeaderData
*column
= new wxListHeaderData( item
);
3907 if ((col
>= 0) && (col
< (int)m_columns
.GetCount()))
3909 wxListHeaderDataList::Node
*node
= m_columns
.Item( col
);
3910 m_columns
.Insert( node
, column
);
3914 m_columns
.Append( column
);
3919 // ----------------------------------------------------------------------------
3921 // ----------------------------------------------------------------------------
3923 wxListCtrlCompare list_ctrl_compare_func_2
;
3924 long list_ctrl_compare_data
;
3926 int LINKAGEMODE
list_ctrl_compare_func_1( wxListLineData
**arg1
, wxListLineData
**arg2
)
3928 wxListLineData
*line1
= *arg1
;
3929 wxListLineData
*line2
= *arg2
;
3931 line1
->GetItem( 0, item
);
3932 long data1
= item
.m_data
;
3933 line2
->GetItem( 0, item
);
3934 long data2
= item
.m_data
;
3935 return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data
);
3938 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data
)
3940 list_ctrl_compare_func_2
= fn
;
3941 list_ctrl_compare_data
= data
;
3942 m_lines
.Sort( list_ctrl_compare_func_1
);
3946 // ----------------------------------------------------------------------------
3948 // ----------------------------------------------------------------------------
3950 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
)
3952 // update our idea of which lines are shown when we redraw the window the
3954 ResetVisibleLinesRange();
3957 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
3958 wxScrolledWindow::OnScroll(event
);
3960 HandleOnScroll( event
);
3963 if ( event
.GetOrientation() == wxHORIZONTAL
&& HasHeader() )
3965 wxListCtrl
* lc
= GetListCtrl();
3966 wxCHECK_RET( lc
, _T("no listctrl window?") );
3968 lc
->m_headerWin
->Refresh() ;
3970 lc
->m_headerWin
->MacUpdateImmediately() ;
3975 int wxListMainWindow::GetCountPerPage() const
3977 if ( !m_linesPerPage
)
3979 wxConstCast(this, wxListMainWindow
)->
3980 m_linesPerPage
= GetClientSize().y
/ GetLineHeight();
3983 return m_linesPerPage
;
3986 void wxListMainWindow::GetVisibleLinesRange(size_t *from
, size_t *to
)
3988 wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("this is for report mode only") );
3990 if ( m_lineFrom
== (size_t)-1 )
3992 m_lineFrom
= GetScrollPos(wxVERTICAL
);
3994 size_t count
= GetItemCount();
3996 wxASSERT_MSG( m_lineFrom
< count
, _T("invalid scroll position?") );
3998 // we redraw one extra line but this is needed to make the redrawing
3999 // logic work when there is a fractional number of lines on screen
4000 m_lineTo
= m_lineFrom
+ m_linesPerPage
;
4001 if ( m_lineTo
>= count
)
4002 m_lineTo
= count
- 1;
4011 // -------------------------------------------------------------------------------------
4013 // -------------------------------------------------------------------------------------
4015 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
)
4017 wxListItem::wxListItem()
4026 m_format
= wxLIST_FORMAT_CENTRE
;
4032 void wxListItem::Clear()
4041 m_format
= wxLIST_FORMAT_CENTRE
;
4048 void wxListItem::ClearAttributes()
4057 // -------------------------------------------------------------------------------------
4059 // -------------------------------------------------------------------------------------
4061 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
)
4063 wxListEvent::wxListEvent( wxEventType commandType
, int id
)
4064 : wxNotifyEvent( commandType
, id
)
4070 m_cancelled
= FALSE
;
4075 void wxListEvent::CopyObject(wxObject
& object_dest
) const
4077 wxListEvent
*obj
= (wxListEvent
*)&object_dest
;
4079 wxNotifyEvent::CopyObject(object_dest
);
4081 obj
->m_code
= m_code
;
4082 obj
->m_itemIndex
= m_itemIndex
;
4083 obj
->m_oldItemIndex
= m_oldItemIndex
;
4085 obj
->m_cancelled
= m_cancelled
;
4086 obj
->m_pointDrag
= m_pointDrag
;
4087 obj
->m_item
.m_mask
= m_item
.m_mask
;
4088 obj
->m_item
.m_itemId
= m_item
.m_itemId
;
4089 obj
->m_item
.m_col
= m_item
.m_col
;
4090 obj
->m_item
.m_state
= m_item
.m_state
;
4091 obj
->m_item
.m_stateMask
= m_item
.m_stateMask
;
4092 obj
->m_item
.m_text
= m_item
.m_text
;
4093 obj
->m_item
.m_image
= m_item
.m_image
;
4094 obj
->m_item
.m_data
= m_item
.m_data
;
4095 obj
->m_item
.m_format
= m_item
.m_format
;
4096 obj
->m_item
.m_width
= m_item
.m_width
;
4098 if ( m_item
.HasAttributes() )
4100 obj
->m_item
.SetTextColour(m_item
.GetTextColour());
4104 // -------------------------------------------------------------------------------------
4106 // -------------------------------------------------------------------------------------
4108 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
)
4110 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
)
4111 EVT_SIZE(wxListCtrl::OnSize
)
4112 EVT_IDLE(wxListCtrl::OnIdle
)
4115 wxListCtrl::wxListCtrl()
4117 m_imageListNormal
= (wxImageList
*) NULL
;
4118 m_imageListSmall
= (wxImageList
*) NULL
;
4119 m_imageListState
= (wxImageList
*) NULL
;
4121 m_ownsImageListNormal
=
4122 m_ownsImageListSmall
=
4123 m_ownsImageListState
= FALSE
;
4125 m_mainWin
= (wxListMainWindow
*) NULL
;
4126 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4129 wxListCtrl::~wxListCtrl()
4132 m_mainWin
->ResetCurrent();
4134 if (m_ownsImageListNormal
)
4135 delete m_imageListNormal
;
4136 if (m_ownsImageListSmall
)
4137 delete m_imageListSmall
;
4138 if (m_ownsImageListState
)
4139 delete m_imageListState
;
4142 void wxListCtrl::CreateHeaderWindow()
4144 m_headerWin
= new wxListHeaderWindow
4146 this, -1, m_mainWin
,
4148 wxSize(GetClientSize().x
, HEADER_HEIGHT
),
4153 bool wxListCtrl::Create(wxWindow
*parent
,
4158 const wxValidator
&validator
,
4159 const wxString
&name
)
4163 m_imageListState
= (wxImageList
*) NULL
;
4164 m_ownsImageListNormal
=
4165 m_ownsImageListSmall
=
4166 m_ownsImageListState
= FALSE
;
4168 m_mainWin
= (wxListMainWindow
*) NULL
;
4169 m_headerWin
= (wxListHeaderWindow
*) NULL
;
4171 if ( !(style
& wxLC_MASK_TYPE
) )
4173 style
= style
| wxLC_LIST
;
4176 if ( !wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name
) )
4179 // don't create the inner window with the border
4180 style
&= ~wxSUNKEN_BORDER
;
4182 m_mainWin
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style
);
4184 if ( HasFlag(wxLC_REPORT
) )
4186 CreateHeaderWindow();
4188 if ( HasFlag(wxLC_NO_HEADER
) )
4190 // VZ: why do we create it at all then?
4191 m_headerWin
->Show( FALSE
);
4198 void wxListCtrl::SetSingleStyle( long style
, bool add
)
4200 wxASSERT_MSG( !(style
& wxLC_VIRTUAL
),
4201 _T("wxLC_VIRTUAL can't be [un]set") );
4203 long flag
= GetWindowStyle();
4207 if (style
& wxLC_MASK_TYPE
)
4208 flag
&= ~(wxLC_MASK_TYPE
| wxLC_VIRTUAL
);
4209 if (style
& wxLC_MASK_ALIGN
)
4210 flag
&= ~wxLC_MASK_ALIGN
;
4211 if (style
& wxLC_MASK_SORT
)
4212 flag
&= ~wxLC_MASK_SORT
;
4224 SetWindowStyleFlag( flag
);
4227 void wxListCtrl::SetWindowStyleFlag( long flag
)
4231 m_mainWin
->DeleteEverything();
4235 GetClientSize( &width
, &height
);
4237 if (flag
& wxLC_REPORT
)
4239 if (!HasFlag(wxLC_REPORT
))
4243 CreateHeaderWindow();
4245 if (HasFlag(wxLC_NO_HEADER
))
4246 m_headerWin
->Show( FALSE
);
4250 if (flag
& wxLC_NO_HEADER
)
4251 m_headerWin
->Show( FALSE
);
4253 m_headerWin
->Show( TRUE
);
4259 if ( m_mainWin
->HasHeader() )
4261 m_headerWin
->Show( FALSE
);
4266 wxWindow::SetWindowStyleFlag( flag
);
4269 bool wxListCtrl::GetColumn(int col
, wxListItem
&item
) const
4271 m_mainWin
->GetColumn( col
, item
);
4275 bool wxListCtrl::SetColumn( int col
, wxListItem
& item
)
4277 m_mainWin
->SetColumn( col
, item
);
4281 int wxListCtrl::GetColumnWidth( int col
) const
4283 return m_mainWin
->GetColumnWidth( col
);
4286 bool wxListCtrl::SetColumnWidth( int col
, int width
)
4288 m_mainWin
->SetColumnWidth( col
, width
);
4292 int wxListCtrl::GetCountPerPage() const
4294 return m_mainWin
->GetCountPerPage(); // different from Windows ?
4297 bool wxListCtrl::GetItem( wxListItem
&info
) const
4299 m_mainWin
->GetItem( info
);
4303 bool wxListCtrl::SetItem( wxListItem
&info
)
4305 m_mainWin
->SetItem( info
);
4309 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId
)
4312 info
.m_text
= label
;
4313 info
.m_mask
= wxLIST_MASK_TEXT
;
4314 info
.m_itemId
= index
;
4318 info
.m_image
= imageId
;
4319 info
.m_mask
|= wxLIST_MASK_IMAGE
;
4321 m_mainWin
->SetItem(info
);
4325 int wxListCtrl::GetItemState( long item
, long stateMask
) const
4327 return m_mainWin
->GetItemState( item
, stateMask
);
4330 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask
)
4332 m_mainWin
->SetItemState( item
, state
, stateMask
);
4336 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) )
4339 info
.m_image
= image
;
4340 info
.m_mask
= wxLIST_MASK_IMAGE
;
4341 info
.m_itemId
= item
;
4342 m_mainWin
->SetItem( info
);
4346 wxString
wxListCtrl::GetItemText( long item
) const
4349 info
.m_itemId
= item
;
4350 m_mainWin
->GetItem( info
);
4354 void wxListCtrl::SetItemText( long item
, const wxString
&str
)
4357 info
.m_mask
= wxLIST_MASK_TEXT
;
4358 info
.m_itemId
= item
;
4360 m_mainWin
->SetItem( info
);
4363 long wxListCtrl::GetItemData( long item
) const
4366 info
.m_itemId
= item
;
4367 m_mainWin
->GetItem( info
);
4371 bool wxListCtrl::SetItemData( long item
, long data
)
4374 info
.m_mask
= wxLIST_MASK_DATA
;
4375 info
.m_itemId
= item
;
4377 m_mainWin
->SetItem( info
);
4381 bool wxListCtrl::GetItemRect( long item
, wxRect
&rect
, int WXUNUSED(code
) ) const
4383 m_mainWin
->GetItemRect( item
, rect
);
4387 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos
) const
4389 m_mainWin
->GetItemPosition( item
, pos
);
4393 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) )
4398 int wxListCtrl::GetItemCount() const
4400 return m_mainWin
->GetItemCount();
4403 int wxListCtrl::GetColumnCount() const
4405 return m_mainWin
->GetColumnCount();
4408 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall
)
4410 m_mainWin
->SetItemSpacing( spacing
, isSmall
);
4413 int wxListCtrl::GetItemSpacing( bool isSmall
) const
4415 return m_mainWin
->GetItemSpacing( isSmall
);
4418 int wxListCtrl::GetSelectedItemCount() const
4420 return m_mainWin
->GetSelectedItemCount();
4423 wxColour
wxListCtrl::GetTextColour() const
4425 return GetForegroundColour();
4428 void wxListCtrl::SetTextColour(const wxColour
& col
)
4430 SetForegroundColour(col
);
4433 long wxListCtrl::GetTopItem() const
4438 long wxListCtrl::GetNextItem( long item
, int geom
, int state
) const
4440 return m_mainWin
->GetNextItem( item
, geom
, state
);
4443 wxImageList
*wxListCtrl::GetImageList(int which
) const
4445 if (which
== wxIMAGE_LIST_NORMAL
)
4447 return m_imageListNormal
;
4449 else if (which
== wxIMAGE_LIST_SMALL
)
4451 return m_imageListSmall
;
4453 else if (which
== wxIMAGE_LIST_STATE
)
4455 return m_imageListState
;
4457 return (wxImageList
*) NULL
;
4460 void wxListCtrl::SetImageList( wxImageList
*imageList
, int which
)
4462 if ( which
== wxIMAGE_LIST_NORMAL
)
4464 if (m_ownsImageListNormal
) delete m_imageListNormal
;
4465 m_imageListNormal
= imageList
;
4466 m_ownsImageListNormal
= FALSE
;
4468 else if ( which
== wxIMAGE_LIST_SMALL
)
4470 if (m_ownsImageListSmall
) delete m_imageListSmall
;
4471 m_imageListSmall
= imageList
;
4472 m_ownsImageListSmall
= FALSE
;
4474 else if ( which
== wxIMAGE_LIST_STATE
)
4476 if (m_ownsImageListState
) delete m_imageListState
;
4477 m_imageListState
= imageList
;
4478 m_ownsImageListState
= FALSE
;
4481 m_mainWin
->SetImageList( imageList
, which
);
4484 void wxListCtrl::AssignImageList(wxImageList
*imageList
, int which
)
4486 SetImageList(imageList
, which
);
4487 if ( which
== wxIMAGE_LIST_NORMAL
)
4488 m_ownsImageListNormal
= TRUE
;
4489 else if ( which
== wxIMAGE_LIST_SMALL
)
4490 m_ownsImageListSmall
= TRUE
;
4491 else if ( which
== wxIMAGE_LIST_STATE
)
4492 m_ownsImageListState
= TRUE
;
4495 bool wxListCtrl::Arrange( int WXUNUSED(flag
) )
4500 bool wxListCtrl::DeleteItem( long item
)
4502 m_mainWin
->DeleteItem( item
);
4506 bool wxListCtrl::DeleteAllItems()
4508 m_mainWin
->DeleteAllItems();
4512 bool wxListCtrl::DeleteAllColumns()
4514 size_t count
= m_mainWin
->m_columns
.GetCount();
4515 for ( size_t n
= 0; n
< count
; n
++ )
4521 void wxListCtrl::ClearAll()
4523 m_mainWin
->DeleteEverything();
4526 bool wxListCtrl::DeleteColumn( int col
)
4528 m_mainWin
->DeleteColumn( col
);
4532 void wxListCtrl::Edit( long item
)
4534 m_mainWin
->EditLabel( item
);
4537 bool wxListCtrl::EnsureVisible( long item
)
4539 m_mainWin
->EnsureVisible( item
);
4543 long wxListCtrl::FindItem( long start
, const wxString
& str
, bool partial
)
4545 return m_mainWin
->FindItem( start
, str
, partial
);
4548 long wxListCtrl::FindItem( long start
, long data
)
4550 return m_mainWin
->FindItem( start
, data
);
4553 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
),
4554 int WXUNUSED(direction
))
4559 long wxListCtrl::HitTest( const wxPoint
&point
, int &flags
)
4561 return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags
);
4564 long wxListCtrl::InsertItem( wxListItem
& info
)
4566 m_mainWin
->InsertItem( info
);
4567 return info
.m_itemId
;
4570 long wxListCtrl::InsertItem( long index
, const wxString
&label
)
4573 info
.m_text
= label
;
4574 info
.m_mask
= wxLIST_MASK_TEXT
;
4575 info
.m_itemId
= index
;
4576 return InsertItem( info
);
4579 long wxListCtrl::InsertItem( long index
, int imageIndex
)
4582 info
.m_mask
= wxLIST_MASK_IMAGE
;
4583 info
.m_image
= imageIndex
;
4584 info
.m_itemId
= index
;
4585 return InsertItem( info
);
4588 long wxListCtrl::InsertItem( long index
, const wxString
&label
, int imageIndex
)
4591 info
.m_text
= label
;
4592 info
.m_image
= imageIndex
;
4593 info
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_IMAGE
;
4594 info
.m_itemId
= index
;
4595 return InsertItem( info
);
4598 long wxListCtrl::InsertColumn( long col
, wxListItem
&item
)
4600 wxASSERT( m_headerWin
);
4601 m_mainWin
->InsertColumn( col
, item
);
4602 m_headerWin
->Refresh();
4607 long wxListCtrl::InsertColumn( long col
, const wxString
&heading
,
4608 int format
, int width
)
4611 item
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_FORMAT
;
4612 item
.m_text
= heading
;
4615 item
.m_mask
|= wxLIST_MASK_WIDTH
;
4616 item
.m_width
= width
;
4618 item
.m_format
= format
;
4620 return InsertColumn( col
, item
);
4623 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) )
4629 // fn is a function which takes 3 long arguments: item1, item2, data.
4630 // item1 is the long data associated with a first item (NOT the index).
4631 // item2 is the long data associated with a second item (NOT the index).
4632 // data is the same value as passed to SortItems.
4633 // The return value is a negative number if the first item should precede the second
4634 // item, a positive number of the second item should precede the first,
4635 // or zero if the two items are equivalent.
4636 // data is arbitrary data to be passed to the sort function.
4638 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data
)
4640 m_mainWin
->SortItems( fn
, data
);
4644 // ----------------------------------------------------------------------------
4646 // ----------------------------------------------------------------------------
4648 void wxListCtrl::OnSize(wxSizeEvent
& event
)
4654 GetClientSize( &cw
, &ch
);
4656 if ( m_mainWin
->HasHeader() )
4658 m_headerWin
->SetSize( 0, 0, cw
, HEADER_HEIGHT
);
4659 m_mainWin
->SetSize( 0, HEADER_HEIGHT
+ 1, cw
, ch
- HEADER_HEIGHT
- 1 );
4661 else // no header window
4663 m_mainWin
->SetSize( 0, 0, cw
, ch
);
4666 m_mainWin
->RecalculatePositions();
4669 void wxListCtrl::OnIdle( wxIdleEvent
& event
)
4673 // do it only if needed
4674 if ( !m_mainWin
->m_dirty
)
4677 m_mainWin
->RecalculatePositions();
4680 // ----------------------------------------------------------------------------
4682 // ----------------------------------------------------------------------------
4684 bool wxListCtrl::SetBackgroundColour( const wxColour
&colour
)
4688 m_mainWin
->SetBackgroundColour( colour
);
4689 m_mainWin
->m_dirty
= TRUE
;
4695 bool wxListCtrl::SetForegroundColour( const wxColour
&colour
)
4697 if ( !wxWindow::SetForegroundColour( colour
) )
4702 m_mainWin
->SetForegroundColour( colour
);
4703 m_mainWin
->m_dirty
= TRUE
;
4708 m_headerWin
->SetForegroundColour( colour
);
4714 bool wxListCtrl::SetFont( const wxFont
&font
)
4716 if ( !wxWindow::SetFont( font
) )
4721 m_mainWin
->SetFont( font
);
4722 m_mainWin
->m_dirty
= TRUE
;
4727 m_headerWin
->SetFont( font
);
4733 // ----------------------------------------------------------------------------
4734 // methods forwarded to m_mainWin
4735 // ----------------------------------------------------------------------------
4737 #if wxUSE_DRAG_AND_DROP
4739 void wxListCtrl::SetDropTarget( wxDropTarget
*dropTarget
)
4741 m_mainWin
->SetDropTarget( dropTarget
);
4744 wxDropTarget
*wxListCtrl::GetDropTarget() const
4746 return m_mainWin
->GetDropTarget();
4749 #endif // wxUSE_DRAG_AND_DROP
4751 bool wxListCtrl::SetCursor( const wxCursor
&cursor
)
4753 return m_mainWin
? m_mainWin
->wxWindow::SetCursor(cursor
) : FALSE
;
4756 wxColour
wxListCtrl::GetBackgroundColour() const
4758 return m_mainWin
? m_mainWin
->GetBackgroundColour() : wxColour();
4761 wxColour
wxListCtrl::GetForegroundColour() const
4763 return m_mainWin
? m_mainWin
->GetForegroundColour() : wxColour();
4766 bool wxListCtrl::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
4769 return m_mainWin
->PopupMenu( menu
, x
, y
);
4772 #endif // wxUSE_MENUS
4775 void wxListCtrl::SetFocus()
4777 /* The test in window.cpp fails as we are a composite
4778 window, so it checks against "this", but not m_mainWin. */
4779 if ( FindFocus() != this )
4780 m_mainWin
->SetFocus();
4783 // ----------------------------------------------------------------------------
4784 // virtual list control support
4785 // ----------------------------------------------------------------------------
4787 wxString
wxListCtrl::OnGetItemText(long item
, long col
) const
4789 // this is a pure virtual function, in fact - which is not really pure
4790 // because the controls which are not virtual don't need to implement it
4791 wxFAIL_MSG( _T("not supposed to be called") );
4793 return wxEmptyString
;
4796 int wxListCtrl::OnGetItemImage(long item
) const
4799 wxFAIL_MSG( _T("not supposed to be called") );
4804 void wxListCtrl::SetItemCount(long count
)
4806 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4808 m_mainWin
->SetItemCount(count
);
4811 #endif // wxUSE_LISTCTRL