]> git.saurik.com Git - wxWidgets.git/blame - src/generic/listctrl.cpp
compilation fix
[wxWidgets.git] / src / generic / listctrl.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
54442116
VZ
2// Name: generic/listctrl.cpp
3// Purpose: generic implementation of wxListCtrl
c801d85f 4// Author: Robert Roebling
cf1dfa6b 5// Vadim Zeitlin (virtual list control support)
0208334d
RR
6// Id: $Id$
7// Copyright: (c) 1998 Robert Roebling
bd8289c1 8// Licence: wxWindows licence
c801d85f
KB
9/////////////////////////////////////////////////////////////////////////////
10
b54e41c5
VZ
11/*
12 FIXME for virtual list controls
13
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
17
18 2. background colour is wrong?
19 */
20
21/*
22 TODO for better virtual list control support:
23
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?)
27
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
31 items and ranges
32
33 => wxSelectionStore
34
35 3. we need to implement searching/sorting somehow
36
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
40 if ( IsVirtual()
41 ... we have it ourselves ...
42 else
43 line->GetFoo();
44 */
45
1370703e
VZ
46// ============================================================================
47// declarations
48// ============================================================================
49
50// ----------------------------------------------------------------------------
51// headers
52// ----------------------------------------------------------------------------
53
c801d85f 54#ifdef __GNUG__
510fc784
RR
55 #pragma implementation "listctrl.h"
56 #pragma implementation "listctrlbase.h"
938b652b 57#endif
5cd89174 58
1e6d9499
JS
59// For compilers that support precompilation, includes "wx.h".
60#include "wx/wxprec.h"
61
62#ifdef __BORLANDC__
63#pragma hdrstop
64#endif
65
1e6feb95
VZ
66#if wxUSE_LISTCTRL
67
0208334d
RR
68#include "wx/dcscreen.h"
69#include "wx/app.h"
02527779 70#include "wx/listctrl.h"
b54e41c5 71#include "wx/imaglist.h"
f6bcfd97 72#include "wx/dynarray.h"
c801d85f 73
3fb435df
RR
74#ifdef __WXGTK__
75#include <gtk/gtk.h>
76#include "wx/gtk/win_gtk.h"
77#endif
78
2e4df4bf
VZ
79// ----------------------------------------------------------------------------
80// events
81// ----------------------------------------------------------------------------
82
83DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG)
84DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG)
85DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
86DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
87DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
88DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
89DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
90DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
91DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
92DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
93DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
94DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
95DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
96DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
97DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
98DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
99
cf1dfa6b
VZ
100// ----------------------------------------------------------------------------
101// constants
102// ----------------------------------------------------------------------------
103
104// the height of the header window (FIXME: should depend on its font!)
105static const int HEADER_HEIGHT = 23;
106
107// the scrollbar units
108static const int SCROLL_UNIT_X = 15;
109static const int SCROLL_UNIT_Y = 15;
110
111// the spacing between the lines (in report mode)
b54e41c5 112static const int LINE_SPACING = 0;
cf1dfa6b
VZ
113
114// extra margins around the text label
115static const int EXTRA_WIDTH = 3;
116static const int EXTRA_HEIGHT = 4;
117
118// offset for the header window
119static const int HEADER_OFFSET_X = 1;
120static const int HEADER_OFFSET_Y = 1;
121
122// when autosizing the columns, add some slack
123static const int AUTOSIZE_COL_MARGIN = 10;
124
125// default and minimal widths for the header columns
126static const int WIDTH_COL_DEFAULT = 80;
127static const int WIDTH_COL_MIN = 10;
128
efbb7287
VZ
129// ============================================================================
130// private classes
131// ============================================================================
132
b54e41c5
VZ
133// ----------------------------------------------------------------------------
134// wxSelectionStore
135// ----------------------------------------------------------------------------
136
137int CMPFUNC_CONV wxSizeTCmpFn(size_t n1, size_t n2) { return n1 - n2; }
138
139WX_DEFINE_SORTED_EXPORTED_ARRAY(size_t, wxIndexArray);
140
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)
144//
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
149// smarter later
150class WXDLLEXPORT wxSelectionStore
151{
152public:
153 wxSelectionStore() : m_itemsSel(wxSizeTCmpFn) { Init(); }
154
155 // set the total number of items we handle
156 void SetItemCount(size_t count) { m_count = count; }
157
158 // special case of SetItemCount(0)
159 void Clear() { m_itemsSel.Clear(); m_count = 0; }
160
161 // must be called when a new item is inserted/added
162 void OnItemAdd(size_t item) { wxFAIL_MSG( _T("TODO") ); }
163
164 // must be called when an item is deleted
165 void OnItemDelete(size_t item);
166
167 // select one item, use SelectRange() insted if possible!
168 //
169 // returns true if the items selection really changed
170 bool SelectItem(size_t item, bool select = TRUE);
171
172 // select the range of items
173 void SelectRange(size_t itemFrom, size_t itemTo, bool select = TRUE);
174
175 // return true if the given item is selected
176 bool IsSelected(size_t item) const;
177
178 // return the total number of selected items
179 size_t GetSelectedCount() const
180 {
181 return m_defaultState ? m_count - m_itemsSel.GetCount()
182 : m_itemsSel.GetCount();
183 }
184
185private:
186 // (re)init
187 void Init() { m_defaultState = FALSE; }
188
189 // the total number of items we handle
190 size_t m_count;
191
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
195 bool m_defaultState;
196
197 // the array of items whose selection state is different from default
198 wxIndexArray m_itemsSel;
199
200 DECLARE_NO_COPY_CLASS(wxSelectionStore)
201};
202
efbb7287
VZ
203//-----------------------------------------------------------------------------
204// wxListItemData (internal)
205//-----------------------------------------------------------------------------
206
cf1dfa6b 207class WXDLLEXPORT wxListItemData
efbb7287 208{
efbb7287 209public:
cf1dfa6b
VZ
210 wxListItemData(wxListMainWindow *owner);
211 ~wxListItemData() { delete m_attr; delete m_rect; }
efbb7287 212
efbb7287 213 void SetItem( const wxListItem &info );
cf1dfa6b
VZ
214 void SetImage( int image ) { m_image = image; }
215 void SetData( long data ) { m_data = data; }
efbb7287
VZ
216 void SetPosition( int x, int y );
217 void SetSize( int width, int height );
54442116
VZ
218
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; }
222
cf1dfa6b
VZ
223 // we can't use empty string for measuring the string width/height, so
224 // always return something
225 wxString GetTextForMeasuring() const
226 {
227 wxString s = GetText();
228 if ( s.empty() )
229 s = _T('H');
230
231 return s;
232 }
233
efbb7287 234 bool IsHit( int x, int y ) const;
54442116 235
cf1dfa6b
VZ
236 int GetX() const;
237 int GetY() const;
efbb7287
VZ
238 int GetWidth() const;
239 int GetHeight() const;
cf1dfa6b
VZ
240
241 int GetImage() const { return m_image; }
242 bool HasImage() const { return GetImage() != -1; }
243
efbb7287
VZ
244 void GetItem( wxListItem &info ) const;
245
246 wxListItemAttr *GetAttributes() const { return m_attr; }
247
54442116 248public:
cf1dfa6b
VZ
249 // the item image or -1
250 int m_image;
251
252 // user data associated with the item
253 long m_data;
54442116 254
cf1dfa6b
VZ
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
257 // size
258 wxRect *m_rect;
259
260 // the list ctrl we are in
261 wxListMainWindow *m_owner;
262
263 // custom attributes or NULL
54442116
VZ
264 wxListItemAttr *m_attr;
265
266protected:
cf1dfa6b
VZ
267 // common part of all ctors
268 void Init();
54442116 269
cf1dfa6b 270 wxString m_text;
efbb7287
VZ
271};
272
273//-----------------------------------------------------------------------------
274// wxListHeaderData (internal)
275//-----------------------------------------------------------------------------
276
277class WXDLLEXPORT wxListHeaderData : public wxObject
278{
279protected:
280 long m_mask;
281 int m_image;
282 wxString m_text;
283 int m_format;
284 int m_width;
2c1f73ee
VZ
285 int m_xpos,
286 m_ypos;
efbb7287
VZ
287 int m_height;
288
289public:
290 wxListHeaderData();
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;
54442116
VZ
298
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; }
302
efbb7287 303 void GetItem( wxListItem &item );
54442116
VZ
304
305 bool IsHit( int x, int y ) const;
efbb7287
VZ
306 int GetImage() const;
307 int GetWidth() const;
308 int GetFormat() const;
f6bcfd97 309
efbb7287
VZ
310private:
311 DECLARE_DYNAMIC_CLASS(wxListHeaderData);
312};
313
314//-----------------------------------------------------------------------------
315// wxListLineData (internal)
316//-----------------------------------------------------------------------------
317
2c1f73ee
VZ
318WX_DECLARE_LIST(wxListItemData, wxListItemDataList);
319#include "wx/listimpl.cpp"
320WX_DEFINE_LIST(wxListItemDataList);
321
cf1dfa6b 322class WXDLLEXPORT wxListLineData
efbb7287
VZ
323{
324public:
cf1dfa6b
VZ
325 // the list of subitems: only may have more than one item in report mode
326 wxListItemDataList m_items;
327
328 // this is not used in report view
329 struct GeometryInfo
330 {
331 // total item rect
332 wxRect m_rectAll;
333
334 // label only
335 wxRect m_rectLabel;
336
337 // icon only
338 wxRect m_rectIcon;
339
340 // the part to be highlighted
b54e41c5 341 wxRect m_rectHighlight;
cf1dfa6b 342 } *m_gi;
efbb7287 343
cf1dfa6b 344 // is this item selected? [NB: not used in virtual mode]
b54e41c5 345 bool m_highlighted;
cf1dfa6b
VZ
346
347 // back pointer to the list ctrl
348 wxListMainWindow *m_owner;
efbb7287
VZ
349
350public:
5cd89174 351 wxListLineData(wxListMainWindow *owner);
cf1dfa6b
VZ
352
353 ~wxListLineData() { delete m_gi; }
354
355 // are we in report mode?
356 inline bool InReportView() const;
357
358 // are we in virtual report mode?
b54e41c5 359 inline bool IsVirtual() const;
cf1dfa6b
VZ
360
361 // these 2 methods shouldn't be called for report view controls, in that
362 // case we determine our position/size ourselves
363
364 // calculate the size of the line
efbb7287 365 void CalculateSize( wxDC *dc, int spacing );
cf1dfa6b
VZ
366
367 // remember the position this line appears at
368 void SetPosition( int x, int y, int window_width, int spacing );
369
5cd89174
VZ
370 // wxListCtrl API
371
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(); }
cf1dfa6b 376
efbb7287
VZ
377 void SetItem( int index, const wxListItem &info );
378 void GetItem( int index, wxListItem &info );
cf1dfa6b 379
54442116 380 wxString GetText(int index) const;
efbb7287 381 void SetText( int index, const wxString s );
cf1dfa6b 382
cf1dfa6b 383 // return true if the highlighting really changed
b54e41c5 384 bool Highlight( bool on );
cf1dfa6b 385
b54e41c5 386 void ReverseHighlight();
cf1dfa6b 387
b54e41c5 388 bool IsHighlighted() const
cf1dfa6b 389 {
b54e41c5 390 wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") );
cf1dfa6b 391
b54e41c5 392 return m_highlighted;
cf1dfa6b
VZ
393 }
394
5cd89174
VZ
395 // draw the line on the given DC in icon/list mode
396 void Draw( wxDC *dc );
397
398 // the same in report mode
399 void DrawInReportMode( wxDC *dc,
400 const wxRect& rect,
401 const wxRect& rectHL,
402 bool highlighted );
f6bcfd97 403
efbb7287 404private:
cf1dfa6b
VZ
405 // set the line to contain num items (only can be > 1 in report mode)
406 void InitItems( int num );
407
408 // get the mode (i.e. style) of the list control
409 inline int GetMode() const;
410
efbb7287
VZ
411 void SetAttributes(wxDC *dc,
412 const wxListItemAttr *attr,
cf1dfa6b
VZ
413 const wxColour& colText,
414 const wxFont& font,
b54e41c5 415 bool highlight);
efbb7287 416
5cd89174
VZ
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;
efbb7287
VZ
421};
422
f6bcfd97
BP
423WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData, wxListLineDataArray);
424#include "wx/arrimpl.cpp"
425WX_DEFINE_OBJARRAY(wxListLineDataArray);
426
efbb7287
VZ
427//-----------------------------------------------------------------------------
428// wxListHeaderWindow (internal)
429//-----------------------------------------------------------------------------
430
431class WXDLLEXPORT wxListHeaderWindow : public wxWindow
432{
433protected:
434 wxListMainWindow *m_owner;
435 wxCursor *m_currentCursor;
436 wxCursor *m_resizeCursor;
437 bool m_isDragging;
f6bcfd97
BP
438
439 // column being resized
440 int m_column;
441
442 // divider line position in logical (unscrolled) coords
443 int m_currentX;
444
445 // minimal position beyond which the divider line can't be dragged in
446 // logical coords
447 int m_minX;
efbb7287
VZ
448
449public:
450 wxListHeaderWindow();
f6bcfd97
BP
451 virtual ~wxListHeaderWindow();
452
453 wxListHeaderWindow( wxWindow *win,
454 wxWindowID id,
455 wxListMainWindow *owner,
456 const wxPoint &pos = wxDefaultPosition,
457 const wxSize &size = wxDefaultSize,
458 long style = 0,
459 const wxString &name = "wxlistctrlcolumntitles" );
460
efbb7287 461 void DoDrawRect( wxDC *dc, int x, int y, int w, int h );
efbb7287 462 void DrawCurrent();
f6bcfd97
BP
463 void AdjustDC(wxDC& dc);
464
465 void OnPaint( wxPaintEvent &event );
efbb7287
VZ
466 void OnMouse( wxMouseEvent &event );
467 void OnSetFocus( wxFocusEvent &event );
468
f6bcfd97
BP
469 // needs refresh
470 bool m_dirty;
471
efbb7287
VZ
472private:
473 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow)
474 DECLARE_EVENT_TABLE()
475};
476
477//-----------------------------------------------------------------------------
478// wxListRenameTimer (internal)
479//-----------------------------------------------------------------------------
480
481class WXDLLEXPORT wxListRenameTimer: public wxTimer
482{
483private:
1370703e 484 wxListMainWindow *m_owner;
efbb7287
VZ
485
486public:
487 wxListRenameTimer( wxListMainWindow *owner );
488 void Notify();
489};
490
491//-----------------------------------------------------------------------------
492// wxListTextCtrl (internal)
493//-----------------------------------------------------------------------------
494
495class WXDLLEXPORT wxListTextCtrl: public wxTextCtrl
496{
497private:
498 bool *m_accept;
499 wxString *m_res;
500 wxListMainWindow *m_owner;
501 wxString m_startValue;
502
503public:
504 wxListTextCtrl() {}
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,
509 int style = 0,
510 const wxValidator& validator = wxDefaultValidator,
809934d2 511 const wxString &name = "listctrltextctrl" );
efbb7287 512 void OnChar( wxKeyEvent &event );
c13cace1 513 void OnKeyUp( wxKeyEvent &event );
efbb7287
VZ
514 void OnKillFocus( wxFocusEvent &event );
515
516private:
517 DECLARE_DYNAMIC_CLASS(wxListTextCtrl);
518 DECLARE_EVENT_TABLE()
519};
520
521//-----------------------------------------------------------------------------
522// wxListMainWindow (internal)
523//-----------------------------------------------------------------------------
524
24b9f055
VZ
525WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList);
526#include "wx/listimpl.cpp"
527WX_DEFINE_LIST(wxListHeaderDataList);
528
cf1dfa6b 529class WXDLLEXPORT wxListMainWindow : public wxScrolledWindow
efbb7287 530{
efbb7287
VZ
531public:
532 wxListMainWindow();
1370703e
VZ
533 wxListMainWindow( wxWindow *parent,
534 wxWindowID id,
535 const wxPoint& pos = wxDefaultPosition,
536 const wxSize& size = wxDefaultSize,
537 long style = 0,
538 const wxString &name = _T("listctrlmainwindow") );
539
540 virtual ~wxListMainWindow();
541
cf1dfa6b
VZ
542 bool HasFlag(int flag) const { return m_parent->HasFlag(flag); }
543
1370703e 544 // return true if this is a virtual list control
cf1dfa6b
VZ
545 bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL); }
546
5cd89174
VZ
547 // return true if the control is in report mode
548 bool InReportView() const { return HasFlag(wxLC_REPORT); }
549
b54e41c5
VZ
550 // return true if we are in single selection mode, false if multi sel
551 bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL); }
552
cf1dfa6b
VZ
553 // do we have a header window?
554 bool HasHeader() const
555 { return HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER); }
1370703e 556
b54e41c5 557 void HighlightAll( bool on );
cf1dfa6b
VZ
558
559 // all these functions only do something if the line is currently visible
560
561 // change the line "selected" state, return TRUE if it really changed
b54e41c5
VZ
562 bool HighlightLine( size_t line, bool highlight = TRUE);
563
564 // as HighlightLine() but do it for the range of lines: this is incredibly
565 // more efficient for virtual list controls!
566 //
567 // NB: unlike HighlightLine() this one does refresh the lines on screen
568 void HighlightLines( size_t lineFrom, size_t lineTo, bool on = TRUE );
cf1dfa6b
VZ
569
570 // toggle the line state and refresh it
b54e41c5
VZ
571 void ReverseHighlight( size_t line )
572 { HighlightLine(line, !IsHighlighted(line)); RefreshLine(line); }
cf1dfa6b
VZ
573
574 // refresh one or several lines at once
575 void RefreshLine( size_t line );
576 void RefreshLines( size_t lineFrom, size_t lineTo );
577
578 // return true if the line is highlighted
b54e41c5 579 bool IsHighlighted(size_t line) const;
efbb7287 580
5cd89174
VZ
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
583 // report mode
584
585 // get the bound rect for the entire line
586 wxRect GetLineRect(size_t line) const;
587
588 // get the bound rect of the label
589 wxRect GetLineLabelRect(size_t line) const;
590
591 // get the bound rect of the items icon (only may be called if we do have
592 // an icon!)
593 wxRect GetLineIconRect(size_t line) const;
594
595 // get the rect to be highlighted when the item has focus
596 wxRect GetLineHighlightRect(size_t line) const;
597
598 // get the size of the total line rect
599 wxSize GetLineSize(size_t line) const
600 { return GetLineRect(line).GetSize(); }
601
602 // return the hit code for the corresponding position (in this line)
603 long HitTestLine(size_t line, int x, int y) const;
604
efbb7287 605 void EditLabel( long item );
efbb7287
VZ
606 void OnRenameTimer();
607 void OnRenameAccept();
608
609 void OnMouse( wxMouseEvent &event );
610 void MoveToFocus();
cf1dfa6b
VZ
611
612 // called to switch the selection from the current item to newCurrent,
613 void OnArrowChar( size_t newCurrent, const wxKeyEvent& event );
614
efbb7287
VZ
615 void OnChar( wxKeyEvent &event );
616 void OnKeyDown( wxKeyEvent &event );
617 void OnSetFocus( wxFocusEvent &event );
618 void OnKillFocus( wxFocusEvent &event );
efbb7287 619 void OnScroll(wxScrollWinEvent& event) ;
f6bcfd97 620
cf1dfa6b
VZ
621 void OnPaint( wxPaintEvent &event );
622
efbb7287 623 void DrawImage( int index, wxDC *dc, int x, int y );
5cd89174
VZ
624 void GetImageSize( int index, int &width, int &height ) const;
625 int GetTextLength( const wxString &s ) const;
efbb7287
VZ
626
627 void SetImageList( wxImageList *imageList, int which );
628 void SetItemSpacing( int spacing, bool isSmall = FALSE );
629 int GetItemSpacing( bool isSmall = FALSE );
cf1dfa6b 630
efbb7287
VZ
631 void SetColumn( int col, wxListItem &item );
632 void SetColumnWidth( int col, int width );
cf1dfa6b
VZ
633 void GetColumn( int col, wxListItem &item ) const;
634 int GetColumnWidth( int col ) const;
635 int GetColumnCount() const { return m_columns.GetCount(); }
636
637 // returns the sum of the heights of all columns
638 int GetHeaderWidth() const;
639
5cd89174 640 int GetCountPerPage() const;
cf1dfa6b 641
efbb7287
VZ
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 );
efbb7287
VZ
646 void GetItemRect( long index, wxRect &rect );
647 bool GetItemPosition( long item, wxPoint& pos );
648 int GetSelectedItemCount();
cf1dfa6b
VZ
649
650 // set the scrollbars and update the positions of the items
b54e41c5
VZ
651 void RecalculatePositions();
652
653 // refresh the window and the header
654 void RefreshAll();
cf1dfa6b 655
efbb7287
VZ
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 );
efbb7287 666 void InsertColumn( long col, wxListItem &item );
efbb7287
VZ
667 void SortItems( wxListCtrlCompare fn, long data );
668
cf1dfa6b 669 size_t GetItemCount() const;
1370703e 670 bool IsEmpty() const { return GetItemCount() == 0; }
2c1f73ee
VZ
671 void SetItemCount(long count);
672
b54e41c5 673 void ResetCurrent() { m_current = (size_t)-1; }
cf1dfa6b
VZ
674 bool HasCurrent() const { return m_current != (size_t)-1; }
675
676 // send out a wxListEvent
677 void SendNotify( size_t line,
678 wxEventType command,
679 wxPoint point = wxDefaultPosition );
680
b54e41c5
VZ
681 // override base class virtual to reset m_lineHeight when the font changes
682 virtual bool SetFont(const wxFont& font)
683 {
684 if ( !wxScrolledWindow::SetFont(font) )
685 return FALSE;
686
687 m_lineHeight = 0;
688
689 return TRUE;
690 }
cf1dfa6b
VZ
691
692 // these are for wxListLineData usage only
693
694 // get the backpointer to the list ctrl
695 wxListCtrl *GetListCtrl() const
696 {
697 return wxStaticCast(GetParent(), wxListCtrl);
698 }
699
700 // get the height of all lines (assuming they all do have the same height)
701 wxCoord GetLineHeight() const;
702
703 // get the y position of the given line (only for report view)
704 wxCoord GetLineY(size_t line) const;
705
706//protected:
707 // the array of all line objects for a non virtual list control
708 wxListLineDataArray m_lines;
709
710 // the list of column objects
711 wxListHeaderDataList m_columns;
712
713 // currently focused item or -1
714 size_t m_current;
715
716 // the item currently being edited or -1
717 size_t m_currentEdit;
718
719 // the number of lines per page
720 int m_linesPerPage;
721
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()
727 // call
728 bool m_dirty;
729
b54e41c5
VZ
730 wxBrush *m_highlightBrush;
731 wxColour *m_highlightColour;
cf1dfa6b
VZ
732 int m_xScroll,
733 m_yScroll;
734 wxImageList *m_small_image_list;
735 wxImageList *m_normal_image_list;
736 int m_small_spacing;
737 int m_normal_spacing;
738 bool m_hasFocus;
739
740 bool m_lastOnSame;
741 wxTimer *m_renameTimer;
742 bool m_renameAccept;
743 wxString m_renameRes;
744 bool m_isCreated;
745 int m_dragCount;
746 wxPoint m_dragStart;
747
748 // for double click logic
749 size_t m_lineLastClicked,
750 m_lineBeforeLastClicked;
751
1370703e 752protected:
cf1dfa6b 753 // the total count of items in a virtual list control
b54e41c5 754 size_t m_countVirt;
cf1dfa6b 755
b54e41c5
VZ
756 // the object maintaining the items selection state, only used in virtual
757 // controls
758 wxSelectionStore m_selStore;
cf1dfa6b 759
1370703e
VZ
760 // common part of all ctors
761 void Init();
762
cf1dfa6b
VZ
763 // intiialize m_[xy]Scroll
764 void InitScrolling();
765
1370703e
VZ
766 // get the line data for the given index
767 wxListLineData *GetLine(size_t n) const
768 {
769 wxASSERT_MSG( n != (size_t)-1, _T("invalid line index") );
770
cf1dfa6b
VZ
771 if ( IsVirtual() )
772 {
773 wxConstCast(this, wxListMainWindow)->CacheLineData(n);
774
775 n = 0;
776 }
777
1370703e
VZ
778 return &m_lines[n];
779 }
780
b54e41c5
VZ
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;
cf1dfa6b
VZ
784
785 // cache the line data of the n-th line in m_lines[0]
786 void CacheLineData(size_t line);
787
b54e41c5
VZ
788 // get the range of visible lines
789 void GetVisibleLinesRange(size_t *from, size_t *to);
790
791 // force us to recalculate the range of visible lines
792 void ResetVisibleLinesRange() { m_lineFrom = (size_t)-1; }
793
794 // get the colour to be used for drawing the rules
795 wxColour GetRuleColour() const
796 {
797#ifdef __WXMAC__
798 return *wxWHITE;
799#else
800 return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT);
801#endif
802 }
cf1dfa6b 803
efbb7287 804private:
cf1dfa6b
VZ
805 // initialize the current item if needed
806 void UpdateCurrent();
807
808 // called when an item is [un]focuded, i.e. becomes [not] current
809 //
810 // currently unused
811 void OnFocusLine( size_t line );
812 void OnUnfocusLine( size_t line );
813
814 // the height of one line using the current font
815 wxCoord m_lineHeight;
816
817 // the total header width or 0 if not calculated yet
818 wxCoord m_headerWidth;
819
b54e41c5
VZ
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
823 size_t m_lineFrom,
824 m_lineTo;
825
efbb7287
VZ
826 DECLARE_DYNAMIC_CLASS(wxListMainWindow);
827 DECLARE_EVENT_TABLE()
828};
829
830// ============================================================================
831// implementation
832// ============================================================================
833
b54e41c5
VZ
834// ----------------------------------------------------------------------------
835// wxSelectionStore
836// ----------------------------------------------------------------------------
837
838bool wxSelectionStore::IsSelected(size_t item) const
839{
840 bool isSel = m_itemsSel.Index(item) != wxNOT_FOUND;
841
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;
845}
846
847bool wxSelectionStore::SelectItem(size_t item, bool select)
848{
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;
854
855 if ( select != m_defaultState )
856 {
857 if ( !isSel )
858 {
859 m_itemsSel.AddAt(item, index);
860
861 return TRUE;
862 }
863 }
864 else // reset to default state
865 {
866 if ( isSel )
867 {
868 m_itemsSel.RemoveAt(index);
869 return TRUE;
870 }
871 }
872
873 return FALSE;
874}
875
876void wxSelectionStore::SelectRange(size_t itemFrom, size_t itemTo, bool select)
877{
878 wxASSERT_MSG( itemFrom <= itemTo, _T("should be in order") );
879
880 // are we going to have more [un]selected items than the other ones?
881 if ( itemTo - itemFrom > m_count / 2 )
882 {
883 if ( select != m_defaultState )
884 {
885 // the default state now becomes the same as 'select'
886 m_defaultState = select;
887
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;
891 m_itemsSel.Empty();
892
893 // TODO: it should be possible to optimize the searches a bit
894 // knowing the possible range
895
896 size_t item;
897 for ( item = 0; item < itemFrom; item++ )
898 {
899 if ( selOld.Index(item) == wxNOT_FOUND )
900 m_itemsSel.Add(item);
901 }
902
903 for ( item = itemTo + 1; item < m_count; item++ )
904 {
905 if ( selOld.Index(item) == wxNOT_FOUND )
906 m_itemsSel.Add(item);
907 }
908 }
909 else // select == m_defaultState
910 {
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);
915
916 if ( start == count || m_itemsSel[start] < itemFrom )
917 {
918 start++;
919 }
920
921 if ( end == count || m_itemsSel[end] > itemTo )
922 {
923 end--;
924 }
925
926 if ( start <= end )
927 {
928 // delete all of them (from end to avoid changing indices)
929 for ( int i = end; i >= (int)start; i-- )
930 {
931 m_itemsSel.RemoveAt(i);
932 }
933 }
934 }
935 }
936 else // "few" items change state
937 {
938 // just add the items to the selection
939 for ( size_t item = itemFrom; item <= itemTo; item++ )
940 {
941 SelectItem(item, select);
942 }
943 }
944}
945
946void wxSelectionStore::OnItemDelete(size_t item)
947{
948 size_t count = m_itemsSel.GetCount(),
949 i = m_itemsSel.IndexForInsert(item);
950
951 if ( i < count && m_itemsSel[i] == item )
952 {
953 // this item itself was in m_itemsSel, remove it from there
954 m_itemsSel.RemoveAt(i);
938b652b
VZ
955
956 count--;
b54e41c5
VZ
957 }
958
959 // and adjust the index of all which follow it
960 while ( i < count )
961 {
962 // all following elements must be greater than the one we deleted
963 wxASSERT_MSG( m_itemsSel[i] > item, _T("logic error") );
964
965 m_itemsSel[i++]--;
966 }
967}
968
c801d85f
KB
969//-----------------------------------------------------------------------------
970// wxListItemData
971//-----------------------------------------------------------------------------
972
cf1dfa6b 973void wxListItemData::Init()
c801d85f 974{
92976ab6
RR
975 m_image = -1;
976 m_data = 0;
cf1dfa6b 977
0530737d 978 m_attr = NULL;
e1e955e1 979}
c801d85f 980
cf1dfa6b 981wxListItemData::wxListItemData(wxListMainWindow *owner)
c801d85f 982{
cf1dfa6b 983 Init();
0530737d 984
cf1dfa6b
VZ
985 m_owner = owner;
986
987 if ( owner->HasFlag(wxLC_REPORT) )
988 {
989 m_rect = NULL;
990 }
991 else
992 {
993 m_rect = new wxRect;
994 }
e1e955e1 995}
c801d85f
KB
996
997void wxListItemData::SetItem( const wxListItem &info )
998{
cf1dfa6b 999 if ( info.m_mask & wxLIST_MASK_TEXT )
54442116 1000 SetText(info.m_text);
cf1dfa6b 1001 if ( info.m_mask & wxLIST_MASK_IMAGE )
54442116 1002 m_image = info.m_image;
cf1dfa6b 1003 if ( info.m_mask & wxLIST_MASK_DATA )
54442116 1004 m_data = info.m_data;
0530737d
VZ
1005
1006 if ( info.HasAttributes() )
1007 {
1008 if ( m_attr )
1009 *m_attr = *info.GetAttributes();
1010 else
1011 m_attr = new wxListItemAttr(*info.GetAttributes());
1012 }
1013
cf1dfa6b
VZ
1014 if ( m_rect )
1015 {
1016 m_rect->x =
1017 m_rect->y =
1018 m_rect->height = 0;
1019 m_rect->width = info.m_width;
1020 }
e1e955e1 1021}
c801d85f 1022
debe6624 1023void wxListItemData::SetPosition( int x, int y )
c801d85f 1024{
cf1dfa6b
VZ
1025 wxCHECK_RET( m_rect, _T("unexpected SetPosition() call") );
1026
1027 m_rect->x = x;
1028 m_rect->y = y;
e1e955e1 1029}
c801d85f 1030
1e6d9499 1031void wxListItemData::SetSize( int width, int height )
c801d85f 1032{
cf1dfa6b 1033 wxCHECK_RET( m_rect, _T("unexpected SetSize() call") );
c801d85f 1034
cf1dfa6b
VZ
1035 if ( width != -1 )
1036 m_rect->width = width;
1037 if ( height != -1 )
1038 m_rect->height = height;
e1e955e1 1039}
c801d85f 1040
debe6624 1041bool wxListItemData::IsHit( int x, int y ) const
c801d85f 1042{
cf1dfa6b
VZ
1043 wxCHECK_MSG( m_rect, FALSE, _T("can't be called in this mode") );
1044
1045 return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x, y);
e1e955e1 1046}
c801d85f 1047
fd9811b1 1048int wxListItemData::GetX() const
c801d85f 1049{
cf1dfa6b
VZ
1050 wxCHECK_MSG( m_rect, 0, _T("can't be called in this mode") );
1051
1052 return m_rect->x;
e1e955e1 1053}
c801d85f 1054
fd9811b1 1055int wxListItemData::GetY() const
c801d85f 1056{
cf1dfa6b
VZ
1057 wxCHECK_MSG( m_rect, 0, _T("can't be called in this mode") );
1058
1059 return m_rect->y;
e1e955e1 1060}
c801d85f 1061
fd9811b1 1062int wxListItemData::GetWidth() const
c801d85f 1063{
cf1dfa6b
VZ
1064 wxCHECK_MSG( m_rect, 0, _T("can't be called in this mode") );
1065
1066 return m_rect->width;
e1e955e1 1067}
c801d85f 1068
fd9811b1 1069int wxListItemData::GetHeight() const
c801d85f 1070{
cf1dfa6b 1071 wxCHECK_MSG( m_rect, 0, _T("can't be called in this mode") );
c801d85f 1072
cf1dfa6b 1073 return m_rect->height;
e1e955e1 1074}
c801d85f 1075
0530737d 1076void wxListItemData::GetItem( wxListItem &info ) const
c801d85f 1077{
92976ab6
RR
1078 info.m_text = m_text;
1079 info.m_image = m_image;
1080 info.m_data = m_data;
c801d85f 1081
0530737d
VZ
1082 if ( m_attr )
1083 {
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());
1090 }
e1e955e1 1091}
c801d85f
KB
1092
1093//-----------------------------------------------------------------------------
1094// wxListHeaderData
1095//-----------------------------------------------------------------------------
1096
1097IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData,wxObject);
1098
fd9811b1 1099wxListHeaderData::wxListHeaderData()
c801d85f 1100{
92976ab6
RR
1101 m_mask = 0;
1102 m_image = 0;
1103 m_format = 0;
1104 m_width = 0;
1105 m_xpos = 0;
1106 m_ypos = 0;
1107 m_height = 0;
e1e955e1 1108}
c801d85f
KB
1109
1110wxListHeaderData::wxListHeaderData( const wxListItem &item )
1111{
92976ab6
RR
1112 SetItem( item );
1113 m_xpos = 0;
1114 m_ypos = 0;
1115 m_height = 0;
e1e955e1 1116}
c801d85f
KB
1117
1118void wxListHeaderData::SetItem( const wxListItem &item )
1119{
92976ab6
RR
1120 m_mask = item.m_mask;
1121 m_text = item.m_text;
1122 m_image = item.m_image;
1123 m_format = item.m_format;
cf1dfa6b
VZ
1124
1125 SetWidth(item.m_width);
e1e955e1 1126}
c801d85f 1127
debe6624 1128void wxListHeaderData::SetPosition( int x, int y )
c801d85f 1129{
92976ab6
RR
1130 m_xpos = x;
1131 m_ypos = y;
e1e955e1 1132}
c801d85f 1133
debe6624 1134void wxListHeaderData::SetHeight( int h )
c801d85f 1135{
92976ab6 1136 m_height = h;
e1e955e1 1137}
c801d85f 1138
debe6624 1139void wxListHeaderData::SetWidth( int w )
c801d85f 1140{
92976ab6 1141 m_width = w;
cf1dfa6b
VZ
1142 if (m_width < 0)
1143 m_width = WIDTH_COL_DEFAULT;
1144 if (m_width < WIDTH_COL_MIN)
1145 m_width = WIDTH_COL_MIN;
e1e955e1 1146}
c801d85f 1147
debe6624 1148void wxListHeaderData::SetFormat( int format )
c801d85f 1149{
92976ab6 1150 m_format = format;
e1e955e1 1151}
c801d85f 1152
fd9811b1 1153bool wxListHeaderData::HasImage() const
c801d85f 1154{
92976ab6 1155 return (m_image != 0);
e1e955e1 1156}
c801d85f 1157
c801d85f
KB
1158bool wxListHeaderData::IsHit( int x, int y ) const
1159{
92976ab6 1160 return ((x >= m_xpos) && (x <= m_xpos+m_width) && (y >= m_ypos) && (y <= m_ypos+m_height));
e1e955e1 1161}
c801d85f
KB
1162
1163void wxListHeaderData::GetItem( wxListItem &item )
1164{
92976ab6
RR
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;
e1e955e1 1170}
c801d85f 1171
fd9811b1 1172int wxListHeaderData::GetImage() const
c801d85f 1173{
92976ab6 1174 return m_image;
e1e955e1 1175}
c801d85f 1176
fd9811b1 1177int wxListHeaderData::GetWidth() const
c801d85f 1178{
92976ab6 1179 return m_width;
e1e955e1 1180}
c801d85f 1181
fd9811b1 1182int wxListHeaderData::GetFormat() const
c801d85f 1183{
92976ab6 1184 return m_format;
e1e955e1 1185}
c801d85f
KB
1186
1187//-----------------------------------------------------------------------------
1188// wxListLineData
1189//-----------------------------------------------------------------------------
1190
cf1dfa6b
VZ
1191inline int wxListLineData::GetMode() const
1192{
b54e41c5 1193 return m_owner->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE;
cf1dfa6b 1194}
c801d85f 1195
cf1dfa6b 1196inline bool wxListLineData::InReportView() const
c801d85f 1197{
cf1dfa6b 1198 return m_owner->HasFlag(wxLC_REPORT);
e1e955e1 1199}
c801d85f 1200
b54e41c5 1201inline bool wxListLineData::IsVirtual() const
c801d85f 1202{
cf1dfa6b
VZ
1203 return m_owner->IsVirtual();
1204}
2c1f73ee 1205
5cd89174 1206wxListLineData::wxListLineData( wxListMainWindow *owner )
cf1dfa6b
VZ
1207{
1208 m_owner = owner;
1209 m_items.DeleteContents( TRUE );
2c1f73ee 1210
cf1dfa6b
VZ
1211 if ( InReportView() )
1212 {
1213 m_gi = NULL;
1214 }
1215 else // !report
1216 {
1217 m_gi = new GeometryInfo;
1218 }
f6bcfd97 1219
b54e41c5 1220 m_highlighted = FALSE;
f6bcfd97 1221
cf1dfa6b
VZ
1222 InitItems( GetMode() == wxLC_REPORT ? m_owner->GetColumnCount() : 1 );
1223}
f6bcfd97 1224
cf1dfa6b
VZ
1225void wxListLineData::CalculateSize( wxDC *dc, int spacing )
1226{
1227 wxListItemDataList::Node *node = m_items.GetFirst();
1228 wxCHECK_RET( node, _T("no subitems at all??") );
1229
1230 wxListItemData *item = node->GetData();
1231
1232 switch ( GetMode() )
1233 {
1234 case wxLC_ICON:
1235 case wxLC_SMALL_ICON:
1236 {
1237 m_gi->m_rectAll.width = spacing;
1238
1239 wxString s = item->GetText();
1240
1241 wxCoord lw, lh;
1242 if ( s.empty() )
5d25c050 1243 {
cf1dfa6b
VZ
1244 lh =
1245 m_gi->m_rectLabel.width =
1246 m_gi->m_rectLabel.height = 0;
5d25c050 1247 }
cf1dfa6b
VZ
1248 else // has label
1249 {
1250 dc->GetTextExtent( s, &lw, &lh );
1251 if (lh < SCROLL_UNIT_Y)
1252 lh = SCROLL_UNIT_Y;
1253 lw += EXTRA_WIDTH;
1254 lh += EXTRA_HEIGHT;
1255
1256 m_gi->m_rectAll.height = spacing + lh;
1257 if (lw > spacing)
1258 m_gi->m_rectAll.width = lw;
1259
1260 m_gi->m_rectLabel.width = lw;
1261 m_gi->m_rectLabel.height = lh;
1262 }
1263
1264 if (item->HasImage())
1265 {
1266 int w, h;
1267 m_owner->GetImageSize( item->GetImage(), w, h );
1268 m_gi->m_rectIcon.width = w + 8;
1269 m_gi->m_rectIcon.height = h + 8;
1270
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;
1275 }
1276
1277 if ( item->HasText() )
5d25c050 1278 {
b54e41c5
VZ
1279 m_gi->m_rectHighlight.width = m_gi->m_rectLabel.width;
1280 m_gi->m_rectHighlight.height = m_gi->m_rectLabel.height;
cf1dfa6b
VZ
1281 }
1282 else // no text, highlight the icon
1283 {
b54e41c5
VZ
1284 m_gi->m_rectHighlight.width = m_gi->m_rectIcon.width;
1285 m_gi->m_rectHighlight.height = m_gi->m_rectIcon.height;
5d25c050 1286 }
92976ab6
RR
1287 }
1288 break;
cf1dfa6b 1289
92976ab6 1290 case wxLC_LIST:
92976ab6 1291 {
cf1dfa6b 1292 wxString s = item->GetTextForMeasuring();
2c1f73ee 1293
13111b2a 1294 wxCoord lw,lh;
92976ab6 1295 dc->GetTextExtent( s, &lw, &lh );
cf1dfa6b
VZ
1296 if (lh < SCROLL_UNIT_Y)
1297 lh = SCROLL_UNIT_Y;
1298 lw += EXTRA_WIDTH;
1299 lh += EXTRA_HEIGHT;
2c1f73ee 1300
cf1dfa6b
VZ
1301 m_gi->m_rectLabel.width = lw;
1302 m_gi->m_rectLabel.height = lh;
f6bcfd97 1303
cf1dfa6b
VZ
1304 m_gi->m_rectAll.width = lw;
1305 m_gi->m_rectAll.height = lh;
f6bcfd97 1306
0b855868
RR
1307 if (item->HasImage())
1308 {
cf1dfa6b 1309 int w, h;
0b855868 1310 m_owner->GetImageSize( item->GetImage(), w, h );
cf1dfa6b
VZ
1311 m_gi->m_rectIcon.width = w;
1312 m_gi->m_rectIcon.height = h;
f6bcfd97 1313
cf1dfa6b
VZ
1314 m_gi->m_rectAll.width += 4 + w;
1315 if (h > m_gi->m_rectAll.height)
1316 m_gi->m_rectAll.height = h;
bffa1c77 1317 }
f6bcfd97 1318
b54e41c5
VZ
1319 m_gi->m_rectHighlight.width = m_gi->m_rectAll.width;
1320 m_gi->m_rectHighlight.height = m_gi->m_rectAll.height;
92976ab6
RR
1321 }
1322 break;
2c1f73ee 1323
cf1dfa6b
VZ
1324 case wxLC_REPORT:
1325 wxFAIL_MSG( _T("unexpected call to SetSize") );
92976ab6 1326 break;
cf1dfa6b
VZ
1327
1328 default:
1329 wxFAIL_MSG( _T("unknown mode") );
e1e955e1 1330 }
e1e955e1 1331}
c801d85f 1332
cf1dfa6b
VZ
1333void wxListLineData::SetPosition( int x, int y,
1334 int window_width,
1335 int spacing )
c801d85f 1336{
2c1f73ee 1337 wxListItemDataList::Node *node = m_items.GetFirst();
cf1dfa6b 1338 wxCHECK_RET( node, _T("no subitems at all??") );
2c1f73ee 1339
cf1dfa6b 1340 wxListItemData *item = node->GetData();
2c1f73ee 1341
cf1dfa6b 1342 switch ( GetMode() )
0b855868
RR
1343 {
1344 case wxLC_ICON:
cf1dfa6b
VZ
1345 case wxLC_SMALL_ICON:
1346 m_gi->m_rectAll.x = x;
1347 m_gi->m_rectAll.y = y;
1348
1349 if ( item->HasImage() )
0b855868 1350 {
cf1dfa6b
VZ
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;
0b855868 1354 }
cf1dfa6b
VZ
1355
1356 if ( item->HasText() )
0b855868 1357 {
cf1dfa6b
VZ
1358 if (m_gi->m_rectAll.width > spacing)
1359 m_gi->m_rectLabel.x = m_gi->m_rectAll.x + 2;
5d25c050 1360 else
cf1dfa6b
VZ
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;
b54e41c5
VZ
1363 m_gi->m_rectHighlight.x = m_gi->m_rectLabel.x - 2;
1364 m_gi->m_rectHighlight.y = m_gi->m_rectLabel.y - 2;
bffa1c77 1365 }
cf1dfa6b 1366 else // no text, highlight the icon
0b855868 1367 {
b54e41c5
VZ
1368 m_gi->m_rectHighlight.x = m_gi->m_rectIcon.x - 4;
1369 m_gi->m_rectHighlight.y = m_gi->m_rectIcon.y - 4;
bffa1c77 1370 }
0b855868 1371 break;
c801d85f 1372
cf1dfa6b
VZ
1373 case wxLC_LIST:
1374 m_gi->m_rectAll.x = x;
1375 m_gi->m_rectAll.y = y;
c801d85f 1376
b54e41c5
VZ
1377 m_gi->m_rectHighlight.x = m_gi->m_rectAll.x;
1378 m_gi->m_rectHighlight.y = m_gi->m_rectAll.y;
cf1dfa6b 1379 m_gi->m_rectLabel.y = m_gi->m_rectAll.y + 2;
c801d85f 1380
cf1dfa6b
VZ
1381 if (item->HasImage())
1382 {
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;
1386 }
1387 else
1388 {
1389 m_gi->m_rectLabel.x = m_gi->m_rectAll.x + 2;
1390 }
1391 break;
c801d85f 1392
cf1dfa6b
VZ
1393 case wxLC_REPORT:
1394 wxFAIL_MSG( _T("unexpected call to SetPosition") );
1395 break;
c801d85f 1396
cf1dfa6b
VZ
1397 default:
1398 wxFAIL_MSG( _T("unknown mode") );
1399 }
e1e955e1 1400}
c801d85f 1401
debe6624 1402void wxListLineData::InitItems( int num )
c801d85f 1403{
2c1f73ee 1404 for (int i = 0; i < num; i++)
cf1dfa6b 1405 m_items.Append( new wxListItemData(m_owner) );
e1e955e1 1406}
c801d85f 1407
debe6624 1408void wxListLineData::SetItem( int index, const wxListItem &info )
c801d85f 1409{
2c1f73ee 1410 wxListItemDataList::Node *node = m_items.Item( index );
1370703e
VZ
1411 wxCHECK_RET( node, _T("invalid column index in SetItem") );
1412
1413 wxListItemData *item = node->GetData();
1414 item->SetItem( info );
e1e955e1 1415}
c801d85f 1416
1e6d9499 1417void wxListLineData::GetItem( int index, wxListItem &info )
c801d85f 1418{
2c1f73ee 1419 wxListItemDataList::Node *node = m_items.Item( index );
139adb6a
RR
1420 if (node)
1421 {
2c1f73ee 1422 wxListItemData *item = node->GetData();
139adb6a
RR
1423 item->GetItem( info );
1424 }
e1e955e1 1425}
c801d85f 1426
54442116 1427wxString wxListLineData::GetText(int index) const
c801d85f 1428{
54442116
VZ
1429 wxString s;
1430
2c1f73ee 1431 wxListItemDataList::Node *node = m_items.Item( index );
139adb6a
RR
1432 if (node)
1433 {
2c1f73ee 1434 wxListItemData *item = node->GetData();
54442116 1435 s = item->GetText();
139adb6a 1436 }
54442116
VZ
1437
1438 return s;
e1e955e1 1439}
c801d85f 1440
debe6624 1441void wxListLineData::SetText( int index, const wxString s )
c801d85f 1442{
2c1f73ee 1443 wxListItemDataList::Node *node = m_items.Item( index );
139adb6a
RR
1444 if (node)
1445 {
2c1f73ee 1446 wxListItemData *item = node->GetData();
139adb6a
RR
1447 item->SetText( s );
1448 }
e1e955e1 1449}
c801d85f 1450
cf1dfa6b 1451void wxListLineData::SetImage( int index, int image )
c801d85f 1452{
2c1f73ee 1453 wxListItemDataList::Node *node = m_items.Item( index );
cf1dfa6b
VZ
1454 wxCHECK_RET( node, _T("invalid column index in SetImage()") );
1455
1456 wxListItemData *item = node->GetData();
1457 item->SetImage(image);
1458}
1459
1460int wxListLineData::GetImage( int index ) const
1461{
1462 wxListItemDataList::Node *node = m_items.Item( index );
1463 wxCHECK_MSG( node, -1, _T("invalid column index in GetImage()") );
1464
1465 wxListItemData *item = node->GetData();
1466 return item->GetImage();
e1e955e1 1467}
c801d85f 1468
0530737d
VZ
1469void wxListLineData::SetAttributes(wxDC *dc,
1470 const wxListItemAttr *attr,
1471 const wxColour& colText,
470caaf9 1472 const wxFont& font,
b54e41c5 1473 bool highlight)
0530737d 1474{
470caaf9
VZ
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)
b54e41c5 1478 if ( !highlight && attr && attr->HasTextColour() )
0530737d
VZ
1479 {
1480 dc->SetTextForeground(attr->GetTextColour());
1481 }
1482 else
1483 {
1484 dc->SetTextForeground(colText);
1485 }
1486
1487 if ( attr && attr->HasFont() )
1488 {
1489 dc->SetFont(attr->GetFont());
1490 }
1491 else
1492 {
1493 dc->SetFont(font);
1494 }
1495}
1496
5cd89174
VZ
1497void wxListLineData::Draw( wxDC *dc )
1498{
1499 wxListItemDataList::Node *node = m_items.GetFirst();
1500 wxCHECK_RET( node, _T("no subitems at all??") );
1501
1502 wxListItemData *item = node->GetData();
1503 if (item->HasImage())
1504 {
1505 wxRect rectIcon = m_gi->m_rectIcon;
1506 m_owner->DrawImage( item->GetImage(), dc,
1507 rectIcon.x, rectIcon.y );
1508 }
1509
1510 if (item->HasText())
1511 {
1512 wxRect rectLabel = m_gi->m_rectLabel;
1513 dc->DrawText( item->GetText(), rectLabel.x, rectLabel.y );
1514 }
1515}
1516
1517void wxListLineData::DrawInReportMode( wxDC *dc,
938b652b 1518 const wxRect& rect,
5cd89174
VZ
1519 const wxRect& rectHL,
1520 bool highlighted )
c801d85f 1521{
cf1dfa6b 1522 // use our own flag if we maintain it
5cd89174 1523 if ( !IsVirtual() )
b54e41c5 1524 highlighted = m_highlighted;
cf1dfa6b 1525
0530737d 1526 // default foreground colour
5cd89174 1527 wxWindow *listctrl = m_owner->GetParent();
0530737d 1528 wxColour colText;
b54e41c5 1529 if ( highlighted )
0530737d
VZ
1530 {
1531 colText = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT );
1532 }
1533 else
1534 {
1535 colText = listctrl->GetForegroundColour();
1536 }
1537
1538 // default font
1539 wxFont font = listctrl->GetFont();
1540
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.
2c1f73ee 1544 wxListItemData *item = m_items.GetFirst()->GetData();
0530737d 1545 wxListItemAttr *attr = item->GetAttributes();
b54e41c5 1546 SetAttributes(dc, attr, colText, font, highlighted);
0530737d
VZ
1547
1548 bool hasBgCol = attr && attr->HasBackgroundColour();
b54e41c5 1549 if ( highlighted || hasBgCol )
c801d85f 1550 {
b54e41c5 1551 if ( highlighted )
63852e78 1552 {
b54e41c5 1553 dc->SetBrush( *m_owner->m_highlightBrush );
63852e78
RR
1554 }
1555 else
1556 {
0530737d
VZ
1557 if ( hasBgCol )
1558 dc->SetBrush(wxBrush(attr->GetBackgroundColour(), wxSOLID));
1559 else
1560 dc->SetBrush( * wxWHITE_BRUSH );
63852e78 1561 }
0530737d
VZ
1562
1563 dc->SetPen( * wxTRANSPARENT_PEN );
5cd89174 1564 dc->DrawRectangle( rectHL );
e1e955e1 1565 }
004fd0c8 1566
2c1f73ee 1567 wxListItemDataList::Node *node = m_items.GetFirst();
5cd89174 1568 wxCHECK_RET( node, _T("no subitems at all??") );
2c1f73ee 1569
5cd89174 1570 size_t col = 0;
938b652b
VZ
1571 wxCoord x = rect.x + HEADER_OFFSET_X,
1572 y = rect.y + (LINE_SPACING + EXTRA_HEIGHT) / 2;
cf1dfa6b 1573
5cd89174
VZ
1574 while ( node )
1575 {
1576 wxListItemData *item = node->GetData();
cf1dfa6b 1577
5cd89174 1578 int xOld = x;
cf1dfa6b 1579
5cd89174
VZ
1580 if ( item->HasImage() )
1581 {
1582 int ix, iy;
938b652b 1583 m_owner->DrawImage( item->GetImage(), dc, x, y );
5cd89174
VZ
1584 m_owner->GetImageSize( item->GetImage(), ix, iy );
1585 x += ix + 5; // FIXME: what is "5"?
1586 }
cf1dfa6b 1587
5cd89174 1588 int width = m_owner->GetColumnWidth(col++);
cf1dfa6b 1589
938b652b 1590 wxDCClipper clipper(*dc, x, y, width, rect.height);
cf1dfa6b 1591
5cd89174
VZ
1592 if ( item->HasText() )
1593 {
938b652b 1594 dc->DrawText( item->GetText(), x, y );
5cd89174 1595 }
cf1dfa6b 1596
5cd89174 1597 x = xOld + width;
cf1dfa6b 1598
5cd89174 1599 node = node->GetNext();
e1e955e1 1600 }
e1e955e1 1601}
c801d85f 1602
b54e41c5 1603bool wxListLineData::Highlight( bool on )
c801d85f 1604{
b54e41c5 1605 wxCHECK_MSG( !m_owner->IsVirtual(), FALSE, _T("unexpected call to Highlight") );
c801d85f 1606
b54e41c5 1607 if ( on == m_highlighted )
cf1dfa6b 1608 return FALSE;
c801d85f 1609
b54e41c5 1610 m_highlighted = on;
c801d85f 1611
cf1dfa6b 1612 return TRUE;
e1e955e1 1613}
c801d85f 1614
b54e41c5 1615void wxListLineData::ReverseHighlight( void )
c801d85f 1616{
b54e41c5 1617 Highlight(!IsHighlighted());
e1e955e1 1618}
c801d85f
KB
1619
1620//-----------------------------------------------------------------------------
1621// wxListHeaderWindow
1622//-----------------------------------------------------------------------------
1623
1624IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow,wxWindow);
1625
1626BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow)
63852e78
RR
1627 EVT_PAINT (wxListHeaderWindow::OnPaint)
1628 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse)
1629 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus)
c801d85f
KB
1630END_EVENT_TABLE()
1631
1632wxListHeaderWindow::wxListHeaderWindow( void )
1633{
63852e78
RR
1634 m_owner = (wxListMainWindow *) NULL;
1635 m_currentCursor = (wxCursor *) NULL;
1636 m_resizeCursor = (wxCursor *) NULL;
cfb50f14 1637 m_isDragging = FALSE;
e1e955e1 1638}
c801d85f 1639
bd8289c1 1640wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, wxWindowID id, wxListMainWindow *owner,
debe6624
JS
1641 const wxPoint &pos, const wxSize &size,
1642 long style, const wxString &name ) :
c801d85f
KB
1643 wxWindow( win, id, pos, size, style, name )
1644{
63852e78 1645 m_owner = owner;
c801d85f 1646// m_currentCursor = wxSTANDARD_CURSOR;
63852e78
RR
1647 m_currentCursor = (wxCursor *) NULL;
1648 m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
cfb50f14 1649 m_isDragging = FALSE;
f6bcfd97
BP
1650 m_dirty = FALSE;
1651
cfb50f14 1652 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ) );
e1e955e1 1653}
c801d85f 1654
a367b9b3
JS
1655wxListHeaderWindow::~wxListHeaderWindow( void )
1656{
63852e78 1657 delete m_resizeCursor;
a367b9b3
JS
1658}
1659
1e6d9499 1660void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h )
c801d85f 1661{
3fb435df 1662#ifdef __WXGTK__
b54e41c5
VZ
1663 GtkStateType state = m_parent->IsEnabled() ? GTK_STATE_NORMAL
1664 : GTK_STATE_INSENSITIVE;
2c1f73ee 1665
3fb435df 1666 x = dc->XLOG2DEV( x );
2c1f73ee 1667
b54e41c5
VZ
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);
4176fb7d
SC
1672#elif defined( __WXMAC__ )
1673 const int m_corner = 1;
1674
1675 dc->SetBrush( *wxTRANSPARENT_BRUSH );
1676
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)
1680
1681 wxPen pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID );
1682
1683 dc->SetPen( pen );
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)
1686
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 );
b54e41c5 1692#else // !GTK, !Mac
63852e78 1693 const int m_corner = 1;
c801d85f 1694
63852e78 1695 dc->SetBrush( *wxTRANSPARENT_BRUSH );
c801d85f 1696
63852e78
RR
1697 dc->SetPen( *wxBLACK_PEN );
1698 dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer)
17867d61 1699 dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer)
bd8289c1 1700
63852e78 1701 wxPen pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID );
004fd0c8 1702
63852e78
RR
1703 dc->SetPen( pen );
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)
bd8289c1 1706
63852e78
RR
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 );
3fb435df 1712#endif
e1e955e1 1713}
c801d85f 1714
f6bcfd97
BP
1715// shift the DC origin to match the position of the main window horz
1716// scrollbar: this allows us to always use logical coords
1717void wxListHeaderWindow::AdjustDC(wxDC& dc)
1718{
f6bcfd97
BP
1719 int xpix;
1720 m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
1721
1722 int x;
1723 m_owner->GetViewStart( &x, NULL );
1724
1725 // account for the horz scrollbar offset
1726 dc.SetDeviceOrigin( -x * xpix, 0 );
f6bcfd97
BP
1727}
1728
c801d85f
KB
1729void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
1730{
10bd0724
JS
1731#ifdef __WXGTK__
1732 wxClientDC dc( this );
1733#else
63852e78 1734 wxPaintDC dc( this );
10bd0724
JS
1735#endif
1736
63852e78 1737 PrepareDC( dc );
f6bcfd97 1738 AdjustDC( dc );
bffa1c77 1739
63852e78 1740 dc.BeginDrawing();
bd8289c1 1741
63852e78 1742 dc.SetFont( GetFont() );
bd8289c1 1743
f6bcfd97
BP
1744 // width and height of the entire header window
1745 int w, h;
63852e78 1746 GetClientSize( &w, &h );
f6bcfd97 1747 m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
c801d85f 1748
f60d0f94 1749 dc.SetBackgroundMode(wxTRANSPARENT);
70846f0a
VZ
1750
1751 // do *not* use the listctrl colour for headers - one day we will have a
1752 // function to set it separately
37d403aa 1753 //dc.SetTextForeground( *wxBLACK );
cf1dfa6b
VZ
1754 dc.SetTextForeground(wxSystemSettings::
1755 GetSystemColour( wxSYS_COLOUR_WINDOWTEXT ));
1756
1757 int x = HEADER_OFFSET_X;
c801d85f 1758
63852e78
RR
1759 int numColumns = m_owner->GetColumnCount();
1760 wxListItem item;
1761 for (int i = 0; i < numColumns; i++)
1762 {
1763 m_owner->GetColumn( i, item );
f6bcfd97
BP
1764 int wCol = item.m_width;
1765 int cw = wCol - 2; // the width of the rect to draw
1766
1767 int xEnd = x + wCol;
1768
63852e78 1769 dc.SetPen( *wxWHITE_PEN );
c801d85f 1770
cf1dfa6b
VZ
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 );
40c70187 1774 dc.DestroyClippingRegion();
f6bcfd97
BP
1775 x += wCol;
1776
1777 if (xEnd > w+5)
1778 break;
63852e78
RR
1779 }
1780 dc.EndDrawing();
e1e955e1 1781}
c801d85f 1782
0208334d
RR
1783void wxListHeaderWindow::DrawCurrent()
1784{
63852e78
RR
1785 int x1 = m_currentX;
1786 int y1 = 0;
f6bcfd97
BP
1787 ClientToScreen( &x1, &y1 );
1788
63852e78
RR
1789 int x2 = m_currentX-1;
1790 int y2 = 0;
f6bcfd97 1791 m_owner->GetClientSize( NULL, &y2 );
63852e78 1792 m_owner->ClientToScreen( &x2, &y2 );
0208334d 1793
63852e78 1794 wxScreenDC dc;
3c679789 1795 dc.SetLogicalFunction( wxINVERT );
63852e78
RR
1796 dc.SetPen( wxPen( *wxBLACK, 2, wxSOLID ) );
1797 dc.SetBrush( *wxTRANSPARENT_BRUSH );
0208334d 1798
f6bcfd97
BP
1799 AdjustDC(dc);
1800
63852e78 1801 dc.DrawLine( x1, y1, x2, y2 );
0208334d 1802
63852e78 1803 dc.SetLogicalFunction( wxCOPY );
0208334d 1804
63852e78
RR
1805 dc.SetPen( wxNullPen );
1806 dc.SetBrush( wxNullBrush );
0208334d
RR
1807}
1808
c801d85f
KB
1809void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
1810{
f6bcfd97 1811 // we want to work with logical coords
3ca6a5f0
BP
1812 int x;
1813 m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
3ca6a5f0 1814 int y = event.GetY();
f6bcfd97 1815
cfb50f14 1816 if (m_isDragging)
0208334d 1817 {
f6bcfd97
BP
1818 // we don't draw the line beyond our window, but we allow dragging it
1819 // there
1820 int w = 0;
1821 GetClientSize( &w, NULL );
f6bcfd97 1822 m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
f6bcfd97
BP
1823 w -= 6;
1824
1825 // erase the line if it was drawn
1826 if ( m_currentX < w )
1827 DrawCurrent();
1828
63852e78
RR
1829 if (event.ButtonUp())
1830 {
1831 ReleaseMouse();
cfb50f14 1832 m_isDragging = FALSE;
f6bcfd97
BP
1833 m_dirty = TRUE;
1834 m_owner->SetColumnWidth( m_column, m_currentX - m_minX );
63852e78
RR
1835 }
1836 else
1837 {
f6bcfd97 1838 if (x > m_minX + 7)
63852e78
RR
1839 m_currentX = x;
1840 else
f6bcfd97 1841 m_currentX = m_minX + 7;
bd8289c1 1842
f6bcfd97
BP
1843 // draw in the new location
1844 if ( m_currentX < w )
1845 DrawCurrent();
bffa1c77 1846 }
0208334d 1847 }
f6bcfd97 1848 else // not dragging
c801d85f 1849 {
f6bcfd97
BP
1850 m_minX = 0;
1851 bool hit_border = FALSE;
1852
1853 // end of the current column
1854 int xpos = 0;
1855
1856 // find the column where this event occured
1857 int countCol = m_owner->GetColumnCount();
cf1dfa6b 1858 for (int col = 0; col < countCol; col++)
bffa1c77 1859 {
cf1dfa6b
VZ
1860 xpos += m_owner->GetColumnWidth( col );
1861 m_column = col;
f6bcfd97
BP
1862
1863 if ( (abs(x-xpos) < 3) && (y < 22) )
1864 {
1865 // near the column border
1866 hit_border = TRUE;
1867 break;
1868 }
1869
1870 if ( x < xpos )
1871 {
1872 // inside the column
1873 break;
1874 }
1875
1876 m_minX = xpos;
bffa1c77 1877 }
63852e78 1878
f6bcfd97 1879 if (event.LeftDown())
63852e78 1880 {
f6bcfd97
BP
1881 if (hit_border)
1882 {
1883 m_isDragging = TRUE;
1884 m_currentX = x;
1885 DrawCurrent();
1886 CaptureMouse();
1887 }
1888 else
1889 {
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 );
1895 }
63852e78 1896 }
f6bcfd97 1897 else if (event.Moving())
63852e78 1898 {
f6bcfd97
BP
1899 bool setCursor;
1900 if (hit_border)
1901 {
1902 setCursor = m_currentCursor == wxSTANDARD_CURSOR;
1903 m_currentCursor = m_resizeCursor;
1904 }
1905 else
1906 {
1907 setCursor = m_currentCursor != wxSTANDARD_CURSOR;
1908 m_currentCursor = wxSTANDARD_CURSOR;
1909 }
1910
1911 if ( setCursor )
1912 SetCursor(*m_currentCursor);
63852e78 1913 }
e1e955e1 1914 }
e1e955e1 1915}
c801d85f
KB
1916
1917void wxListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
1918{
63852e78 1919 m_owner->SetFocus();
e1e955e1 1920}
c801d85f
KB
1921
1922//-----------------------------------------------------------------------------
1923// wxListRenameTimer (internal)
1924//-----------------------------------------------------------------------------
1925
bd8289c1
VZ
1926wxListRenameTimer::wxListRenameTimer( wxListMainWindow *owner )
1927{
63852e78 1928 m_owner = owner;
e1e955e1 1929}
c801d85f 1930
bd8289c1
VZ
1931void wxListRenameTimer::Notify()
1932{
63852e78 1933 m_owner->OnRenameTimer();
e1e955e1 1934}
c801d85f 1935
ee7ee469
RR
1936//-----------------------------------------------------------------------------
1937// wxListTextCtrl (internal)
1938//-----------------------------------------------------------------------------
1939
1940IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl,wxTextCtrl);
bd8289c1 1941
ee7ee469 1942BEGIN_EVENT_TABLE(wxListTextCtrl,wxTextCtrl)
63852e78 1943 EVT_CHAR (wxListTextCtrl::OnChar)
2c1f73ee 1944 EVT_KEY_UP (wxListTextCtrl::OnKeyUp)
63852e78 1945 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus)
ee7ee469
RR
1946END_EVENT_TABLE()
1947
674ac8b9
VZ
1948wxListTextCtrl::wxListTextCtrl( wxWindow *parent,
1949 const wxWindowID id,
1950 bool *accept,
1951 wxString *res,
1952 wxListMainWindow *owner,
1953 const wxString &value,
1954 const wxPoint &pos,
1955 const wxSize &size,
1956 int style,
1957 const wxValidator& validator,
1958 const wxString &name )
1959 : wxTextCtrl( parent, id, value, pos, size, style, validator, name )
ee7ee469 1960{
63852e78
RR
1961 m_res = res;
1962 m_accept = accept;
1963 m_owner = owner;
5f1ea0ee
RR
1964 (*m_accept) = FALSE;
1965 (*m_res) = "";
1966 m_startValue = value;
ee7ee469
RR
1967}
1968
1969void wxListTextCtrl::OnChar( wxKeyEvent &event )
1970{
63852e78
RR
1971 if (event.m_keyCode == WXK_RETURN)
1972 {
1973 (*m_accept) = TRUE;
1974 (*m_res) = GetValue();
f6bcfd97 1975
bce1406b
RR
1976 if (!wxPendingDelete.Member(this))
1977 wxPendingDelete.Append(this);
1978
1979 if ((*m_accept) && ((*m_res) != m_startValue))
1980 m_owner->OnRenameAccept();
f6bcfd97 1981
63852e78
RR
1982 return;
1983 }
1984 if (event.m_keyCode == WXK_ESCAPE)
1985 {
1986 (*m_accept) = FALSE;
1987 (*m_res) = "";
f6bcfd97 1988
bce1406b
RR
1989 if (!wxPendingDelete.Member(this))
1990 wxPendingDelete.Append(this);
f6bcfd97 1991
63852e78
RR
1992 return;
1993 }
f6bcfd97 1994
63852e78
RR
1995 event.Skip();
1996}
1997
c13cace1
VS
1998void wxListTextCtrl::OnKeyUp( wxKeyEvent &event )
1999{
2000 // auto-grow the textctrl:
2001 wxSize parentSize = m_owner->GetSize();
2002 wxPoint myPos = GetPosition();
2003 wxSize mySize = GetSize();
2004 int sx, sy;
cf1dfa6b
VZ
2005 GetTextExtent(GetValue() + _T("MM"), &sx, &sy); // FIXME: MM??
2006 if (myPos.x + sx > parentSize.x)
2007 sx = parentSize.x - myPos.x;
2008 if (mySize.x > sx)
2009 sx = mySize.x;
c13cace1 2010 SetSize(sx, -1);
2c1f73ee 2011
c13cace1
VS
2012 event.Skip();
2013}
2014
63852e78
RR
2015void wxListTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
2016{
bce1406b
RR
2017 if (!wxPendingDelete.Member(this))
2018 wxPendingDelete.Append(this);
004fd0c8 2019
5f1ea0ee
RR
2020 if ((*m_accept) && ((*m_res) != m_startValue))
2021 m_owner->OnRenameAccept();
ee7ee469
RR
2022}
2023
c801d85f
KB
2024//-----------------------------------------------------------------------------
2025// wxListMainWindow
2026//-----------------------------------------------------------------------------
2027
2028IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow,wxScrolledWindow);
bd8289c1 2029
c801d85f
KB
2030BEGIN_EVENT_TABLE(wxListMainWindow,wxScrolledWindow)
2031 EVT_PAINT (wxListMainWindow::OnPaint)
c801d85f
KB
2032 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse)
2033 EVT_CHAR (wxListMainWindow::OnChar)
3dfb93fd 2034 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown)
c801d85f
KB
2035 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus)
2036 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus)
2fa7c206 2037 EVT_SCROLLWIN (wxListMainWindow::OnScroll)
c801d85f
KB
2038END_EVENT_TABLE()
2039
1370703e 2040void wxListMainWindow::Init()
c801d85f 2041{
139adb6a 2042 m_columns.DeleteContents( TRUE );
139adb6a 2043 m_dirty = TRUE;
cf1dfa6b
VZ
2044 m_countVirt = 0;
2045 m_lineFrom =
b54e41c5 2046 m_lineTo = (size_t)-1;
cf1dfa6b
VZ
2047 m_linesPerPage = 0;
2048
2049 m_headerWidth =
2050 m_lineHeight = 0;
1370703e 2051
139adb6a
RR
2052 m_small_image_list = (wxImageList *) NULL;
2053 m_normal_image_list = (wxImageList *) NULL;
1370703e 2054
139adb6a
RR
2055 m_small_spacing = 30;
2056 m_normal_spacing = 40;
1370703e 2057
139adb6a 2058 m_hasFocus = FALSE;
1370703e
VZ
2059 m_dragCount = 0;
2060 m_isCreated = FALSE;
2061
139adb6a
RR
2062 m_lastOnSame = FALSE;
2063 m_renameTimer = new wxListRenameTimer( this );
1370703e
VZ
2064 m_renameAccept = FALSE;
2065
cf1dfa6b
VZ
2066 m_current =
2067 m_currentEdit =
efbb7287 2068 m_lineLastClicked =
1370703e 2069 m_lineBeforeLastClicked = (size_t)-1;
e1e955e1 2070}
c801d85f 2071
cf1dfa6b
VZ
2072void wxListMainWindow::InitScrolling()
2073{
2074 if ( HasFlag(wxLC_REPORT) )
2075 {
2076 m_xScroll = SCROLL_UNIT_X;
2077 m_yScroll = SCROLL_UNIT_Y;
2078 }
2079 else
2080 {
2081 m_xScroll = SCROLL_UNIT_Y;
2082 m_yScroll = 0;
2083 }
2084}
2085
1370703e 2086wxListMainWindow::wxListMainWindow()
c801d85f 2087{
1370703e
VZ
2088 Init();
2089
b54e41c5 2090 m_highlightBrush = (wxBrush *) NULL;
1370703e
VZ
2091
2092 m_xScroll =
2093 m_yScroll = 0;
2094}
2095
2096wxListMainWindow::wxListMainWindow( wxWindow *parent,
2097 wxWindowID id,
2098 const wxPoint& pos,
2099 const wxSize& size,
2100 long style,
2101 const wxString &name )
2102 : wxScrolledWindow( parent, id, pos, size,
2103 style | wxHSCROLL | wxVSCROLL, name )
2104{
2105 Init();
2106
b54e41c5 2107 m_highlightBrush = new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), wxSOLID );
139adb6a
RR
2108 wxSize sz = size;
2109 sz.y = 25;
bd8289c1 2110
cf1dfa6b 2111 InitScrolling();
139adb6a 2112 SetScrollbars( m_xScroll, m_yScroll, 0, 0, 0, 0 );
bd8289c1 2113
91fc2bdc 2114 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) );
e1e955e1 2115}
c801d85f 2116
fd9811b1 2117wxListMainWindow::~wxListMainWindow()
c801d85f 2118{
12c1b46a
RR
2119 DeleteEverything();
2120
b54e41c5 2121 delete m_highlightBrush;
004fd0c8 2122
139adb6a 2123 delete m_renameTimer;
e1e955e1 2124}
c801d85f 2125
cf1dfa6b 2126void wxListMainWindow::CacheLineData(size_t line)
c801d85f 2127{
cf1dfa6b 2128 wxListCtrl *listctrl = GetListCtrl();
25e3a937 2129
b54e41c5 2130 wxListLineData *ld = GetDummyLine();
f6bcfd97 2131
cf1dfa6b
VZ
2132 size_t countCol = GetColumnCount();
2133 for ( size_t col = 0; col < countCol; col++ )
2134 {
2135 ld->SetText(col, listctrl->OnGetItemText(line, col));
2136 }
2137
5cd89174 2138 ld->SetImage(listctrl->OnGetItemImage(line));
e1e955e1 2139}
c801d85f 2140
b54e41c5 2141wxListLineData *wxListMainWindow::GetDummyLine() const
c801d85f 2142{
cf1dfa6b 2143 wxASSERT_MSG( !IsEmpty(), _T("invalid line index") );
2c1f73ee 2144
cf1dfa6b 2145 if ( m_lines.IsEmpty() )
2c1f73ee 2146 {
cf1dfa6b
VZ
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") );
2150
2151 wxListMainWindow *self = wxConstCast(this, wxListMainWindow);
5cd89174 2152 wxListLineData *line = new wxListLineData(self);
cf1dfa6b 2153 self->m_lines.Add(line);
2c1f73ee
VZ
2154 }
2155
cf1dfa6b
VZ
2156 return &m_lines[0];
2157}
2158
5cd89174
VZ
2159// ----------------------------------------------------------------------------
2160// line geometry (report mode only)
2161// ----------------------------------------------------------------------------
2162
cf1dfa6b
VZ
2163wxCoord wxListMainWindow::GetLineHeight() const
2164{
2165 wxASSERT_MSG( HasFlag(wxLC_REPORT), _T("only works in report mode") );
673dfcfa 2166
cf1dfa6b
VZ
2167 // we cache the line height as calling GetTextExtent() is slow
2168 if ( !m_lineHeight )
2c1f73ee 2169 {
cf1dfa6b 2170 wxListMainWindow *self = wxConstCast(this, wxListMainWindow);
bd8289c1 2171
cf1dfa6b
VZ
2172 wxClientDC dc( self );
2173 dc.SetFont( GetFont() );
c801d85f 2174
cf1dfa6b
VZ
2175 wxCoord y;
2176 dc.GetTextExtent(_T("H"), NULL, &y);
004fd0c8 2177
cf1dfa6b
VZ
2178 if ( y < SCROLL_UNIT_Y )
2179 y = SCROLL_UNIT_Y;
2180 y += EXTRA_HEIGHT;
206b0a67 2181
cf1dfa6b
VZ
2182 self->m_lineHeight = y + LINE_SPACING;
2183 }
bffa1c77 2184
cf1dfa6b
VZ
2185 return m_lineHeight;
2186}
bffa1c77 2187
cf1dfa6b
VZ
2188wxCoord wxListMainWindow::GetLineY(size_t line) const
2189{
2190 wxASSERT_MSG( HasFlag(wxLC_REPORT), _T("only works in report mode") );
1370703e 2191
cf1dfa6b
VZ
2192 return LINE_SPACING + line*GetLineHeight();
2193}
206b0a67 2194
5cd89174
VZ
2195wxRect wxListMainWindow::GetLineRect(size_t line) const
2196{
2197 if ( !InReportView() )
2198 return GetLine(line)->m_gi->m_rectAll;
2199
2200 wxRect rect;
2201 rect.x = HEADER_OFFSET_X;
2202 rect.y = GetLineY(line);
2203 rect.width = GetHeaderWidth();
2204 rect.height = GetLineHeight();
2205
2206 return rect;
2207}
2208
2209wxRect wxListMainWindow::GetLineLabelRect(size_t line) const
2210{
2211 if ( !InReportView() )
2212 return GetLine(line)->m_gi->m_rectLabel;
2213
2214 wxRect rect;
2215 rect.x = HEADER_OFFSET_X;
2216 rect.y = GetLineY(line);
2217 rect.width = GetColumnWidth(0);
2218 rect.height = GetLineHeight();
2219
2220 return rect;
2221}
2222
2223wxRect wxListMainWindow::GetLineIconRect(size_t line) const
2224{
2225 if ( !InReportView() )
2226 return GetLine(line)->m_gi->m_rectIcon;
2227
2228 wxListLineData *ld = GetLine(line);
2229 wxASSERT_MSG( ld->HasImage(), _T("should have an image") );
2230
2231 wxRect rect;
2232 rect.x = HEADER_OFFSET_X;
2233 rect.y = GetLineY(line);
2234 GetImageSize(ld->GetImage(), rect.width, rect.height);
2235
2236 return rect;
2237}
2238
2239wxRect wxListMainWindow::GetLineHighlightRect(size_t line) const
2240{
2241 return InReportView() ? GetLineRect(line)
2242 : GetLine(line)->m_gi->m_rectHighlight;
2243}
2244
2245long wxListMainWindow::HitTestLine(size_t line, int x, int y) const
2246{
2247 wxListLineData *ld = GetLine(line);
2248
2249 if ( ld->HasImage() && GetLineIconRect(line).Inside(x, y) )
2250 return wxLIST_HITTEST_ONITEMICON;
2251
2252 if ( ld->HasText() )
2253 {
2254 wxRect rect = InReportView() ? GetLineRect(line)
2255 : GetLineLabelRect(line);
2256
2257 if ( rect.Inside(x, y) )
2258 return wxLIST_HITTEST_ONITEMLABEL;
2259 }
2260
2261 return 0;
2262}
2263
2264// ----------------------------------------------------------------------------
2265// highlight (selection) handling
2266// ----------------------------------------------------------------------------
2267
b54e41c5 2268bool wxListMainWindow::IsHighlighted(size_t line) const
cf1dfa6b
VZ
2269{
2270 if ( IsVirtual() )
2271 {
b54e41c5 2272 return m_selStore.IsSelected(line);
cf1dfa6b
VZ
2273 }
2274 else // !virtual
2275 {
2276 wxListLineData *ld = GetLine(line);
b54e41c5 2277 wxCHECK_MSG( ld, FALSE, _T("invalid index in IsHighlighted") );
cf1dfa6b 2278
b54e41c5 2279 return ld->IsHighlighted();
cf1dfa6b
VZ
2280 }
2281}
2282
b54e41c5 2283void wxListMainWindow::HighlightLines( size_t lineFrom, size_t lineTo, bool highlight )
cf1dfa6b 2284{
cf1dfa6b
VZ
2285 if ( IsVirtual() )
2286 {
b54e41c5
VZ
2287 m_selStore.SelectRange(lineFrom, lineTo, highlight);
2288 RefreshLines(lineFrom, lineTo);
2289 }
2290 else
2291 {
2292 // do it the dumb way
2293 bool needsRefresh = FALSE;
2294 for ( size_t line = lineFrom; line <= lineTo; line++ )
cf1dfa6b 2295 {
b54e41c5
VZ
2296 if ( HighlightLine(line, highlight) )
2297 needsRefresh = TRUE;
cf1dfa6b 2298 }
b54e41c5
VZ
2299
2300 if ( needsRefresh )
2301 RefreshLines(lineFrom, lineTo);
2302 }
2303}
2304
2305bool wxListMainWindow::HighlightLine( size_t line, bool highlight )
2306{
2307 bool changed;
2308
2309 if ( IsVirtual() )
2310 {
2311 changed = m_selStore.SelectItem(line, highlight);
cf1dfa6b
VZ
2312 }
2313 else // !virtual
2314 {
2315 wxListLineData *ld = GetLine(line);
b54e41c5 2316 wxCHECK_MSG( ld, FALSE, _T("invalid index in IsHighlighted") );
cf1dfa6b 2317
b54e41c5 2318 changed = ld->Highlight(highlight);
cf1dfa6b
VZ
2319 }
2320
2321 if ( changed )
2322 {
b54e41c5 2323 SendNotify( line, highlight ? wxEVT_COMMAND_LIST_ITEM_SELECTED
5cd89174 2324 : wxEVT_COMMAND_LIST_ITEM_DESELECTED );
cf1dfa6b
VZ
2325 }
2326
2327 return changed;
2328}
2329
2330void wxListMainWindow::RefreshLine( size_t line )
2331{
5cd89174 2332 wxRect rect = GetLineRect(line);
cf1dfa6b
VZ
2333
2334 CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
2335 RefreshRect( rect );
2336}
2337
2338void wxListMainWindow::RefreshLines( size_t lineFrom, size_t lineTo )
2339{
2340 // we suppose that they are ordered by caller
2341 wxASSERT_MSG( lineFrom <= lineTo, _T("indices in disorder") );
2342
2343 if ( HasFlag(wxLC_REPORT) )
2344 {
b54e41c5
VZ
2345 size_t visibleFrom, visibleTo;
2346 GetVisibleLinesRange(&visibleFrom, &visibleTo);
2347
2348 if ( lineFrom < visibleFrom )
2349 lineFrom = visibleFrom;
2350 if ( lineTo > visibleTo )
2351 lineTo = visibleTo;
cf1dfa6b
VZ
2352
2353 wxRect rect;
2354 rect.x = 0;
2355 rect.y = GetLineY(lineFrom);
2356 rect.width = GetClientSize().x;
2357 rect.height = GetLineY(lineTo) - rect.y;
2358
2359 CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
2360 RefreshRect( rect );
2361 }
2362 else // !report
2363 {
2364 // TODO: this should be optimized...
2365 for ( size_t line = lineFrom; line <= lineTo; line++ )
2366 {
2367 RefreshLine(line);
2368 }
2369 }
2370}
2371
2372void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
2373{
2374 // Note: a wxPaintDC must be constructed even if no drawing is
2375 // done (a Windows requirement).
2376 wxPaintDC dc( this );
2377
cf1dfa6b
VZ
2378 if ( IsEmpty() )
2379 {
2380 // empty control. nothing to draw
2381 return;
2382 }
2383
2384 PrepareDC( dc );
2385
2386 int dev_x, dev_y;
2387 CalcScrolledPosition( 0, 0, &dev_x, &dev_y );
2388
2389 dc.BeginDrawing();
2390
2391 dc.SetFont( GetFont() );
2392
2393 if ( HasFlag(wxLC_REPORT) )
2394 {
b54e41c5 2395 int lineHeight = GetLineHeight();
cf1dfa6b 2396
b54e41c5
VZ
2397 size_t visibleFrom, visibleTo;
2398 GetVisibleLinesRange(&visibleFrom, &visibleTo);
2399 for ( size_t line = visibleFrom; line <= visibleTo; line++ )
cf1dfa6b 2400 {
5cd89174
VZ
2401 GetLine(line)->DrawInReportMode( &dc,
2402 GetLineRect(line),
2403 GetLineHighlightRect(line),
2404 IsHighlighted(line) );
cf1dfa6b
VZ
2405 }
2406
2407 if ( HasFlag(wxLC_HRULES) )
2408 {
b54e41c5 2409 wxPen pen(GetRuleColour(), 1, wxSOLID);
cf1dfa6b
VZ
2410 wxSize clientSize = GetClientSize();
2411
b54e41c5 2412 for ( size_t i = visibleFrom; i <= visibleTo; i++ )
cf1dfa6b
VZ
2413 {
2414 dc.SetPen(pen);
2415 dc.SetBrush( *wxTRANSPARENT_BRUSH );
b54e41c5
VZ
2416 dc.DrawLine(0 - dev_x, i*lineHeight,
2417 clientSize.x - dev_x, i*lineHeight);
cf1dfa6b
VZ
2418 }
2419
2420 // Draw last horizontal rule
b54e41c5 2421 if ( visibleTo > visibleFrom )
cf1dfa6b
VZ
2422 {
2423 dc.SetPen(pen);
2424 dc.SetBrush( *wxTRANSPARENT_BRUSH );
b54e41c5
VZ
2425 dc.DrawLine(0 - dev_x, m_lineTo*lineHeight,
2426 clientSize.x - dev_x , m_lineTo*lineHeight );
cf1dfa6b 2427 }
2c1f73ee 2428 }
206b0a67
JS
2429
2430 // Draw vertical rules if required
cf1dfa6b 2431 if ( HasFlag(wxLC_VRULES) && !IsEmpty() )
206b0a67 2432 {
b54e41c5 2433 wxPen pen(GetRuleColour(), 1, wxSOLID);
cf1dfa6b 2434
206b0a67
JS
2435 int col = 0;
2436 wxRect firstItemRect;
2437 wxRect lastItemRect;
2438 GetItemRect(0, firstItemRect);
2439 GetItemRect(GetItemCount() - 1, lastItemRect);
2440 int x = firstItemRect.GetX();
673dfcfa
JS
2441 dc.SetPen(pen);
2442 dc.SetBrush(* wxTRANSPARENT_BRUSH);
206b0a67
JS
2443 for (col = 0; col < GetColumnCount(); col++)
2444 {
2445 int colWidth = GetColumnWidth(col);
cf1dfa6b
VZ
2446 x += colWidth;
2447 dc.DrawLine(x - dev_x, firstItemRect.GetY() - 1 - dev_y,
2448 x - dev_x, lastItemRect.GetBottom() + 1 - dev_y);
206b0a67 2449 }
d786bf87 2450 }
139adb6a 2451 }
cf1dfa6b 2452 else // !report
139adb6a 2453 {
1370703e 2454 size_t count = GetItemCount();
cf1dfa6b
VZ
2455 for ( size_t i = 0; i < count; i++ )
2456 {
2457 GetLine(i)->Draw( &dc );
2458 }
139adb6a 2459 }
004fd0c8 2460
cf1dfa6b
VZ
2461 if ( HasCurrent() && m_hasFocus )
2462 {
4176fb7d
SC
2463#ifdef __WXMAC__
2464 // no rect outline, we already have the background color
2465#else
cf1dfa6b
VZ
2466 dc.SetPen( *wxBLACK_PEN );
2467 dc.SetBrush( *wxTRANSPARENT_BRUSH );
5cd89174 2468 dc.DrawRectangle( GetLineHighlightRect(m_current) );
4176fb7d 2469#endif
cf1dfa6b 2470 }
c801d85f 2471
139adb6a 2472 dc.EndDrawing();
e1e955e1 2473}
c801d85f 2474
b54e41c5 2475void wxListMainWindow::HighlightAll( bool on )
c801d85f 2476{
b54e41c5 2477 if ( IsSingleSel() )
c801d85f 2478 {
b54e41c5
VZ
2479 wxASSERT_MSG( !on, _T("can't do this in a single sel control") );
2480
2481 // we just have one item to turn off
2482 if ( HasCurrent() && IsHighlighted(m_current) )
139adb6a 2483 {
b54e41c5
VZ
2484 HighlightLine(m_current, FALSE);
2485 RefreshLine(m_current);
139adb6a 2486 }
e1e955e1 2487 }
b54e41c5 2488 else // multi sel
cf1dfa6b 2489 {
b54e41c5 2490 HighlightLines(0, GetItemCount() - 1, on);
cf1dfa6b 2491 }
e1e955e1 2492}
c801d85f 2493
cf1dfa6b 2494void wxListMainWindow::SendNotify( size_t line,
05a7f61d
VZ
2495 wxEventType command,
2496 wxPoint point )
c801d85f 2497{
139adb6a
RR
2498 wxListEvent le( command, GetParent()->GetId() );
2499 le.SetEventObject( GetParent() );
cf1dfa6b 2500 le.m_itemIndex = line;
05a7f61d
VZ
2501
2502 // set only for events which have position
2503 if ( point != wxDefaultPosition )
2504 le.m_pointDrag = point;
2505
cf1dfa6b 2506 GetLine(line)->GetItem( 0, le.m_item );
6e228e42 2507 GetParent()->GetEventHandler()->ProcessEvent( le );
e1e955e1 2508}
c801d85f 2509
cf1dfa6b 2510void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line) )
c801d85f
KB
2511{
2512// SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
e1e955e1 2513}
c801d85f 2514
cf1dfa6b 2515void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line) )
c801d85f
KB
2516{
2517// SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
e1e955e1 2518}
c801d85f 2519
5f1ea0ee 2520void wxListMainWindow::EditLabel( long item )
c801d85f 2521{
cf1dfa6b
VZ
2522 wxCHECK_RET( (item >= 0) && ((size_t)item < GetItemCount()),
2523 wxT("wrong index in wxListCtrl::EditLabel()") );
004fd0c8 2524
1370703e 2525 m_currentEdit = (size_t)item;
e179bd65 2526
fd9811b1 2527 wxListEvent le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, GetParent()->GetId() );
139adb6a 2528 le.SetEventObject( GetParent() );
1370703e
VZ
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 );
139adb6a 2533 GetParent()->GetEventHandler()->ProcessEvent( le );
004fd0c8 2534
86f975a8 2535 if (!le.IsAllowed())
5f1ea0ee 2536 return;
004fd0c8 2537
cf1dfa6b
VZ
2538 // We have to call this here because the label in question might just have
2539 // been added and no screen update taken place.
2540 if (m_dirty)
2541 wxSafeYield();
004fd0c8 2542
92976ab6
RR
2543 wxClientDC dc(this);
2544 PrepareDC( dc );
bd8289c1 2545
cf1dfa6b 2546 wxString s = data->GetText(0);
5cd89174 2547 wxRect rectLabel = GetLineLabelRect(m_currentEdit);
cf1dfa6b
VZ
2548
2549 rectLabel.x = dc.LogicalToDeviceX( rectLabel.x );
2550 rectLabel.y = dc.LogicalToDeviceY( rectLabel.y );
2551
2552 wxListTextCtrl *text = new wxListTextCtrl
2553 (
2554 this, -1,
2555 &m_renameAccept,
2556 &m_renameRes,
2557 this,
2558 s,
2559 wxPoint(rectLabel.x-4,rectLabel.y-4),
2560 wxSize(rectLabel.width+11,rectLabel.height+8)
2561 );
92976ab6 2562 text->SetFocus();
e1e955e1 2563}
c801d85f 2564
e179bd65
RR
2565void wxListMainWindow::OnRenameTimer()
2566{
cf1dfa6b 2567 wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") );
004fd0c8 2568
cf1dfa6b 2569 EditLabel( m_current );
e179bd65
RR
2570}
2571
c801d85f
KB
2572void wxListMainWindow::OnRenameAccept()
2573{
e179bd65
RR
2574 wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
2575 le.SetEventObject( GetParent() );
1370703e
VZ
2576 le.m_itemIndex = m_currentEdit;
2577
2578 wxListLineData *data = GetLine(m_currentEdit);
2579 wxCHECK_RET( data, _T("invalid index in OnRenameAccept()") );
2580
2581 data->GetItem( 0, le.m_item );
e179bd65
RR
2582 le.m_item.m_text = m_renameRes;
2583 GetParent()->GetEventHandler()->ProcessEvent( le );
004fd0c8 2584
e179bd65 2585 if (!le.IsAllowed()) return;
004fd0c8 2586
5f1ea0ee
RR
2587 wxListItem info;
2588 info.m_mask = wxLIST_MASK_TEXT;
2589 info.m_itemId = le.m_itemIndex;
2590 info.m_text = m_renameRes;
aaa37c0d 2591 info.SetTextColour(le.m_item.GetTextColour());
5f1ea0ee 2592 SetItem( info );
e1e955e1 2593}
c801d85f
KB
2594
2595void wxListMainWindow::OnMouse( wxMouseEvent &event )
2596{
3e1c4e00 2597 event.SetEventObject( GetParent() );
cf1dfa6b
VZ
2598 if ( GetParent()->GetEventHandler()->ProcessEvent( event) )
2599 return;
2600
2601 if ( !HasCurrent() || IsEmpty() )
2602 return;
2603
2604 if (m_dirty)
2605 return;
e3e65dac 2606
cf1dfa6b
VZ
2607 if ( !(event.Dragging() || event.ButtonDown() || event.LeftUp() ||
2608 event.ButtonDClick()) )
2609 return;
c801d85f 2610
aaef15bf
RR
2611 int x = event.GetX();
2612 int y = event.GetY();
2613 CalcUnscrolledPosition( x, y, &x, &y );
004fd0c8 2614
51cc4dad 2615 /* Did we actually hit an item ? */
92976ab6 2616 long hitResult = 0;
1370703e 2617
cf1dfa6b
VZ
2618 size_t count = GetItemCount(),
2619 current;
2620
2621 if ( HasFlag(wxLC_REPORT) )
92976ab6 2622 {
5cd89174
VZ
2623 current = y / GetLineHeight();
2624 hitResult = HitTestLine(current, x, y);
cf1dfa6b
VZ
2625 }
2626 else // !report
2627 {
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!!
5cd89174 2630 for ( current = 0; current < count && !hitResult; current++ )
cf1dfa6b 2631 {
5cd89174 2632 hitResult = HitTestLine(current, x, y);
cf1dfa6b 2633 }
92976ab6 2634 }
bd8289c1 2635
fd9811b1 2636 if (event.Dragging())
92976ab6 2637 {
fd9811b1 2638 if (m_dragCount == 0)
bffa1c77
VZ
2639 m_dragStart = wxPoint(x,y);
2640
fd9811b1 2641 m_dragCount++;
bffa1c77 2642
cf1dfa6b
VZ
2643 if (m_dragCount != 3)
2644 return;
bffa1c77 2645
05a7f61d
VZ
2646 int command = event.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2647 : wxEVT_COMMAND_LIST_BEGIN_DRAG;
bffa1c77 2648
fd9811b1 2649 wxListEvent le( command, GetParent()->GetId() );
92976ab6 2650 le.SetEventObject( GetParent() );
bffa1c77
VZ
2651 le.m_pointDrag = m_dragStart;
2652 GetParent()->GetEventHandler()->ProcessEvent( le );
2653
2654 return;
92976ab6 2655 }
fd9811b1
RR
2656 else
2657 {
2658 m_dragCount = 0;
2659 }
bd8289c1 2660
cf1dfa6b
VZ
2661 if ( !hitResult )
2662 {
2663 // outside of any item
2664 return;
2665 }
bd8289c1 2666
efbb7287 2667 bool forceClick = FALSE;
92976ab6
RR
2668 if (event.ButtonDClick())
2669 {
92976ab6 2670 m_renameTimer->Stop();
efbb7287
VZ
2671 m_lastOnSame = FALSE;
2672
cf1dfa6b 2673 if ( current == m_lineBeforeLastClicked )
efbb7287 2674 {
cf1dfa6b 2675 SendNotify( current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
004fd0c8 2676
efbb7287
VZ
2677 return;
2678 }
2679 else
2680 {
2681 // the first click was on another item, so don't interpret this as
2682 // a double click, but as a simple click instead
2683 forceClick = TRUE;
2684 }
92976ab6 2685 }
bd8289c1 2686
92976ab6 2687 if (event.LeftUp() && m_lastOnSame)
c801d85f 2688 {
cf1dfa6b 2689 if ((current == m_current) &&
92976ab6 2690 (hitResult == wxLIST_HITTEST_ONITEMLABEL) &&
cf1dfa6b 2691 HasFlag(wxLC_EDIT_LABELS) )
92976ab6
RR
2692 {
2693 m_renameTimer->Start( 100, TRUE );
2694 }
2695 m_lastOnSame = FALSE;
e1e955e1 2696 }
cf1dfa6b 2697 else if (event.RightDown())
b204641e 2698 {
cf1dfa6b 2699 SendNotify( current, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK,
05a7f61d 2700 event.GetPosition() );
b204641e 2701 }
cf1dfa6b 2702 else if (event.MiddleDown())
b204641e 2703 {
cf1dfa6b 2704 SendNotify( current, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK );
92976ab6 2705 }
cf1dfa6b 2706 else if ( event.LeftDown() || forceClick )
92976ab6 2707 {
efbb7287 2708 m_lineBeforeLastClicked = m_lineLastClicked;
cf1dfa6b
VZ
2709 m_lineLastClicked = current;
2710
2711 size_t oldCurrent = m_current;
efbb7287 2712
b54e41c5 2713 if ( IsSingleSel() || !(event.ControlDown() || event.ShiftDown()) )
b204641e 2714 {
b54e41c5 2715 HighlightAll( FALSE );
cf1dfa6b 2716 m_current = current;
cf1dfa6b 2717
b54e41c5 2718 ReverseHighlight(m_current);
e1e955e1 2719 }
b54e41c5 2720 else // multi sel & either ctrl or shift is down
b204641e 2721 {
473d087e 2722 if (event.ControlDown())
92976ab6 2723 {
cf1dfa6b
VZ
2724 m_current = current;
2725
b54e41c5 2726 ReverseHighlight(m_current);
92976ab6 2727 }
473d087e 2728 else if (event.ShiftDown())
92976ab6 2729 {
cf1dfa6b 2730 m_current = current;
bffa1c77 2731
cf1dfa6b
VZ
2732 size_t lineFrom = oldCurrent,
2733 lineTo = current;
f6bcfd97 2734
cf1dfa6b 2735 if ( lineTo < lineFrom )
92976ab6 2736 {
cf1dfa6b
VZ
2737 lineTo = lineFrom;
2738 lineFrom = m_current;
92976ab6
RR
2739 }
2740
b54e41c5 2741 HighlightLines(lineFrom, lineTo);
92976ab6 2742 }
cf1dfa6b 2743 else // !ctrl, !shift
92976ab6 2744 {
cf1dfa6b
VZ
2745 // test in the enclosing if should make it impossible
2746 wxFAIL_MSG( _T("how did we get here?") );
92976ab6 2747 }
e1e955e1 2748 }
cf1dfa6b 2749
92976ab6
RR
2750 if (m_current != oldCurrent)
2751 {
2752 RefreshLine( oldCurrent );
cf1dfa6b
VZ
2753 OnUnfocusLine( oldCurrent );
2754 OnFocusLine( m_current );
92976ab6 2755 }
efbb7287
VZ
2756
2757 // forceClick is only set if the previous click was on another item
2758 m_lastOnSame = !forceClick && (m_current == oldCurrent);
e1e955e1 2759 }
e1e955e1 2760}
c801d85f 2761
e179bd65 2762void wxListMainWindow::MoveToFocus()
c801d85f 2763{
b54e41c5 2764 if ( !HasCurrent() )
cf1dfa6b 2765 return;
004fd0c8 2766
5cd89174 2767 wxRect rect = GetLineRect(m_current);
cf3da716 2768
cf1dfa6b 2769 int client_w, client_h;
cf3da716 2770 GetClientSize( &client_w, &client_h );
f6bcfd97 2771
cf3da716
RR
2772 int view_x = m_xScroll*GetScrollPos( wxHORIZONTAL );
2773 int view_y = m_yScroll*GetScrollPos( wxVERTICAL );
004fd0c8 2774
cf1dfa6b 2775 if ( HasFlag(wxLC_REPORT) )
92976ab6 2776 {
b54e41c5
VZ
2777 // the next we need the range of lines shown it might be different, so
2778 // recalculate it
2779 ResetVisibleLinesRange();
2780
cf1dfa6b
VZ
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 );
92976ab6 2785 }
b54e41c5 2786 else // !report
92976ab6 2787 {
cf1dfa6b
VZ
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 );
92976ab6 2792 }
e1e955e1 2793}
c801d85f 2794
cf1dfa6b
VZ
2795// ----------------------------------------------------------------------------
2796// keyboard handling
2797// ----------------------------------------------------------------------------
2798
2799void wxListMainWindow::OnArrowChar(size_t newCurrent, const wxKeyEvent& event)
c801d85f 2800{
cf1dfa6b
VZ
2801 wxCHECK_RET( newCurrent < (size_t)GetItemCount(),
2802 _T("invalid item index in OnArrowChar()") );
2803
2804 size_t oldCurrent = m_current;
2805
2806 // in single selection we just ignore Shift as we can't select several
2807 // items anyhow
b54e41c5 2808 if ( event.ShiftDown() && !IsSingleSel() )
cf1dfa6b
VZ
2809 {
2810 m_current = newCurrent;
2811
2812 // select all the items between the old and the new one
2813 if ( oldCurrent > newCurrent )
2814 {
2815 newCurrent = oldCurrent;
2816 oldCurrent = m_current;
2817 }
2818
b54e41c5 2819 HighlightLines(oldCurrent, newCurrent);
cf1dfa6b
VZ
2820 }
2821 else // !shift
2822 {
b54e41c5
VZ
2823 // all previously selected items are unselected unless ctrl is held
2824 if ( !event.ControlDown() )
2825 HighlightAll(FALSE);
2826
cf1dfa6b
VZ
2827 m_current = newCurrent;
2828
b54e41c5 2829 HighlightLine( oldCurrent, FALSE );
cf1dfa6b
VZ
2830 RefreshLine( oldCurrent );
2831
2832 if ( !event.ControlDown() )
2833 {
b54e41c5 2834 HighlightLine( m_current, TRUE );
cf1dfa6b
VZ
2835 }
2836 }
2837
2838 OnUnfocusLine( oldCurrent );
2839 OnFocusLine( m_current );
92976ab6 2840 RefreshLine( m_current );
cf1dfa6b 2841
cf3da716 2842 MoveToFocus();
e1e955e1 2843}
c801d85f 2844
3dfb93fd
RR
2845void wxListMainWindow::OnKeyDown( wxKeyEvent &event )
2846{
2847 wxWindow *parent = GetParent();
004fd0c8 2848
3dfb93fd
RR
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;
2856 ke.m_x = event.m_x;
2857 ke.m_y = event.m_y;
2858 ke.SetEventObject( parent );
2859 if (parent->GetEventHandler()->ProcessEvent( ke )) return;
004fd0c8 2860
3dfb93fd
RR
2861 event.Skip();
2862}
004fd0c8 2863
c801d85f
KB
2864void wxListMainWindow::OnChar( wxKeyEvent &event )
2865{
51cc4dad 2866 wxWindow *parent = GetParent();
004fd0c8 2867
51cc4dad 2868 /* we send a list_key event up */
cf1dfa6b 2869 if ( HasCurrent() )
f6bcfd97
BP
2870 {
2871 wxListEvent le( wxEVT_COMMAND_LIST_KEY_DOWN, GetParent()->GetId() );
cf1dfa6b
VZ
2872 le.m_itemIndex = m_current;
2873 GetLine(m_current)->GetItem( 0, le.m_item );
f6bcfd97
BP
2874 le.m_code = (int)event.KeyCode();
2875 le.SetEventObject( parent );
2876 parent->GetEventHandler()->ProcessEvent( le );
2877 }
51cc4dad 2878
3dfb93fd
RR
2879 /* we propagate the char event up */
2880 wxKeyEvent ke( wxEVT_CHAR );
51cc4dad
RR
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;
2886 ke.m_x = event.m_x;
2887 ke.m_y = event.m_y;
2888 ke.SetEventObject( parent );
2889 if (parent->GetEventHandler()->ProcessEvent( ke )) return;
004fd0c8 2890
012a03e0
RR
2891 if (event.KeyCode() == WXK_TAB)
2892 {
2893 wxNavigationKeyEvent nevent;
c5145d41 2894 nevent.SetWindowChange( event.ControlDown() );
012a03e0 2895 nevent.SetDirection( !event.ShiftDown() );
8253c7fd 2896 nevent.SetEventObject( GetParent()->GetParent() );
012a03e0 2897 nevent.SetCurrentFocus( m_parent );
8253c7fd 2898 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent )) return;
012a03e0 2899 }
004fd0c8 2900
51cc4dad 2901 /* no item -> nothing to do */
cf1dfa6b 2902 if (!HasCurrent())
c801d85f 2903 {
51cc4dad
RR
2904 event.Skip();
2905 return;
e1e955e1 2906 }
51cc4dad
RR
2907
2908 switch (event.KeyCode())
c801d85f 2909 {
51cc4dad 2910 case WXK_UP:
cf1dfa6b
VZ
2911 if ( m_current > 0 )
2912 OnArrowChar( m_current - 1, event );
51cc4dad 2913 break;
cf1dfa6b 2914
51cc4dad 2915 case WXK_DOWN:
cf1dfa6b
VZ
2916 if ( m_current < (size_t)GetItemCount() - 1 )
2917 OnArrowChar( m_current + 1, event );
51cc4dad 2918 break;
cf1dfa6b 2919
51cc4dad 2920 case WXK_END:
1370703e 2921 if (!IsEmpty())
cf1dfa6b 2922 OnArrowChar( GetItemCount() - 1, event );
51cc4dad 2923 break;
cf1dfa6b 2924
51cc4dad 2925 case WXK_HOME:
1370703e 2926 if (!IsEmpty())
cf1dfa6b 2927 OnArrowChar( 0, event );
51cc4dad 2928 break;
cf1dfa6b 2929
51cc4dad 2930 case WXK_PRIOR:
f6bcfd97 2931 {
cf1dfa6b
VZ
2932 int steps = 0;
2933 if ( HasFlag(wxLC_REPORT) )
2934 {
2935 steps = m_linesPerPage - 1;
2936 }
2937 else
2938 {
2939 steps = m_current % m_linesPerPage;
2940 }
2941
2942 int index = m_current - steps;
2943 if (index < 0)
2944 index = 0;
2945
2946 OnArrowChar( index, event );
51cc4dad 2947 }
51cc4dad 2948 break;
cf1dfa6b 2949
51cc4dad 2950 case WXK_NEXT:
bffa1c77 2951 {
cf1dfa6b
VZ
2952 int steps = 0;
2953 if ( HasFlag(wxLC_REPORT) )
2954 {
2955 steps = m_linesPerPage - 1;
2956 }
2957 else
2958 {
2959 steps = m_linesPerPage - (m_current % m_linesPerPage) - 1;
2960 }
f6bcfd97 2961
cf1dfa6b
VZ
2962 size_t index = m_current + steps;
2963 size_t count = GetItemCount();
2964 if ( index >= count )
2965 index = count - 1;
2966
2967 OnArrowChar( index, event );
51cc4dad 2968 }
51cc4dad 2969 break;
cf1dfa6b 2970
51cc4dad 2971 case WXK_LEFT:
cf1dfa6b 2972 if ( !HasFlag(wxLC_REPORT) )
51cc4dad 2973 {
cf1dfa6b
VZ
2974 int index = m_current - m_linesPerPage;
2975 if (index < 0)
2976 index = 0;
2977
2978 OnArrowChar( index, event );
51cc4dad
RR
2979 }
2980 break;
cf1dfa6b 2981
51cc4dad 2982 case WXK_RIGHT:
cf1dfa6b 2983 if ( !HasFlag(wxLC_REPORT) )
51cc4dad 2984 {
cf1dfa6b
VZ
2985 size_t index = m_current + m_linesPerPage;
2986
2987 size_t count = GetItemCount();
2988 if ( index >= count )
2989 index = count - 1;
2990
2991 OnArrowChar( index, event );
51cc4dad
RR
2992 }
2993 break;
cf1dfa6b 2994
51cc4dad 2995 case WXK_SPACE:
b54e41c5 2996 if ( IsSingleSel() )
33d0e17c 2997 {
cf1dfa6b
VZ
2998 wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
2999 GetParent()->GetId() );
33d0e17c 3000 le.SetEventObject( GetParent() );
cf1dfa6b
VZ
3001 le.m_itemIndex = m_current;
3002 GetLine(m_current)->GetItem( 0, le.m_item );
33d0e17c
RR
3003 GetParent()->GetEventHandler()->ProcessEvent( le );
3004 }
3005 else
3006 {
b54e41c5 3007 ReverseHighlight(m_current);
51cc4dad
RR
3008 }
3009 break;
cf1dfa6b 3010
51cc4dad
RR
3011 case WXK_RETURN:
3012 case WXK_EXECUTE:
cf1dfa6b
VZ
3013 {
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 );
3020 }
51cc4dad 3021 break;
cf1dfa6b 3022
51cc4dad 3023 default:
51cc4dad 3024 event.Skip();
e1e955e1 3025 }
e1e955e1 3026}
c801d85f 3027
cf1dfa6b
VZ
3028// ----------------------------------------------------------------------------
3029// focus handling
3030// ----------------------------------------------------------------------------
3031
cae5359f
RR
3032#ifdef __WXGTK__
3033extern wxWindow *g_focusWindow;
3034#endif
3035
c801d85f
KB
3036void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
3037{
63852e78 3038 m_hasFocus = TRUE;
bd8289c1 3039
cf1dfa6b
VZ
3040 if ( HasCurrent() )
3041 RefreshLine( m_current );
3042
3043 if (!GetParent())
3044 return;
004fd0c8 3045
cae5359f
RR
3046#ifdef __WXGTK__
3047 g_focusWindow = GetParent();
3048#endif
bd8289c1 3049
63852e78
RR
3050 wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
3051 event.SetEventObject( GetParent() );
3052 GetParent()->GetEventHandler()->ProcessEvent( event );
e1e955e1 3053}
c801d85f
KB
3054
3055void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
3056{
63852e78 3057 m_hasFocus = FALSE;
004fd0c8 3058
cf1dfa6b
VZ
3059 if ( HasCurrent() )
3060 RefreshLine( m_current );
e1e955e1 3061}
c801d85f 3062
1e6d9499 3063void wxListMainWindow::DrawImage( int index, wxDC *dc, int x, int y )
c801d85f 3064{
cf1dfa6b 3065 if ( HasFlag(wxLC_ICON) && (m_normal_image_list))
63852e78
RR
3066 {
3067 m_normal_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
63852e78 3068 }
cf1dfa6b 3069 else if ( HasFlag(wxLC_SMALL_ICON) && (m_small_image_list))
63852e78
RR
3070 {
3071 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
3072 }
cf1dfa6b 3073 else if ( HasFlag(wxLC_LIST) && (m_small_image_list))
0b855868
RR
3074 {
3075 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
3076 }
cf1dfa6b 3077 else if ( HasFlag(wxLC_REPORT) && (m_small_image_list))
63852e78
RR
3078 {
3079 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
63852e78 3080 }
e1e955e1 3081}
c801d85f 3082
5cd89174 3083void wxListMainWindow::GetImageSize( int index, int &width, int &height ) const
c801d85f 3084{
cf1dfa6b 3085 if ( HasFlag(wxLC_ICON) && m_normal_image_list )
63852e78
RR
3086 {
3087 m_normal_image_list->GetSize( index, width, height );
63852e78 3088 }
cf1dfa6b 3089 else if ( HasFlag(wxLC_SMALL_ICON) && m_small_image_list )
63852e78
RR
3090 {
3091 m_small_image_list->GetSize( index, width, height );
63852e78 3092 }
cf1dfa6b 3093 else if ( HasFlag(wxLC_LIST) && m_small_image_list )
0b855868
RR
3094 {
3095 m_small_image_list->GetSize( index, width, height );
0b855868 3096 }
cf1dfa6b 3097 else if ( HasFlag(wxLC_REPORT) && m_small_image_list )
63852e78
RR
3098 {
3099 m_small_image_list->GetSize( index, width, height );
63852e78 3100 }
cf1dfa6b
VZ
3101 else
3102 {
3103 width =
3104 height = 0;
3105 }
e1e955e1 3106}
c801d85f 3107
5cd89174 3108int wxListMainWindow::GetTextLength( const wxString &s ) const
c801d85f 3109{
5cd89174 3110 wxClientDC dc( wxConstCast(this, wxListMainWindow) );
cf1dfa6b 3111 dc.SetFont( GetFont() );
c801d85f 3112
cf1dfa6b
VZ
3113 wxCoord lw;
3114 dc.GetTextExtent( s, &lw, NULL );
3115
3116 return lw + AUTOSIZE_COL_MARGIN;
e1e955e1 3117}
c801d85f 3118
debe6624 3119void wxListMainWindow::SetImageList( wxImageList *imageList, int which )
c801d85f 3120{
139adb6a 3121 m_dirty = TRUE;
f6bcfd97
BP
3122
3123 // calc the spacing from the icon size
3124 int width = 0,
3125 height = 0;
3126 if ((imageList) && (imageList->GetImageCount()) )
3127 {
3128 imageList->GetSize(0, width, height);
3129 }
3130
3131 if (which == wxIMAGE_LIST_NORMAL)
3132 {
3133 m_normal_image_list = imageList;
3134 m_normal_spacing = width + 8;
3135 }
3136
3137 if (which == wxIMAGE_LIST_SMALL)
3138 {
3139 m_small_image_list = imageList;
3140 m_small_spacing = width + 14;
3141 }
e1e955e1 3142}
c801d85f 3143
debe6624 3144void wxListMainWindow::SetItemSpacing( int spacing, bool isSmall )
c801d85f 3145{
139adb6a
RR
3146 m_dirty = TRUE;
3147 if (isSmall)
3148 {
3149 m_small_spacing = spacing;
3150 }
3151 else
3152 {
3153 m_normal_spacing = spacing;
3154 }
e1e955e1 3155}
c801d85f 3156
debe6624 3157int wxListMainWindow::GetItemSpacing( bool isSmall )
c801d85f 3158{
f6bcfd97 3159 return isSmall ? m_small_spacing : m_normal_spacing;
e1e955e1 3160}
c801d85f 3161
cf1dfa6b
VZ
3162// ----------------------------------------------------------------------------
3163// columns
3164// ----------------------------------------------------------------------------
3165
debe6624 3166void wxListMainWindow::SetColumn( int col, wxListItem &item )
c801d85f 3167{
24b9f055 3168 wxListHeaderDataList::Node *node = m_columns.Item( col );
f6bcfd97 3169
cf1dfa6b
VZ
3170 wxCHECK_RET( node, _T("invalid column index in SetColumn") );
3171
3172 if ( item.m_width == wxLIST_AUTOSIZE_USEHEADER )
3173 item.m_width = GetTextLength( item.m_text );
3174
3175 wxListHeaderData *column = node->GetData();
3176 column->SetItem( item );
3177
3178 wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin;
f6bcfd97
BP
3179 if ( headerWin )
3180 headerWin->m_dirty = TRUE;
cf1dfa6b
VZ
3181
3182 m_dirty = TRUE;
3183
3184 // invalidate it as it has to be recalculated
3185 m_headerWidth = 0;
e1e955e1 3186}
c801d85f 3187
debe6624 3188void wxListMainWindow::SetColumnWidth( int col, int width )
c801d85f 3189{
cf1dfa6b
VZ
3190 wxCHECK_RET( col >= 0 && col < GetColumnCount(),
3191 _T("invalid column index") );
3192
3193 wxCHECK_RET( HasFlag(wxLC_REPORT),
f6bcfd97 3194 _T("SetColumnWidth() can only be called in report mode.") );
0208334d 3195
63852e78 3196 m_dirty = TRUE;
bd8289c1 3197
cf1dfa6b
VZ
3198 wxListHeaderDataList::Node *node = m_columns.Item( col );
3199 wxCHECK_RET( node, _T("no column?") );
3200
3201 wxListHeaderData *column = node->GetData();
3202
3203 size_t count = GetItemCount();
3204
f6bcfd97
BP
3205 if (width == wxLIST_AUTOSIZE_USEHEADER)
3206 {
cf1dfa6b 3207 width = GetTextLength(column->GetText());
f6bcfd97 3208 }
cf1dfa6b 3209 else if ( width == wxLIST_AUTOSIZE )
0180dad6 3210 {
cf1dfa6b
VZ
3211 if ( IsVirtual() )
3212 {
3213 // TODO: determine the max width somehow...
3214 width = WIDTH_COL_DEFAULT;
3215 }
3216 else // !virtual
0180dad6 3217 {
cf1dfa6b
VZ
3218 wxClientDC dc(this);
3219 dc.SetFont( GetFont() );
3220
3221 int max = AUTOSIZE_COL_MARGIN;
3222
3223 for ( size_t i = 0; i < count; i++ )
0180dad6 3224 {
cf1dfa6b
VZ
3225 wxListLineData *line = GetLine(i);
3226 wxListItemDataList::Node *n = line->m_items.Item( col );
3227
3228 wxCHECK_RET( n, _T("no subitem?") );
3229
2c1f73ee 3230 wxListItemData *item = n->GetData();
cf1dfa6b
VZ
3231 int current = 0;
3232
bffa1c77
VZ
3233 if (item->HasImage())
3234 {
cf1dfa6b 3235 int ix, iy;
0180dad6 3236 GetImageSize( item->GetImage(), ix, iy );
cf1dfa6b 3237 current += ix + 5;
bffa1c77 3238 }
cf1dfa6b 3239
bffa1c77
VZ
3240 if (item->HasText())
3241 {
cf1dfa6b
VZ
3242 wxCoord w;
3243 dc.GetTextExtent( item->GetText(), &w, NULL );
3244 current += w;
bffa1c77 3245 }
cf1dfa6b 3246
2c1f73ee
VZ
3247 if (current > max)
3248 max = current;
0180dad6 3249 }
cf1dfa6b
VZ
3250
3251 width = max + AUTOSIZE_COL_MARGIN;
0180dad6 3252 }
0180dad6
RR
3253 }
3254
cf1dfa6b 3255 column->SetWidth( width );
bd8289c1 3256
cf1dfa6b
VZ
3257 // invalidate it as it has to be recalculated
3258 m_headerWidth = 0;
3259}
3260
3261int wxListMainWindow::GetHeaderWidth() const
3262{
3263 if ( !m_headerWidth )
0208334d 3264 {
cf1dfa6b
VZ
3265 wxListMainWindow *self = wxConstCast(this, wxListMainWindow);
3266
3267 size_t count = GetColumnCount();
3268 for ( size_t col = 0; col < count; col++ )
63852e78 3269 {
cf1dfa6b 3270 self->m_headerWidth += GetColumnWidth(col);
63852e78 3271 }
0208334d 3272 }
bd8289c1 3273
cf1dfa6b 3274 return m_headerWidth;
e1e955e1 3275}
c801d85f 3276
cf1dfa6b 3277void wxListMainWindow::GetColumn( int col, wxListItem &item ) const
c801d85f 3278{
24b9f055 3279 wxListHeaderDataList::Node *node = m_columns.Item( col );
cf1dfa6b
VZ
3280 wxCHECK_RET( node, _T("invalid column index in GetColumn") );
3281
3282 wxListHeaderData *column = node->GetData();
3283 column->GetItem( item );
e1e955e1 3284}
c801d85f 3285
cf1dfa6b 3286int wxListMainWindow::GetColumnWidth( int col ) const
c801d85f 3287{
24b9f055
VZ
3288 wxListHeaderDataList::Node *node = m_columns.Item( col );
3289 wxCHECK_MSG( node, 0, _T("invalid column index") );
3290
3291 wxListHeaderData *column = node->GetData();
3292 return column->GetWidth();
e1e955e1 3293}
c801d85f 3294
cf1dfa6b
VZ
3295// ----------------------------------------------------------------------------
3296// item state
3297// ----------------------------------------------------------------------------
c801d85f
KB
3298
3299void wxListMainWindow::SetItem( wxListItem &item )
3300{
cf1dfa6b
VZ
3301 long id = item.m_itemId;
3302 wxCHECK_RET( id >= 0 && (size_t)id < GetItemCount(),
3303 _T("invalid item index in SetItem") );
3304
3305 if ( IsVirtual() )
3306 {
3307 // just refresh the line to show the new value of the text/image
3308 RefreshLine((size_t)id);
3309 }
3310 else // !virtual
92976ab6 3311 {
cf1dfa6b
VZ
3312 m_dirty = TRUE;
3313
3314 wxListLineData *line = GetLine((size_t)id);
3315 if ( HasFlag(wxLC_REPORT) )
3316 item.m_width = GetColumnWidth( item.m_col );
92976ab6
RR
3317 line->SetItem( item.m_col, item );
3318 }
e1e955e1 3319}
c801d85f 3320
cf1dfa6b 3321void wxListMainWindow::SetItemState( long litem, long state, long stateMask )
c801d85f 3322{
cf1dfa6b 3323 wxCHECK_RET( litem >= 0 && (size_t)litem < GetItemCount(),
54442116
VZ
3324 _T("invalid list ctrl item index in SetItem") );
3325
cf1dfa6b
VZ
3326 size_t oldCurrent = m_current;
3327 size_t item = (size_t)litem; // sdafe because of the check above
bd8289c1 3328
54442116 3329 if ( stateMask & wxLIST_STATE_FOCUSED )
c801d85f 3330 {
54442116 3331 if ( state & wxLIST_STATE_FOCUSED )
92976ab6 3332 {
54442116 3333 // don't do anything if this item is already focused
cf1dfa6b 3334 if ( item != m_current )
92976ab6 3335 {
cf1dfa6b
VZ
3336 OnUnfocusLine( m_current );
3337 m_current = item;
3338 OnFocusLine( m_current );
3339
b54e41c5 3340 if ( IsSingleSel() && (oldCurrent != (size_t)-1) )
cf1dfa6b 3341 {
b54e41c5 3342 HighlightLine(oldCurrent, FALSE);
cf1dfa6b
VZ
3343 RefreshLine(oldCurrent);
3344 }
54442116 3345
92976ab6 3346 RefreshLine( m_current );
92976ab6 3347 }
54442116
VZ
3348 }
3349 else // unfocus
3350 {
3351 // don't do anything if this item is not focused
cf1dfa6b 3352 if ( item == m_current )
bffa1c77 3353 {
cf1dfa6b
VZ
3354 OnUnfocusLine( m_current );
3355 m_current = (size_t)-1;
bffa1c77 3356 }
92976ab6 3357 }
e1e955e1 3358 }
54442116
VZ
3359
3360 if ( stateMask & wxLIST_STATE_SELECTED )
3361 {
3362 bool on = (state & wxLIST_STATE_SELECTED) != 0;
54442116 3363
b54e41c5 3364 if ( IsSingleSel() )
54442116 3365 {
cf1dfa6b
VZ
3366 if ( on )
3367 {
3368 // selecting the item also makes it the focused one in the
3369 // single sel mode
3370 if ( m_current != item )
3371 {
3372 OnUnfocusLine( m_current );
3373 m_current = item;
3374 OnFocusLine( m_current );
3375
3376 if ( oldCurrent != (size_t)-1 )
3377 {
b54e41c5 3378 HighlightLine( oldCurrent, FALSE );
cf1dfa6b
VZ
3379 RefreshLine( oldCurrent );
3380 }
3381 }
3382 }
3383 else // off
3384 {
3385 // only the current item may be selected anyhow
3386 if ( item != m_current )
3387 return;
3388 }
54442116
VZ
3389 }
3390
b54e41c5 3391 if ( HighlightLine(item, on) )
54442116 3392 {
cf1dfa6b 3393 RefreshLine(item);
54442116
VZ
3394 }
3395 }
e1e955e1 3396}
c801d85f 3397
debe6624 3398int wxListMainWindow::GetItemState( long item, long stateMask )
c801d85f 3399{
cf1dfa6b
VZ
3400 wxCHECK_MSG( item >= 0 && (size_t)item < GetItemCount(), 0,
3401 _T("invalid list ctrl item index in GetItemState()") );
3402
92976ab6 3403 int ret = wxLIST_STATE_DONTCARE;
cf1dfa6b
VZ
3404
3405 if ( stateMask & wxLIST_STATE_FOCUSED )
c801d85f 3406 {
cf1dfa6b
VZ
3407 if ( (size_t)item == m_current )
3408 ret |= wxLIST_STATE_FOCUSED;
e1e955e1 3409 }
cf1dfa6b
VZ
3410
3411 if ( stateMask & wxLIST_STATE_SELECTED )
c801d85f 3412 {
b54e41c5 3413 if ( IsHighlighted(item) )
cf1dfa6b 3414 ret |= wxLIST_STATE_SELECTED;
e1e955e1 3415 }
cf1dfa6b 3416
92976ab6 3417 return ret;
e1e955e1 3418}
c801d85f
KB
3419
3420void wxListMainWindow::GetItem( wxListItem &item )
3421{
cf1dfa6b
VZ
3422 wxCHECK_RET( item.m_itemId >= 0 && (size_t)item.m_itemId < GetItemCount(),
3423 _T("invalid item index in GetItem") );
3424
3425 wxListLineData *line = GetLine((size_t)item.m_itemId);
3426 line->GetItem( item.m_col, item );
e1e955e1 3427}
c801d85f 3428
cf1dfa6b
VZ
3429// ----------------------------------------------------------------------------
3430// item count
3431// ----------------------------------------------------------------------------
3432
3433size_t wxListMainWindow::GetItemCount() const
1370703e
VZ
3434{
3435 return IsVirtual() ? m_countVirt : m_lines.GetCount();
3436}
3437
3438void wxListMainWindow::SetItemCount(long count)
c801d85f 3439{
b54e41c5 3440 m_selStore.SetItemCount(count);
1370703e
VZ
3441 m_countVirt = count;
3442
3443 Refresh();
e1e955e1 3444}
c801d85f 3445
cf1dfa6b 3446int wxListMainWindow::GetSelectedItemCount()
c801d85f 3447{
cf1dfa6b 3448 // deal with the quick case first
b54e41c5 3449 if ( IsSingleSel() )
92976ab6 3450 {
b54e41c5 3451 return HasCurrent() ? IsHighlighted(m_current) : FALSE;
92976ab6 3452 }
cf1dfa6b
VZ
3453
3454 // virtual controls remmebers all its selections itself
3455 if ( IsVirtual() )
b54e41c5 3456 return m_selStore.GetSelectedCount();
cf1dfa6b
VZ
3457
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++ )
92976ab6 3463 {
b54e41c5 3464 if ( GetLine(line)->IsHighlighted() )
cf1dfa6b 3465 countSel++;
92976ab6 3466 }
c801d85f 3467
cf1dfa6b 3468 return countSel;
e1e955e1 3469}
e3e65dac 3470
cf1dfa6b
VZ
3471// ----------------------------------------------------------------------------
3472// item position/size
3473// ----------------------------------------------------------------------------
3474
3475void wxListMainWindow::GetItemRect( long index, wxRect &rect )
c801d85f 3476{
cf1dfa6b
VZ
3477 wxCHECK_RET( index >= 0 && (size_t)index < GetItemCount(),
3478 _T("invalid index in GetItemRect") );
3479
5cd89174 3480 rect = GetLineRect((size_t)index);
b54e41c5 3481
cf1dfa6b 3482 CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
e1e955e1 3483}
c801d85f 3484
cf1dfa6b 3485bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos)
c801d85f 3486{
cf1dfa6b
VZ
3487 wxRect rect;
3488 GetItemRect(item, rect);
bd8289c1 3489
cf1dfa6b
VZ
3490 pos.x = rect.x;
3491 pos.y = rect.y;
bd8289c1 3492
cf1dfa6b 3493 return TRUE;
e1e955e1 3494}
c801d85f 3495
cf1dfa6b
VZ
3496// ----------------------------------------------------------------------------
3497// geometry calculation
3498// ----------------------------------------------------------------------------
3499
b54e41c5 3500void wxListMainWindow::RecalculatePositions()
c801d85f 3501{
1370703e
VZ
3502 if ( IsEmpty() )
3503 return;
e487524e 3504
1e6d9499 3505 wxClientDC dc( this );
92976ab6 3506 dc.SetFont( GetFont() );
c801d85f 3507
cf1dfa6b
VZ
3508 int iconSpacing;
3509 if ( HasFlag(wxLC_ICON) )
3510 iconSpacing = m_normal_spacing;
3511 else if ( HasFlag(wxLC_SMALL_ICON) )
3512 iconSpacing = m_small_spacing;
3513 else
3514 iconSpacing = 0;
004fd0c8 3515
cf1dfa6b
VZ
3516 int clientWidth,
3517 clientHeight;
3518 GetClientSize( &clientWidth, &clientHeight );
004fd0c8 3519
cf1dfa6b
VZ
3520 if ( HasFlag(wxLC_REPORT) )
3521 {
3522 // all lines have the same height
b54e41c5 3523 int lineHeight = GetLineHeight();
c801d85f 3524
cf1dfa6b 3525 // scroll one line per step
b54e41c5 3526 m_yScroll = lineHeight;
bd8289c1 3527
cf1dfa6b 3528 size_t lineCount = GetItemCount();
b54e41c5 3529 int entireHeight = lineCount*lineHeight + LINE_SPACING;
bd8289c1 3530
b54e41c5
VZ
3531 m_linesPerPage = clientHeight / lineHeight;
3532
3533 ResetVisibleLinesRange();
2c1f73ee 3534
cf1dfa6b
VZ
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),
3540 TRUE );
e1e955e1 3541 }
cf1dfa6b 3542 else // !report
92976ab6
RR
3543 {
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
004fd0c8 3547
bffa1c77 3548 clientHeight -= 4; // sunken frame
bd8289c1 3549
b54e41c5 3550 int entireWidth = 0;
bd8289c1 3551
92976ab6 3552 for (int tries = 0; tries < 2; tries++)
e487524e 3553 {
92976ab6 3554 entireWidth = 0;
5d25c050
RR
3555 int x = 2;
3556 int y = 2;
92976ab6 3557 int maxWidth = 0;
cf1dfa6b
VZ
3558 m_linesPerPage = 0;
3559 int currentlyVisibleLines = 0;
3560
3561 size_t count = GetItemCount();
3562 for (size_t i = 0; i < count; i++)
92976ab6 3563 {
cf1dfa6b
VZ
3564 currentlyVisibleLines++;
3565 wxListLineData *line = GetLine(i);
92976ab6 3566 line->CalculateSize( &dc, iconSpacing );
cf1dfa6b
VZ
3567 line->SetPosition( x, y, clientWidth, iconSpacing );
3568
5cd89174 3569 wxSize sizeLine = GetLineSize(i);
cf1dfa6b
VZ
3570
3571 if ( maxWidth < sizeLine.x )
3572 maxWidth = sizeLine.x;
3573
3574 y += sizeLine.y;
3575 if (currentlyVisibleLines > m_linesPerPage)
3576 m_linesPerPage = currentlyVisibleLines;
3577
3578 // assume that the size of the next one is the same... (FIXME)
3579 if ( y + sizeLine.y - 6 >= clientHeight )
92976ab6 3580 {
cf1dfa6b 3581 currentlyVisibleLines = 0;
e1208c31 3582 y = 2;
8b53e5a2
RR
3583 x += maxWidth+6;
3584 entireWidth += maxWidth+6;
92976ab6
RR
3585 maxWidth = 0;
3586 }
cf1dfa6b
VZ
3587 if ( i == count - 1 )
3588 entireWidth += maxWidth;
92976ab6
RR
3589 if ((tries == 0) && (entireWidth > clientWidth))
3590 {
3591 clientHeight -= 15; // scrollbar height
cf1dfa6b
VZ
3592 m_linesPerPage = 0;
3593 currentlyVisibleLines = 0;
92976ab6
RR
3594 break;
3595 }
cf1dfa6b
VZ
3596 if ( i == count - 1 )
3597 tries = 1; // everything fits, no second try required
92976ab6 3598 }
e487524e 3599 }
bffa1c77 3600
92976ab6 3601 int scroll_pos = GetScrollPos( wxHORIZONTAL );
cf1dfa6b 3602 SetScrollbars( m_xScroll, m_yScroll, (entireWidth+SCROLL_UNIT_X) / m_xScroll, 0, scroll_pos, 0, TRUE );
e1e955e1 3603 }
cf1dfa6b
VZ
3604
3605 // FIXME: why should we call it from here?
3606 UpdateCurrent();
b54e41c5
VZ
3607
3608 RefreshAll();
3609}
3610
3611void wxListMainWindow::RefreshAll()
3612{
3613 m_dirty = FALSE;
3614 Refresh();
3615
3616 wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin;
3617 if ( headerWin )
3618 {
3619 headerWin->m_dirty = FALSE;
3620 headerWin->Refresh();
3621 }
e1e955e1 3622}
c801d85f 3623
cf1dfa6b 3624void wxListMainWindow::UpdateCurrent()
c801d85f 3625{
b54e41c5 3626 if ( !HasCurrent() && !IsEmpty() )
92976ab6 3627 {
cf1dfa6b 3628 m_current = 0;
92976ab6 3629 }
cf1dfa6b
VZ
3630
3631 if ( m_current != (size_t)-1 )
92976ab6 3632 {
cf1dfa6b 3633 OnFocusLine( m_current );
92976ab6 3634 }
e1e955e1 3635}
c801d85f 3636
19695fbd
VZ
3637long wxListMainWindow::GetNextItem( long item,
3638 int WXUNUSED(geometry),
3639 int state )
c801d85f 3640{
d1022fd6
VZ
3641 long ret = item,
3642 max = GetItemCount();
3643 wxCHECK_MSG( (ret == -1) || (ret < max), -1,
13771c08 3644 _T("invalid listctrl index in GetNextItem()") );
19695fbd
VZ
3645
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
d1022fd6
VZ
3649 ret++;
3650 if ( ret == max )
3651 {
3652 // this is not an error because the index was ok initially, just no
3653 // such item
3654 return -1;
3655 }
3656
cf1dfa6b
VZ
3657 if ( !state )
3658 {
3659 // any will do
3660 return (size_t)ret;
3661 }
3662
3663 size_t count = GetItemCount();
3664 for ( size_t line = (size_t)ret; line < count; line++ )
63852e78 3665 {
cf1dfa6b
VZ
3666 if ( (state & wxLIST_STATE_FOCUSED) && (line == m_current) )
3667 return line;
3668
b54e41c5 3669 if ( (state & wxLIST_STATE_SELECTED) && IsHighlighted(line) )
cf1dfa6b 3670 return line;
63852e78 3671 }
19695fbd 3672
63852e78 3673 return -1;
e1e955e1 3674}
c801d85f 3675
cf1dfa6b
VZ
3676// ----------------------------------------------------------------------------
3677// deleting stuff
3678// ----------------------------------------------------------------------------
3679
b54e41c5 3680void wxListMainWindow::DeleteItem( long lindex )
c801d85f 3681{
cf1dfa6b
VZ
3682 size_t count = GetItemCount();
3683
b54e41c5 3684 wxCHECK_RET( (lindex >= 0) && ((size_t)lindex < count),
cf1dfa6b
VZ
3685 _T("invalid item index in DeleteItem") );
3686
b54e41c5
VZ
3687 size_t index = (size_t)lindex;
3688
63852e78 3689 m_dirty = TRUE;
cf1dfa6b
VZ
3690
3691 // select the next item when the selected one is deleted
b54e41c5 3692 if ( m_current == index )
cf1dfa6b
VZ
3693 {
3694 // the last valid index after deleting the item will be count-2
5cd89174 3695 if ( m_current == count - 1 )
cf1dfa6b 3696 {
5cd89174 3697 m_current--;
cf1dfa6b
VZ
3698 }
3699 }
3700
b54e41c5 3701 SendNotify( index, wxEVT_COMMAND_LIST_DELETE_ITEM );
cf1dfa6b 3702
938b652b 3703 if ( InReportView() )
63852e78 3704 {
938b652b 3705 if ( m_lineTo == GetItemCount() - 1 )
b54e41c5
VZ
3706 {
3707 m_lineTo--;
3708 }
938b652b
VZ
3709 }
3710
3711 // refresh before removing the line
3712 RefreshLines(index, GetItemCount() - 1);
3713
3714 if ( IsVirtual() )
3715 {
3716 m_countVirt--;
b54e41c5
VZ
3717
3718 m_selStore.OnItemDelete(index);
3719 }
3720 else
3721 {
3722 m_lines.RemoveAt( index );
63852e78 3723 }
e1e955e1 3724}
c801d85f 3725
debe6624 3726void wxListMainWindow::DeleteColumn( int col )
c801d85f 3727{
24b9f055
VZ
3728 wxListHeaderDataList::Node *node = m_columns.Item( col );
3729
3730 wxCHECK_RET( node, wxT("invalid column index in DeleteColumn()") );
bd8289c1 3731
5b077d48 3732 m_dirty = TRUE;
24b9f055 3733 m_columns.DeleteNode( node );
e1e955e1 3734}
c801d85f 3735
12c1b46a 3736void wxListMainWindow::DeleteAllItems()
c801d85f 3737{
cf1dfa6b
VZ
3738 if ( IsEmpty() )
3739 {
3740 // nothing to do - in particular, don't send the event
3741 return;
3742 }
3743
5b077d48 3744 m_dirty = TRUE;
b54e41c5
VZ
3745
3746 ResetCurrent();
7c0ea335
VZ
3747
3748 // to make the deletion of all items faster, we don't send the
cf1dfa6b
VZ
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
bffa1c77 3752
12c1b46a
RR
3753 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, GetParent()->GetId() );
3754 event.SetEventObject( GetParent() );
3755 GetParent()->GetEventHandler()->ProcessEvent( event );
7c0ea335 3756
b54e41c5
VZ
3757 if ( IsVirtual() )
3758 {
3759 m_countVirt = 0;
3760
3761 ResetVisibleLinesRange();
3762 }
3763
5b077d48 3764 m_lines.Clear();
cf1dfa6b 3765
b54e41c5 3766 m_selStore.Clear();
e1e955e1 3767}
c801d85f 3768
12c1b46a 3769void wxListMainWindow::DeleteEverything()
c801d85f 3770{
12c1b46a 3771 DeleteAllItems();
f6bcfd97 3772
5b077d48 3773 m_columns.Clear();
e1e955e1 3774}
c801d85f 3775
cf1dfa6b
VZ
3776// ----------------------------------------------------------------------------
3777// scanning for an item
3778// ----------------------------------------------------------------------------
3779
debe6624 3780void wxListMainWindow::EnsureVisible( long index )
c801d85f 3781{
cf1dfa6b
VZ
3782 wxCHECK_RET( index >= 0 && (size_t)index < GetItemCount(),
3783 _T("invalid index in EnsureVisible") );
3784
3785 // We have to call this here because the label in question might just have
3786 // been added and no screen update taken place.
3787 if (m_dirty)
3788 wxSafeYield();
dc6c62a9 3789
cf1dfa6b
VZ
3790 size_t oldCurrent = m_current;
3791 m_current = (size_t)index;
3792 MoveToFocus();
5b077d48 3793 m_current = oldCurrent;
e1e955e1 3794}
c801d85f 3795
debe6624 3796long wxListMainWindow::FindItem(long start, const wxString& str, bool WXUNUSED(partial) )
c801d85f 3797{
5b077d48
RR
3798 long pos = start;
3799 wxString tmp = str;
cf1dfa6b
VZ
3800 if (pos < 0)
3801 pos = 0;
54442116 3802
cf1dfa6b
VZ
3803 size_t count = GetItemCount();
3804 for ( size_t i = (size_t)pos; i < count; i++ )
3805 {
3806 wxListLineData *line = GetLine(i);
3807 if ( line->GetText(0) == tmp )
3808 return i;
5b077d48 3809 }
cf1dfa6b
VZ
3810
3811 return wxNOT_FOUND;
e1e955e1 3812}
c801d85f 3813
debe6624 3814long wxListMainWindow::FindItem(long start, long data)
c801d85f 3815{
5b077d48 3816 long pos = start;
cf1dfa6b
VZ
3817 if (pos < 0)
3818 pos = 0;
3819
3820 size_t count = GetItemCount();
3821 for (size_t i = (size_t)pos; i < count; i++)
5b077d48 3822 {
cf1dfa6b 3823 wxListLineData *line = GetLine(i);
5b077d48
RR
3824 wxListItem item;
3825 line->GetItem( 0, item );
cf1dfa6b
VZ
3826 if (item.m_data == data)
3827 return i;
5b077d48 3828 }
cf1dfa6b
VZ
3829
3830 return wxNOT_FOUND;
e1e955e1 3831}
c801d85f 3832
debe6624 3833long wxListMainWindow::HitTest( int x, int y, int &flags )
c801d85f 3834{
aaef15bf 3835 CalcUnscrolledPosition( x, y, &x, &y );
e8741cca 3836
5cd89174 3837 if ( HasFlag(wxLC_REPORT) )
c801d85f 3838 {
5cd89174
VZ
3839 size_t current = y / GetLineHeight();
3840 flags = HitTestLine(current, x, y);
3841 if ( flags )
3842 return current;
3843 }
3844 else // !report
3845 {
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++ )
5b077d48 3850 {
5cd89174
VZ
3851 flags = HitTestLine(current, x, y);
3852 if ( flags )
3853 return current;
5b077d48 3854 }
e1e955e1 3855 }
cf1dfa6b
VZ
3856
3857 return wxNOT_FOUND;
e1e955e1 3858}
c801d85f 3859
cf1dfa6b
VZ
3860// ----------------------------------------------------------------------------
3861// adding stuff
3862// ----------------------------------------------------------------------------
3863
c801d85f
KB
3864void wxListMainWindow::InsertItem( wxListItem &item )
3865{
cf1dfa6b
VZ
3866 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") );
3867
3868 size_t count = GetItemCount();
3869 wxCHECK_RET( item.m_itemId >= 0 && (size_t)item.m_itemId <= count,
3870 _T("invalid item index") );
3871
3872 size_t id = item.m_itemId;
3873
5b077d48 3874 m_dirty = TRUE;
cf1dfa6b 3875
5b077d48 3876 int mode = 0;
cf1dfa6b 3877 if ( HasFlag(wxLC_REPORT) )
1370703e 3878 mode = wxLC_REPORT;
cf1dfa6b 3879 else if ( HasFlag(wxLC_LIST) )
1370703e 3880 mode = wxLC_LIST;
cf1dfa6b 3881 else if ( HasFlag(wxLC_ICON) )
1370703e 3882 mode = wxLC_ICON;
cf1dfa6b 3883 else if ( HasFlag(wxLC_SMALL_ICON) )
1370703e
VZ
3884 mode = wxLC_ICON; // no typo
3885 else
3886 {
3887 wxFAIL_MSG( _T("unknown mode") );
3888 }
004fd0c8 3889
5cd89174 3890 wxListLineData *line = new wxListLineData(this);
004fd0c8 3891
5b077d48 3892 line->SetItem( 0, item );
cf1dfa6b
VZ
3893
3894 m_lines.Insert( line, id );
5cd89174
VZ
3895
3896 RefreshLines(id, GetItemCount() - 1);
e1e955e1 3897}
c801d85f 3898
debe6624 3899void wxListMainWindow::InsertColumn( long col, wxListItem &item )
c801d85f 3900{
5b077d48 3901 m_dirty = TRUE;
cf1dfa6b 3902 if ( HasFlag(wxLC_REPORT) )
3db7be80 3903 {
54442116
VZ
3904 if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
3905 item.m_width = GetTextLength( item.m_text );
5b077d48
RR
3906 wxListHeaderData *column = new wxListHeaderData( item );
3907 if ((col >= 0) && (col < (int)m_columns.GetCount()))
3908 {
24b9f055
VZ
3909 wxListHeaderDataList::Node *node = m_columns.Item( col );
3910 m_columns.Insert( node, column );
5b077d48
RR
3911 }
3912 else
3913 {
3914 m_columns.Append( column );
3915 }
3db7be80 3916 }
e1e955e1 3917}
c801d85f 3918
cf1dfa6b
VZ
3919// ----------------------------------------------------------------------------
3920// sorting
3921// ----------------------------------------------------------------------------
3922
c801d85f
KB
3923wxListCtrlCompare list_ctrl_compare_func_2;
3924long list_ctrl_compare_data;
3925
f6bcfd97 3926int LINKAGEMODE list_ctrl_compare_func_1( wxListLineData **arg1, wxListLineData **arg2 )
c801d85f 3927{
f6bcfd97
BP
3928 wxListLineData *line1 = *arg1;
3929 wxListLineData *line2 = *arg2;
5b077d48
RR
3930 wxListItem item;
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 );
e1e955e1 3936}
c801d85f
KB
3937
3938void wxListMainWindow::SortItems( wxListCtrlCompare fn, long data )
3939{
5b077d48
RR
3940 list_ctrl_compare_func_2 = fn;
3941 list_ctrl_compare_data = data;
3942 m_lines.Sort( list_ctrl_compare_func_1 );
af7c1052 3943 m_dirty = TRUE;
e1e955e1 3944}
c801d85f 3945
cf1dfa6b
VZ
3946// ----------------------------------------------------------------------------
3947// scrolling
3948// ----------------------------------------------------------------------------
3949
7c74e7fe
SC
3950void wxListMainWindow::OnScroll(wxScrollWinEvent& event)
3951{
b54e41c5
VZ
3952 // update our idea of which lines are shown when we redraw the window the
3953 // next time
3954 ResetVisibleLinesRange();
cf1dfa6b 3955
29149a64 3956 // FIXME
3a8c693a 3957#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
29149a64
VZ
3958 wxScrolledWindow::OnScroll(event);
3959#else
1e6feb95 3960 HandleOnScroll( event );
29149a64 3961#endif
30954328 3962
cf1dfa6b 3963 if ( event.GetOrientation() == wxHORIZONTAL && HasHeader() )
7c74e7fe 3964 {
cf1dfa6b
VZ
3965 wxListCtrl* lc = GetListCtrl();
3966 wxCHECK_RET( lc, _T("no listctrl window?") );
3967
3968 lc->m_headerWin->Refresh() ;
7c74e7fe 3969#ifdef __WXMAC__
cf1dfa6b 3970 lc->m_headerWin->MacUpdateImmediately() ;
7c74e7fe 3971#endif
7c74e7fe 3972 }
cf1dfa6b
VZ
3973}
3974
5cd89174
VZ
3975int wxListMainWindow::GetCountPerPage() const
3976{
3977 if ( !m_linesPerPage )
3978 {
3979 wxConstCast(this, wxListMainWindow)->
3980 m_linesPerPage = GetClientSize().y / GetLineHeight();
3981 }
3982
3983 return m_linesPerPage;
3984}
3985
b54e41c5 3986void wxListMainWindow::GetVisibleLinesRange(size_t *from, size_t *to)
cf1dfa6b 3987{
b54e41c5 3988 wxASSERT_MSG( HasFlag(wxLC_REPORT), _T("this is for report mode only") );
cf1dfa6b 3989
b54e41c5
VZ
3990 if ( m_lineFrom == (size_t)-1 )
3991 {
3992 m_lineFrom = GetScrollPos(wxVERTICAL);
cf1dfa6b 3993
b54e41c5 3994 size_t count = GetItemCount();
cf1dfa6b 3995
b54e41c5 3996 wxASSERT_MSG( m_lineFrom < count, _T("invalid scroll position?") );
cf1dfa6b 3997
938b652b
VZ
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;
b54e41c5
VZ
4001 if ( m_lineTo >= count )
4002 m_lineTo = count - 1;
cf1dfa6b 4003 }
b54e41c5
VZ
4004
4005 if ( from )
4006 *from = m_lineFrom;
4007 if ( to )
4008 *to = m_lineTo;
7c74e7fe
SC
4009}
4010
c801d85f
KB
4011// -------------------------------------------------------------------------------------
4012// wxListItem
4013// -------------------------------------------------------------------------------------
4014
4015IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
4016
fd9811b1 4017wxListItem::wxListItem()
c801d85f 4018{
63852e78
RR
4019 m_mask = 0;
4020 m_itemId = 0;
4021 m_col = 0;
4022 m_state = 0;
4023 m_stateMask = 0;
4024 m_image = 0;
4025 m_data = 0;
4026 m_format = wxLIST_FORMAT_CENTRE;
4027 m_width = 0;
aaa37c0d
VZ
4028
4029 m_attr = NULL;
c801d85f
KB
4030}
4031
9b00bb16
RR
4032void wxListItem::Clear()
4033{
4034 m_mask = 0;
4035 m_itemId = 0;
4036 m_col = 0;
4037 m_state = 0;
4038 m_stateMask = 0;
4039 m_image = 0;
4040 m_data = 0;
4041 m_format = wxLIST_FORMAT_CENTRE;
4042 m_width = 0;
54442116 4043 m_text = _T("");
9b00bb16 4044
cf1dfa6b 4045 ClearAttributes();
9b00bb16
RR
4046}
4047
4048void wxListItem::ClearAttributes()
4049{
cf1dfa6b
VZ
4050 if (m_attr)
4051 {
4052 delete m_attr;
4053 m_attr = NULL;
4054 }
9b00bb16
RR
4055}
4056
c801d85f
KB
4057// -------------------------------------------------------------------------------------
4058// wxListEvent
4059// -------------------------------------------------------------------------------------
4060
92976ab6 4061IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
c801d85f 4062
cf1dfa6b
VZ
4063wxListEvent::wxListEvent( wxEventType commandType, int id )
4064 : wxNotifyEvent( commandType, id )
c801d85f 4065{
5b077d48
RR
4066 m_code = 0;
4067 m_itemIndex = 0;
4068 m_oldItemIndex = 0;
4069 m_col = 0;
4070 m_cancelled = FALSE;
4071 m_pointDrag.x = 0;
4072 m_pointDrag.y = 0;
e1e955e1 4073}
c801d85f 4074
72a7edf0
RR
4075void wxListEvent::CopyObject(wxObject& object_dest) const
4076{
4077 wxListEvent *obj = (wxListEvent *)&object_dest;
4078
4079 wxNotifyEvent::CopyObject(object_dest);
4080
4081 obj->m_code = m_code;
4082 obj->m_itemIndex = m_itemIndex;
4083 obj->m_oldItemIndex = m_oldItemIndex;
4084 obj->m_col = m_col;
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;
aaa37c0d
VZ
4097
4098 if ( m_item.HasAttributes() )
4099 {
4100 obj->m_item.SetTextColour(m_item.GetTextColour());
4101 }
72a7edf0
RR
4102}
4103
c801d85f
KB
4104// -------------------------------------------------------------------------------------
4105// wxListCtrl
4106// -------------------------------------------------------------------------------------
4107
4108IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
4109
4110BEGIN_EVENT_TABLE(wxListCtrl,wxControl)
cf1dfa6b
VZ
4111 EVT_SIZE(wxListCtrl::OnSize)
4112 EVT_IDLE(wxListCtrl::OnIdle)
c801d85f
KB
4113END_EVENT_TABLE()
4114
fd9811b1 4115wxListCtrl::wxListCtrl()
c801d85f 4116{
5b077d48
RR
4117 m_imageListNormal = (wxImageList *) NULL;
4118 m_imageListSmall = (wxImageList *) NULL;
4119 m_imageListState = (wxImageList *) NULL;
cf1dfa6b
VZ
4120
4121 m_ownsImageListNormal =
4122 m_ownsImageListSmall =
4123 m_ownsImageListState = FALSE;
4124
5b077d48
RR
4125 m_mainWin = (wxListMainWindow*) NULL;
4126 m_headerWin = (wxListHeaderWindow*) NULL;
c801d85f
KB
4127}
4128
fd9811b1 4129wxListCtrl::~wxListCtrl()
c801d85f 4130{
b54e41c5
VZ
4131 if ( m_mainWin )
4132 m_mainWin->ResetCurrent();
4133
cf1dfa6b
VZ
4134 if (m_ownsImageListNormal)
4135 delete m_imageListNormal;
4136 if (m_ownsImageListSmall)
4137 delete m_imageListSmall;
4138 if (m_ownsImageListState)
4139 delete m_imageListState;
4140}
4141
4142void wxListCtrl::CreateHeaderWindow()
4143{
4144 m_headerWin = new wxListHeaderWindow
4145 (
4146 this, -1, m_mainWin,
4147 wxPoint(0, 0),
4148 wxSize(GetClientSize().x, HEADER_HEIGHT),
4149 wxTAB_TRAVERSAL
4150 );
c801d85f
KB
4151}
4152
25e3a937
VZ
4153bool wxListCtrl::Create(wxWindow *parent,
4154 wxWindowID id,
4155 const wxPoint &pos,
4156 const wxSize &size,
4157 long style,
25e3a937 4158 const wxValidator &validator,
25e3a937 4159 const wxString &name)
c801d85f 4160{
cf1dfa6b
VZ
4161 m_imageListNormal =
4162 m_imageListSmall =
5b077d48 4163 m_imageListState = (wxImageList *) NULL;
cf1dfa6b
VZ
4164 m_ownsImageListNormal =
4165 m_ownsImageListSmall =
4166 m_ownsImageListState = FALSE;
4167
5b077d48
RR
4168 m_mainWin = (wxListMainWindow*) NULL;
4169 m_headerWin = (wxListHeaderWindow*) NULL;
bd8289c1 4170
b54e41c5 4171 if ( !(style & wxLC_MASK_TYPE) )
5b077d48 4172 {
25e3a937 4173 style = style | wxLC_LIST;
5b077d48 4174 }
f6bcfd97 4175
cf1dfa6b
VZ
4176 if ( !wxControl::Create( parent, id, pos, size, style, validator, name ) )
4177 return FALSE;
f6bcfd97 4178
b54e41c5
VZ
4179 // don't create the inner window with the border
4180 style &= ~wxSUNKEN_BORDER;
bd8289c1 4181
25e3a937 4182 m_mainWin = new wxListMainWindow( this, -1, wxPoint(0,0), size, style );
bd8289c1 4183
b54e41c5 4184 if ( HasFlag(wxLC_REPORT) )
ea451729 4185 {
cf1dfa6b
VZ
4186 CreateHeaderWindow();
4187
b54e41c5 4188 if ( HasFlag(wxLC_NO_HEADER) )
cf1dfa6b
VZ
4189 {
4190 // VZ: why do we create it at all then?
ea451729 4191 m_headerWin->Show( FALSE );
cf1dfa6b 4192 }
ea451729 4193 }
bd8289c1 4194
cf1dfa6b 4195 return TRUE;
e1e955e1 4196}
c801d85f 4197
debe6624 4198void wxListCtrl::SetSingleStyle( long style, bool add )
c801d85f 4199{
b54e41c5
VZ
4200 wxASSERT_MSG( !(style & wxLC_VIRTUAL),
4201 _T("wxLC_VIRTUAL can't be [un]set") );
4202
f03fc89f 4203 long flag = GetWindowStyle();
bd8289c1 4204
5b077d48
RR
4205 if (add)
4206 {
cf1dfa6b 4207 if (style & wxLC_MASK_TYPE)
b54e41c5 4208 flag &= ~(wxLC_MASK_TYPE | wxLC_VIRTUAL);
cf1dfa6b
VZ
4209 if (style & wxLC_MASK_ALIGN)
4210 flag &= ~wxLC_MASK_ALIGN;
4211 if (style & wxLC_MASK_SORT)
4212 flag &= ~wxLC_MASK_SORT;
5b077d48 4213 }
c801d85f 4214
5b077d48
RR
4215 if (add)
4216 {
4217 flag |= style;
4218 }
4219 else
4220 {
cf1dfa6b 4221 flag &= ~style;
5b077d48 4222 }
bd8289c1 4223
5b077d48 4224 SetWindowStyleFlag( flag );
e1e955e1 4225}
c801d85f 4226
debe6624 4227void wxListCtrl::SetWindowStyleFlag( long flag )
c801d85f 4228{
121a3581
RR
4229 if (m_mainWin)
4230 {
4231 m_mainWin->DeleteEverything();
c801d85f 4232
121a3581
RR
4233 int width = 0;
4234 int height = 0;
4235 GetClientSize( &width, &height );
c801d85f 4236
121a3581 4237 if (flag & wxLC_REPORT)
5b077d48 4238 {
121a3581 4239 if (!HasFlag(wxLC_REPORT))
5b077d48 4240 {
121a3581
RR
4241 if (!m_headerWin)
4242 {
cf1dfa6b
VZ
4243 CreateHeaderWindow();
4244
bffa1c77
VZ
4245 if (HasFlag(wxLC_NO_HEADER))
4246 m_headerWin->Show( FALSE );
121a3581
RR
4247 }
4248 else
004fd0c8 4249 {
bffa1c77
VZ
4250 if (flag & wxLC_NO_HEADER)
4251 m_headerWin->Show( FALSE );
4252 else
8636aed8 4253 m_headerWin->Show( TRUE );
004fd0c8 4254 }
5b077d48
RR
4255 }
4256 }
cf1dfa6b 4257 else // !report
5b077d48 4258 {
cf1dfa6b 4259 if ( m_mainWin->HasHeader() )
121a3581
RR
4260 {
4261 m_headerWin->Show( FALSE );
4262 }
bffa1c77 4263 }
e1e955e1 4264 }
004fd0c8 4265
5b077d48 4266 wxWindow::SetWindowStyleFlag( flag );
e1e955e1 4267}
c801d85f 4268
e487524e 4269bool wxListCtrl::GetColumn(int col, wxListItem &item) const
c801d85f 4270{
5b077d48
RR
4271 m_mainWin->GetColumn( col, item );
4272 return TRUE;
e1e955e1 4273}
c801d85f 4274
debe6624 4275bool wxListCtrl::SetColumn( int col, wxListItem& item )
c801d85f 4276{
5b077d48
RR
4277 m_mainWin->SetColumn( col, item );
4278 return TRUE;
e1e955e1 4279}
c801d85f 4280
e487524e 4281int wxListCtrl::GetColumnWidth( int col ) const
c801d85f 4282{
5b077d48 4283 return m_mainWin->GetColumnWidth( col );
e1e955e1 4284}
c801d85f 4285
debe6624 4286bool wxListCtrl::SetColumnWidth( int col, int width )
c801d85f 4287{
5b077d48
RR
4288 m_mainWin->SetColumnWidth( col, width );
4289 return TRUE;
e1e955e1 4290}
c801d85f 4291
fd9811b1 4292int wxListCtrl::GetCountPerPage() const
c801d85f
KB
4293{
4294 return m_mainWin->GetCountPerPage(); // different from Windows ?
e1e955e1 4295}
c801d85f 4296
e487524e 4297bool wxListCtrl::GetItem( wxListItem &info ) const
c801d85f 4298{
5b077d48
RR
4299 m_mainWin->GetItem( info );
4300 return TRUE;
e1e955e1 4301}
c801d85f
KB
4302
4303bool wxListCtrl::SetItem( wxListItem &info )
4304{
5b077d48
RR
4305 m_mainWin->SetItem( info );
4306 return TRUE;
e1e955e1 4307}
c801d85f 4308
debe6624 4309long wxListCtrl::SetItem( long index, int col, const wxString& label, int imageId )
c801d85f 4310{
5b077d48
RR
4311 wxListItem info;
4312 info.m_text = label;
4313 info.m_mask = wxLIST_MASK_TEXT;
4314 info.m_itemId = index;
4315 info.m_col = col;
4316 if ( imageId > -1 )
4317 {
4318 info.m_image = imageId;
4319 info.m_mask |= wxLIST_MASK_IMAGE;
4320 };
4321 m_mainWin->SetItem(info);
4322 return TRUE;
e1e955e1 4323}
c801d85f 4324
e487524e 4325int wxListCtrl::GetItemState( long item, long stateMask ) const
c801d85f 4326{
5b077d48 4327 return m_mainWin->GetItemState( item, stateMask );
e1e955e1 4328}
c801d85f 4329
debe6624 4330bool wxListCtrl::SetItemState( long item, long state, long stateMask )
c801d85f 4331{
5b077d48
RR
4332 m_mainWin->SetItemState( item, state, stateMask );
4333 return TRUE;
e1e955e1 4334}
c801d85f 4335
debe6624 4336bool wxListCtrl::SetItemImage( long item, int image, int WXUNUSED(selImage) )
c801d85f 4337{
5b077d48
RR
4338 wxListItem info;
4339 info.m_image = image;
4340 info.m_mask = wxLIST_MASK_IMAGE;
4341 info.m_itemId = item;
4342 m_mainWin->SetItem( info );
4343 return TRUE;
e1e955e1 4344}
c801d85f 4345
e487524e 4346wxString wxListCtrl::GetItemText( long item ) const
c801d85f 4347{
5b077d48
RR
4348 wxListItem info;
4349 info.m_itemId = item;
4350 m_mainWin->GetItem( info );
4351 return info.m_text;
e1e955e1 4352}
c801d85f 4353
debe6624 4354void wxListCtrl::SetItemText( long item, const wxString &str )
c801d85f 4355{
5b077d48
RR
4356 wxListItem info;
4357 info.m_mask = wxLIST_MASK_TEXT;
4358 info.m_itemId = item;
4359 info.m_text = str;
4360 m_mainWin->SetItem( info );
e1e955e1 4361}
c801d85f 4362
e487524e 4363long wxListCtrl::GetItemData( long item ) const
c801d85f 4364{
5b077d48
RR
4365 wxListItem info;
4366 info.m_itemId = item;
4367 m_mainWin->GetItem( info );
4368 return info.m_data;
e1e955e1 4369}
c801d85f 4370
debe6624 4371bool wxListCtrl::SetItemData( long item, long data )
c801d85f 4372{
5b077d48
RR
4373 wxListItem info;
4374 info.m_mask = wxLIST_MASK_DATA;
4375 info.m_itemId = item;
4376 info.m_data = data;
4377 m_mainWin->SetItem( info );
4378 return TRUE;
e1e955e1 4379}
c801d85f 4380
0a240683 4381bool wxListCtrl::GetItemRect( long item, wxRect &rect, int WXUNUSED(code) ) const
c801d85f 4382{
5b077d48
RR
4383 m_mainWin->GetItemRect( item, rect );
4384 return TRUE;
e1e955e1 4385}
c801d85f 4386
e487524e 4387bool wxListCtrl::GetItemPosition( long item, wxPoint& pos ) const
c801d85f 4388{
5b077d48
RR
4389 m_mainWin->GetItemPosition( item, pos );
4390 return TRUE;
e1e955e1 4391}
c801d85f 4392
debe6624 4393bool wxListCtrl::SetItemPosition( long WXUNUSED(item), const wxPoint& WXUNUSED(pos) )
c801d85f 4394{
5b077d48 4395 return 0;
e1e955e1 4396}
c801d85f 4397
fd9811b1 4398int wxListCtrl::GetItemCount() const
c801d85f 4399{
5b077d48 4400 return m_mainWin->GetItemCount();
e1e955e1 4401}
c801d85f 4402
fd9811b1 4403int wxListCtrl::GetColumnCount() const
92976ab6 4404{
5b077d48 4405 return m_mainWin->GetColumnCount();
92976ab6
RR
4406}
4407
33d0b396
RR
4408void wxListCtrl::SetItemSpacing( int spacing, bool isSmall )
4409{
5b077d48 4410 m_mainWin->SetItemSpacing( spacing, isSmall );
e1e955e1 4411}
33d0b396 4412
e487524e 4413int wxListCtrl::GetItemSpacing( bool isSmall ) const
c801d85f 4414{
5b077d48 4415 return m_mainWin->GetItemSpacing( isSmall );
e1e955e1 4416}
c801d85f 4417
fd9811b1 4418int wxListCtrl::GetSelectedItemCount() const
c801d85f 4419{
5b077d48 4420 return m_mainWin->GetSelectedItemCount();
e1e955e1 4421}
c801d85f 4422
fd9811b1 4423wxColour wxListCtrl::GetTextColour() const
c801d85f 4424{
0530737d 4425 return GetForegroundColour();
e1e955e1 4426}
c801d85f 4427
0530737d 4428void wxListCtrl::SetTextColour(const wxColour& col)
c801d85f 4429{
0530737d 4430 SetForegroundColour(col);
e1e955e1 4431}
c801d85f 4432
fd9811b1 4433long wxListCtrl::GetTopItem() const
c801d85f 4434{
5b077d48 4435 return 0;
e1e955e1 4436}
c801d85f 4437
6de97a3b 4438long wxListCtrl::GetNextItem( long item, int geom, int state ) const
c801d85f 4439{
5b077d48 4440 return m_mainWin->GetNextItem( item, geom, state );
e1e955e1 4441}
c801d85f 4442
e487524e 4443wxImageList *wxListCtrl::GetImageList(int which) const
c801d85f 4444{
5b077d48
RR
4445 if (which == wxIMAGE_LIST_NORMAL)
4446 {
4447 return m_imageListNormal;
4448 }
4449 else if (which == wxIMAGE_LIST_SMALL)
4450 {
4451 return m_imageListSmall;
4452 }
4453 else if (which == wxIMAGE_LIST_STATE)
4454 {
4455 return m_imageListState;
4456 }
4457 return (wxImageList *) NULL;
e1e955e1 4458}
c801d85f 4459
debe6624 4460void wxListCtrl::SetImageList( wxImageList *imageList, int which )
c801d85f 4461{
2e12c11a
VS
4462 if ( which == wxIMAGE_LIST_NORMAL )
4463 {
4464 if (m_ownsImageListNormal) delete m_imageListNormal;
4465 m_imageListNormal = imageList;
4466 m_ownsImageListNormal = FALSE;
4467 }
4468 else if ( which == wxIMAGE_LIST_SMALL )
4469 {
4470 if (m_ownsImageListSmall) delete m_imageListSmall;
4471 m_imageListSmall = imageList;
4472 m_ownsImageListSmall = FALSE;
4473 }
4474 else if ( which == wxIMAGE_LIST_STATE )
4475 {
4476 if (m_ownsImageListState) delete m_imageListState;
4477 m_imageListState = imageList;
4478 m_ownsImageListState = FALSE;
4479 }
4480
5b077d48 4481 m_mainWin->SetImageList( imageList, which );
e1e955e1 4482}
c801d85f 4483
2e12c11a
VS
4484void wxListCtrl::AssignImageList(wxImageList *imageList, int which)
4485{
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;
4493}
4494
debe6624 4495bool wxListCtrl::Arrange( int WXUNUSED(flag) )
c801d85f 4496{
5b077d48 4497 return 0;
e1e955e1 4498}
c801d85f 4499
debe6624 4500bool wxListCtrl::DeleteItem( long item )
c801d85f 4501{
5b077d48
RR
4502 m_mainWin->DeleteItem( item );
4503 return TRUE;
e1e955e1 4504}
c801d85f 4505
fd9811b1 4506bool wxListCtrl::DeleteAllItems()
c801d85f 4507{
5b077d48
RR
4508 m_mainWin->DeleteAllItems();
4509 return TRUE;
e1e955e1 4510}
c801d85f 4511
4f22cf8d 4512bool wxListCtrl::DeleteAllColumns()
bd8289c1 4513{
24b9f055
VZ
4514 size_t count = m_mainWin->m_columns.GetCount();
4515 for ( size_t n = 0; n < count; n++ )
bd8289c1 4516 DeleteColumn(n);
bffa1c77 4517
5b077d48 4518 return TRUE;
4f22cf8d
RR
4519}
4520
4521void wxListCtrl::ClearAll()
4522{
5b077d48 4523 m_mainWin->DeleteEverything();
bd8289c1
VZ
4524}
4525
debe6624 4526bool wxListCtrl::DeleteColumn( int col )
c801d85f 4527{
5b077d48
RR
4528 m_mainWin->DeleteColumn( col );
4529 return TRUE;
e1e955e1 4530}
c801d85f 4531
e179bd65 4532void wxListCtrl::Edit( long item )
c801d85f 4533{
cf1dfa6b 4534 m_mainWin->EditLabel( item );
e1e955e1 4535}
c801d85f 4536
debe6624 4537bool wxListCtrl::EnsureVisible( long item )
c801d85f 4538{
5b077d48
RR
4539 m_mainWin->EnsureVisible( item );
4540 return TRUE;
e1e955e1 4541}
c801d85f 4542
debe6624 4543long wxListCtrl::FindItem( long start, const wxString& str, bool partial )
c801d85f 4544{
5b077d48 4545 return m_mainWin->FindItem( start, str, partial );
e1e955e1 4546}
c801d85f 4547
debe6624 4548long wxListCtrl::FindItem( long start, long data )
c801d85f 4549{
5b077d48 4550 return m_mainWin->FindItem( start, data );
e1e955e1 4551}
c801d85f 4552
bd8289c1 4553long wxListCtrl::FindItem( long WXUNUSED(start), const wxPoint& WXUNUSED(pt),
debe6624 4554 int WXUNUSED(direction))
c801d85f 4555{
5b077d48 4556 return 0;
e1e955e1 4557}
c801d85f
KB
4558
4559long wxListCtrl::HitTest( const wxPoint &point, int &flags )
4560{
5b077d48 4561 return m_mainWin->HitTest( (int)point.x, (int)point.y, flags );
e1e955e1 4562}
c801d85f
KB
4563
4564long wxListCtrl::InsertItem( wxListItem& info )
4565{
5b077d48 4566 m_mainWin->InsertItem( info );
2ebcd5f5 4567 return info.m_itemId;
e1e955e1 4568}
c801d85f 4569
debe6624 4570long wxListCtrl::InsertItem( long index, const wxString &label )
c801d85f 4571{
51cc4dad
RR
4572 wxListItem info;
4573 info.m_text = label;
4574 info.m_mask = wxLIST_MASK_TEXT;
4575 info.m_itemId = index;
4576 return InsertItem( info );
e1e955e1 4577}
c801d85f 4578
debe6624 4579long wxListCtrl::InsertItem( long index, int imageIndex )
c801d85f 4580{
51cc4dad
RR
4581 wxListItem info;
4582 info.m_mask = wxLIST_MASK_IMAGE;
4583 info.m_image = imageIndex;
4584 info.m_itemId = index;
4585 return InsertItem( info );
e1e955e1 4586}
c801d85f 4587
debe6624 4588long wxListCtrl::InsertItem( long index, const wxString &label, int imageIndex )
c801d85f 4589{
51cc4dad
RR
4590 wxListItem info;
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 );
e1e955e1 4596}
c801d85f 4597
debe6624 4598long wxListCtrl::InsertColumn( long col, wxListItem &item )
c801d85f 4599{
d3e90957 4600 wxASSERT( m_headerWin );
51cc4dad 4601 m_mainWin->InsertColumn( col, item );
d3e90957 4602 m_headerWin->Refresh();
25e3a937 4603
51cc4dad 4604 return 0;
e1e955e1 4605}
c801d85f 4606
debe6624
JS
4607long wxListCtrl::InsertColumn( long col, const wxString &heading,
4608 int format, int width )
c801d85f 4609{
51cc4dad
RR
4610 wxListItem item;
4611 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
4612 item.m_text = heading;
4613 if (width >= -2)
4614 {
4615 item.m_mask |= wxLIST_MASK_WIDTH;
4616 item.m_width = width;
4617 }
4618 item.m_format = format;
c801d85f 4619
51cc4dad 4620 return InsertColumn( col, item );
e1e955e1 4621}
c801d85f 4622
debe6624 4623bool wxListCtrl::ScrollList( int WXUNUSED(dx), int WXUNUSED(dy) )
c801d85f 4624{
51cc4dad 4625 return 0;
e1e955e1 4626}
c801d85f
KB
4627
4628// Sort items.
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.
4637
4638bool wxListCtrl::SortItems( wxListCtrlCompare fn, long data )
4639{
51cc4dad
RR
4640 m_mainWin->SortItems( fn, data );
4641 return TRUE;
e1e955e1 4642}
c801d85f 4643
cf1dfa6b 4644// ----------------------------------------------------------------------------
b54e41c5 4645// event handlers
cf1dfa6b
VZ
4646// ----------------------------------------------------------------------------
4647
b54e41c5 4648void wxListCtrl::OnSize(wxSizeEvent& event)
53010e52 4649{
b54e41c5 4650 if ( !m_mainWin )
cf1dfa6b 4651 return;
53010e52 4652
b54e41c5 4653 int cw, ch;
51cc4dad 4654 GetClientSize( &cw, &ch );
bd8289c1 4655
cf1dfa6b 4656 if ( m_mainWin->HasHeader() )
51cc4dad 4657 {
cf1dfa6b
VZ
4658 m_headerWin->SetSize( 0, 0, cw, HEADER_HEIGHT );
4659 m_mainWin->SetSize( 0, HEADER_HEIGHT + 1, cw, ch - HEADER_HEIGHT - 1 );
51cc4dad 4660 }
cf1dfa6b 4661 else // no header window
51cc4dad 4662 {
cf1dfa6b 4663 m_mainWin->SetSize( 0, 0, cw, ch );
51cc4dad 4664 }
bd8289c1 4665
b54e41c5
VZ
4666 m_mainWin->RecalculatePositions();
4667}
cf1dfa6b 4668
b54e41c5
VZ
4669void wxListCtrl::OnIdle( wxIdleEvent & event )
4670{
4671 event.Skip();
f6bcfd97 4672
b54e41c5
VZ
4673 // do it only if needed
4674 if ( !m_mainWin->m_dirty )
4675 return;
4676
4677 m_mainWin->RecalculatePositions();
e1e955e1 4678}
53010e52 4679
cf1dfa6b
VZ
4680// ----------------------------------------------------------------------------
4681// font/colours
4682// ----------------------------------------------------------------------------
4683
f03fc89f 4684bool wxListCtrl::SetBackgroundColour( const wxColour &colour )
bd8289c1 4685{
51cc4dad
RR
4686 if (m_mainWin)
4687 {
4688 m_mainWin->SetBackgroundColour( colour );
4689 m_mainWin->m_dirty = TRUE;
4690 }
004fd0c8 4691
f03fc89f 4692 return TRUE;
e4d06860
RR
4693}
4694
f03fc89f 4695bool wxListCtrl::SetForegroundColour( const wxColour &colour )
bd8289c1 4696{
f03fc89f
VZ
4697 if ( !wxWindow::SetForegroundColour( colour ) )
4698 return FALSE;
004fd0c8 4699
51cc4dad
RR
4700 if (m_mainWin)
4701 {
4702 m_mainWin->SetForegroundColour( colour );
4703 m_mainWin->m_dirty = TRUE;
4704 }
004fd0c8 4705
51cc4dad
RR
4706 if (m_headerWin)
4707 {
4708 m_headerWin->SetForegroundColour( colour );
4709 }
f03fc89f
VZ
4710
4711 return TRUE;
e4d06860 4712}
bd8289c1 4713
f03fc89f 4714bool wxListCtrl::SetFont( const wxFont &font )
bd8289c1 4715{
f03fc89f
VZ
4716 if ( !wxWindow::SetFont( font ) )
4717 return FALSE;
004fd0c8 4718
51cc4dad
RR
4719 if (m_mainWin)
4720 {
4721 m_mainWin->SetFont( font );
4722 m_mainWin->m_dirty = TRUE;
4723 }
004fd0c8 4724
51cc4dad
RR
4725 if (m_headerWin)
4726 {
4727 m_headerWin->SetFont( font );
4728 }
f03fc89f
VZ
4729
4730 return TRUE;
e4d06860 4731}
c801d85f 4732
cf1dfa6b
VZ
4733// ----------------------------------------------------------------------------
4734// methods forwarded to m_mainWin
4735// ----------------------------------------------------------------------------
4736
efbb7287
VZ
4737#if wxUSE_DRAG_AND_DROP
4738
4739void wxListCtrl::SetDropTarget( wxDropTarget *dropTarget )
4740{
4741 m_mainWin->SetDropTarget( dropTarget );
4742}
4743
4744wxDropTarget *wxListCtrl::GetDropTarget() const
4745{
4746 return m_mainWin->GetDropTarget();
4747}
4748
4749#endif // wxUSE_DRAG_AND_DROP
4750
4751bool wxListCtrl::SetCursor( const wxCursor &cursor )
4752{
4753 return m_mainWin ? m_mainWin->wxWindow::SetCursor(cursor) : FALSE;
4754}
4755
4756wxColour wxListCtrl::GetBackgroundColour() const
4757{
4758 return m_mainWin ? m_mainWin->GetBackgroundColour() : wxColour();
4759}
4760
4761wxColour wxListCtrl::GetForegroundColour() const
4762{
4763 return m_mainWin ? m_mainWin->GetForegroundColour() : wxColour();
4764}
4765
4766bool wxListCtrl::DoPopupMenu( wxMenu *menu, int x, int y )
4767{
3a8c693a 4768#if wxUSE_MENUS
efbb7287 4769 return m_mainWin->PopupMenu( menu, x, y );
3a8c693a
VZ
4770#else
4771 return FALSE;
4772#endif // wxUSE_MENUS
efbb7287
VZ
4773}
4774
4775void wxListCtrl::SetFocus()
4776{
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();
4781}
1e6feb95 4782
2c1f73ee
VZ
4783// ----------------------------------------------------------------------------
4784// virtual list control support
4785// ----------------------------------------------------------------------------
4786
4787wxString wxListCtrl::OnGetItemText(long item, long col) const
4788{
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") );
4792
4793 return wxEmptyString;
4794}
4795
4796int wxListCtrl::OnGetItemImage(long item) const
4797{
4798 // same as above
4799 wxFAIL_MSG( _T("not supposed to be called") );
4800
4801 return -1;
4802}
4803
4804void wxListCtrl::SetItemCount(long count)
4805{
4806 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4807
4808 m_mainWin->SetItemCount(count);
4809}
4810
1e6feb95 4811#endif // wxUSE_LISTCTRL