]> git.saurik.com Git - wxWidgets.git/blame - src/generic/listctrl.cpp
Added a file
[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
0208334d
RR
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
bd8289c1 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
1370703e
VZ
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
c801d85f 18#ifdef __GNUG__
510fc784
RR
19 #pragma implementation "listctrl.h"
20 #pragma implementation "listctrlbase.h"
c801d85f
KB
21#endif
22
1e6d9499
JS
23// For compilers that support precompilation, includes "wx.h".
24#include "wx/wxprec.h"
25
26#ifdef __BORLANDC__
27#pragma hdrstop
28#endif
29
1e6feb95
VZ
30#if wxUSE_LISTCTRL
31
0208334d
RR
32#include "wx/dcscreen.h"
33#include "wx/app.h"
02527779 34#include "wx/listctrl.h"
f60d0f94 35#include "wx/generic/imaglist.h"
f6bcfd97 36#include "wx/dynarray.h"
c801d85f 37
3fb435df
RR
38#ifdef __WXGTK__
39#include <gtk/gtk.h>
40#include "wx/gtk/win_gtk.h"
41#endif
42
7c74e7fe 43#ifndef wxUSE_GENERIC_LIST_EXTENSIONS
d6d26e04 44#define wxUSE_GENERIC_LIST_EXTENSIONS 1
7c74e7fe
SC
45#endif
46
2e4df4bf
VZ
47// ----------------------------------------------------------------------------
48// events
49// ----------------------------------------------------------------------------
50
51DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG)
52DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG)
53DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
54DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
55DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
56DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
57DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
58DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
59DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
60DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
61DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
62DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
63DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
64DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
65DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
66DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
67
efbb7287
VZ
68// ============================================================================
69// private classes
70// ============================================================================
71
72//-----------------------------------------------------------------------------
73// wxListItemData (internal)
74//-----------------------------------------------------------------------------
75
76class WXDLLEXPORT wxListItemData : public wxObject
77{
efbb7287
VZ
78public:
79 wxListItemData();
80 ~wxListItemData() { delete m_attr; }
81
82 wxListItemData( const wxListItem &info );
83 void SetItem( const wxListItem &info );
efbb7287
VZ
84 void SetImage( int image );
85 void SetData( long data );
86 void SetPosition( int x, int y );
87 void SetSize( int width, int height );
88 bool HasImage() const;
54442116
VZ
89
90 bool HasText() const { return !m_text.empty(); }
91 const wxString& GetText() const { return m_text; }
92 void SetText(const wxString& text) { m_text = text; }
93
efbb7287 94 bool IsHit( int x, int y ) const;
54442116 95
efbb7287
VZ
96 int GetX( void ) const;
97 int GetY( void ) const;
98 int GetWidth() const;
99 int GetHeight() const;
100 int GetImage() const;
101 void GetItem( wxListItem &info ) const;
102
103 wxListItemAttr *GetAttributes() const { return m_attr; }
104
54442116
VZ
105public:
106 int m_image;
107 long m_data;
108 int m_xpos,
109 m_ypos;
110 int m_width,
111 m_height;
112
113 wxListItemAttr *m_attr;
114
115protected:
116 wxString m_text;
117
efbb7287
VZ
118private:
119 DECLARE_DYNAMIC_CLASS(wxListItemData);
120};
121
122//-----------------------------------------------------------------------------
123// wxListHeaderData (internal)
124//-----------------------------------------------------------------------------
125
126class WXDLLEXPORT wxListHeaderData : public wxObject
127{
128protected:
129 long m_mask;
130 int m_image;
131 wxString m_text;
132 int m_format;
133 int m_width;
2c1f73ee
VZ
134 int m_xpos,
135 m_ypos;
efbb7287
VZ
136 int m_height;
137
138public:
139 wxListHeaderData();
140 wxListHeaderData( const wxListItem &info );
141 void SetItem( const wxListItem &item );
142 void SetPosition( int x, int y );
143 void SetWidth( int w );
144 void SetFormat( int format );
145 void SetHeight( int h );
146 bool HasImage() const;
54442116
VZ
147
148 bool HasText() const { return !m_text.empty(); }
149 const wxString& GetText() const { return m_text; }
150 void SetText(const wxString& text) { m_text = text; }
151
efbb7287 152 void GetItem( wxListItem &item );
54442116
VZ
153
154 bool IsHit( int x, int y ) const;
efbb7287
VZ
155 int GetImage() const;
156 int GetWidth() const;
157 int GetFormat() const;
f6bcfd97 158
efbb7287
VZ
159private:
160 DECLARE_DYNAMIC_CLASS(wxListHeaderData);
161};
162
163//-----------------------------------------------------------------------------
164// wxListLineData (internal)
165//-----------------------------------------------------------------------------
166
2c1f73ee
VZ
167WX_DECLARE_LIST(wxListItemData, wxListItemDataList);
168#include "wx/listimpl.cpp"
169WX_DEFINE_LIST(wxListItemDataList);
170
efbb7287
VZ
171class WXDLLEXPORT wxListLineData : public wxObject
172{
173public:
2c1f73ee 174 wxListItemDataList m_items;
efbb7287
VZ
175 wxRect m_bound_all;
176 wxRect m_bound_label;
177 wxRect m_bound_icon;
178 wxRect m_bound_hilight;
179 int m_mode;
180 bool m_hilighted;
181 wxBrush *m_hilightBrush;
182 int m_spacing;
183 wxListMainWindow *m_owner;
184
185 void DoDraw( wxDC *dc, bool hilight, bool paintBG );
186
187public:
188 wxListLineData() {}
189 wxListLineData( wxListMainWindow *owner, int mode, wxBrush *hilightBrush );
190 void CalculateSize( wxDC *dc, int spacing );
191 void SetPosition( wxDC *dc, int x, int y, int window_width );
192 void SetColumnPosition( int index, int x );
193 void GetSize( int &width, int &height );
194 void GetExtent( int &x, int &y, int &width, int &height );
195 void GetLabelExtent( int &x, int &y, int &width, int &height );
196 long IsHit( int x, int y );
197 void InitItems( int num );
198 void SetItem( int index, const wxListItem &info );
199 void GetItem( int index, wxListItem &info );
54442116 200 wxString GetText(int index) const;
efbb7287
VZ
201 void SetText( int index, const wxString s );
202 int GetImage( int index );
203 void GetRect( wxRect &rect );
204 void Hilight( bool on );
205 void ReverseHilight();
206 void DrawRubberBand( wxDC *dc, bool on );
207 void Draw( wxDC *dc );
208 bool IsInRect( int x, int y, const wxRect &rect );
209 bool IsHilighted();
210 void AssignRect( wxRect &dest, int x, int y, int width, int height );
211 void AssignRect( wxRect &dest, const wxRect &source );
f6bcfd97 212
efbb7287
VZ
213private:
214 void SetAttributes(wxDC *dc,
215 const wxListItemAttr *attr,
216 const wxColour& colText, const wxFont& font,
217 bool hilight);
218
219 DECLARE_DYNAMIC_CLASS(wxListLineData);
220};
221
f6bcfd97
BP
222
223WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData, wxListLineDataArray);
224#include "wx/arrimpl.cpp"
225WX_DEFINE_OBJARRAY(wxListLineDataArray);
226
efbb7287
VZ
227//-----------------------------------------------------------------------------
228// wxListHeaderWindow (internal)
229//-----------------------------------------------------------------------------
230
231class WXDLLEXPORT wxListHeaderWindow : public wxWindow
232{
233protected:
234 wxListMainWindow *m_owner;
235 wxCursor *m_currentCursor;
236 wxCursor *m_resizeCursor;
237 bool m_isDragging;
f6bcfd97
BP
238
239 // column being resized
240 int m_column;
241
242 // divider line position in logical (unscrolled) coords
243 int m_currentX;
244
245 // minimal position beyond which the divider line can't be dragged in
246 // logical coords
247 int m_minX;
efbb7287
VZ
248
249public:
250 wxListHeaderWindow();
f6bcfd97
BP
251 virtual ~wxListHeaderWindow();
252
253 wxListHeaderWindow( wxWindow *win,
254 wxWindowID id,
255 wxListMainWindow *owner,
256 const wxPoint &pos = wxDefaultPosition,
257 const wxSize &size = wxDefaultSize,
258 long style = 0,
259 const wxString &name = "wxlistctrlcolumntitles" );
260
efbb7287 261 void DoDrawRect( wxDC *dc, int x, int y, int w, int h );
efbb7287 262 void DrawCurrent();
f6bcfd97
BP
263 void AdjustDC(wxDC& dc);
264
265 void OnPaint( wxPaintEvent &event );
efbb7287
VZ
266 void OnMouse( wxMouseEvent &event );
267 void OnSetFocus( wxFocusEvent &event );
268
f6bcfd97
BP
269 // needs refresh
270 bool m_dirty;
271
efbb7287
VZ
272private:
273 DECLARE_DYNAMIC_CLASS(wxListHeaderWindow)
274 DECLARE_EVENT_TABLE()
275};
276
277//-----------------------------------------------------------------------------
278// wxListRenameTimer (internal)
279//-----------------------------------------------------------------------------
280
281class WXDLLEXPORT wxListRenameTimer: public wxTimer
282{
283private:
1370703e 284 wxListMainWindow *m_owner;
efbb7287
VZ
285
286public:
287 wxListRenameTimer( wxListMainWindow *owner );
288 void Notify();
289};
290
291//-----------------------------------------------------------------------------
292// wxListTextCtrl (internal)
293//-----------------------------------------------------------------------------
294
295class WXDLLEXPORT wxListTextCtrl: public wxTextCtrl
296{
297private:
298 bool *m_accept;
299 wxString *m_res;
300 wxListMainWindow *m_owner;
301 wxString m_startValue;
302
303public:
304 wxListTextCtrl() {}
305 wxListTextCtrl( wxWindow *parent, const wxWindowID id,
306 bool *accept, wxString *res, wxListMainWindow *owner,
307 const wxString &value = "",
308 const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize,
309 int style = 0,
310 const wxValidator& validator = wxDefaultValidator,
809934d2 311 const wxString &name = "listctrltextctrl" );
efbb7287 312 void OnChar( wxKeyEvent &event );
c13cace1 313 void OnKeyUp( wxKeyEvent &event );
efbb7287
VZ
314 void OnKillFocus( wxFocusEvent &event );
315
316private:
317 DECLARE_DYNAMIC_CLASS(wxListTextCtrl);
318 DECLARE_EVENT_TABLE()
319};
320
321//-----------------------------------------------------------------------------
322// wxListMainWindow (internal)
323//-----------------------------------------------------------------------------
324
24b9f055
VZ
325WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList);
326#include "wx/listimpl.cpp"
327WX_DEFINE_LIST(wxListHeaderDataList);
328
efbb7287
VZ
329class WXDLLEXPORT wxListMainWindow: public wxScrolledWindow
330{
331public:
1370703e 332 // the style of the control (combination of wxLC_XXX)
efbb7287 333 long m_mode;
1370703e
VZ
334
335 // the array of all line objects for a non virtual list control
f6bcfd97 336 wxListLineDataArray m_lines;
1370703e
VZ
337
338 // the total count of items in a virtual list control
339 long m_countVirt;
340
341 // the list of column objects
24b9f055 342 wxListHeaderDataList m_columns;
1370703e
VZ
343
344 // currently focused item or NULL
efbb7287 345 wxListLineData *m_current;
1370703e
VZ
346
347 // the item currently being edited or -1
348 size_t m_currentEdit;
349
efbb7287
VZ
350 int m_visibleLines;
351 wxBrush *m_hilightBrush;
352 wxColour *m_hilightColour;
1370703e
VZ
353 int m_xScroll,
354 m_yScroll;
efbb7287
VZ
355 bool m_dirty;
356 wxImageList *m_small_image_list;
357 wxImageList *m_normal_image_list;
358 int m_small_spacing;
359 int m_normal_spacing;
360 bool m_hasFocus;
361 bool m_usedKeys;
362 bool m_lastOnSame;
363 wxTimer *m_renameTimer;
364 bool m_renameAccept;
365 wxString m_renameRes;
366 bool m_isCreated;
367 int m_dragCount;
368 wxPoint m_dragStart;
369
370 // for double click logic
1370703e
VZ
371 size_t m_lineLastClicked,
372 m_lineBeforeLastClicked;
efbb7287
VZ
373
374public:
375 wxListMainWindow();
1370703e
VZ
376 wxListMainWindow( wxWindow *parent,
377 wxWindowID id,
378 const wxPoint& pos = wxDefaultPosition,
379 const wxSize& size = wxDefaultSize,
380 long style = 0,
381 const wxString &name = _T("listctrlmainwindow") );
382
383 virtual ~wxListMainWindow();
384
385 // return true if this is a virtual list control
386 bool IsVirtual() const { return (m_mode & wxLC_VIRTUAL) != 0; }
387
efbb7287
VZ
388 void RefreshLine( wxListLineData *line );
389 void OnPaint( wxPaintEvent &event );
390 void HilightAll( bool on );
05a7f61d
VZ
391 void SendNotify( wxListLineData *line,
392 wxEventType command,
393 wxPoint point = wxDefaultPosition );
efbb7287
VZ
394 void FocusLine( wxListLineData *line );
395 void UnfocusLine( wxListLineData *line );
396 void SelectLine( wxListLineData *line );
397 void DeselectLine( wxListLineData *line );
398 void DeleteLine( wxListLineData *line );
399
400 void EditLabel( long item );
401 void Edit( long item ) { EditLabel(item); } // deprecated
402 void OnRenameTimer();
403 void OnRenameAccept();
404
405 void OnMouse( wxMouseEvent &event );
406 void MoveToFocus();
407 void OnArrowChar( wxListLineData *newCurrent, bool shiftDown );
408 void OnChar( wxKeyEvent &event );
409 void OnKeyDown( wxKeyEvent &event );
410 void OnSetFocus( wxFocusEvent &event );
411 void OnKillFocus( wxFocusEvent &event );
412 void OnSize( wxSizeEvent &event );
413 void OnScroll(wxScrollWinEvent& event) ;
f6bcfd97 414
efbb7287
VZ
415 void DrawImage( int index, wxDC *dc, int x, int y );
416 void GetImageSize( int index, int &width, int &height );
417 int GetIndexOfLine( const wxListLineData *line );
418 int GetTextLength( wxString &s ); // should be const
419
420 void SetImageList( wxImageList *imageList, int which );
421 void SetItemSpacing( int spacing, bool isSmall = FALSE );
422 int GetItemSpacing( bool isSmall = FALSE );
423 void SetColumn( int col, wxListItem &item );
424 void SetColumnWidth( int col, int width );
425 void GetColumn( int col, wxListItem &item );
426 int GetColumnWidth( int vol );
427 int GetColumnCount();
428 int GetCountPerPage();
429 void SetItem( wxListItem &item );
430 void GetItem( wxListItem &item );
431 void SetItemState( long item, long state, long stateMask );
432 int GetItemState( long item, long stateMask );
efbb7287
VZ
433 void GetItemRect( long index, wxRect &rect );
434 bool GetItemPosition( long item, wxPoint& pos );
435 int GetSelectedItemCount();
436 void SetMode( long mode );
437 long GetMode() const;
438 void CalculatePositions();
439 void RealizeChanges();
440 long GetNextItem( long item, int geometry, int state );
441 void DeleteItem( long index );
442 void DeleteAllItems();
443 void DeleteColumn( int col );
444 void DeleteEverything();
445 void EnsureVisible( long index );
446 long FindItem( long start, const wxString& str, bool partial = FALSE );
447 long FindItem( long start, long data);
448 long HitTest( int x, int y, int &flags );
449 void InsertItem( wxListItem &item );
450// void AddItem( wxListItem &item );
451 void InsertColumn( long col, wxListItem &item );
452// void AddColumn( wxListItem &item );
453 void SortItems( wxListCtrlCompare fn, long data );
454
1370703e
VZ
455 int GetItemCount() const;
456 bool IsEmpty() const { return GetItemCount() == 0; }
2c1f73ee
VZ
457 void SetItemCount(long count);
458
1370703e
VZ
459protected:
460 // common part of all ctors
461 void Init();
462
463 // get the line data for the given index
464 wxListLineData *GetLine(size_t n) const
465 {
466 wxASSERT_MSG( n != (size_t)-1, _T("invalid line index") );
467
468 return &m_lines[n];
469 }
470
efbb7287
VZ
471private:
472 DECLARE_DYNAMIC_CLASS(wxListMainWindow);
473 DECLARE_EVENT_TABLE()
474};
475
476// ============================================================================
477// implementation
478// ============================================================================
479
c801d85f
KB
480//-----------------------------------------------------------------------------
481// wxListItemData
482//-----------------------------------------------------------------------------
483
484IMPLEMENT_DYNAMIC_CLASS(wxListItemData,wxObject);
485
fd9811b1 486wxListItemData::wxListItemData()
c801d85f 487{
92976ab6
RR
488 m_image = -1;
489 m_data = 0;
490 m_xpos = 0;
491 m_ypos = 0;
492 m_width = 0;
493 m_height = 0;
0530737d 494 m_attr = NULL;
e1e955e1 495}
c801d85f
KB
496
497wxListItemData::wxListItemData( const wxListItem &info )
498{
92976ab6
RR
499 m_image = -1;
500 m_data = 0;
0530737d
VZ
501 m_attr = NULL;
502
92976ab6 503 SetItem( info );
e1e955e1 504}
c801d85f
KB
505
506void wxListItemData::SetItem( const wxListItem &info )
507{
54442116
VZ
508 if (info.m_mask & wxLIST_MASK_TEXT)
509 SetText(info.m_text);
510 if (info.m_mask & wxLIST_MASK_IMAGE)
511 m_image = info.m_image;
512 if (info.m_mask & wxLIST_MASK_DATA)
513 m_data = info.m_data;
0530737d
VZ
514
515 if ( info.HasAttributes() )
516 {
517 if ( m_attr )
518 *m_attr = *info.GetAttributes();
519 else
520 m_attr = new wxListItemAttr(*info.GetAttributes());
521 }
522
92976ab6
RR
523 m_xpos = 0;
524 m_ypos = 0;
525 m_width = info.m_width;
526 m_height = 0;
e1e955e1 527}
c801d85f 528
debe6624 529void wxListItemData::SetImage( int image )
c801d85f 530{
92976ab6 531 m_image = image;
e1e955e1 532}
c801d85f 533
debe6624 534void wxListItemData::SetData( long data )
c801d85f 535{
92976ab6 536 m_data = data;
e1e955e1 537}
c801d85f 538
debe6624 539void wxListItemData::SetPosition( int x, int y )
c801d85f 540{
92976ab6
RR
541 m_xpos = x;
542 m_ypos = y;
e1e955e1 543}
c801d85f 544
1e6d9499 545void wxListItemData::SetSize( int width, int height )
c801d85f 546{
92976ab6
RR
547 if (width != -1) m_width = width;
548 if (height != -1) m_height = height;
e1e955e1 549}
c801d85f 550
fd9811b1 551bool wxListItemData::HasImage() const
c801d85f 552{
92976ab6 553 return (m_image >= 0);
e1e955e1 554}
c801d85f 555
debe6624 556bool wxListItemData::IsHit( int x, int y ) const
c801d85f 557{
92976ab6 558 return ((x >= m_xpos) && (x <= m_xpos+m_width) && (y >= m_ypos) && (y <= m_ypos+m_height));
e1e955e1 559}
c801d85f 560
fd9811b1 561int wxListItemData::GetX() const
c801d85f 562{
92976ab6 563 return m_xpos;
e1e955e1 564}
c801d85f 565
fd9811b1 566int wxListItemData::GetY() const
c801d85f 567{
92976ab6 568 return m_ypos;
e1e955e1 569}
c801d85f 570
fd9811b1 571int wxListItemData::GetWidth() const
c801d85f 572{
92976ab6 573 return m_width;
e1e955e1 574}
c801d85f 575
fd9811b1 576int wxListItemData::GetHeight() const
c801d85f 577{
92976ab6 578 return m_height;
e1e955e1 579}
c801d85f 580
fd9811b1 581int wxListItemData::GetImage() const
c801d85f 582{
92976ab6 583 return m_image;
e1e955e1 584}
c801d85f 585
0530737d 586void wxListItemData::GetItem( wxListItem &info ) const
c801d85f 587{
92976ab6
RR
588 info.m_text = m_text;
589 info.m_image = m_image;
590 info.m_data = m_data;
c801d85f 591
0530737d
VZ
592 if ( m_attr )
593 {
594 if ( m_attr->HasTextColour() )
595 info.SetTextColour(m_attr->GetTextColour());
596 if ( m_attr->HasBackgroundColour() )
597 info.SetBackgroundColour(m_attr->GetBackgroundColour());
598 if ( m_attr->HasFont() )
599 info.SetFont(m_attr->GetFont());
600 }
e1e955e1 601}
c801d85f
KB
602
603//-----------------------------------------------------------------------------
604// wxListHeaderData
605//-----------------------------------------------------------------------------
606
607IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData,wxObject);
608
fd9811b1 609wxListHeaderData::wxListHeaderData()
c801d85f 610{
92976ab6
RR
611 m_mask = 0;
612 m_image = 0;
613 m_format = 0;
614 m_width = 0;
615 m_xpos = 0;
616 m_ypos = 0;
617 m_height = 0;
e1e955e1 618}
c801d85f
KB
619
620wxListHeaderData::wxListHeaderData( const wxListItem &item )
621{
92976ab6
RR
622 SetItem( item );
623 m_xpos = 0;
624 m_ypos = 0;
625 m_height = 0;
e1e955e1 626}
c801d85f
KB
627
628void wxListHeaderData::SetItem( const wxListItem &item )
629{
92976ab6
RR
630 m_mask = item.m_mask;
631 m_text = item.m_text;
632 m_image = item.m_image;
633 m_format = item.m_format;
634 m_width = item.m_width;
635 if (m_width < 0) m_width = 80;
636 if (m_width < 6) m_width = 6;
e1e955e1 637}
c801d85f 638
debe6624 639void wxListHeaderData::SetPosition( int x, int y )
c801d85f 640{
92976ab6
RR
641 m_xpos = x;
642 m_ypos = y;
e1e955e1 643}
c801d85f 644
debe6624 645void wxListHeaderData::SetHeight( int h )
c801d85f 646{
92976ab6 647 m_height = h;
e1e955e1 648}
c801d85f 649
debe6624 650void wxListHeaderData::SetWidth( int w )
c801d85f 651{
92976ab6
RR
652 m_width = w;
653 if (m_width < 0) m_width = 80;
654 if (m_width < 6) m_width = 6;
e1e955e1 655}
c801d85f 656
debe6624 657void wxListHeaderData::SetFormat( int format )
c801d85f 658{
92976ab6 659 m_format = format;
e1e955e1 660}
c801d85f 661
fd9811b1 662bool wxListHeaderData::HasImage() const
c801d85f 663{
92976ab6 664 return (m_image != 0);
e1e955e1 665}
c801d85f 666
c801d85f
KB
667bool wxListHeaderData::IsHit( int x, int y ) const
668{
92976ab6 669 return ((x >= m_xpos) && (x <= m_xpos+m_width) && (y >= m_ypos) && (y <= m_ypos+m_height));
e1e955e1 670}
c801d85f
KB
671
672void wxListHeaderData::GetItem( wxListItem &item )
673{
92976ab6
RR
674 item.m_mask = m_mask;
675 item.m_text = m_text;
676 item.m_image = m_image;
677 item.m_format = m_format;
678 item.m_width = m_width;
e1e955e1 679}
c801d85f 680
fd9811b1 681int wxListHeaderData::GetImage() const
c801d85f 682{
92976ab6 683 return m_image;
e1e955e1 684}
c801d85f 685
fd9811b1 686int wxListHeaderData::GetWidth() const
c801d85f 687{
92976ab6 688 return m_width;
e1e955e1 689}
c801d85f 690
fd9811b1 691int wxListHeaderData::GetFormat() const
c801d85f 692{
92976ab6 693 return m_format;
e1e955e1 694}
c801d85f
KB
695
696//-----------------------------------------------------------------------------
697// wxListLineData
698//-----------------------------------------------------------------------------
699
700IMPLEMENT_DYNAMIC_CLASS(wxListLineData,wxObject);
701
debe6624 702wxListLineData::wxListLineData( wxListMainWindow *owner, int mode, wxBrush *hilightBrush )
c801d85f 703{
92976ab6
RR
704 m_mode = mode;
705 m_hilighted = FALSE;
706 m_owner = owner;
707 m_hilightBrush = hilightBrush;
708 m_items.DeleteContents( TRUE );
709 m_spacing = 0;
e1e955e1 710}
c801d85f 711
1e6d9499 712void wxListLineData::CalculateSize( wxDC *dc, int spacing )
c801d85f 713{
2c1f73ee
VZ
714 wxListItemDataList::Node *node = m_items.GetFirst();
715
92976ab6
RR
716 m_spacing = spacing;
717 switch (m_mode)
c801d85f 718 {
92976ab6
RR
719 case wxLC_ICON:
720 {
721 m_bound_all.width = m_spacing;
92976ab6
RR
722 if (node)
723 {
2c1f73ee 724 wxListItemData *item = node->GetData();
0530737d 725 wxString s = item->GetText();
2c1f73ee
VZ
726 if (s.IsEmpty())
727 s = wxT("H");
728
13111b2a 729 wxCoord lw,lh;
92976ab6 730 dc->GetTextExtent( s, &lw, &lh );
2c1f73ee
VZ
731 if (lh < 15)
732 lh = 15;
5d25c050
RR
733 lw += 4;
734 lh += 3;
f6bcfd97 735
5d25c050 736 m_bound_all.height = m_spacing+lh;
2c1f73ee
VZ
737 if (lw > m_spacing)
738 m_bound_all.width = lw;
5d25c050
RR
739 m_bound_label.width = lw;
740 m_bound_label.height = lh;
f6bcfd97 741
5d25c050
RR
742 if (item->HasImage())
743 {
744 int w = 0;
745 int h = 0;
746 m_owner->GetImageSize( item->GetImage(), w, h );
747 m_bound_icon.width = w + 8;
748 m_bound_icon.height = h + 8;
f6bcfd97
BP
749
750 if ( m_bound_icon.width > m_bound_all.width )
751 m_bound_all.width = m_bound_icon.width;
752 if ( h + lh > m_bound_all.height - 4 )
753 m_bound_all.height = h + lh + 4;
5d25c050 754 }
f6bcfd97 755
5d25c050
RR
756 if (!item->HasText())
757 {
758 m_bound_hilight.width = m_bound_icon.width;
759 m_bound_hilight.height = m_bound_icon.height;
760 }
761 else
762 {
763 m_bound_hilight.width = m_bound_label.width;
764 m_bound_hilight.height = m_bound_label.height;
765 }
92976ab6
RR
766 }
767 break;
768 }
769 case wxLC_LIST:
770 {
92976ab6
RR
771 if (node)
772 {
2c1f73ee 773 wxListItemData *item = node->GetData();
f6bcfd97 774
0530737d 775 wxString s = item->GetText();
2c1f73ee
VZ
776 if (s.IsEmpty())
777 s = wxT("H");
778
13111b2a 779 wxCoord lw,lh;
92976ab6 780 dc->GetTextExtent( s, &lw, &lh );
2c1f73ee
VZ
781 if (lh < 15)
782 lh = 15;
5d25c050
RR
783 lw += 4;
784 lh += 3;
2c1f73ee 785
5d25c050
RR
786 m_bound_label.width = lw;
787 m_bound_label.height = lh;
f6bcfd97 788
92976ab6
RR
789 m_bound_all.width = lw;
790 m_bound_all.height = lh;
f6bcfd97 791
0b855868
RR
792 if (item->HasImage())
793 {
5dd26b08
JS
794 int w = 0;
795 int h = 0;
0b855868 796 m_owner->GetImageSize( item->GetImage(), w, h );
5d25c050
RR
797 m_bound_icon.width = w;
798 m_bound_icon.height = h;
f6bcfd97 799
bffa1c77
VZ
800 m_bound_all.width += 4 + w;
801 if (h > m_bound_all.height) m_bound_all.height = h;
802 }
f6bcfd97 803
5d25c050
RR
804 m_bound_hilight.width = m_bound_all.width;
805 m_bound_hilight.height = m_bound_all.height;
92976ab6
RR
806 }
807 break;
808 }
809 case wxLC_REPORT:
810 {
811 m_bound_all.width = 0;
812 m_bound_all.height = 0;
efad36b8
RR
813 if (node)
814 {
2c1f73ee 815 wxListItemData *item = node->GetData();
efad36b8
RR
816 if (item->HasImage())
817 {
818 int w = 0;
819 int h = 0;
820 m_owner->GetImageSize( item->GetImage(), w, h );
821 m_bound_icon.width = w;
822 m_bound_icon.height = h;
823 }
824 else
825 {
826 m_bound_icon.width = 0;
827 m_bound_icon.height = 0;
828 }
829 }
2c1f73ee 830
92976ab6
RR
831 while (node)
832 {
2c1f73ee 833 wxListItemData *item = node->GetData();
5d25c050 834 wxString s = item->GetText();
2c1f73ee
VZ
835 if (s.IsEmpty())
836 s = wxT("H");
837
13111b2a 838 wxCoord lw,lh;
7c74e7fe 839 dc->GetTextExtent( s, &lw, &lh );
2c1f73ee
VZ
840 if (lh < 15)
841 lh = 15;
5d25c050
RR
842 lw += 4;
843 lh += 3;
f6bcfd97 844
92976ab6 845 item->SetSize( item->GetWidth(), lh );
7c74e7fe 846 m_bound_all.width += lw;
92976ab6 847 m_bound_all.height = lh;
2c1f73ee 848 node = node->GetNext();
92976ab6 849 }
d7ace8a9
VS
850 m_bound_label.width = m_bound_all.width;
851 m_bound_label.height = m_bound_all.height;
92976ab6
RR
852 break;
853 }
e1e955e1 854 }
e1e955e1 855}
c801d85f 856
bc1dcfc1
VZ
857void wxListLineData::SetPosition( wxDC * WXUNUSED(dc),
858 int x, int y, int window_width )
c801d85f 859{
2c1f73ee
VZ
860 wxListItemDataList::Node *node = m_items.GetFirst();
861
0b855868
RR
862 m_bound_all.x = x;
863 m_bound_all.y = y;
2c1f73ee 864
0b855868
RR
865 switch (m_mode)
866 {
867 case wxLC_ICON:
c801d85f 868 {
0b855868
RR
869 if (node)
870 {
2c1f73ee 871 wxListItemData *item = node->GetData();
0b855868
RR
872 if (item->HasImage())
873 {
f6bcfd97
BP
874 m_bound_icon.x = m_bound_all.x + 4
875 + (m_spacing - m_bound_icon.width)/2;
5d25c050 876 m_bound_icon.y = m_bound_all.y + 4;
0b855868
RR
877 }
878 if (item->HasText())
879 {
0b855868 880 if (m_bound_all.width > m_spacing)
5d25c050 881 m_bound_label.x = m_bound_all.x + 2;
0b855868 882 else
5d25c050
RR
883 m_bound_label.x = m_bound_all.x + 2 + (m_spacing/2) - (m_bound_label.width/2);
884 m_bound_label.y = m_bound_all.y + m_bound_all.height + 2 - m_bound_label.height;
885 m_bound_hilight.x = m_bound_label.x - 2;
886 m_bound_hilight.y = m_bound_label.y - 2;
887 }
888 else
889 {
890 m_bound_hilight.x = m_bound_icon.x - 4;
891 m_bound_hilight.y = m_bound_icon.y - 4;
0b855868
RR
892 }
893 }
894 break;
e1e955e1 895 }
0b855868 896 case wxLC_LIST:
c801d85f 897 {
5d25c050
RR
898 m_bound_hilight.x = m_bound_all.x;
899 m_bound_hilight.y = m_bound_all.y;
900 m_bound_label.y = m_bound_all.y + 2;
0b855868
RR
901 if (node)
902 {
2c1f73ee 903 wxListItemData *item = node->GetData();
0b855868 904 if (item->HasImage())
bffa1c77 905 {
0b855868
RR
906 m_bound_icon.x = m_bound_all.x + 2;
907 m_bound_icon.y = m_bound_all.y + 2;
5d25c050
RR
908 m_bound_label.x = m_bound_all.x + 6 + m_bound_icon.width;
909 }
910 else
911 {
912 m_bound_label.x = m_bound_all.x + 2;
bffa1c77
VZ
913 }
914 }
0b855868
RR
915 break;
916 }
917 case wxLC_REPORT:
918 {
0b855868 919 m_bound_all.x = 0;
0b855868
RR
920 m_bound_all.width = window_width;
921 AssignRect( m_bound_hilight, m_bound_all );
5d25c050
RR
922 m_bound_label.x = m_bound_all.x + 2;
923 m_bound_label.y = m_bound_all.y + 2;
0b855868
RR
924 if (node)
925 {
2c1f73ee 926 wxListItemData *item = node->GetData();
bffa1c77
VZ
927 if (item->HasImage())
928 {
0b855868
RR
929 m_bound_icon.x = m_bound_all.x + 2;
930 m_bound_icon.y = m_bound_all.y + 2;
5d25c050 931 m_bound_label.x += 4 + m_bound_icon.width;
bffa1c77
VZ
932 }
933 }
0b855868 934 break;
e1e955e1 935 }
e1e955e1 936 }
e1e955e1 937}
c801d85f 938
debe6624 939void wxListLineData::SetColumnPosition( int index, int x )
c801d85f 940{
2c1f73ee 941 wxListItemDataList::Node *node = m_items.Item( (size_t)index );
92976ab6
RR
942 if (node)
943 {
2c1f73ee 944 wxListItemData *item = node->GetData();
92976ab6
RR
945 item->SetPosition( x, m_bound_all.y+1 );
946 }
e1e955e1 947}
c801d85f
KB
948
949void wxListLineData::GetSize( int &width, int &height )
950{
139adb6a
RR
951 width = m_bound_all.width;
952 height = m_bound_all.height;
e1e955e1 953}
c801d85f
KB
954
955void wxListLineData::GetExtent( int &x, int &y, int &width, int &height )
956{
139adb6a
RR
957 x = m_bound_all.x;
958 y = m_bound_all.y;
959 width = m_bound_all.width;
960 height = m_bound_all.height;
e1e955e1 961}
c801d85f
KB
962
963void wxListLineData::GetLabelExtent( int &x, int &y, int &width, int &height )
964{
139adb6a
RR
965 x = m_bound_label.x;
966 y = m_bound_label.y;
967 width = m_bound_label.width;
968 height = m_bound_label.height;
e1e955e1 969}
c801d85f 970
0a240683 971void wxListLineData::GetRect( wxRect &rect )
c801d85f 972{
139adb6a 973 AssignRect( rect, m_bound_all );
e1e955e1 974}
c801d85f 975
debe6624 976long wxListLineData::IsHit( int x, int y )
c801d85f 977{
2c1f73ee 978 wxListItemDataList::Node *node = m_items.GetFirst();
139adb6a
RR
979 if (node)
980 {
2c1f73ee
VZ
981 wxListItemData *item = node->GetData();
982 if (item->HasImage() && IsInRect( x, y, m_bound_icon ))
983 return wxLIST_HITTEST_ONITEMICON;
984 if (item->HasText() && IsInRect( x, y, m_bound_label ))
985 return wxLIST_HITTEST_ONITEMLABEL;
986
139adb6a 987 }
2c1f73ee 988
139adb6a 989 // if there is no icon or text = empty
2c1f73ee
VZ
990 if (IsInRect( x, y, m_bound_all ))
991 return wxLIST_HITTEST_ONITEMICON;
992
139adb6a 993 return 0;
e1e955e1 994}
c801d85f 995
debe6624 996void wxListLineData::InitItems( int num )
c801d85f 997{
2c1f73ee
VZ
998 for (int i = 0; i < num; i++)
999 m_items.Append( new wxListItemData() );
e1e955e1 1000}
c801d85f 1001
debe6624 1002void wxListLineData::SetItem( int index, const wxListItem &info )
c801d85f 1003{
2c1f73ee 1004 wxListItemDataList::Node *node = m_items.Item( index );
1370703e
VZ
1005 wxCHECK_RET( node, _T("invalid column index in SetItem") );
1006
1007 wxListItemData *item = node->GetData();
1008 item->SetItem( info );
e1e955e1 1009}
c801d85f 1010
1e6d9499 1011void wxListLineData::GetItem( int index, wxListItem &info )
c801d85f 1012{
2c1f73ee 1013 wxListItemDataList::Node *node = m_items.Item( index );
139adb6a
RR
1014 if (node)
1015 {
2c1f73ee 1016 wxListItemData *item = node->GetData();
139adb6a
RR
1017 item->GetItem( info );
1018 }
e1e955e1 1019}
c801d85f 1020
54442116 1021wxString wxListLineData::GetText(int index) const
c801d85f 1022{
54442116
VZ
1023 wxString s;
1024
2c1f73ee 1025 wxListItemDataList::Node *node = m_items.Item( index );
139adb6a
RR
1026 if (node)
1027 {
2c1f73ee 1028 wxListItemData *item = node->GetData();
54442116 1029 s = item->GetText();
139adb6a 1030 }
54442116
VZ
1031
1032 return s;
e1e955e1 1033}
c801d85f 1034
debe6624 1035void wxListLineData::SetText( int index, const wxString s )
c801d85f 1036{
2c1f73ee 1037 wxListItemDataList::Node *node = m_items.Item( index );
139adb6a
RR
1038 if (node)
1039 {
2c1f73ee 1040 wxListItemData *item = node->GetData();
139adb6a
RR
1041 item->SetText( s );
1042 }
e1e955e1 1043}
c801d85f 1044
debe6624 1045int wxListLineData::GetImage( int index )
c801d85f 1046{
2c1f73ee 1047 wxListItemDataList::Node *node = m_items.Item( index );
139adb6a
RR
1048 if (node)
1049 {
2c1f73ee 1050 wxListItemData *item = node->GetData();
139adb6a
RR
1051 return item->GetImage();
1052 }
1053 return -1;
e1e955e1 1054}
c801d85f 1055
0530737d
VZ
1056void wxListLineData::SetAttributes(wxDC *dc,
1057 const wxListItemAttr *attr,
1058 const wxColour& colText,
470caaf9
VZ
1059 const wxFont& font,
1060 bool hilight)
0530737d 1061{
470caaf9
VZ
1062 // don't use foregroud colour for drawing highlighted items - this might
1063 // make them completely invisible (and there is no way to do bit
1064 // arithmetics on wxColour, unfortunately)
1065 if ( !hilight && attr && attr->HasTextColour() )
0530737d
VZ
1066 {
1067 dc->SetTextForeground(attr->GetTextColour());
1068 }
1069 else
1070 {
1071 dc->SetTextForeground(colText);
1072 }
1073
1074 if ( attr && attr->HasFont() )
1075 {
1076 dc->SetFont(attr->GetFont());
1077 }
1078 else
1079 {
1080 dc->SetFont(font);
1081 }
1082}
1083
1e6d9499 1084void wxListLineData::DoDraw( wxDC *dc, bool hilight, bool paintBG )
c801d85f 1085{
e06b9569
JS
1086 int dev_x = 0;
1087 int dev_y = 0;
3d2d8da1
RR
1088 m_owner->CalcScrolledPosition( m_bound_all.x, m_bound_all.y, &dev_x, &dev_y );
1089 wxCoord dev_w = m_bound_all.width;
1090 wxCoord dev_h = m_bound_all.height;
004fd0c8 1091
139adb6a 1092 if (!m_owner->IsExposed( dev_x, dev_y, dev_w, dev_h ))
139adb6a 1093 return;
bd8289c1 1094
0530737d
VZ
1095 wxWindow *listctrl = m_owner->GetParent();
1096
1097 // default foreground colour
1098 wxColour colText;
1099 if ( hilight )
1100 {
1101 colText = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT );
1102 }
1103 else
1104 {
1105 colText = listctrl->GetForegroundColour();
1106 }
1107
1108 // default font
1109 wxFont font = listctrl->GetFont();
1110
1111 // VZ: currently we set the colours/fonts only once, but like this (i.e.
1112 // using SetAttributes() inside the loop), it will be trivial to
1113 // customize the subitems (in report mode) too.
2c1f73ee 1114 wxListItemData *item = m_items.GetFirst()->GetData();
0530737d 1115 wxListItemAttr *attr = item->GetAttributes();
470caaf9 1116 SetAttributes(dc, attr, colText, font, hilight);
0530737d
VZ
1117
1118 bool hasBgCol = attr && attr->HasBackgroundColour();
1119 if ( paintBG || hasBgCol )
c801d85f 1120 {
63852e78
RR
1121 if (hilight)
1122 {
1123 dc->SetBrush( * m_hilightBrush );
63852e78
RR
1124 }
1125 else
1126 {
0530737d
VZ
1127 if ( hasBgCol )
1128 dc->SetBrush(wxBrush(attr->GetBackgroundColour(), wxSOLID));
1129 else
1130 dc->SetBrush( * wxWHITE_BRUSH );
63852e78 1131 }
0530737d
VZ
1132
1133 dc->SetPen( * wxTRANSPARENT_PEN );
63852e78
RR
1134 dc->DrawRectangle( m_bound_hilight.x, m_bound_hilight.y,
1135 m_bound_hilight.width, m_bound_hilight.height );
e1e955e1 1136 }
004fd0c8 1137
2c1f73ee
VZ
1138 wxListItemDataList::Node *node = m_items.GetFirst();
1139
63852e78 1140 if (m_mode == wxLC_REPORT)
c801d85f 1141 {
63852e78
RR
1142 while (node)
1143 {
2c1f73ee 1144 wxListItemData *item = node->GetData();
63852e78
RR
1145 int x = item->GetX();
1146 if (item->HasImage())
1147 {
1148 int y = 0;
1149 m_owner->DrawImage( item->GetImage(), dc, x, item->GetY() );
1150 m_owner->GetImageSize( item->GetImage(), x, y );
1151 x += item->GetX() + 5;
1152 }
40c70187 1153 dc->SetClippingRegion( item->GetX(), item->GetY(), item->GetWidth()-3, item->GetHeight() );
63852e78
RR
1154 if (item->HasText())
1155 {
40c70187 1156 dc->DrawText( item->GetText(), x, item->GetY()+1 );
63852e78
RR
1157 }
1158 dc->DestroyClippingRegion();
2c1f73ee 1159 node = node->GetNext();
63852e78 1160 }
e1e955e1 1161 }
2c1f73ee 1162 else // !report
c801d85f 1163 {
63852e78
RR
1164 if (node)
1165 {
2c1f73ee 1166 wxListItemData *item = node->GetData();
63852e78
RR
1167 if (item->HasImage())
1168 {
1169 m_owner->DrawImage( item->GetImage(), dc, m_bound_icon.x, m_bound_icon.y );
1170 }
1171 if (item->HasText())
1172 {
0530737d 1173 dc->DrawText( item->GetText(), m_bound_label.x, m_bound_label.y );
63852e78
RR
1174 }
1175 }
e1e955e1 1176 }
e1e955e1 1177}
c801d85f 1178
debe6624 1179void wxListLineData::Hilight( bool on )
c801d85f 1180{
63852e78 1181 if (on == m_hilighted) return;
6e228e42 1182 m_hilighted = on;
63852e78
RR
1183 if (on)
1184 m_owner->SelectLine( this );
1185 else
1186 m_owner->DeselectLine( this );
e1e955e1 1187}
c801d85f
KB
1188
1189void wxListLineData::ReverseHilight( void )
1190{
63852e78
RR
1191 m_hilighted = !m_hilighted;
1192 if (m_hilighted)
1193 m_owner->SelectLine( this );
1194 else
1195 m_owner->DeselectLine( this );
e1e955e1 1196}
c801d85f 1197
1e6d9499 1198void wxListLineData::DrawRubberBand( wxDC *dc, bool on )
c801d85f 1199{
63852e78
RR
1200 if (on)
1201 {
1202 dc->SetPen( * wxBLACK_PEN );
1203 dc->SetBrush( * wxTRANSPARENT_BRUSH );
1204 dc->DrawRectangle( m_bound_hilight.x, m_bound_hilight.y,
1205 m_bound_hilight.width, m_bound_hilight.height );
1206 }
e1e955e1 1207}
c801d85f 1208
1e6d9499 1209void wxListLineData::Draw( wxDC *dc )
c801d85f 1210{
63852e78 1211 DoDraw( dc, m_hilighted, m_hilighted );
e1e955e1 1212}
c801d85f 1213
0a240683 1214bool wxListLineData::IsInRect( int x, int y, const wxRect &rect )
c801d85f 1215{
004fd0c8 1216 return ((x >= rect.x) && (x <= rect.x+rect.width) &&
63852e78 1217 (y >= rect.y) && (y <= rect.y+rect.height));
e1e955e1 1218}
c801d85f
KB
1219
1220bool wxListLineData::IsHilighted( void )
1221{
63852e78 1222 return m_hilighted;
e1e955e1 1223}
c801d85f 1224
0a240683 1225void wxListLineData::AssignRect( wxRect &dest, int x, int y, int width, int height )
c801d85f 1226{
63852e78
RR
1227 dest.x = x;
1228 dest.y = y;
1229 dest.width = width;
1230 dest.height = height;
e1e955e1 1231}
c801d85f 1232
0a240683 1233void wxListLineData::AssignRect( wxRect &dest, const wxRect &source )
c801d85f 1234{
63852e78
RR
1235 dest.x = source.x;
1236 dest.y = source.y;
1237 dest.width = source.width;
1238 dest.height = source.height;
e1e955e1 1239}
c801d85f
KB
1240
1241//-----------------------------------------------------------------------------
1242// wxListHeaderWindow
1243//-----------------------------------------------------------------------------
1244
1245IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow,wxWindow);
1246
1247BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow)
63852e78
RR
1248 EVT_PAINT (wxListHeaderWindow::OnPaint)
1249 EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse)
1250 EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus)
c801d85f
KB
1251END_EVENT_TABLE()
1252
1253wxListHeaderWindow::wxListHeaderWindow( void )
1254{
63852e78
RR
1255 m_owner = (wxListMainWindow *) NULL;
1256 m_currentCursor = (wxCursor *) NULL;
1257 m_resizeCursor = (wxCursor *) NULL;
cfb50f14 1258 m_isDragging = FALSE;
e1e955e1 1259}
c801d85f 1260
bd8289c1 1261wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, wxWindowID id, wxListMainWindow *owner,
debe6624
JS
1262 const wxPoint &pos, const wxSize &size,
1263 long style, const wxString &name ) :
c801d85f
KB
1264 wxWindow( win, id, pos, size, style, name )
1265{
63852e78 1266 m_owner = owner;
c801d85f 1267// m_currentCursor = wxSTANDARD_CURSOR;
63852e78
RR
1268 m_currentCursor = (wxCursor *) NULL;
1269 m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
cfb50f14 1270 m_isDragging = FALSE;
f6bcfd97
BP
1271 m_dirty = FALSE;
1272
cfb50f14 1273 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ) );
e1e955e1 1274}
c801d85f 1275
a367b9b3
JS
1276wxListHeaderWindow::~wxListHeaderWindow( void )
1277{
63852e78 1278 delete m_resizeCursor;
a367b9b3
JS
1279}
1280
1e6d9499 1281void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h )
c801d85f 1282{
3fb435df
RR
1283#ifdef __WXGTK__
1284 GtkStateType state = GTK_STATE_NORMAL;
1285 if (!m_parent->IsEnabled()) state = GTK_STATE_INSENSITIVE;
2c1f73ee 1286
3fb435df 1287 x = dc->XLOG2DEV( x );
2c1f73ee 1288
05a7f61d
VZ
1289 gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window, state, GTK_SHADOW_OUT,
1290 (GdkRectangle*) NULL, m_wxwindow, "button", x-1, y-1, w+2, h+2);
3fb435df 1291#else
63852e78 1292 const int m_corner = 1;
c801d85f 1293
63852e78 1294 dc->SetBrush( *wxTRANSPARENT_BRUSH );
c801d85f 1295
63852e78
RR
1296 dc->SetPen( *wxBLACK_PEN );
1297 dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer)
17867d61 1298 dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer)
bd8289c1 1299
63852e78 1300 wxPen pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID );
004fd0c8 1301
63852e78
RR
1302 dc->SetPen( pen );
1303 dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner)
1304 dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner)
bd8289c1 1305
63852e78
RR
1306 dc->SetPen( *wxWHITE_PEN );
1307 dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer)
1308 dc->DrawRectangle( x, y, 1, h ); // left (outer)
1309 dc->DrawLine( x, y+h-1, x+1, y+h-1 );
1310 dc->DrawLine( x+w-1, y, x+w-1, y+1 );
3fb435df 1311#endif
e1e955e1 1312}
c801d85f 1313
f6bcfd97
BP
1314// shift the DC origin to match the position of the main window horz
1315// scrollbar: this allows us to always use logical coords
1316void wxListHeaderWindow::AdjustDC(wxDC& dc)
1317{
1318#if wxUSE_GENERIC_LIST_EXTENSIONS
1319 int xpix;
1320 m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
1321
1322 int x;
1323 m_owner->GetViewStart( &x, NULL );
1324
1325 // account for the horz scrollbar offset
1326 dc.SetDeviceOrigin( -x * xpix, 0 );
1327#endif // wxUSE_GENERIC_LIST_EXTENSIONS
1328}
1329
c801d85f
KB
1330void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
1331{
10bd0724
JS
1332#ifdef __WXGTK__
1333 wxClientDC dc( this );
1334#else
63852e78 1335 wxPaintDC dc( this );
10bd0724
JS
1336#endif
1337
63852e78 1338 PrepareDC( dc );
f6bcfd97 1339 AdjustDC( dc );
bffa1c77 1340
63852e78 1341 dc.BeginDrawing();
bd8289c1 1342
63852e78 1343 dc.SetFont( GetFont() );
bd8289c1 1344
f6bcfd97
BP
1345 // width and height of the entire header window
1346 int w, h;
63852e78 1347 GetClientSize( &w, &h );
f6bcfd97
BP
1348#if wxUSE_GENERIC_LIST_EXTENSIONS
1349 m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1350#endif // wxUSE_GENERIC_LIST_EXTENSIONS
c801d85f 1351
f60d0f94 1352 dc.SetBackgroundMode(wxTRANSPARENT);
70846f0a
VZ
1353
1354 // do *not* use the listctrl colour for headers - one day we will have a
1355 // function to set it separately
37d403aa
JS
1356 //dc.SetTextForeground( *wxBLACK );
1357 dc.SetTextForeground(wxSystemSettings::GetSystemColour( wxSYS_COLOUR_WINDOWTEXT ));
c801d85f 1358
f6bcfd97
BP
1359 int x = 1; // left of the header rect
1360 const int y = 1; // top
63852e78
RR
1361 int numColumns = m_owner->GetColumnCount();
1362 wxListItem item;
1363 for (int i = 0; i < numColumns; i++)
1364 {
1365 m_owner->GetColumn( i, item );
f6bcfd97
BP
1366 int wCol = item.m_width;
1367 int cw = wCol - 2; // the width of the rect to draw
1368
1369 int xEnd = x + wCol;
1370
1371 // VZ: no, draw it normally - this is better now as we allow resizing
1372 // of the last column as well
1373#if 0
1374 // let the last column occupy all available space
1375 if ( i == numColumns - 1 )
470caaf9 1376 cw = w-x-1;
f6bcfd97
BP
1377#endif // 0
1378
63852e78 1379 dc.SetPen( *wxWHITE_PEN );
c801d85f 1380
63852e78 1381 DoDrawRect( &dc, x, y, cw, h-2 );
40c70187 1382 dc.SetClippingRegion( x, y, cw-5, h-4 );
54442116 1383 dc.DrawText( item.GetText(), x+4, y+3 );
40c70187 1384 dc.DestroyClippingRegion();
f6bcfd97
BP
1385 x += wCol;
1386
1387 if (xEnd > w+5)
1388 break;
63852e78
RR
1389 }
1390 dc.EndDrawing();
e1e955e1 1391}
c801d85f 1392
0208334d
RR
1393void wxListHeaderWindow::DrawCurrent()
1394{
63852e78
RR
1395 int x1 = m_currentX;
1396 int y1 = 0;
f6bcfd97
BP
1397 ClientToScreen( &x1, &y1 );
1398
63852e78
RR
1399 int x2 = m_currentX-1;
1400 int y2 = 0;
f6bcfd97 1401 m_owner->GetClientSize( NULL, &y2 );
63852e78 1402 m_owner->ClientToScreen( &x2, &y2 );
0208334d 1403
63852e78 1404 wxScreenDC dc;
3c679789 1405 dc.SetLogicalFunction( wxINVERT );
63852e78
RR
1406 dc.SetPen( wxPen( *wxBLACK, 2, wxSOLID ) );
1407 dc.SetBrush( *wxTRANSPARENT_BRUSH );
0208334d 1408
f6bcfd97
BP
1409 AdjustDC(dc);
1410
63852e78 1411 dc.DrawLine( x1, y1, x2, y2 );
0208334d 1412
63852e78 1413 dc.SetLogicalFunction( wxCOPY );
0208334d 1414
63852e78
RR
1415 dc.SetPen( wxNullPen );
1416 dc.SetBrush( wxNullBrush );
0208334d
RR
1417}
1418
c801d85f
KB
1419void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
1420{
f6bcfd97
BP
1421 // we want to work with logical coords
1422#if wxUSE_GENERIC_LIST_EXTENSIONS
3ca6a5f0
BP
1423 int x;
1424 m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
f6bcfd97
BP
1425#else // !wxUSE_GENERIC_LIST_EXTENSIONS
1426 int x = event.GetX();
f6bcfd97 1427#endif // wxUSE_GENERIC_LIST_EXTENSIONS
3ca6a5f0 1428 int y = event.GetY();
f6bcfd97 1429
cfb50f14 1430 if (m_isDragging)
0208334d 1431 {
f6bcfd97
BP
1432 // we don't draw the line beyond our window, but we allow dragging it
1433 // there
1434 int w = 0;
1435 GetClientSize( &w, NULL );
1436#if wxUSE_GENERIC_LIST_EXTENSIONS
1437 m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1438#endif // wxUSE_GENERIC_LIST_EXTENSIONS
1439 w -= 6;
1440
1441 // erase the line if it was drawn
1442 if ( m_currentX < w )
1443 DrawCurrent();
1444
63852e78
RR
1445 if (event.ButtonUp())
1446 {
1447 ReleaseMouse();
cfb50f14 1448 m_isDragging = FALSE;
f6bcfd97
BP
1449 m_dirty = TRUE;
1450 m_owner->SetColumnWidth( m_column, m_currentX - m_minX );
63852e78
RR
1451 }
1452 else
1453 {
f6bcfd97 1454 if (x > m_minX + 7)
63852e78
RR
1455 m_currentX = x;
1456 else
f6bcfd97 1457 m_currentX = m_minX + 7;
bd8289c1 1458
f6bcfd97
BP
1459 // draw in the new location
1460 if ( m_currentX < w )
1461 DrawCurrent();
bffa1c77 1462 }
0208334d 1463 }
f6bcfd97 1464 else // not dragging
c801d85f 1465 {
f6bcfd97
BP
1466 m_minX = 0;
1467 bool hit_border = FALSE;
1468
1469 // end of the current column
1470 int xpos = 0;
1471
1472 // find the column where this event occured
1473 int countCol = m_owner->GetColumnCount();
1474 for (int j = 0; j < countCol; j++)
bffa1c77 1475 {
f6bcfd97
BP
1476 xpos += m_owner->GetColumnWidth( j );
1477 m_column = j;
1478
1479 if ( (abs(x-xpos) < 3) && (y < 22) )
1480 {
1481 // near the column border
1482 hit_border = TRUE;
1483 break;
1484 }
1485
1486 if ( x < xpos )
1487 {
1488 // inside the column
1489 break;
1490 }
1491
1492 m_minX = xpos;
bffa1c77 1493 }
63852e78 1494
f6bcfd97 1495 if (event.LeftDown())
63852e78 1496 {
f6bcfd97
BP
1497 if (hit_border)
1498 {
1499 m_isDragging = TRUE;
1500 m_currentX = x;
1501 DrawCurrent();
1502 CaptureMouse();
1503 }
1504 else
1505 {
1506 wxWindow *parent = GetParent();
1507 wxListEvent le( wxEVT_COMMAND_LIST_COL_CLICK, parent->GetId() );
1508 le.SetEventObject( parent );
1509 le.m_col = m_column;
1510 parent->GetEventHandler()->ProcessEvent( le );
1511 }
63852e78 1512 }
f6bcfd97 1513 else if (event.Moving())
63852e78 1514 {
f6bcfd97
BP
1515 bool setCursor;
1516 if (hit_border)
1517 {
1518 setCursor = m_currentCursor == wxSTANDARD_CURSOR;
1519 m_currentCursor = m_resizeCursor;
1520 }
1521 else
1522 {
1523 setCursor = m_currentCursor != wxSTANDARD_CURSOR;
1524 m_currentCursor = wxSTANDARD_CURSOR;
1525 }
1526
1527 if ( setCursor )
1528 SetCursor(*m_currentCursor);
63852e78 1529 }
e1e955e1 1530 }
e1e955e1 1531}
c801d85f
KB
1532
1533void wxListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
1534{
63852e78 1535 m_owner->SetFocus();
e1e955e1 1536}
c801d85f
KB
1537
1538//-----------------------------------------------------------------------------
1539// wxListRenameTimer (internal)
1540//-----------------------------------------------------------------------------
1541
bd8289c1
VZ
1542wxListRenameTimer::wxListRenameTimer( wxListMainWindow *owner )
1543{
63852e78 1544 m_owner = owner;
e1e955e1 1545}
c801d85f 1546
bd8289c1
VZ
1547void wxListRenameTimer::Notify()
1548{
63852e78 1549 m_owner->OnRenameTimer();
e1e955e1 1550}
c801d85f 1551
ee7ee469
RR
1552//-----------------------------------------------------------------------------
1553// wxListTextCtrl (internal)
1554//-----------------------------------------------------------------------------
1555
1556IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl,wxTextCtrl);
bd8289c1 1557
ee7ee469 1558BEGIN_EVENT_TABLE(wxListTextCtrl,wxTextCtrl)
63852e78 1559 EVT_CHAR (wxListTextCtrl::OnChar)
2c1f73ee 1560 EVT_KEY_UP (wxListTextCtrl::OnKeyUp)
63852e78 1561 EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus)
ee7ee469
RR
1562END_EVENT_TABLE()
1563
674ac8b9
VZ
1564wxListTextCtrl::wxListTextCtrl( wxWindow *parent,
1565 const wxWindowID id,
1566 bool *accept,
1567 wxString *res,
1568 wxListMainWindow *owner,
1569 const wxString &value,
1570 const wxPoint &pos,
1571 const wxSize &size,
1572 int style,
1573 const wxValidator& validator,
1574 const wxString &name )
1575 : wxTextCtrl( parent, id, value, pos, size, style, validator, name )
ee7ee469 1576{
63852e78
RR
1577 m_res = res;
1578 m_accept = accept;
1579 m_owner = owner;
5f1ea0ee
RR
1580 (*m_accept) = FALSE;
1581 (*m_res) = "";
1582 m_startValue = value;
ee7ee469
RR
1583}
1584
1585void wxListTextCtrl::OnChar( wxKeyEvent &event )
1586{
63852e78
RR
1587 if (event.m_keyCode == WXK_RETURN)
1588 {
1589 (*m_accept) = TRUE;
1590 (*m_res) = GetValue();
f6bcfd97 1591
bce1406b
RR
1592 if (!wxPendingDelete.Member(this))
1593 wxPendingDelete.Append(this);
1594
1595 if ((*m_accept) && ((*m_res) != m_startValue))
1596 m_owner->OnRenameAccept();
f6bcfd97 1597
63852e78
RR
1598 return;
1599 }
1600 if (event.m_keyCode == WXK_ESCAPE)
1601 {
1602 (*m_accept) = FALSE;
1603 (*m_res) = "";
f6bcfd97 1604
bce1406b
RR
1605 if (!wxPendingDelete.Member(this))
1606 wxPendingDelete.Append(this);
f6bcfd97 1607
63852e78
RR
1608 return;
1609 }
f6bcfd97 1610
63852e78
RR
1611 event.Skip();
1612}
1613
c13cace1
VS
1614void wxListTextCtrl::OnKeyUp( wxKeyEvent &event )
1615{
1616 // auto-grow the textctrl:
1617 wxSize parentSize = m_owner->GetSize();
1618 wxPoint myPos = GetPosition();
1619 wxSize mySize = GetSize();
1620 int sx, sy;
1621 GetTextExtent(GetValue() + _T("MM"), &sx, &sy);
1622 if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x;
1623 if (mySize.x > sx) sx = mySize.x;
1624 SetSize(sx, -1);
2c1f73ee 1625
c13cace1
VS
1626 event.Skip();
1627}
1628
63852e78
RR
1629void wxListTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
1630{
bce1406b
RR
1631 if (!wxPendingDelete.Member(this))
1632 wxPendingDelete.Append(this);
004fd0c8 1633
5f1ea0ee
RR
1634 if ((*m_accept) && ((*m_res) != m_startValue))
1635 m_owner->OnRenameAccept();
ee7ee469
RR
1636}
1637
c801d85f
KB
1638//-----------------------------------------------------------------------------
1639// wxListMainWindow
1640//-----------------------------------------------------------------------------
1641
1642IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow,wxScrolledWindow);
bd8289c1 1643
c801d85f
KB
1644BEGIN_EVENT_TABLE(wxListMainWindow,wxScrolledWindow)
1645 EVT_PAINT (wxListMainWindow::OnPaint)
1646 EVT_SIZE (wxListMainWindow::OnSize)
1647 EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse)
1648 EVT_CHAR (wxListMainWindow::OnChar)
3dfb93fd 1649 EVT_KEY_DOWN (wxListMainWindow::OnKeyDown)
c801d85f
KB
1650 EVT_SET_FOCUS (wxListMainWindow::OnSetFocus)
1651 EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus)
2fa7c206 1652 EVT_SCROLLWIN (wxListMainWindow::OnScroll)
c801d85f
KB
1653END_EVENT_TABLE()
1654
1370703e 1655void wxListMainWindow::Init()
c801d85f 1656{
139adb6a
RR
1657 m_columns.DeleteContents( TRUE );
1658 m_current = (wxListLineData *) NULL;
139adb6a 1659 m_dirty = TRUE;
1370703e
VZ
1660 m_visibleLines = 0;
1661
139adb6a
RR
1662 m_small_image_list = (wxImageList *) NULL;
1663 m_normal_image_list = (wxImageList *) NULL;
1370703e 1664
139adb6a
RR
1665 m_small_spacing = 30;
1666 m_normal_spacing = 40;
1370703e 1667
139adb6a 1668 m_hasFocus = FALSE;
1370703e
VZ
1669 m_dragCount = 0;
1670 m_isCreated = FALSE;
1671
139adb6a
RR
1672 m_usedKeys = TRUE;
1673 m_lastOnSame = FALSE;
1674 m_renameTimer = new wxListRenameTimer( this );
1370703e
VZ
1675 m_renameAccept = FALSE;
1676
1677 m_currentEdit = (size_t)-1;
efbb7287
VZ
1678
1679 m_lineLastClicked =
1370703e 1680 m_lineBeforeLastClicked = (size_t)-1;
e1e955e1 1681}
c801d85f 1682
1370703e 1683wxListMainWindow::wxListMainWindow()
c801d85f 1684{
1370703e
VZ
1685 Init();
1686
1687 m_mode = 0;
1688
1689 m_hilightBrush = (wxBrush *) NULL;
1690
1691 m_xScroll =
1692 m_yScroll = 0;
1693}
1694
1695wxListMainWindow::wxListMainWindow( wxWindow *parent,
1696 wxWindowID id,
1697 const wxPoint& pos,
1698 const wxSize& size,
1699 long style,
1700 const wxString &name )
1701 : wxScrolledWindow( parent, id, pos, size,
1702 style | wxHSCROLL | wxVSCROLL, name )
1703{
1704 Init();
1705
139adb6a 1706 m_mode = style;
139adb6a 1707 m_hilightBrush = new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), wxSOLID );
139adb6a
RR
1708 wxSize sz = size;
1709 sz.y = 25;
bd8289c1 1710
139adb6a
RR
1711 if (m_mode & wxLC_REPORT)
1712 {
7c74e7fe
SC
1713#if wxUSE_GENERIC_LIST_EXTENSIONS
1714 m_xScroll = 15;
1715#else
139adb6a 1716 m_xScroll = 0;
7c74e7fe 1717#endif
139adb6a
RR
1718 m_yScroll = 15;
1719 }
1720 else
1721 {
1722 m_xScroll = 15;
1723 m_yScroll = 0;
1724 }
1725 SetScrollbars( m_xScroll, m_yScroll, 0, 0, 0, 0 );
bd8289c1 1726
91fc2bdc 1727 SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) );
e1e955e1 1728}
c801d85f 1729
fd9811b1 1730wxListMainWindow::~wxListMainWindow()
c801d85f 1731{
12c1b46a
RR
1732 DeleteEverything();
1733
139adb6a 1734 if (m_hilightBrush) delete m_hilightBrush;
004fd0c8 1735
139adb6a 1736 delete m_renameTimer;
e1e955e1 1737}
c801d85f
KB
1738
1739void wxListMainWindow::RefreshLine( wxListLineData *line )
1740{
e6527f9d 1741 if (m_dirty) return;
25e3a937 1742
3d2d8da1 1743 if (!line) return;
f6bcfd97 1744
139adb6a
RR
1745 int x = 0;
1746 int y = 0;
1747 int w = 0;
1748 int h = 0;
3d2d8da1
RR
1749 line->GetExtent( x, y, w, h );
1750 CalcScrolledPosition( x, y, &x, &y );
1751 wxRect rect( x, y, w, h );
1752 Refresh( TRUE, &rect );
e1e955e1 1753}
c801d85f
KB
1754
1755void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
1756{
f60d0f94
JS
1757 // Note: a wxPaintDC must be constructed even if no drawing is
1758 // done (a Windows requirement).
1759 wxPaintDC dc( this );
2c1f73ee
VZ
1760
1761 if (m_dirty)
1762 {
1763 // postpone redrawing until the next OnIdle() call to minimize flicker
1764 return;
1765 }
1766
f60d0f94
JS
1767 PrepareDC( dc );
1768
2c1f73ee 1769 int dev_x, dev_y;
673dfcfa
JS
1770 CalcScrolledPosition( 0, 0, &dev_x, &dev_y );
1771
1370703e 1772 if ( GetItemCount() == 0 )
2c1f73ee
VZ
1773 {
1774 // empty control. nothing to draw
1775 return;
1776 }
bd8289c1 1777
139adb6a 1778 dc.BeginDrawing();
c801d85f 1779
139adb6a 1780 dc.SetFont( GetFont() );
004fd0c8 1781
139adb6a
RR
1782 if (m_mode & wxLC_REPORT)
1783 {
206b0a67 1784 wxPen pen(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID);
206b0a67 1785 wxSize clientSize = GetClientSize();
206b0a67 1786
139adb6a 1787 int lineSpacing = 0;
f6bcfd97 1788 wxListLineData *line = &m_lines[0];
139adb6a
RR
1789 int dummy = 0;
1790 line->GetSize( dummy, lineSpacing );
1791 lineSpacing += 1;
bffa1c77 1792
139adb6a 1793 int y_s = m_yScroll*GetScrollPos( wxVERTICAL );
bffa1c77 1794
f6bcfd97 1795 size_t i_to = y_s / lineSpacing + m_visibleLines+2;
1370703e
VZ
1796 if (i_to >= m_lines.GetCount())
1797 i_to = m_lines.GetCount();
1798
206b0a67
JS
1799 size_t i;
1800 for (i = y_s / lineSpacing; i < i_to; i++)
bffa1c77 1801 {
f6bcfd97 1802 m_lines[i].Draw( &dc );
206b0a67 1803 // Draw horizontal rule if required
ef7c5bd2 1804 if (m_mode & wxLC_HRULES)
673dfcfa
JS
1805 {
1806 dc.SetPen(pen);
1807 dc.SetBrush(* wxTRANSPARENT_BRUSH);
1808 dc.DrawLine(0 - dev_x , i*lineSpacing , clientSize.x - dev_x , i*lineSpacing );
2c1f73ee 1809 }
bffa1c77 1810 }
206b0a67
JS
1811
1812 // Draw last horizontal rule
ef7c5bd2 1813 if ((i > (size_t) (y_s / lineSpacing)) && (m_mode & wxLC_HRULES))
673dfcfa
JS
1814 {
1815 dc.SetPen(pen);
1816 dc.SetBrush(* wxTRANSPARENT_BRUSH);
1817 dc.DrawLine(0 - dev_x , i*lineSpacing , clientSize.x - dev_x , i*lineSpacing );
2c1f73ee 1818 }
206b0a67
JS
1819
1820 // Draw vertical rules if required
ef7c5bd2 1821 if ((m_mode & wxLC_VRULES) && (GetItemCount() > 0))
206b0a67
JS
1822 {
1823 int col = 0;
1824 wxRect firstItemRect;
1825 wxRect lastItemRect;
1826 GetItemRect(0, firstItemRect);
1827 GetItemRect(GetItemCount() - 1, lastItemRect);
1828 int x = firstItemRect.GetX();
673dfcfa
JS
1829 dc.SetPen(pen);
1830 dc.SetBrush(* wxTRANSPARENT_BRUSH);
206b0a67
JS
1831 for (col = 0; col < GetColumnCount(); col++)
1832 {
1833 int colWidth = GetColumnWidth(col);
1834 x += colWidth ;
673dfcfa 1835 dc.DrawLine(x - dev_x, firstItemRect.GetY() - 1 - dev_y, x - dev_x, lastItemRect.GetBottom() + 1 - dev_y);
206b0a67 1836 }
d786bf87 1837 }
139adb6a 1838 }
2c1f73ee 1839 else // !report mode
139adb6a 1840 {
1370703e
VZ
1841 size_t count = GetItemCount();
1842 for (size_t i = 0; i < count; i++)
f6bcfd97 1843 m_lines[i].Draw( &dc );
139adb6a 1844 }
004fd0c8 1845
2c1f73ee
VZ
1846 if (m_current)
1847 m_current->DrawRubberBand( &dc, m_hasFocus );
c801d85f 1848
139adb6a 1849 dc.EndDrawing();
e1e955e1 1850}
c801d85f 1851
debe6624 1852void wxListMainWindow::HilightAll( bool on )
c801d85f 1853{
1370703e
VZ
1854 size_t count = GetItemCount();
1855 for (size_t i = 0; i < count; i++)
c801d85f 1856 {
f6bcfd97 1857 wxListLineData *line = &m_lines[i];
139adb6a
RR
1858 if (line->IsHilighted() != on)
1859 {
1860 line->Hilight( on );
1861 RefreshLine( line );
1862 }
e1e955e1 1863 }
e1e955e1 1864}
c801d85f 1865
05a7f61d
VZ
1866void wxListMainWindow::SendNotify( wxListLineData *line,
1867 wxEventType command,
1868 wxPoint point )
c801d85f 1869{
139adb6a
RR
1870 wxListEvent le( command, GetParent()->GetId() );
1871 le.SetEventObject( GetParent() );
1872 le.m_itemIndex = GetIndexOfLine( line );
05a7f61d
VZ
1873
1874 // set only for events which have position
1875 if ( point != wxDefaultPosition )
1876 le.m_pointDrag = point;
1877
139adb6a 1878 line->GetItem( 0, le.m_item );
6e228e42
RR
1879 GetParent()->GetEventHandler()->ProcessEvent( le );
1880// GetParent()->GetEventHandler()->AddPendingEvent( le );
e1e955e1 1881}
c801d85f
KB
1882
1883void wxListMainWindow::FocusLine( wxListLineData *WXUNUSED(line) )
1884{
1885// SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
e1e955e1 1886}
c801d85f
KB
1887
1888void wxListMainWindow::UnfocusLine( wxListLineData *WXUNUSED(line) )
1889{
1890// SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
e1e955e1 1891}
c801d85f
KB
1892
1893void wxListMainWindow::SelectLine( wxListLineData *line )
1894{
139adb6a 1895 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_SELECTED );
e1e955e1 1896}
c801d85f
KB
1897
1898void wxListMainWindow::DeselectLine( wxListLineData *line )
1899{
139adb6a 1900 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_DESELECTED );
e1e955e1 1901}
c801d85f
KB
1902
1903void wxListMainWindow::DeleteLine( wxListLineData *line )
1904{
139adb6a 1905 SendNotify( line, wxEVT_COMMAND_LIST_DELETE_ITEM );
e1e955e1 1906}
c801d85f 1907
e179bd65 1908/* *** */
ee7ee469 1909
5f1ea0ee 1910void wxListMainWindow::EditLabel( long item )
c801d85f 1911{
1370703e 1912 wxCHECK_RET( (item >= 0) && (item < GetItemCount()),
f6bcfd97 1913 wxT("wrong index in wxListCtrl::Edit()") );
004fd0c8 1914
1370703e 1915 m_currentEdit = (size_t)item;
e179bd65 1916
fd9811b1 1917 wxListEvent le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, GetParent()->GetId() );
139adb6a 1918 le.SetEventObject( GetParent() );
1370703e
VZ
1919 le.m_itemIndex = item;
1920 wxListLineData *data = GetLine(m_currentEdit);
1921 wxCHECK_RET( data, _T("invalid index in EditLabel()") );
1922 data->GetItem( 0, le.m_item );
139adb6a 1923 GetParent()->GetEventHandler()->ProcessEvent( le );
004fd0c8 1924
86f975a8 1925 if (!le.IsAllowed())
5f1ea0ee 1926 return;
004fd0c8 1927
dc6c62a9
RR
1928 // We have to call this here because the label in
1929 // question might just have been added and no screen
1930 // update taken place.
1931 if (m_dirty) wxYield();
1932
1370703e 1933 wxString s = data->GetText(0);
92976ab6
RR
1934 int x = 0;
1935 int y = 0;
1936 int w = 0;
1937 int h = 0;
1370703e 1938 data->GetLabelExtent( x, y, w, h );
004fd0c8 1939
92976ab6
RR
1940 wxClientDC dc(this);
1941 PrepareDC( dc );
1942 x = dc.LogicalToDeviceX( x );
1943 y = dc.LogicalToDeviceY( y );
bd8289c1 1944
92976ab6
RR
1945 wxListTextCtrl *text = new wxListTextCtrl(
1946 this, -1, &m_renameAccept, &m_renameRes, this, s, wxPoint(x-4,y-4), wxSize(w+11,h+8) );
1947 text->SetFocus();
e1e955e1 1948}
c801d85f 1949
e179bd65
RR
1950void wxListMainWindow::OnRenameTimer()
1951{
223d09f6 1952 wxCHECK_RET( m_current, wxT("invalid m_current") );
004fd0c8 1953
f6bcfd97 1954 Edit( m_lines.Index( *m_current ) );
e179bd65
RR
1955}
1956
c801d85f
KB
1957void wxListMainWindow::OnRenameAccept()
1958{
e179bd65
RR
1959 wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
1960 le.SetEventObject( GetParent() );
1370703e
VZ
1961 le.m_itemIndex = m_currentEdit;
1962
1963 wxListLineData *data = GetLine(m_currentEdit);
1964 wxCHECK_RET( data, _T("invalid index in OnRenameAccept()") );
1965
1966 data->GetItem( 0, le.m_item );
e179bd65
RR
1967 le.m_item.m_text = m_renameRes;
1968 GetParent()->GetEventHandler()->ProcessEvent( le );
004fd0c8 1969
e179bd65 1970 if (!le.IsAllowed()) return;
004fd0c8 1971
5f1ea0ee
RR
1972 wxListItem info;
1973 info.m_mask = wxLIST_MASK_TEXT;
1974 info.m_itemId = le.m_itemIndex;
1975 info.m_text = m_renameRes;
aaa37c0d 1976 info.SetTextColour(le.m_item.GetTextColour());
5f1ea0ee 1977 SetItem( info );
e1e955e1 1978}
c801d85f
KB
1979
1980void wxListMainWindow::OnMouse( wxMouseEvent &event )
1981{
3e1c4e00 1982 event.SetEventObject( GetParent() );
92976ab6 1983 if (GetParent()->GetEventHandler()->ProcessEvent( event)) return;
e3e65dac 1984
92976ab6
RR
1985 if (!m_current) return;
1986 if (m_dirty) return;
0b855868 1987 if ( !(event.Dragging() || event.ButtonDown() || event.LeftUp() || event.ButtonDClick()) ) return;
c801d85f 1988
aaef15bf
RR
1989 int x = event.GetX();
1990 int y = event.GetY();
1991 CalcUnscrolledPosition( x, y, &x, &y );
004fd0c8 1992
51cc4dad 1993 /* Did we actually hit an item ? */
92976ab6 1994 long hitResult = 0;
92976ab6 1995 wxListLineData *line = (wxListLineData *) NULL;
1370703e
VZ
1996
1997 size_t idx;
1998 for (idx = 0; idx < m_lines.GetCount(); idx++)
92976ab6 1999 {
1370703e 2000 line = &m_lines[idx];
92976ab6 2001 hitResult = line->IsHit( x, y );
1370703e
VZ
2002 if (hitResult)
2003 break;
92976ab6 2004 line = (wxListLineData *) NULL;
92976ab6 2005 }
bd8289c1 2006
fd9811b1 2007 if (event.Dragging())
92976ab6 2008 {
fd9811b1 2009 if (m_dragCount == 0)
bffa1c77
VZ
2010 m_dragStart = wxPoint(x,y);
2011
fd9811b1 2012 m_dragCount++;
bffa1c77
VZ
2013
2014 if (m_dragCount != 3) return;
2015
05a7f61d
VZ
2016 int command = event.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
2017 : wxEVT_COMMAND_LIST_BEGIN_DRAG;
bffa1c77 2018
fd9811b1 2019 wxListEvent le( command, GetParent()->GetId() );
92976ab6 2020 le.SetEventObject( GetParent() );
bffa1c77
VZ
2021 le.m_pointDrag = m_dragStart;
2022 GetParent()->GetEventHandler()->ProcessEvent( le );
2023
2024 return;
92976ab6 2025 }
fd9811b1
RR
2026 else
2027 {
2028 m_dragCount = 0;
2029 }
bd8289c1 2030
92976ab6 2031 if (!line) return;
bd8289c1 2032
efbb7287 2033 bool forceClick = FALSE;
92976ab6
RR
2034 if (event.ButtonDClick())
2035 {
92976ab6 2036 m_renameTimer->Stop();
efbb7287
VZ
2037 m_lastOnSame = FALSE;
2038
1370703e 2039 if ( idx == m_lineBeforeLastClicked )
efbb7287
VZ
2040 {
2041 m_usedKeys = FALSE;
004fd0c8 2042
efbb7287 2043 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
004fd0c8 2044
efbb7287
VZ
2045 return;
2046 }
2047 else
2048 {
2049 // the first click was on another item, so don't interpret this as
2050 // a double click, but as a simple click instead
2051 forceClick = TRUE;
2052 }
92976ab6 2053 }
bd8289c1 2054
92976ab6 2055 if (event.LeftUp() && m_lastOnSame)
c801d85f 2056 {
92976ab6
RR
2057 m_usedKeys = FALSE;
2058 if ((line == m_current) &&
2059 (hitResult == wxLIST_HITTEST_ONITEMLABEL) &&
2060 (m_mode & wxLC_EDIT_LABELS) )
2061 {
2062 m_renameTimer->Start( 100, TRUE );
2063 }
2064 m_lastOnSame = FALSE;
2065 return;
e1e955e1 2066 }
bd8289c1 2067
92976ab6 2068 if (event.RightDown())
b204641e 2069 {
05a7f61d
VZ
2070 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK,
2071 event.GetPosition() );
92976ab6 2072 return;
b204641e 2073 }
004fd0c8 2074
92976ab6 2075 if (event.MiddleDown())
b204641e 2076 {
92976ab6
RR
2077 SendNotify( line, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK );
2078 return;
2079 }
004fd0c8 2080
efbb7287 2081 if ( event.LeftDown() || forceClick )
92976ab6 2082 {
efbb7287 2083 m_lineBeforeLastClicked = m_lineLastClicked;
1370703e 2084 m_lineLastClicked = idx;
efbb7287 2085
92976ab6
RR
2086 m_usedKeys = FALSE;
2087 wxListLineData *oldCurrent = m_current;
2088 if (m_mode & wxLC_SINGLE_SEL)
b204641e 2089 {
92976ab6
RR
2090 m_current = line;
2091 HilightAll( FALSE );
2092 m_current->ReverseHilight();
2093 RefreshLine( m_current );
e1e955e1 2094 }
92976ab6 2095 else
b204641e 2096 {
473d087e 2097 if (event.ControlDown())
92976ab6
RR
2098 {
2099 m_current = line;
2100 m_current->ReverseHilight();
2101 RefreshLine( m_current );
2102 }
473d087e 2103 else if (event.ShiftDown())
92976ab6 2104 {
f6bcfd97 2105 size_t j;
3e1c4e00 2106
92976ab6 2107 m_current = line;
bffa1c77 2108
92976ab6 2109 int numOfCurrent = -1;
f6bcfd97 2110 for (j = 0; j < m_lines.GetCount(); j++)
92976ab6 2111 {
f6bcfd97 2112 wxListLineData *test_line = &m_lines[j];
92976ab6
RR
2113 numOfCurrent++;
2114 if (test_line == oldCurrent) break;
92976ab6 2115 }
bffa1c77 2116
92976ab6 2117 int numOfLine = -1;
f6bcfd97
BP
2118
2119 for (j = 0; j < m_lines.GetCount(); j++)
92976ab6 2120 {
f6bcfd97 2121 wxListLineData *test_line = &m_lines[j];
92976ab6
RR
2122 numOfLine++;
2123 if (test_line == line) break;
92976ab6
RR
2124 }
2125
2126 if (numOfLine < numOfCurrent)
004fd0c8 2127 {
bffa1c77
VZ
2128 int i = numOfLine;
2129 numOfLine = numOfCurrent;
2130 numOfCurrent = i;
2131 }
2132
92976ab6
RR
2133 for (int i = 0; i <= numOfLine-numOfCurrent; i++)
2134 {
f6bcfd97 2135 wxListLineData *test_line= &m_lines[numOfCurrent + i];
92976ab6
RR
2136 test_line->Hilight(TRUE);
2137 RefreshLine( test_line );
92976ab6
RR
2138 }
2139 }
2140 else
2141 {
2142 m_current = line;
2143 HilightAll( FALSE );
2144 m_current->ReverseHilight();
2145 RefreshLine( m_current );
2146 }
e1e955e1 2147 }
92976ab6
RR
2148 if (m_current != oldCurrent)
2149 {
2150 RefreshLine( oldCurrent );
2151 UnfocusLine( oldCurrent );
2152 FocusLine( m_current );
2153 }
efbb7287
VZ
2154
2155 // forceClick is only set if the previous click was on another item
2156 m_lastOnSame = !forceClick && (m_current == oldCurrent);
2157
92976ab6 2158 return;
e1e955e1 2159 }
e1e955e1 2160}
c801d85f 2161
e179bd65 2162void wxListMainWindow::MoveToFocus()
c801d85f 2163{
92976ab6 2164 if (!m_current) return;
004fd0c8 2165
cf3da716
RR
2166 int item_x = 0;
2167 int item_y = 0;
2168 int item_w = 0;
2169 int item_h = 0;
2170 m_current->GetExtent( item_x, item_y, item_w, item_h );
2171
2172 int client_w = 0;
2173 int client_h = 0;
2174 GetClientSize( &client_w, &client_h );
f6bcfd97 2175
cf3da716
RR
2176 int view_x = m_xScroll*GetScrollPos( wxHORIZONTAL );
2177 int view_y = m_yScroll*GetScrollPos( wxVERTICAL );
004fd0c8 2178
92976ab6
RR
2179 if (m_mode & wxLC_REPORT)
2180 {
08bf1d5d
RR
2181 if (item_y < view_y )
2182 Scroll( -1, (item_y)/m_yScroll );
f6bcfd97 2183 if (item_y+item_h+5 > view_y+client_h)
cf3da716 2184 Scroll( -1, (item_y+item_h-client_h+15)/m_yScroll );
92976ab6
RR
2185 }
2186 else
2187 {
f6bcfd97 2188 if (item_x-view_x < 5)
cf3da716 2189 Scroll( (item_x-5)/m_xScroll, -1 );
f6bcfd97 2190 if (item_x+item_w-5 > view_x+client_w)
cf3da716 2191 Scroll( (item_x+item_w-client_w+15)/m_xScroll, -1 );
92976ab6 2192 }
e1e955e1 2193}
c801d85f
KB
2194
2195void wxListMainWindow::OnArrowChar( wxListLineData *newCurrent, bool shiftDown )
2196{
92976ab6
RR
2197 if ((m_mode & wxLC_SINGLE_SEL) || (m_usedKeys == FALSE)) m_current->Hilight( FALSE );
2198 wxListLineData *oldCurrent = m_current;
2199 m_current = newCurrent;
92976ab6
RR
2200 if (shiftDown || (m_mode & wxLC_SINGLE_SEL)) m_current->Hilight( TRUE );
2201 RefreshLine( m_current );
2202 RefreshLine( oldCurrent );
2203 FocusLine( m_current );
2204 UnfocusLine( oldCurrent );
cf3da716 2205 MoveToFocus();
e1e955e1 2206}
c801d85f 2207
3dfb93fd
RR
2208void wxListMainWindow::OnKeyDown( wxKeyEvent &event )
2209{
2210 wxWindow *parent = GetParent();
004fd0c8 2211
3dfb93fd
RR
2212 /* we propagate the key event up */
2213 wxKeyEvent ke( wxEVT_KEY_DOWN );
2214 ke.m_shiftDown = event.m_shiftDown;
2215 ke.m_controlDown = event.m_controlDown;
2216 ke.m_altDown = event.m_altDown;
2217 ke.m_metaDown = event.m_metaDown;
2218 ke.m_keyCode = event.m_keyCode;
2219 ke.m_x = event.m_x;
2220 ke.m_y = event.m_y;
2221 ke.SetEventObject( parent );
2222 if (parent->GetEventHandler()->ProcessEvent( ke )) return;
004fd0c8 2223
3dfb93fd
RR
2224 event.Skip();
2225}
004fd0c8 2226
c801d85f
KB
2227void wxListMainWindow::OnChar( wxKeyEvent &event )
2228{
51cc4dad 2229 wxWindow *parent = GetParent();
004fd0c8 2230
51cc4dad 2231 /* we send a list_key event up */
f6bcfd97
BP
2232 if ( m_current )
2233 {
2234 wxListEvent le( wxEVT_COMMAND_LIST_KEY_DOWN, GetParent()->GetId() );
2235 le.m_itemIndex = GetIndexOfLine( m_current );
2236 m_current->GetItem( 0, le.m_item );
2237 le.m_code = (int)event.KeyCode();
2238 le.SetEventObject( parent );
2239 parent->GetEventHandler()->ProcessEvent( le );
2240 }
51cc4dad 2241
3dfb93fd
RR
2242 /* we propagate the char event up */
2243 wxKeyEvent ke( wxEVT_CHAR );
51cc4dad
RR
2244 ke.m_shiftDown = event.m_shiftDown;
2245 ke.m_controlDown = event.m_controlDown;
2246 ke.m_altDown = event.m_altDown;
2247 ke.m_metaDown = event.m_metaDown;
2248 ke.m_keyCode = event.m_keyCode;
2249 ke.m_x = event.m_x;
2250 ke.m_y = event.m_y;
2251 ke.SetEventObject( parent );
2252 if (parent->GetEventHandler()->ProcessEvent( ke )) return;
004fd0c8 2253
012a03e0
RR
2254 if (event.KeyCode() == WXK_TAB)
2255 {
2256 wxNavigationKeyEvent nevent;
c5145d41 2257 nevent.SetWindowChange( event.ControlDown() );
012a03e0 2258 nevent.SetDirection( !event.ShiftDown() );
8253c7fd 2259 nevent.SetEventObject( GetParent()->GetParent() );
012a03e0 2260 nevent.SetCurrentFocus( m_parent );
8253c7fd 2261 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent )) return;
012a03e0 2262 }
004fd0c8 2263
51cc4dad
RR
2264 /* no item -> nothing to do */
2265 if (!m_current)
c801d85f 2266 {
51cc4dad
RR
2267 event.Skip();
2268 return;
e1e955e1 2269 }
51cc4dad
RR
2270
2271 switch (event.KeyCode())
c801d85f 2272 {
51cc4dad
RR
2273 case WXK_UP:
2274 {
f6bcfd97
BP
2275 int index = m_lines.Index(*m_current);
2276 if (index != wxNOT_FOUND && index > 0)
2277 OnArrowChar( &m_lines[index-1], event.ShiftDown() );
51cc4dad
RR
2278 break;
2279 }
2280 case WXK_DOWN:
2281 {
f6bcfd97
BP
2282 int index = m_lines.Index(*m_current);
2283 if (index != wxNOT_FOUND && (size_t)index < m_lines.GetCount()-1)
2284 OnArrowChar( &m_lines[index+1], event.ShiftDown() );
51cc4dad
RR
2285 break;
2286 }
2287 case WXK_END:
2288 {
1370703e 2289 if (!IsEmpty())
f6bcfd97 2290 OnArrowChar( &m_lines.Last(), event.ShiftDown() );
51cc4dad
RR
2291 break;
2292 }
2293 case WXK_HOME:
2294 {
1370703e 2295 if (!IsEmpty())
f6bcfd97 2296 OnArrowChar( &m_lines[0], event.ShiftDown() );
51cc4dad
RR
2297 break;
2298 }
2299 case WXK_PRIOR:
2300 {
2301 int steps = 0;
f6bcfd97 2302 int index = m_lines.Index(*m_current);
004fd0c8 2303 if (m_mode & wxLC_REPORT)
bffa1c77
VZ
2304 {
2305 steps = m_visibleLines-1;
2306 }
51cc4dad
RR
2307 else
2308 {
f6bcfd97
BP
2309 steps = index % m_visibleLines;
2310 }
2311 if (index != wxNOT_FOUND)
2312 {
2313 index -= steps;
3e1c4e00 2314 if (index < 0) index = 0;
f6bcfd97 2315 OnArrowChar( &m_lines[index], event.ShiftDown() );
51cc4dad 2316 }
51cc4dad
RR
2317 break;
2318 }
2319 case WXK_NEXT:
2320 {
2321 int steps = 0;
f6bcfd97 2322 int index = m_lines.Index(*m_current);
004fd0c8 2323 if (m_mode & wxLC_REPORT)
bffa1c77
VZ
2324 {
2325 steps = m_visibleLines-1;
2326 }
51cc4dad
RR
2327 else
2328 {
f6bcfd97
BP
2329 steps = m_visibleLines-(index % m_visibleLines)-1;
2330 }
2331
2332 if (index != wxNOT_FOUND)
2333 {
2334 index += steps;
3e1c4e00 2335 if ((size_t)index >= m_lines.GetCount())
f6bcfd97
BP
2336 index = m_lines.GetCount()-1;
2337 OnArrowChar( &m_lines[index], event.ShiftDown() );
51cc4dad 2338 }
51cc4dad
RR
2339 break;
2340 }
2341 case WXK_LEFT:
2342 {
2343 if (!(m_mode & wxLC_REPORT))
2344 {
f6bcfd97
BP
2345 int index = m_lines.Index(*m_current);
2346 if (index != wxNOT_FOUND)
2347 {
2348 index -= m_visibleLines;
2349 if (index < 0) index = 0;
2350 OnArrowChar( &m_lines[index], event.ShiftDown() );
2351 }
51cc4dad
RR
2352 }
2353 break;
2354 }
2355 case WXK_RIGHT:
2356 {
2357 if (!(m_mode & wxLC_REPORT))
2358 {
f6bcfd97
BP
2359 int index = m_lines.Index(*m_current);
2360 if (index != wxNOT_FOUND)
2361 {
2362 index += m_visibleLines;
3e1c4e00 2363 if ((size_t)index >= m_lines.GetCount())
f6bcfd97
BP
2364 index = m_lines.GetCount()-1;
2365 OnArrowChar( &m_lines[index], event.ShiftDown() );
2366 }
51cc4dad
RR
2367 }
2368 break;
2369 }
2370 case WXK_SPACE:
2371 {
33d0e17c
RR
2372 if (m_mode & wxLC_SINGLE_SEL)
2373 {
2374 wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, GetParent()->GetId() );
2375 le.SetEventObject( GetParent() );
2376 le.m_itemIndex = GetIndexOfLine( m_current );
2377 m_current->GetItem( 0, le.m_item );
2378 GetParent()->GetEventHandler()->ProcessEvent( le );
2379 }
2380 else
2381 {
2382 m_current->ReverseHilight();
2383 RefreshLine( m_current );
2384 }
51cc4dad
RR
2385 break;
2386 }
2387 case WXK_INSERT:
2388 {
2389 if (!(m_mode & wxLC_SINGLE_SEL))
2390 {
2391 wxListLineData *oldCurrent = m_current;
2392 m_current->ReverseHilight();
f6bcfd97
BP
2393 int index = m_lines.Index( *m_current ) + 1;
2394 if ( (size_t)index < m_lines.GetCount() )
2395 m_current = &m_lines[index];
51cc4dad
RR
2396 RefreshLine( oldCurrent );
2397 RefreshLine( m_current );
2398 UnfocusLine( oldCurrent );
2399 FocusLine( m_current );
cf3da716 2400 MoveToFocus();
51cc4dad
RR
2401 }
2402 break;
2403 }
2404 case WXK_RETURN:
2405 case WXK_EXECUTE:
2406 {
2407 wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, GetParent()->GetId() );
2408 le.SetEventObject( GetParent() );
2409 le.m_itemIndex = GetIndexOfLine( m_current );
2410 m_current->GetItem( 0, le.m_item );
2411 GetParent()->GetEventHandler()->ProcessEvent( le );
2412 break;
2413 }
2414 default:
2415 {
2416 event.Skip();
2417 return;
2418 }
e1e955e1 2419 }
51cc4dad 2420 m_usedKeys = TRUE;
e1e955e1 2421}
c801d85f 2422
cae5359f
RR
2423#ifdef __WXGTK__
2424extern wxWindow *g_focusWindow;
2425#endif
2426
c801d85f
KB
2427void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
2428{
63852e78
RR
2429 m_hasFocus = TRUE;
2430 RefreshLine( m_current );
bd8289c1 2431
63852e78 2432 if (!GetParent()) return;
004fd0c8 2433
cae5359f
RR
2434#ifdef __WXGTK__
2435 g_focusWindow = GetParent();
2436#endif
bd8289c1 2437
63852e78
RR
2438 wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
2439 event.SetEventObject( GetParent() );
2440 GetParent()->GetEventHandler()->ProcessEvent( event );
e1e955e1 2441}
c801d85f
KB
2442
2443void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
2444{
63852e78
RR
2445 m_hasFocus = FALSE;
2446 RefreshLine( m_current );
e1e955e1 2447}
c801d85f
KB
2448
2449void wxListMainWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
2450{
2451/*
2452 We don't even allow the wxScrolledWindow::AdjustScrollbars() call
004fd0c8 2453
c801d85f 2454*/
2035e10e 2455 m_dirty = TRUE;
e1e955e1 2456}
c801d85f 2457
1e6d9499 2458void wxListMainWindow::DrawImage( int index, wxDC *dc, int x, int y )
c801d85f 2459{
63852e78
RR
2460 if ((m_mode & wxLC_ICON) && (m_normal_image_list))
2461 {
2462 m_normal_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
2463 return;
2464 }
2465 if ((m_mode & wxLC_SMALL_ICON) && (m_small_image_list))
2466 {
2467 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
2468 }
0b855868
RR
2469 if ((m_mode & wxLC_LIST) && (m_small_image_list))
2470 {
2471 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
2472 }
63852e78
RR
2473 if ((m_mode & wxLC_REPORT) && (m_small_image_list))
2474 {
2475 m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
2476 return;
2477 }
e1e955e1 2478}
c801d85f
KB
2479
2480void wxListMainWindow::GetImageSize( int index, int &width, int &height )
2481{
63852e78
RR
2482 if ((m_mode & wxLC_ICON) && (m_normal_image_list))
2483 {
2484 m_normal_image_list->GetSize( index, width, height );
2485 return;
2486 }
2487 if ((m_mode & wxLC_SMALL_ICON) && (m_small_image_list))
2488 {
2489 m_small_image_list->GetSize( index, width, height );
2490 return;
2491 }
0b855868
RR
2492 if ((m_mode & wxLC_LIST) && (m_small_image_list))
2493 {
2494 m_small_image_list->GetSize( index, width, height );
2495 return;
2496 }
63852e78
RR
2497 if ((m_mode & wxLC_REPORT) && (m_small_image_list))
2498 {
2499 m_small_image_list->GetSize( index, width, height );
2500 return;
2501 }
2502 width = 0;
2503 height = 0;
e1e955e1 2504}
c801d85f
KB
2505
2506int wxListMainWindow::GetTextLength( wxString &s )
2507{
1e6d9499 2508 wxClientDC dc( this );
13111b2a
VZ
2509 wxCoord lw = 0;
2510 wxCoord lh = 0;
139adb6a
RR
2511 dc.GetTextExtent( s, &lw, &lh );
2512 return lw + 6;
e1e955e1 2513}
c801d85f
KB
2514
2515int wxListMainWindow::GetIndexOfLine( const wxListLineData *line )
2516{
1370703e 2517 return m_lines.Index(*line);
e1e955e1 2518}
c801d85f 2519
debe6624 2520void wxListMainWindow::SetImageList( wxImageList *imageList, int which )
c801d85f 2521{
139adb6a 2522 m_dirty = TRUE;
f6bcfd97
BP
2523
2524 // calc the spacing from the icon size
2525 int width = 0,
2526 height = 0;
2527 if ((imageList) && (imageList->GetImageCount()) )
2528 {
2529 imageList->GetSize(0, width, height);
2530 }
2531
2532 if (which == wxIMAGE_LIST_NORMAL)
2533 {
2534 m_normal_image_list = imageList;
2535 m_normal_spacing = width + 8;
2536 }
2537
2538 if (which == wxIMAGE_LIST_SMALL)
2539 {
2540 m_small_image_list = imageList;
2541 m_small_spacing = width + 14;
2542 }
e1e955e1 2543}
c801d85f 2544
debe6624 2545void wxListMainWindow::SetItemSpacing( int spacing, bool isSmall )
c801d85f 2546{
139adb6a
RR
2547 m_dirty = TRUE;
2548 if (isSmall)
2549 {
2550 m_small_spacing = spacing;
2551 }
2552 else
2553 {
2554 m_normal_spacing = spacing;
2555 }
e1e955e1 2556}
c801d85f 2557
debe6624 2558int wxListMainWindow::GetItemSpacing( bool isSmall )
c801d85f 2559{
f6bcfd97 2560 return isSmall ? m_small_spacing : m_normal_spacing;
e1e955e1 2561}
c801d85f 2562
debe6624 2563void wxListMainWindow::SetColumn( int col, wxListItem &item )
c801d85f 2564{
63852e78 2565 m_dirty = TRUE;
24b9f055 2566 wxListHeaderDataList::Node *node = m_columns.Item( col );
63852e78
RR
2567 if (node)
2568 {
54442116
VZ
2569 if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
2570 item.m_width = GetTextLength( item.m_text )+7;
24b9f055 2571 wxListHeaderData *column = node->GetData();
63852e78
RR
2572 column->SetItem( item );
2573 }
f6bcfd97
BP
2574
2575 wxListHeaderWindow *headerWin = ((wxListCtrl*) GetParent())->m_headerWin;
2576 if ( headerWin )
2577 headerWin->m_dirty = TRUE;
e1e955e1 2578}
c801d85f 2579
debe6624 2580void wxListMainWindow::SetColumnWidth( int col, int width )
c801d85f 2581{
f6bcfd97
BP
2582 wxCHECK_RET( m_mode & wxLC_REPORT,
2583 _T("SetColumnWidth() can only be called in report mode.") );
0208334d 2584
63852e78 2585 m_dirty = TRUE;
bd8289c1 2586
f6bcfd97
BP
2587 if (width == wxLIST_AUTOSIZE_USEHEADER)
2588 {
2589 // TODO do use the header
2590 width = 80;
2591 }
2592 else if (width == wxLIST_AUTOSIZE)
0180dad6
RR
2593 {
2594 wxClientDC dc(this);
2595 dc.SetFont( GetFont() );
2596 int max = 10;
3e1c4e00 2597
f6bcfd97 2598 for (size_t i = 0; i < m_lines.GetCount(); i++)
0180dad6 2599 {
f6bcfd97 2600 wxListLineData *line = &m_lines[i];
2c1f73ee 2601 wxListItemDataList::Node *n = line->m_items.Item( col );
0180dad6
RR
2602 if (n)
2603 {
2c1f73ee 2604 wxListItemData *item = n->GetData();
bffa1c77 2605 int current = 0, ix = 0, iy = 0;
13111b2a 2606 wxCoord lx = 0, ly = 0;
bffa1c77
VZ
2607 if (item->HasImage())
2608 {
0180dad6 2609 GetImageSize( item->GetImage(), ix, iy );
bffa1c77
VZ
2610 current = ix + 5;
2611 }
2612 if (item->HasText())
2613 {
54442116 2614 wxString str = item->GetText();
bffa1c77
VZ
2615 dc.GetTextExtent( str, &lx, &ly );
2616 current += lx;
2617 }
2c1f73ee
VZ
2618 if (current > max)
2619 max = current;
0180dad6 2620 }
0180dad6 2621 }
bffa1c77 2622 width = max+10;
0180dad6
RR
2623 }
2624
24b9f055 2625 wxListHeaderDataList::Node *node = m_columns.Item( col );
63852e78
RR
2626 if (node)
2627 {
24b9f055 2628 wxListHeaderData *column = node->GetData();
63852e78
RR
2629 column->SetWidth( width );
2630 }
bd8289c1 2631
2c1f73ee
VZ
2632 size_t count = m_lines.GetCount();
2633 for (size_t i = 0; i < count; i++)
0208334d 2634 {
f6bcfd97 2635 wxListLineData *line = &m_lines[i];
2c1f73ee 2636 wxListItemDataList::Node *n = line->m_items.Item( col );
63852e78
RR
2637 if (n)
2638 {
2c1f73ee 2639 wxListItemData *item = n->GetData();
63852e78
RR
2640 item->SetSize( width, -1 );
2641 }
0208334d 2642 }
bd8289c1 2643
f6bcfd97
BP
2644 wxListHeaderWindow *headerWin = ((wxListCtrl*) GetParent())->m_headerWin;
2645 if ( headerWin )
2646 headerWin->m_dirty = TRUE;
e1e955e1 2647}
c801d85f 2648
debe6624 2649void wxListMainWindow::GetColumn( int col, wxListItem &item )
c801d85f 2650{
24b9f055 2651 wxListHeaderDataList::Node *node = m_columns.Item( col );
63852e78
RR
2652 if (node)
2653 {
24b9f055 2654 wxListHeaderData *column = node->GetData();
63852e78
RR
2655 column->GetItem( item );
2656 }
2657 else
2658 {
2659 item.m_format = 0;
2660 item.m_width = 0;
54442116 2661 item.m_text = _T("");
63852e78
RR
2662 item.m_image = 0;
2663 item.m_data = 0;
2664 }
e1e955e1 2665}
c801d85f 2666
bd8289c1 2667int wxListMainWindow::GetColumnWidth( int col )
c801d85f 2668{
24b9f055
VZ
2669 wxListHeaderDataList::Node *node = m_columns.Item( col );
2670 wxCHECK_MSG( node, 0, _T("invalid column index") );
2671
2672 wxListHeaderData *column = node->GetData();
2673 return column->GetWidth();
e1e955e1 2674}
c801d85f 2675
e179bd65 2676int wxListMainWindow::GetColumnCount()
c801d85f 2677{
24b9f055 2678 return m_columns.GetCount();
e1e955e1 2679}
c801d85f 2680
e179bd65 2681int wxListMainWindow::GetCountPerPage()
c801d85f 2682{
92976ab6 2683 return m_visibleLines;
e1e955e1 2684}
c801d85f
KB
2685
2686void wxListMainWindow::SetItem( wxListItem &item )
2687{
92976ab6 2688 m_dirty = TRUE;
f6bcfd97 2689 if (item.m_itemId >= 0 && (size_t)item.m_itemId < m_lines.GetCount())
92976ab6 2690 {
f6bcfd97 2691 wxListLineData *line = &m_lines[(size_t)item.m_itemId];
92976ab6
RR
2692 if (m_mode & wxLC_REPORT) item.m_width = GetColumnWidth( item.m_col )-3;
2693 line->SetItem( item.m_col, item );
2694 }
e1e955e1 2695}
c801d85f 2696
debe6624 2697void wxListMainWindow::SetItemState( long item, long state, long stateMask )
c801d85f 2698{
54442116
VZ
2699 wxCHECK_RET( item >= 0 && (size_t)item < m_lines.GetCount(),
2700 _T("invalid list ctrl item index in SetItem") );
2701
92976ab6 2702 // m_dirty = TRUE; no recalcs needed
bd8289c1 2703
92976ab6 2704 wxListLineData *oldCurrent = m_current;
bd8289c1 2705
54442116 2706 if ( stateMask & wxLIST_STATE_FOCUSED )
c801d85f 2707 {
54442116
VZ
2708 wxListLineData *line = &m_lines[(size_t)item];
2709 if ( state & wxLIST_STATE_FOCUSED )
92976ab6 2710 {
54442116
VZ
2711 // don't do anything if this item is already focused
2712 if ( line != m_current )
92976ab6
RR
2713 {
2714 UnfocusLine( m_current );
2715 m_current = line;
2716 FocusLine( m_current );
54442116
VZ
2717 if ( (m_mode & wxLC_SINGLE_SEL) && oldCurrent )
2718 oldCurrent->Hilight( FALSE );
2719
92976ab6 2720 RefreshLine( m_current );
54442116
VZ
2721 if ( oldCurrent )
2722 RefreshLine( oldCurrent );
92976ab6 2723 }
54442116
VZ
2724 }
2725 else // unfocus
2726 {
2727 // don't do anything if this item is not focused
2728 if ( line == m_current )
bffa1c77 2729 {
54442116
VZ
2730 UnfocusLine( m_current );
2731 m_current = NULL;
bffa1c77 2732 }
92976ab6 2733 }
e1e955e1 2734 }
54442116
VZ
2735
2736 if ( stateMask & wxLIST_STATE_SELECTED )
2737 {
2738 bool on = (state & wxLIST_STATE_SELECTED) != 0;
2739 if (!on && (m_mode & wxLC_SINGLE_SEL))
2740 return;
2741
2742 wxListLineData *line = &m_lines[(size_t)item];
2743 if (m_mode & wxLC_SINGLE_SEL)
2744 {
2745 UnfocusLine( m_current );
2746 m_current = line;
2747 FocusLine( m_current );
2748 if (oldCurrent)
2749 oldCurrent->Hilight( FALSE );
2750 RefreshLine( m_current );
2751 if (oldCurrent)
2752 RefreshLine( oldCurrent );
2753 }
2754
2755 if (on != line->IsHilighted())
2756 {
2757 line->Hilight( on );
2758 RefreshLine( line );
2759 }
2760 }
e1e955e1 2761}
c801d85f 2762
debe6624 2763int wxListMainWindow::GetItemState( long item, long stateMask )
c801d85f 2764{
92976ab6
RR
2765 int ret = wxLIST_STATE_DONTCARE;
2766 if (stateMask & wxLIST_STATE_FOCUSED)
c801d85f 2767 {
f6bcfd97 2768 if (item >= 0 && (size_t)item < m_lines.GetCount())
92976ab6 2769 {
f6bcfd97 2770 wxListLineData *line = &m_lines[(size_t)item];
92976ab6
RR
2771 if (line == m_current) ret |= wxLIST_STATE_FOCUSED;
2772 }
e1e955e1 2773 }
92976ab6 2774 if (stateMask & wxLIST_STATE_SELECTED)
c801d85f 2775 {
f6bcfd97 2776 if (item >= 0 && (size_t)item < m_lines.GetCount())
92976ab6 2777 {
f6bcfd97 2778 wxListLineData *line = &m_lines[(size_t)item];
c9c1c60f 2779 if (line->IsHilighted()) ret |= wxLIST_STATE_SELECTED;
92976ab6 2780 }
e1e955e1 2781 }
92976ab6 2782 return ret;
e1e955e1 2783}
c801d85f
KB
2784
2785void wxListMainWindow::GetItem( wxListItem &item )
2786{
f6bcfd97 2787 if (item.m_itemId >= 0 && (size_t)item.m_itemId < m_lines.GetCount())
92976ab6 2788 {
f6bcfd97 2789 wxListLineData *line = &m_lines[(size_t)item.m_itemId];
92976ab6
RR
2790 line->GetItem( item.m_col, item );
2791 }
2792 else
2793 {
2794 item.m_mask = 0;
54442116 2795 item.m_text = _T("");
92976ab6
RR
2796 item.m_image = 0;
2797 item.m_data = 0;
2798 }
e1e955e1 2799}
c801d85f 2800
1370703e
VZ
2801int wxListMainWindow::GetItemCount() const
2802{
2803 return IsVirtual() ? m_countVirt : m_lines.GetCount();
2804}
2805
2806void wxListMainWindow::SetItemCount(long count)
c801d85f 2807{
1370703e
VZ
2808 m_countVirt = count;
2809
2810 Refresh();
e1e955e1 2811}
c801d85f 2812
0a240683 2813void wxListMainWindow::GetItemRect( long index, wxRect &rect )
c801d85f 2814{
f6bcfd97 2815 if (index >= 0 && (size_t)index < m_lines.GetCount())
92976ab6 2816 {
f6bcfd97 2817 m_lines[(size_t)index].GetRect( rect );
ea5ac909 2818 this->CalcScrolledPosition(rect.x,rect.y,&rect.x,&rect.y);
92976ab6
RR
2819 }
2820 else
2821 {
2822 rect.x = 0;
2823 rect.y = 0;
2824 rect.width = 0;
2825 rect.height = 0;
2826 }
e1e955e1 2827}
c801d85f 2828
e3e65dac
RR
2829bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos)
2830{
ea5ac909
VZ
2831 wxRect rect;
2832 this->GetItemRect(item,rect);
2833 pos.x=rect.x; pos.y=rect.y;
92976ab6 2834 return TRUE;
e1e955e1 2835}
e3e65dac 2836
e179bd65 2837int wxListMainWindow::GetSelectedItemCount()
c801d85f 2838{
92976ab6 2839 int ret = 0;
f6bcfd97 2840 for (size_t i = 0; i < m_lines.GetCount(); i++)
92976ab6 2841 {
f6bcfd97 2842 if (m_lines[i].IsHilighted()) ret++;
92976ab6
RR
2843 }
2844 return ret;
e1e955e1 2845}
c801d85f 2846
debe6624 2847void wxListMainWindow::SetMode( long mode )
c801d85f 2848{
92976ab6
RR
2849 m_dirty = TRUE;
2850 m_mode = mode;
bd8289c1 2851
92976ab6 2852 DeleteEverything();
bd8289c1 2853
92976ab6
RR
2854 if (m_mode & wxLC_REPORT)
2855 {
7c74e7fe
SC
2856#if wxUSE_GENERIC_LIST_EXTENSIONS
2857 m_xScroll = 15;
2858#else
92976ab6 2859 m_xScroll = 0;
7c74e7fe 2860#endif
92976ab6
RR
2861 m_yScroll = 15;
2862 }
2863 else
2864 {
2865 m_xScroll = 15;
2866 m_yScroll = 0;
2867 }
e1e955e1 2868}
c801d85f 2869
e179bd65 2870long wxListMainWindow::GetMode() const
c801d85f 2871{
63852e78 2872 return m_mode;
e1e955e1 2873}
c801d85f 2874
e179bd65 2875void wxListMainWindow::CalculatePositions()
c801d85f 2876{
1370703e
VZ
2877 if ( IsEmpty() )
2878 return;
e487524e 2879
1e6d9499 2880 wxClientDC dc( this );
92976ab6 2881 dc.SetFont( GetFont() );
c801d85f 2882
92976ab6
RR
2883 int iconSpacing = 0;
2884 if (m_mode & wxLC_ICON) iconSpacing = m_normal_spacing;
2885 if (m_mode & wxLC_SMALL_ICON) iconSpacing = m_small_spacing;
004fd0c8 2886
92976ab6
RR
2887 // we take the first line (which also can be an icon or
2888 // an a text item in wxLC_ICON and wxLC_LIST modes) to
2889 // measure the size of the line
004fd0c8 2890
92976ab6
RR
2891 int lineWidth = 0;
2892 int lineHeight = 0;
2893 int lineSpacing = 0;
c801d85f 2894
f6bcfd97 2895 wxListLineData *line = &m_lines[0];
92976ab6
RR
2896 line->CalculateSize( &dc, iconSpacing );
2897 int dummy = 0;
2898 line->GetSize( dummy, lineSpacing );
5d25c050 2899 lineSpacing += 1;
bd8289c1 2900
92976ab6
RR
2901 int clientWidth = 0;
2902 int clientHeight = 0;
bd8289c1 2903
92976ab6 2904 if (m_mode & wxLC_REPORT)
c801d85f 2905 {
08bf1d5d
RR
2906 // scroll one line per step
2907 m_yScroll = lineSpacing;
2c1f73ee 2908
92976ab6
RR
2909 int x = 4;
2910 int y = 1;
f6bcfd97 2911 int entireHeight = m_lines.GetCount() * lineSpacing + 2;
92976ab6 2912 int scroll_pos = GetScrollPos( wxVERTICAL );
7c74e7fe 2913#if wxUSE_GENERIC_LIST_EXTENSIONS
7c0ea335 2914 int x_scroll_pos = GetScrollPos( wxHORIZONTAL );
7c74e7fe 2915#else
08bf1d5d 2916 SetScrollbars( m_xScroll, m_yScroll, 0, entireHeight/m_yScroll +1, 0, scroll_pos, TRUE );
7c74e7fe 2917#endif
92976ab6
RR
2918 GetClientSize( &clientWidth, &clientHeight );
2919
7c74e7fe 2920 int entireWidth = 0 ;
f6bcfd97 2921 for (size_t j = 0; j < m_lines.GetCount(); j++)
92976ab6 2922 {
f6bcfd97 2923 wxListLineData *line = &m_lines[j];
92976ab6
RR
2924 line->CalculateSize( &dc, iconSpacing );
2925 line->SetPosition( &dc, x, y, clientWidth );
2926 int col_x = 2;
2927 for (int i = 0; i < GetColumnCount(); i++)
2928 {
2929 line->SetColumnPosition( i, col_x );
2930 col_x += GetColumnWidth( i );
2931 }
7c74e7fe
SC
2932 entireWidth = wxMax( entireWidth , col_x ) ;
2933#if wxUSE_GENERIC_LIST_EXTENSIONS
2934 line->SetPosition( &dc, x, y, col_x );
2935#endif
92976ab6 2936 y += lineSpacing; // one pixel blank line between items
92976ab6 2937 }
08bf1d5d 2938 m_visibleLines = clientHeight / lineSpacing;
7c74e7fe 2939#if wxUSE_GENERIC_LIST_EXTENSIONS
08bf1d5d 2940 SetScrollbars( m_xScroll, m_yScroll, entireWidth/m_xScroll +1, entireHeight/m_yScroll +1, x_scroll_pos , scroll_pos, TRUE );
7c74e7fe 2941#endif
e1e955e1 2942 }
92976ab6
RR
2943 else
2944 {
2945 // at first we try without any scrollbar. if the items don't
2946 // fit into the window, we recalculate after subtracting an
2947 // approximated 15 pt for the horizontal scrollbar
004fd0c8 2948
92976ab6 2949 GetSize( &clientWidth, &clientHeight );
bffa1c77 2950 clientHeight -= 4; // sunken frame
bd8289c1 2951
92976ab6 2952 int entireWidth = 0;
bd8289c1 2953
92976ab6 2954 for (int tries = 0; tries < 2; tries++)
e487524e 2955 {
92976ab6 2956 entireWidth = 0;
5d25c050
RR
2957 int x = 2;
2958 int y = 2;
92976ab6 2959 int maxWidth = 0;
0b855868 2960 m_visibleLines = 0;
bffa1c77 2961 int m_currentVisibleLines = 0;
f6bcfd97 2962 for (size_t i = 0; i < m_lines.GetCount(); i++)
92976ab6 2963 {
bffa1c77 2964 m_currentVisibleLines++;
f6bcfd97 2965 wxListLineData *line = &m_lines[i];
92976ab6
RR
2966 line->CalculateSize( &dc, iconSpacing );
2967 line->SetPosition( &dc, x, y, clientWidth );
2968 line->GetSize( lineWidth, lineHeight );
2969 if (lineWidth > maxWidth) maxWidth = lineWidth;
2970 y += lineSpacing;
bffa1c77
VZ
2971 if (m_currentVisibleLines > m_visibleLines)
2972 m_visibleLines = m_currentVisibleLines;
8b53e5a2 2973 if (y+lineSpacing-6 >= clientHeight) // -6 for earlier "line breaking"
92976ab6 2974 {
bffa1c77 2975 m_currentVisibleLines = 0;
e1208c31 2976 y = 2;
8b53e5a2
RR
2977 x += maxWidth+6;
2978 entireWidth += maxWidth+6;
92976ab6
RR
2979 maxWidth = 0;
2980 }
f6bcfd97 2981 if (i == m_lines.GetCount()-1) entireWidth += maxWidth;
92976ab6
RR
2982 if ((tries == 0) && (entireWidth > clientWidth))
2983 {
2984 clientHeight -= 15; // scrollbar height
0b855868 2985 m_visibleLines = 0;
bffa1c77 2986 m_currentVisibleLines = 0;
92976ab6
RR
2987 break;
2988 }
f6bcfd97 2989 if (i == m_lines.GetCount()-1) tries = 1; // everything fits, no second try required
92976ab6 2990 }
e487524e 2991 }
bffa1c77 2992
92976ab6
RR
2993 int scroll_pos = GetScrollPos( wxHORIZONTAL );
2994 SetScrollbars( m_xScroll, m_yScroll, (entireWidth+15) / m_xScroll, 0, scroll_pos, 0, TRUE );
e1e955e1 2995 }
e1e955e1 2996}
c801d85f 2997
f6bcfd97 2998void wxListMainWindow::RealizeChanges()
c801d85f 2999{
92976ab6
RR
3000 if (!m_current)
3001 {
1370703e 3002 if ( !IsEmpty() )
f6bcfd97 3003 m_current = &m_lines[0];
92976ab6
RR
3004 }
3005 if (m_current)
3006 {
3007 FocusLine( m_current );
f6bcfd97
BP
3008 // TODO: MSW doesn't automatically hilight the
3009 // first item.
3010 // if (m_mode & wxLC_SINGLE_SEL) m_current->Hilight( TRUE );
92976ab6 3011 }
e1e955e1 3012}
c801d85f 3013
19695fbd
VZ
3014long wxListMainWindow::GetNextItem( long item,
3015 int WXUNUSED(geometry),
3016 int state )
c801d85f 3017{
d1022fd6
VZ
3018 long ret = item,
3019 max = GetItemCount();
3020 wxCHECK_MSG( (ret == -1) || (ret < max), -1,
13771c08 3021 _T("invalid listctrl index in GetNextItem()") );
19695fbd
VZ
3022
3023 // notice that we start with the next item (or the first one if item == -1)
3024 // and this is intentional to allow writing a simple loop to iterate over
3025 // all selected items
d1022fd6
VZ
3026 ret++;
3027 if ( ret == max )
3028 {
3029 // this is not an error because the index was ok initially, just no
3030 // such item
3031 return -1;
3032 }
3033
f6bcfd97 3034 for (size_t i = (size_t)ret; i < m_lines.GetCount(); i++)
63852e78 3035 {
f6bcfd97 3036 wxListLineData *line = &m_lines[i];
19695fbd
VZ
3037 if ((state & wxLIST_STATE_FOCUSED) && (line == m_current))
3038 return ret;
3039 if ((state & wxLIST_STATE_SELECTED) && (line->IsHilighted()))
3040 return ret;
3041 if (!state)
3042 return ret;
63852e78 3043 ret++;
63852e78 3044 }
19695fbd 3045
63852e78 3046 return -1;
e1e955e1 3047}
c801d85f 3048
debe6624 3049void wxListMainWindow::DeleteItem( long index )
c801d85f 3050{
63852e78 3051 m_dirty = TRUE;
f6bcfd97 3052 if (index >= 0 && (size_t)index < m_lines.GetCount())
63852e78 3053 {
f6bcfd97 3054 wxListLineData *line = &m_lines[(size_t)index];
63852e78
RR
3055 if (m_current == line) m_current = (wxListLineData *) NULL;
3056 DeleteLine( line );
f6bcfd97 3057 m_lines.RemoveAt( (size_t)index );
63852e78 3058 }
e1e955e1 3059}
c801d85f 3060
debe6624 3061void wxListMainWindow::DeleteColumn( int col )
c801d85f 3062{
24b9f055
VZ
3063 wxListHeaderDataList::Node *node = m_columns.Item( col );
3064
3065 wxCHECK_RET( node, wxT("invalid column index in DeleteColumn()") );
bd8289c1 3066
5b077d48 3067 m_dirty = TRUE;
24b9f055 3068 m_columns.DeleteNode( node );
e1e955e1 3069}
c801d85f 3070
12c1b46a 3071void wxListMainWindow::DeleteAllItems()
c801d85f 3072{
5b077d48
RR
3073 m_dirty = TRUE;
3074 m_current = (wxListLineData *) NULL;
7c0ea335
VZ
3075
3076 // to make the deletion of all items faster, we don't send the
3077 // notifications in this case: this is compatible with wxMSW and
3078 // documented in DeleteAllItems() description
bffa1c77 3079
12c1b46a
RR
3080 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, GetParent()->GetId() );
3081 event.SetEventObject( GetParent() );
3082 GetParent()->GetEventHandler()->ProcessEvent( event );
7c0ea335 3083
5b077d48 3084 m_lines.Clear();
e1e955e1 3085}
c801d85f 3086
12c1b46a 3087void wxListMainWindow::DeleteEverything()
c801d85f 3088{
12c1b46a 3089 DeleteAllItems();
f6bcfd97 3090
5b077d48 3091 m_columns.Clear();
e1e955e1 3092}
c801d85f 3093
debe6624 3094void wxListMainWindow::EnsureVisible( long index )
c801d85f 3095{
dc6c62a9
RR
3096 // We have to call this here because the label in
3097 // question might just have been added and no screen
3098 // update taken place.
3099 if (m_dirty) wxYield();
3100
5b077d48
RR
3101 wxListLineData *oldCurrent = m_current;
3102 m_current = (wxListLineData *) NULL;
f6bcfd97
BP
3103 if (index >= 0 && (size_t)index < m_lines.GetCount())
3104 m_current = &m_lines[(size_t)index];
5b077d48
RR
3105 if (m_current) MoveToFocus();
3106 m_current = oldCurrent;
e1e955e1 3107}
c801d85f 3108
debe6624 3109long wxListMainWindow::FindItem(long start, const wxString& str, bool WXUNUSED(partial) )
c801d85f 3110{
5b077d48
RR
3111 long pos = start;
3112 wxString tmp = str;
3113 if (pos < 0) pos = 0;
3ca6a5f0 3114 for (size_t i = (size_t)pos; i < m_lines.GetCount(); i++)
5b077d48 3115 {
f6bcfd97 3116 wxListLineData *line = &m_lines[i];
54442116
VZ
3117 wxString s = line->GetText(0);
3118 if (s == tmp)
3119 return pos;
3120
5b077d48
RR
3121 pos++;
3122 }
3123 return -1;
e1e955e1 3124}
c801d85f 3125
debe6624 3126long wxListMainWindow::FindItem(long start, long data)
c801d85f 3127{
5b077d48
RR
3128 long pos = start;
3129 if (pos < 0) pos = 0;
3ca6a5f0 3130 for (size_t i = (size_t)pos; i < m_lines.GetCount(); i++)
5b077d48 3131 {
f6bcfd97 3132 wxListLineData *line = &m_lines[i];
5b077d48
RR
3133 wxListItem item;
3134 line->GetItem( 0, item );
3135 if (item.m_data == data) return pos;
5b077d48
RR
3136 pos++;
3137 }
3138 return -1;
e1e955e1 3139}
c801d85f 3140
debe6624 3141long wxListMainWindow::HitTest( int x, int y, int &flags )
c801d85f 3142{
aaef15bf 3143 CalcUnscrolledPosition( x, y, &x, &y );
e8741cca 3144
5b077d48 3145 int count = 0;
f6bcfd97 3146 for (size_t i = 0; i < m_lines.GetCount(); i++)
c801d85f 3147 {
f6bcfd97 3148 wxListLineData *line = &m_lines[i];
aaef15bf 3149 long ret = line->IsHit( x, y );
191ebf4d 3150 if (ret) // & flags) // No: flags is output-only so may be garbage at this point
5b077d48 3151 {
6f2a55e3 3152 flags = (int)ret;
5b077d48
RR
3153 return count;
3154 }
5b077d48 3155 count++;
e1e955e1 3156 }
5b077d48 3157 return -1;
e1e955e1 3158}
c801d85f
KB
3159
3160void wxListMainWindow::InsertItem( wxListItem &item )
3161{
5b077d48
RR
3162 m_dirty = TRUE;
3163 int mode = 0;
1370703e
VZ
3164 if (m_mode & wxLC_REPORT)
3165 mode = wxLC_REPORT;
3166 else if (m_mode & wxLC_LIST)
3167 mode = wxLC_LIST;
3168 else if (m_mode & wxLC_ICON)
3169 mode = wxLC_ICON;
3170 else if (m_mode & wxLC_SMALL_ICON)
3171 mode = wxLC_ICON; // no typo
3172 else
3173 {
3174 wxFAIL_MSG( _T("unknown mode") );
3175 }
004fd0c8 3176
5b077d48 3177 wxListLineData *line = new wxListLineData( this, mode, m_hilightBrush );
004fd0c8 3178
5b077d48
RR
3179 if (m_mode & wxLC_REPORT)
3180 {
3181 line->InitItems( GetColumnCount() );
3182 item.m_width = GetColumnWidth( 0 )-3;
3183 }
3184 else
3185 {
3186 line->InitItems( 1 );
3187 }
004fd0c8 3188
5b077d48 3189 line->SetItem( 0, item );
f6bcfd97 3190 if ((item.m_itemId >= 0) && ((size_t)item.m_itemId < m_lines.GetCount()))
5b077d48 3191 {
f6bcfd97 3192 m_lines.Insert( line, (size_t)item.m_itemId );
5b077d48
RR
3193 }
3194 else
3195 {
f6bcfd97 3196 m_lines.Add( line );
300aaa8f 3197 item.m_itemId = m_lines.GetCount()-1;
5b077d48 3198 }
e1e955e1 3199}
c801d85f 3200
debe6624 3201void wxListMainWindow::InsertColumn( long col, wxListItem &item )
c801d85f 3202{
5b077d48
RR
3203 m_dirty = TRUE;
3204 if (m_mode & wxLC_REPORT)
3db7be80 3205 {
54442116
VZ
3206 if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
3207 item.m_width = GetTextLength( item.m_text );
5b077d48
RR
3208 wxListHeaderData *column = new wxListHeaderData( item );
3209 if ((col >= 0) && (col < (int)m_columns.GetCount()))
3210 {
24b9f055
VZ
3211 wxListHeaderDataList::Node *node = m_columns.Item( col );
3212 m_columns.Insert( node, column );
5b077d48
RR
3213 }
3214 else
3215 {
3216 m_columns.Append( column );
3217 }
3db7be80 3218 }
e1e955e1 3219}
c801d85f
KB
3220
3221wxListCtrlCompare list_ctrl_compare_func_2;
3222long list_ctrl_compare_data;
3223
f6bcfd97 3224int LINKAGEMODE list_ctrl_compare_func_1( wxListLineData **arg1, wxListLineData **arg2 )
c801d85f 3225{
f6bcfd97
BP
3226 wxListLineData *line1 = *arg1;
3227 wxListLineData *line2 = *arg2;
5b077d48
RR
3228 wxListItem item;
3229 line1->GetItem( 0, item );
3230 long data1 = item.m_data;
3231 line2->GetItem( 0, item );
3232 long data2 = item.m_data;
3233 return list_ctrl_compare_func_2( data1, data2, list_ctrl_compare_data );
e1e955e1 3234}
c801d85f
KB
3235
3236void wxListMainWindow::SortItems( wxListCtrlCompare fn, long data )
3237{
5b077d48
RR
3238 list_ctrl_compare_func_2 = fn;
3239 list_ctrl_compare_data = data;
3240 m_lines.Sort( list_ctrl_compare_func_1 );
af7c1052 3241 m_dirty = TRUE;
e1e955e1 3242}
c801d85f 3243
7c74e7fe
SC
3244void wxListMainWindow::OnScroll(wxScrollWinEvent& event)
3245{
29149a64 3246 // FIXME
3a8c693a 3247#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
29149a64
VZ
3248 wxScrolledWindow::OnScroll(event);
3249#else
1e6feb95 3250 HandleOnScroll( event );
29149a64 3251#endif
30954328 3252
7c74e7fe
SC
3253#if wxUSE_GENERIC_LIST_EXTENSIONS
3254
3255 if (event.GetOrientation() == wxHORIZONTAL && ( m_mode & wxLC_REPORT ))
3256 {
bffa1c77
VZ
3257 wxListCtrl* lc = wxDynamicCast( GetParent() , wxListCtrl ) ;
3258 if ( lc )
3259 {
3260 lc->m_headerWin->Refresh() ;
7c74e7fe 3261#ifdef __WXMAC__
1e6feb95 3262 lc->m_headerWin->MacUpdateImmediately() ;
7c74e7fe 3263#endif
bffa1c77 3264 }
7c74e7fe
SC
3265 }
3266#endif
3267}
3268
c801d85f
KB
3269// -------------------------------------------------------------------------------------
3270// wxListItem
3271// -------------------------------------------------------------------------------------
3272
3273IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
3274
fd9811b1 3275wxListItem::wxListItem()
c801d85f 3276{
63852e78
RR
3277 m_mask = 0;
3278 m_itemId = 0;
3279 m_col = 0;
3280 m_state = 0;
3281 m_stateMask = 0;
3282 m_image = 0;
3283 m_data = 0;
3284 m_format = wxLIST_FORMAT_CENTRE;
3285 m_width = 0;
aaa37c0d
VZ
3286
3287 m_attr = NULL;
c801d85f
KB
3288}
3289
9b00bb16
RR
3290void wxListItem::Clear()
3291{
3292 m_mask = 0;
3293 m_itemId = 0;
3294 m_col = 0;
3295 m_state = 0;
3296 m_stateMask = 0;
3297 m_image = 0;
3298 m_data = 0;
3299 m_format = wxLIST_FORMAT_CENTRE;
3300 m_width = 0;
54442116 3301 m_text = _T("");
9b00bb16
RR
3302
3303 if (m_attr) delete m_attr;
3304 m_attr = NULL;
3305}
3306
3307void wxListItem::ClearAttributes()
3308{
3309 if (m_attr) delete m_attr;
3310 m_attr = NULL;
3311}
3312
c801d85f
KB
3313// -------------------------------------------------------------------------------------
3314// wxListEvent
3315// -------------------------------------------------------------------------------------
3316
92976ab6 3317IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
c801d85f 3318
8f79098a 3319wxListEvent::wxListEvent( wxEventType commandType, int id ):
92976ab6 3320 wxNotifyEvent( commandType, id )
c801d85f 3321{
5b077d48
RR
3322 m_code = 0;
3323 m_itemIndex = 0;
3324 m_oldItemIndex = 0;
3325 m_col = 0;
3326 m_cancelled = FALSE;
3327 m_pointDrag.x = 0;
3328 m_pointDrag.y = 0;
e1e955e1 3329}
c801d85f 3330
72a7edf0
RR
3331void wxListEvent::CopyObject(wxObject& object_dest) const
3332{
3333 wxListEvent *obj = (wxListEvent *)&object_dest;
3334
3335 wxNotifyEvent::CopyObject(object_dest);
3336
3337 obj->m_code = m_code;
3338 obj->m_itemIndex = m_itemIndex;
3339 obj->m_oldItemIndex = m_oldItemIndex;
3340 obj->m_col = m_col;
3341 obj->m_cancelled = m_cancelled;
3342 obj->m_pointDrag = m_pointDrag;
3343 obj->m_item.m_mask = m_item.m_mask;
3344 obj->m_item.m_itemId = m_item.m_itemId;
3345 obj->m_item.m_col = m_item.m_col;
3346 obj->m_item.m_state = m_item.m_state;
3347 obj->m_item.m_stateMask = m_item.m_stateMask;
3348 obj->m_item.m_text = m_item.m_text;
3349 obj->m_item.m_image = m_item.m_image;
3350 obj->m_item.m_data = m_item.m_data;
3351 obj->m_item.m_format = m_item.m_format;
3352 obj->m_item.m_width = m_item.m_width;
aaa37c0d
VZ
3353
3354 if ( m_item.HasAttributes() )
3355 {
3356 obj->m_item.SetTextColour(m_item.GetTextColour());
3357 }
72a7edf0
RR
3358}
3359
c801d85f
KB
3360// -------------------------------------------------------------------------------------
3361// wxListCtrl
3362// -------------------------------------------------------------------------------------
3363
3364IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
3365
3366BEGIN_EVENT_TABLE(wxListCtrl,wxControl)
3367 EVT_SIZE (wxListCtrl::OnSize)
53010e52 3368 EVT_IDLE (wxListCtrl::OnIdle)
c801d85f
KB
3369END_EVENT_TABLE()
3370
fd9811b1 3371wxListCtrl::wxListCtrl()
c801d85f 3372{
5b077d48
RR
3373 m_imageListNormal = (wxImageList *) NULL;
3374 m_imageListSmall = (wxImageList *) NULL;
3375 m_imageListState = (wxImageList *) NULL;
2e12c11a 3376 m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE;
5b077d48
RR
3377 m_mainWin = (wxListMainWindow*) NULL;
3378 m_headerWin = (wxListHeaderWindow*) NULL;
c801d85f
KB
3379}
3380
fd9811b1 3381wxListCtrl::~wxListCtrl()
c801d85f 3382{
2e12c11a
VS
3383 if (m_ownsImageListNormal) delete m_imageListNormal;
3384 if (m_ownsImageListSmall) delete m_imageListSmall;
3385 if (m_ownsImageListState) delete m_imageListState;
c801d85f
KB
3386}
3387
25e3a937
VZ
3388bool wxListCtrl::Create(wxWindow *parent,
3389 wxWindowID id,
3390 const wxPoint &pos,
3391 const wxSize &size,
3392 long style,
25e3a937 3393 const wxValidator &validator,
25e3a937 3394 const wxString &name)
c801d85f 3395{
5b077d48
RR
3396 m_imageListNormal = (wxImageList *) NULL;
3397 m_imageListSmall = (wxImageList *) NULL;
3398 m_imageListState = (wxImageList *) NULL;
2e12c11a 3399 m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE;
5b077d48
RR
3400 m_mainWin = (wxListMainWindow*) NULL;
3401 m_headerWin = (wxListHeaderWindow*) NULL;
bd8289c1 3402
25e3a937 3403 if ( !(style & (wxLC_REPORT | wxLC_LIST | wxLC_ICON)) )
5b077d48 3404 {
25e3a937 3405 style = style | wxLC_LIST;
5b077d48 3406 }
f6bcfd97 3407
098963c3 3408 bool ret = wxControl::Create( parent, id, pos, size, style, validator, name );
f6bcfd97
BP
3409
3410
25e3a937
VZ
3411 if (style & wxSUNKEN_BORDER)
3412 style -= wxSUNKEN_BORDER;
bd8289c1 3413
25e3a937 3414 m_mainWin = new wxListMainWindow( this, -1, wxPoint(0,0), size, style );
bd8289c1 3415
f03fc89f 3416 if (HasFlag(wxLC_REPORT))
ea451729 3417 {
5b077d48 3418 m_headerWin = new wxListHeaderWindow( this, -1, m_mainWin, wxPoint(0,0), wxSize(size.x,23), wxTAB_TRAVERSAL );
ea451729
RR
3419 if (HasFlag(wxLC_NO_HEADER))
3420 m_headerWin->Show( FALSE );
3421 }
5b077d48 3422 else
ea451729 3423 {
5b077d48 3424 m_headerWin = (wxListHeaderWindow *) NULL;
ea451729 3425 }
bd8289c1 3426
5b077d48 3427 return ret;
e1e955e1 3428}
c801d85f
KB
3429
3430void wxListCtrl::OnSize( wxSizeEvent &WXUNUSED(event) )
3431{
5b077d48 3432 /* handled in OnIdle */
bd8289c1 3433
5b077d48 3434 if (m_mainWin) m_mainWin->m_dirty = TRUE;
e1e955e1 3435}
c801d85f 3436
debe6624 3437void wxListCtrl::SetSingleStyle( long style, bool add )
c801d85f 3438{
f03fc89f 3439 long flag = GetWindowStyle();
bd8289c1 3440
5b077d48
RR
3441 if (add)
3442 {
3443 if (style & wxLC_MASK_TYPE) flag = flag & ~wxLC_MASK_TYPE;
3444 if (style & wxLC_MASK_ALIGN) flag = flag & ~wxLC_MASK_ALIGN;
3445 if (style & wxLC_MASK_SORT) flag = flag & ~wxLC_MASK_SORT;
3446 }
c801d85f 3447
5b077d48
RR
3448 if (add)
3449 {
3450 flag |= style;
3451 }
3452 else
3453 {
3454 if (flag & style) flag -= style;
3455 }
bd8289c1 3456
5b077d48 3457 SetWindowStyleFlag( flag );
e1e955e1 3458}
c801d85f 3459
debe6624 3460void wxListCtrl::SetWindowStyleFlag( long flag )
c801d85f 3461{
121a3581
RR
3462 if (m_mainWin)
3463 {
3464 m_mainWin->DeleteEverything();
c801d85f 3465
121a3581
RR
3466 int width = 0;
3467 int height = 0;
3468 GetClientSize( &width, &height );
c801d85f 3469
121a3581 3470 m_mainWin->SetMode( flag );
bd8289c1 3471
121a3581 3472 if (flag & wxLC_REPORT)
5b077d48 3473 {
121a3581 3474 if (!HasFlag(wxLC_REPORT))
5b077d48 3475 {
121a3581
RR
3476 if (!m_headerWin)
3477 {
004fd0c8 3478 m_headerWin = new wxListHeaderWindow( this, -1, m_mainWin,
bffa1c77
VZ
3479 wxPoint(0,0), wxSize(width,23), wxTAB_TRAVERSAL );
3480 if (HasFlag(wxLC_NO_HEADER))
3481 m_headerWin->Show( FALSE );
121a3581
RR
3482 }
3483 else
004fd0c8 3484 {
bffa1c77
VZ
3485 if (flag & wxLC_NO_HEADER)
3486 m_headerWin->Show( FALSE );
3487 else
8636aed8 3488 m_headerWin->Show( TRUE );
004fd0c8 3489 }
5b077d48
RR
3490 }
3491 }
121a3581 3492 else
5b077d48 3493 {
8636aed8 3494 if (HasFlag(wxLC_REPORT) && !(HasFlag(wxLC_NO_HEADER)))
121a3581
RR
3495 {
3496 m_headerWin->Show( FALSE );
3497 }
bffa1c77 3498 }
e1e955e1 3499 }
004fd0c8 3500
5b077d48 3501 wxWindow::SetWindowStyleFlag( flag );
e1e955e1 3502}
c801d85f 3503
e487524e 3504bool wxListCtrl::GetColumn(int col, wxListItem &item) const
c801d85f 3505{
5b077d48
RR
3506 m_mainWin->GetColumn( col, item );
3507 return TRUE;
e1e955e1 3508}
c801d85f 3509
debe6624 3510bool wxListCtrl::SetColumn( int col, wxListItem& item )
c801d85f 3511{
5b077d48
RR
3512 m_mainWin->SetColumn( col, item );
3513 return TRUE;
e1e955e1 3514}
c801d85f 3515
e487524e 3516int wxListCtrl::GetColumnWidth( int col ) const
c801d85f 3517{
5b077d48 3518 return m_mainWin->GetColumnWidth( col );
e1e955e1 3519}
c801d85f 3520
debe6624 3521bool wxListCtrl::SetColumnWidth( int col, int width )
c801d85f 3522{
5b077d48
RR
3523 m_mainWin->SetColumnWidth( col, width );
3524 return TRUE;
e1e955e1 3525}
c801d85f 3526
fd9811b1 3527int wxListCtrl::GetCountPerPage() const
c801d85f
KB
3528{
3529 return m_mainWin->GetCountPerPage(); // different from Windows ?
e1e955e1 3530}
c801d85f 3531
e487524e 3532bool wxListCtrl::GetItem( wxListItem &info ) const
c801d85f 3533{
5b077d48
RR
3534 m_mainWin->GetItem( info );
3535 return TRUE;
e1e955e1 3536}
c801d85f
KB
3537
3538bool wxListCtrl::SetItem( wxListItem &info )
3539{
5b077d48
RR
3540 m_mainWin->SetItem( info );
3541 return TRUE;
e1e955e1 3542}
c801d85f 3543
debe6624 3544long wxListCtrl::SetItem( long index, int col, const wxString& label, int imageId )
c801d85f 3545{
5b077d48
RR
3546 wxListItem info;
3547 info.m_text = label;
3548 info.m_mask = wxLIST_MASK_TEXT;
3549 info.m_itemId = index;
3550 info.m_col = col;
3551 if ( imageId > -1 )
3552 {
3553 info.m_image = imageId;
3554 info.m_mask |= wxLIST_MASK_IMAGE;
3555 };
3556 m_mainWin->SetItem(info);
3557 return TRUE;
e1e955e1 3558}
c801d85f 3559
e487524e 3560int wxListCtrl::GetItemState( long item, long stateMask ) const
c801d85f 3561{
5b077d48 3562 return m_mainWin->GetItemState( item, stateMask );
e1e955e1 3563}
c801d85f 3564
debe6624 3565bool wxListCtrl::SetItemState( long item, long state, long stateMask )
c801d85f 3566{
5b077d48
RR
3567 m_mainWin->SetItemState( item, state, stateMask );
3568 return TRUE;
e1e955e1 3569}
c801d85f 3570
debe6624 3571bool wxListCtrl::SetItemImage( long item, int image, int WXUNUSED(selImage) )
c801d85f 3572{
5b077d48
RR
3573 wxListItem info;
3574 info.m_image = image;
3575 info.m_mask = wxLIST_MASK_IMAGE;
3576 info.m_itemId = item;
3577 m_mainWin->SetItem( info );
3578 return TRUE;
e1e955e1 3579}
c801d85f 3580
e487524e 3581wxString wxListCtrl::GetItemText( long item ) const
c801d85f 3582{
5b077d48
RR
3583 wxListItem info;
3584 info.m_itemId = item;
3585 m_mainWin->GetItem( info );
3586 return info.m_text;
e1e955e1 3587}
c801d85f 3588
debe6624 3589void wxListCtrl::SetItemText( long item, const wxString &str )
c801d85f 3590{
5b077d48
RR
3591 wxListItem info;
3592 info.m_mask = wxLIST_MASK_TEXT;
3593 info.m_itemId = item;
3594 info.m_text = str;
3595 m_mainWin->SetItem( info );
e1e955e1 3596}
c801d85f 3597
e487524e 3598long wxListCtrl::GetItemData( long item ) const
c801d85f 3599{
5b077d48
RR
3600 wxListItem info;
3601 info.m_itemId = item;
3602 m_mainWin->GetItem( info );
3603 return info.m_data;
e1e955e1 3604}
c801d85f 3605
debe6624 3606bool wxListCtrl::SetItemData( long item, long data )
c801d85f 3607{
5b077d48
RR
3608 wxListItem info;
3609 info.m_mask = wxLIST_MASK_DATA;
3610 info.m_itemId = item;
3611 info.m_data = data;
3612 m_mainWin->SetItem( info );
3613 return TRUE;
e1e955e1 3614}
c801d85f 3615
0a240683 3616bool wxListCtrl::GetItemRect( long item, wxRect &rect, int WXUNUSED(code) ) const
c801d85f 3617{
5b077d48
RR
3618 m_mainWin->GetItemRect( item, rect );
3619 return TRUE;
e1e955e1 3620}
c801d85f 3621
e487524e 3622bool wxListCtrl::GetItemPosition( long item, wxPoint& pos ) const
c801d85f 3623{
5b077d48
RR
3624 m_mainWin->GetItemPosition( item, pos );
3625 return TRUE;
e1e955e1 3626}
c801d85f 3627
debe6624 3628bool wxListCtrl::SetItemPosition( long WXUNUSED(item), const wxPoint& WXUNUSED(pos) )
c801d85f 3629{
5b077d48 3630 return 0;
e1e955e1 3631}
c801d85f 3632
fd9811b1 3633int wxListCtrl::GetItemCount() const
c801d85f 3634{
5b077d48 3635 return m_mainWin->GetItemCount();
e1e955e1 3636}
c801d85f 3637
fd9811b1 3638int wxListCtrl::GetColumnCount() const
92976ab6 3639{
5b077d48 3640 return m_mainWin->GetColumnCount();
92976ab6
RR
3641}
3642
33d0b396
RR
3643void wxListCtrl::SetItemSpacing( int spacing, bool isSmall )
3644{
5b077d48 3645 m_mainWin->SetItemSpacing( spacing, isSmall );
e1e955e1 3646}
33d0b396 3647
e487524e 3648int wxListCtrl::GetItemSpacing( bool isSmall ) const
c801d85f 3649{
5b077d48 3650 return m_mainWin->GetItemSpacing( isSmall );
e1e955e1 3651}
c801d85f 3652
fd9811b1 3653int wxListCtrl::GetSelectedItemCount() const
c801d85f 3654{
5b077d48 3655 return m_mainWin->GetSelectedItemCount();
e1e955e1 3656}
c801d85f 3657
fd9811b1 3658wxColour wxListCtrl::GetTextColour() const
c801d85f 3659{
0530737d 3660 return GetForegroundColour();
e1e955e1 3661}
c801d85f 3662
0530737d 3663void wxListCtrl::SetTextColour(const wxColour& col)
c801d85f 3664{
0530737d 3665 SetForegroundColour(col);
e1e955e1 3666}
c801d85f 3667
fd9811b1 3668long wxListCtrl::GetTopItem() const
c801d85f 3669{
5b077d48 3670 return 0;
e1e955e1 3671}
c801d85f 3672
6de97a3b 3673long wxListCtrl::GetNextItem( long item, int geom, int state ) const
c801d85f 3674{
5b077d48 3675 return m_mainWin->GetNextItem( item, geom, state );
e1e955e1 3676}
c801d85f 3677
e487524e 3678wxImageList *wxListCtrl::GetImageList(int which) const
c801d85f 3679{
5b077d48
RR
3680 if (which == wxIMAGE_LIST_NORMAL)
3681 {
3682 return m_imageListNormal;
3683 }
3684 else if (which == wxIMAGE_LIST_SMALL)
3685 {
3686 return m_imageListSmall;
3687 }
3688 else if (which == wxIMAGE_LIST_STATE)
3689 {
3690 return m_imageListState;
3691 }
3692 return (wxImageList *) NULL;
e1e955e1 3693}
c801d85f 3694
debe6624 3695void wxListCtrl::SetImageList( wxImageList *imageList, int which )
c801d85f 3696{
2e12c11a
VS
3697 if ( which == wxIMAGE_LIST_NORMAL )
3698 {
3699 if (m_ownsImageListNormal) delete m_imageListNormal;
3700 m_imageListNormal = imageList;
3701 m_ownsImageListNormal = FALSE;
3702 }
3703 else if ( which == wxIMAGE_LIST_SMALL )
3704 {
3705 if (m_ownsImageListSmall) delete m_imageListSmall;
3706 m_imageListSmall = imageList;
3707 m_ownsImageListSmall = FALSE;
3708 }
3709 else if ( which == wxIMAGE_LIST_STATE )
3710 {
3711 if (m_ownsImageListState) delete m_imageListState;
3712 m_imageListState = imageList;
3713 m_ownsImageListState = FALSE;
3714 }
3715
5b077d48 3716 m_mainWin->SetImageList( imageList, which );
e1e955e1 3717}
c801d85f 3718
2e12c11a
VS
3719void wxListCtrl::AssignImageList(wxImageList *imageList, int which)
3720{
3721 SetImageList(imageList, which);
3722 if ( which == wxIMAGE_LIST_NORMAL )
3723 m_ownsImageListNormal = TRUE;
3724 else if ( which == wxIMAGE_LIST_SMALL )
3725 m_ownsImageListSmall = TRUE;
3726 else if ( which == wxIMAGE_LIST_STATE )
3727 m_ownsImageListState = TRUE;
3728}
3729
debe6624 3730bool wxListCtrl::Arrange( int WXUNUSED(flag) )
c801d85f 3731{
5b077d48 3732 return 0;
e1e955e1 3733}
c801d85f 3734
debe6624 3735bool wxListCtrl::DeleteItem( long item )
c801d85f 3736{
5b077d48
RR
3737 m_mainWin->DeleteItem( item );
3738 return TRUE;
e1e955e1 3739}
c801d85f 3740
fd9811b1 3741bool wxListCtrl::DeleteAllItems()
c801d85f 3742{
5b077d48
RR
3743 m_mainWin->DeleteAllItems();
3744 return TRUE;
e1e955e1 3745}
c801d85f 3746
4f22cf8d 3747bool wxListCtrl::DeleteAllColumns()
bd8289c1 3748{
24b9f055
VZ
3749 size_t count = m_mainWin->m_columns.GetCount();
3750 for ( size_t n = 0; n < count; n++ )
bd8289c1 3751 DeleteColumn(n);
bffa1c77 3752
5b077d48 3753 return TRUE;
4f22cf8d
RR
3754}
3755
3756void wxListCtrl::ClearAll()
3757{
5b077d48 3758 m_mainWin->DeleteEverything();
bd8289c1
VZ
3759}
3760
debe6624 3761bool wxListCtrl::DeleteColumn( int col )
c801d85f 3762{
5b077d48
RR
3763 m_mainWin->DeleteColumn( col );
3764 return TRUE;
e1e955e1 3765}
c801d85f 3766
e179bd65 3767void wxListCtrl::Edit( long item )
c801d85f 3768{
e179bd65 3769 m_mainWin->Edit( item );
e1e955e1 3770}
c801d85f 3771
debe6624 3772bool wxListCtrl::EnsureVisible( long item )
c801d85f 3773{
5b077d48
RR
3774 m_mainWin->EnsureVisible( item );
3775 return TRUE;
e1e955e1 3776}
c801d85f 3777
debe6624 3778long wxListCtrl::FindItem( long start, const wxString& str, bool partial )
c801d85f 3779{
5b077d48 3780 return m_mainWin->FindItem( start, str, partial );
e1e955e1 3781}
c801d85f 3782
debe6624 3783long wxListCtrl::FindItem( long start, long data )
c801d85f 3784{
5b077d48 3785 return m_mainWin->FindItem( start, data );
e1e955e1 3786}
c801d85f 3787
bd8289c1 3788long wxListCtrl::FindItem( long WXUNUSED(start), const wxPoint& WXUNUSED(pt),
debe6624 3789 int WXUNUSED(direction))
c801d85f 3790{
5b077d48 3791 return 0;
e1e955e1 3792}
c801d85f
KB
3793
3794long wxListCtrl::HitTest( const wxPoint &point, int &flags )
3795{
5b077d48 3796 return m_mainWin->HitTest( (int)point.x, (int)point.y, flags );
e1e955e1 3797}
c801d85f
KB
3798
3799long wxListCtrl::InsertItem( wxListItem& info )
3800{
5b077d48 3801 m_mainWin->InsertItem( info );
2ebcd5f5 3802 return info.m_itemId;
e1e955e1 3803}
c801d85f 3804
debe6624 3805long wxListCtrl::InsertItem( long index, const wxString &label )
c801d85f 3806{
51cc4dad
RR
3807 wxListItem info;
3808 info.m_text = label;
3809 info.m_mask = wxLIST_MASK_TEXT;
3810 info.m_itemId = index;
3811 return InsertItem( info );
e1e955e1 3812}
c801d85f 3813
debe6624 3814long wxListCtrl::InsertItem( long index, int imageIndex )
c801d85f 3815{
51cc4dad
RR
3816 wxListItem info;
3817 info.m_mask = wxLIST_MASK_IMAGE;
3818 info.m_image = imageIndex;
3819 info.m_itemId = index;
3820 return InsertItem( info );
e1e955e1 3821}
c801d85f 3822
debe6624 3823long wxListCtrl::InsertItem( long index, const wxString &label, int imageIndex )
c801d85f 3824{
51cc4dad
RR
3825 wxListItem info;
3826 info.m_text = label;
3827 info.m_image = imageIndex;
3828 info.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE;
3829 info.m_itemId = index;
3830 return InsertItem( info );
e1e955e1 3831}
c801d85f 3832
debe6624 3833long wxListCtrl::InsertColumn( long col, wxListItem &item )
c801d85f 3834{
d3e90957 3835 wxASSERT( m_headerWin );
51cc4dad 3836 m_mainWin->InsertColumn( col, item );
d3e90957 3837 m_headerWin->Refresh();
25e3a937 3838
51cc4dad 3839 return 0;
e1e955e1 3840}
c801d85f 3841
debe6624
JS
3842long wxListCtrl::InsertColumn( long col, const wxString &heading,
3843 int format, int width )
c801d85f 3844{
51cc4dad
RR
3845 wxListItem item;
3846 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
3847 item.m_text = heading;
3848 if (width >= -2)
3849 {
3850 item.m_mask |= wxLIST_MASK_WIDTH;
3851 item.m_width = width;
3852 }
3853 item.m_format = format;
c801d85f 3854
51cc4dad 3855 return InsertColumn( col, item );
e1e955e1 3856}
c801d85f 3857
debe6624 3858bool wxListCtrl::ScrollList( int WXUNUSED(dx), int WXUNUSED(dy) )
c801d85f 3859{
51cc4dad 3860 return 0;
e1e955e1 3861}
c801d85f
KB
3862
3863// Sort items.
3864// fn is a function which takes 3 long arguments: item1, item2, data.
3865// item1 is the long data associated with a first item (NOT the index).
3866// item2 is the long data associated with a second item (NOT the index).
3867// data is the same value as passed to SortItems.
3868// The return value is a negative number if the first item should precede the second
3869// item, a positive number of the second item should precede the first,
3870// or zero if the two items are equivalent.
3871// data is arbitrary data to be passed to the sort function.
3872
3873bool wxListCtrl::SortItems( wxListCtrlCompare fn, long data )
3874{
51cc4dad
RR
3875 m_mainWin->SortItems( fn, data );
3876 return TRUE;
e1e955e1 3877}
c801d85f 3878
e3e65dac 3879void wxListCtrl::OnIdle( wxIdleEvent &WXUNUSED(event) )
53010e52 3880{
51cc4dad 3881 if (!m_mainWin->m_dirty) return;
53010e52 3882
51cc4dad
RR
3883 int cw = 0;
3884 int ch = 0;
3885 GetClientSize( &cw, &ch );
bd8289c1 3886
51cc4dad
RR
3887 int x = 0;
3888 int y = 0;
3889 int w = 0;
3890 int h = 0;
bd8289c1 3891
8636aed8 3892 if (HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER))
51cc4dad
RR
3893 {
3894 m_headerWin->GetPosition( &x, &y );
3895 m_headerWin->GetSize( &w, &h );
3896 if ((x != 0) || (y != 0) || (w != cw) || (h != 23))
3897 m_headerWin->SetSize( 0, 0, cw, 23 );
3898
3899 m_mainWin->GetPosition( &x, &y );
3900 m_mainWin->GetSize( &w, &h );
3901 if ((x != 0) || (y != 24) || (w != cw) || (h != ch-24))
3902 m_mainWin->SetSize( 0, 24, cw, ch-24 );
3903 }
3904 else
3905 {
3906 m_mainWin->GetPosition( &x, &y );
3907 m_mainWin->GetSize( &w, &h );
3908 if ((x != 0) || (y != 24) || (w != cw) || (h != ch))
3909 m_mainWin->SetSize( 0, 0, cw, ch );
3910 }
bd8289c1 3911
51cc4dad
RR
3912 m_mainWin->CalculatePositions();
3913 m_mainWin->RealizeChanges();
3914 m_mainWin->m_dirty = FALSE;
3915 m_mainWin->Refresh();
f6bcfd97
BP
3916
3917 if ( m_headerWin && m_headerWin->m_dirty )
3918 {
3919 m_headerWin->m_dirty = FALSE;
3920 m_headerWin->Refresh();
3921 }
e1e955e1 3922}
53010e52 3923
f03fc89f 3924bool wxListCtrl::SetBackgroundColour( const wxColour &colour )
bd8289c1 3925{
51cc4dad
RR
3926 if (m_mainWin)
3927 {
3928 m_mainWin->SetBackgroundColour( colour );
3929 m_mainWin->m_dirty = TRUE;
3930 }
004fd0c8 3931
f03fc89f 3932 return TRUE;
e4d06860
RR
3933}
3934
f03fc89f 3935bool wxListCtrl::SetForegroundColour( const wxColour &colour )
bd8289c1 3936{
f03fc89f
VZ
3937 if ( !wxWindow::SetForegroundColour( colour ) )
3938 return FALSE;
004fd0c8 3939
51cc4dad
RR
3940 if (m_mainWin)
3941 {
3942 m_mainWin->SetForegroundColour( colour );
3943 m_mainWin->m_dirty = TRUE;
3944 }
004fd0c8 3945
51cc4dad
RR
3946 if (m_headerWin)
3947 {
3948 m_headerWin->SetForegroundColour( colour );
3949 }
f03fc89f
VZ
3950
3951 return TRUE;
e4d06860 3952}
bd8289c1 3953
f03fc89f 3954bool wxListCtrl::SetFont( const wxFont &font )
bd8289c1 3955{
f03fc89f
VZ
3956 if ( !wxWindow::SetFont( font ) )
3957 return FALSE;
004fd0c8 3958
51cc4dad
RR
3959 if (m_mainWin)
3960 {
3961 m_mainWin->SetFont( font );
3962 m_mainWin->m_dirty = TRUE;
3963 }
004fd0c8 3964
51cc4dad
RR
3965 if (m_headerWin)
3966 {
3967 m_headerWin->SetFont( font );
3968 }
f03fc89f
VZ
3969
3970 return TRUE;
e4d06860 3971}
c801d85f 3972
efbb7287
VZ
3973#if wxUSE_DRAG_AND_DROP
3974
3975void wxListCtrl::SetDropTarget( wxDropTarget *dropTarget )
3976{
3977 m_mainWin->SetDropTarget( dropTarget );
3978}
3979
3980wxDropTarget *wxListCtrl::GetDropTarget() const
3981{
3982 return m_mainWin->GetDropTarget();
3983}
3984
3985#endif // wxUSE_DRAG_AND_DROP
3986
3987bool wxListCtrl::SetCursor( const wxCursor &cursor )
3988{
3989 return m_mainWin ? m_mainWin->wxWindow::SetCursor(cursor) : FALSE;
3990}
3991
3992wxColour wxListCtrl::GetBackgroundColour() const
3993{
3994 return m_mainWin ? m_mainWin->GetBackgroundColour() : wxColour();
3995}
3996
3997wxColour wxListCtrl::GetForegroundColour() const
3998{
3999 return m_mainWin ? m_mainWin->GetForegroundColour() : wxColour();
4000}
4001
4002bool wxListCtrl::DoPopupMenu( wxMenu *menu, int x, int y )
4003{
3a8c693a 4004#if wxUSE_MENUS
efbb7287 4005 return m_mainWin->PopupMenu( menu, x, y );
3a8c693a
VZ
4006#else
4007 return FALSE;
4008#endif // wxUSE_MENUS
efbb7287
VZ
4009}
4010
4011void wxListCtrl::SetFocus()
4012{
4013 /* The test in window.cpp fails as we are a composite
4014 window, so it checks against "this", but not m_mainWin. */
4015 if ( FindFocus() != this )
4016 m_mainWin->SetFocus();
4017}
1e6feb95 4018
2c1f73ee
VZ
4019// ----------------------------------------------------------------------------
4020// virtual list control support
4021// ----------------------------------------------------------------------------
4022
4023wxString wxListCtrl::OnGetItemText(long item, long col) const
4024{
4025 // this is a pure virtual function, in fact - which is not really pure
4026 // because the controls which are not virtual don't need to implement it
4027 wxFAIL_MSG( _T("not supposed to be called") );
4028
4029 return wxEmptyString;
4030}
4031
4032int wxListCtrl::OnGetItemImage(long item) const
4033{
4034 // same as above
4035 wxFAIL_MSG( _T("not supposed to be called") );
4036
4037 return -1;
4038}
4039
4040void wxListCtrl::SetItemCount(long count)
4041{
4042 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
4043
4044 m_mainWin->SetItemCount(count);
4045}
4046
1e6feb95 4047#endif // wxUSE_LISTCTRL