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