]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/listctrl_mac.cpp
mac cleanup
[wxWidgets.git] / src / mac / carbon / listctrl_mac.cpp
CommitLineData
e96bbb45 1/////////////////////////////////////////////////////////////////////////////
e409b62a 2// Name: src/mac/listctrl_mac.cpp
e96bbb45
KO
3// Purpose: wxListCtrl
4// Author: Julian Smart
5// Modified by: Agron Selimaj
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_LISTCTRL
28
e409b62a
PC
29#include "wx/listctrl.h"
30
e96bbb45 31#ifndef WX_PRECOMP
e96bbb45 32 #include "wx/intl.h"
e96bbb45
KO
33#endif
34
35#include "wx/mac/uma.h"
36
37#include "wx/imaglist.h"
e96bbb45 38#include "wx/sysopt.h"
7ac21a67 39#include "wx/timer.h"
e96bbb45 40
bc63f2c9
KO
41#include "wx/hashmap.h"
42
e96bbb45
KO
43#if wxUSE_EXTENDED_RTTI
44WX_DEFINE_FLAGS( wxListCtrlStyle )
45
46wxBEGIN_FLAGS( wxListCtrlStyle )
47 // new style border flags, we put them first to
48 // use them for streaming out
49 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
50 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
51 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
52 wxFLAGS_MEMBER(wxBORDER_RAISED)
53 wxFLAGS_MEMBER(wxBORDER_STATIC)
54 wxFLAGS_MEMBER(wxBORDER_NONE)
55
56 // old style border flags
57 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
58 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
59 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
60 wxFLAGS_MEMBER(wxRAISED_BORDER)
61 wxFLAGS_MEMBER(wxSTATIC_BORDER)
62 wxFLAGS_MEMBER(wxBORDER)
63
64 // standard window styles
65 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
66 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
67 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
68 wxFLAGS_MEMBER(wxWANTS_CHARS)
69 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
70 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
71 wxFLAGS_MEMBER(wxVSCROLL)
72 wxFLAGS_MEMBER(wxHSCROLL)
73
74 wxFLAGS_MEMBER(wxLC_LIST)
75 wxFLAGS_MEMBER(wxLC_REPORT)
76 wxFLAGS_MEMBER(wxLC_ICON)
77 wxFLAGS_MEMBER(wxLC_SMALL_ICON)
78 wxFLAGS_MEMBER(wxLC_ALIGN_TOP)
79 wxFLAGS_MEMBER(wxLC_ALIGN_LEFT)
80 wxFLAGS_MEMBER(wxLC_AUTOARRANGE)
81 wxFLAGS_MEMBER(wxLC_USER_TEXT)
82 wxFLAGS_MEMBER(wxLC_EDIT_LABELS)
83 wxFLAGS_MEMBER(wxLC_NO_HEADER)
84 wxFLAGS_MEMBER(wxLC_SINGLE_SEL)
85 wxFLAGS_MEMBER(wxLC_SORT_ASCENDING)
86 wxFLAGS_MEMBER(wxLC_SORT_DESCENDING)
87 wxFLAGS_MEMBER(wxLC_VIRTUAL)
88
89wxEND_FLAGS( wxListCtrlStyle )
90
91IMPLEMENT_DYNAMIC_CLASS_XTI(wxListCtrl, wxControl,"wx/listctrl.h")
92
93wxBEGIN_PROPERTIES_TABLE(wxListCtrl)
94 wxEVENT_PROPERTY( TextUpdated , wxEVT_COMMAND_TEXT_UPDATED , wxCommandEvent )
95
96 wxPROPERTY_FLAGS( WindowStyle , wxListCtrlStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
97wxEND_PROPERTIES_TABLE()
98
99wxBEGIN_HANDLERS_TABLE(wxListCtrl)
100wxEND_HANDLERS_TABLE()
101
102wxCONSTRUCTOR_5( wxListCtrl , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
103
104/*
6239ee05 105 TODO : Expose more information of a list's layout etc. via appropriate objects (¢ la NotebookPageInfo)
e96bbb45
KO
106*/
107#else
108IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
109#endif
110
111IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
112IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
113
114IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
115
bc63f2c9
KO
116WX_DECLARE_HASH_MAP( int, wxListItem*, wxIntegerHash, wxIntegerEqual, wxListItemList );
117
e96bbb45 118#include "wx/listimpl.cpp"
e9a0cc4b 119WX_DEFINE_LIST(wxColumnList)
e96bbb45 120
3fd864a1
KO
121// so we can check for column clicks
122static const EventTypeSpec eventList[] =
123{
124 { kEventClassControl, kEventControlHit },
e9a0cc4b 125 { kEventClassControl, kEventControlDraw }
3fd864a1
KO
126};
127
128static pascal OSStatus wxMacListCtrlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
129{
130 OSStatus result = eventNotHandledErr ;
131
132 wxMacCarbonEvent cEvent( event ) ;
133
134 ControlRef controlRef ;
135 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
136
137 wxListCtrl *window = (wxListCtrl*) data ;
138 wxListEvent le( wxEVT_COMMAND_LIST_COL_CLICK, window->GetId() );
139 le.SetEventObject( window );
0ed77610 140
3fd864a1
KO
141 switch ( GetEventKind( event ) )
142 {
143 // check if the column was clicked on and fire an event if so
144 case kEventControlHit :
145 {
146 ControlPartCode result = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart, typeControlPartCode) ;
147 if (result == kControlButtonPart){
148 DataBrowserPropertyID col;
149 GetDataBrowserSortProperty(controlRef, &col);
150 int column = col - kMinColumnId;
151 le.m_col = column;
3611cec2
KO
152 // FIXME: we can't use the sort property for virtual listctrls
153 // so we need to find a better way to determine which column was clicked...
154 if (!window->IsVirtual())
155 window->GetEventHandler()->ProcessEvent( le );
3fd864a1
KO
156 }
157 result = CallNextEventHandler(handler, event);
0ed77610 158 break;
3fd864a1 159 }
e9a0cc4b 160 case kEventControlDraw:
b80e3a2a
RD
161 {
162 CGContextRef context = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, typeCGContextRef) ;
163 window->MacSetDrawingContext(context);
164 result = CallNextEventHandler(handler, event);
165 window->MacSetDrawingContext(NULL);
166 break;
167 }
3fd864a1
KO
168 default :
169 break ;
170 }
171
0ed77610 172
3fd864a1
KO
173 return result ;
174}
175
176DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacListCtrlEventHandler )
177
e96bbb45
KO
178class wxMacListCtrlItem : public wxMacListBoxItem
179{
180public:
181 wxMacListCtrlItem();
e330eb46 182
e96bbb45
KO
183 virtual void Notification(wxMacDataItemBrowserControl *owner ,
184 DataBrowserItemNotification message,
185 DataBrowserItemDataRef itemData ) const;
e330eb46 186
e96bbb45
KO
187 virtual void SetColumnInfo( unsigned int column, wxListItem* item );
188 virtual wxListItem* GetColumnInfo( unsigned int column );
189 virtual bool HasColumnInfo( unsigned int column );
e330eb46 190
e96bbb45 191 virtual void SetColumnTextValue( unsigned int column, const wxString& text );
f8a98fa2 192 virtual wxString GetColumnTextValue( unsigned int column );
e330eb46 193
e96bbb45
KO
194 virtual int GetColumnImageValue( unsigned int column );
195 virtual void SetColumnImageValue( unsigned int column, int imageIndex );
493e7eb4 196
e96bbb45
KO
197 virtual ~wxMacListCtrlItem();
198protected:
199 wxListItemList m_rowItems;
200};
201
e9a0cc4b
KO
202DataBrowserDrawItemUPP gDataBrowserDrawItemUPP = NULL;
203//DataBrowserEditItemUPP gDataBrowserEditItemUPP = NULL;
204DataBrowserHitTestUPP gDataBrowserHitTestUPP = NULL;
205
e96bbb45
KO
206// TODO: Make a better name!!
207class wxMacDataBrowserListCtrlControl : public wxMacDataItemBrowserControl
208{
209public:
210 wxMacDataBrowserListCtrlControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style );
bf9a1615 211 wxMacDataBrowserListCtrlControl() {}
e96bbb45
KO
212 virtual ~wxMacDataBrowserListCtrlControl();
213
214 // create a list item (can be a subclass of wxMacListBoxItem)
215
9ce05df4 216 virtual wxMacDataItem* CreateItem();
e330eb46 217
e96bbb45
KO
218 virtual void MacInsertItem( unsigned int n, wxListItem* item );
219 virtual void MacSetColumnInfo( unsigned int row, unsigned int column, wxListItem* item );
220 virtual void MacGetColumnInfo( unsigned int row, unsigned int column, wxListItem& item );
221 virtual void UpdateState(wxMacDataItem* dataItem, wxListItem* item);
de387fc9 222 int GetFlags() { return m_flags; }
07977ff2 223
e96bbb45 224protected:
67650ea0
KO
225 // we need to override to provide specialized handling for virtual wxListCtrls
226 virtual OSStatus GetSetItemData(DataBrowserItemID itemID,
227 DataBrowserPropertyID property,
228 DataBrowserItemDataRef itemData,
229 Boolean changeValue );
230
231 virtual void ItemNotification(
232 DataBrowserItemID itemID,
233 DataBrowserItemNotification message,
234 DataBrowserItemDataRef itemData);
493e7eb4 235
67650ea0
KO
236 virtual Boolean CompareItems(DataBrowserItemID itemOneID,
237 DataBrowserItemID itemTwoID,
238 DataBrowserPropertyID sortProperty);
239
e9a0cc4b
KO
240 static pascal void DataBrowserDrawItemProc(ControlRef browser,
241 DataBrowserItemID item,
242 DataBrowserPropertyID property,
243 DataBrowserItemState itemState,
244 const Rect *theRect,
245 SInt16 gdDepth,
246 Boolean colorDevice);
0ed77610 247
e9a0cc4b
KO
248 virtual void DrawItem(DataBrowserItemID itemID,
249 DataBrowserPropertyID property,
250 DataBrowserItemState itemState,
251 const Rect *itemRect,
252 SInt16 gdDepth,
253 Boolean colorDevice);
254
255 static pascal Boolean DataBrowserEditTextProc(ControlRef browser,
256 DataBrowserItemID item,
257 DataBrowserPropertyID property,
258 CFStringRef theString,
259 Rect *maxEditTextRect,
260 Boolean *shrinkToFit);
261
89954433
VZ
262 static pascal Boolean DataBrowserHitTestProc(ControlRef WXUNUSED(browser),
263 DataBrowserItemID WXUNUSED(itemID),
264 DataBrowserPropertyID WXUNUSED(property),
265 const Rect *WXUNUSED(theRect),
266 const Rect *WXUNUSED(mouseRect)) { return true; }
e9a0cc4b
KO
267
268 virtual bool ConfirmEditText(DataBrowserItemID item,
269 DataBrowserPropertyID property,
270 CFStringRef theString,
271 Rect *maxEditTextRect,
272 Boolean *shrinkToFit);
273
0ed77610 274
e9a0cc4b 275
e96bbb45 276 wxClientDataType m_clientDataItemsType;
67650ea0 277 bool m_isVirtual;
de387fc9 278 int m_flags;
bf9a1615 279 DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacDataBrowserListCtrlControl)
e96bbb45
KO
280};
281
0ed77610 282class wxMacListCtrlEventDelegate : public wxEvtHandler
e9a0cc4b
KO
283{
284public:
285 wxMacListCtrlEventDelegate( wxListCtrl* list, int id );
286 virtual bool ProcessEvent( wxEvent& event );
0ed77610 287
e9a0cc4b
KO
288private:
289 wxListCtrl* m_list;
290 int m_id;
291};
292
293wxMacListCtrlEventDelegate::wxMacListCtrlEventDelegate( wxListCtrl* list, int id )
294{
295 m_list = list;
296 m_id = id;
297}
298
299bool wxMacListCtrlEventDelegate::ProcessEvent( wxEvent& event )
300{
301 // even though we use a generic list ctrl underneath, make sure
302 // we present ourselves as wxListCtrl.
303 event.SetEventObject( m_list );
304 event.SetId( m_id );
0ed77610 305
90347071
KO
306 if ( !event.IsKindOf( CLASSINFO( wxCommandEvent ) ) )
307 {
308 if (m_list->GetEventHandler()->ProcessEvent( event ))
309 return true;
0ed77610 310 }
e9a0cc4b
KO
311 return wxEvtHandler::ProcessEvent(event);
312}
e96bbb45 313
7ac21a67
KO
314//-----------------------------------------------------------------------------
315// wxListCtrlRenameTimer (internal)
316//-----------------------------------------------------------------------------
317
318class wxListCtrlRenameTimer: public wxTimer
319{
320private:
321 wxListCtrl *m_owner;
322
323public:
324 wxListCtrlRenameTimer( wxListCtrl *owner );
325 void Notify();
326};
327
328//-----------------------------------------------------------------------------
329// wxListCtrlTextCtrlWrapper: wraps a wxTextCtrl to make it work for inline editing
330//-----------------------------------------------------------------------------
331
332class wxListCtrlTextCtrlWrapper : public wxEvtHandler
333{
334public:
335 // NB: text must be a valid object but not Create()d yet
336 wxListCtrlTextCtrlWrapper(wxListCtrl *owner,
337 wxTextCtrl *text,
338 long itemEdit);
339
340 wxTextCtrl *GetText() const { return m_text; }
341
342 void AcceptChangesAndFinish();
343
344protected:
345 void OnChar( wxKeyEvent &event );
346 void OnKeyUp( wxKeyEvent &event );
347 void OnKillFocus( wxFocusEvent &event );
348
349 bool AcceptChanges();
350 void Finish();
351
352private:
353 wxListCtrl *m_owner;
354 wxTextCtrl *m_text;
355 wxString m_startValue;
356 long m_itemEdited;
357 bool m_finished;
358 bool m_aboutToFinish;
359
360 DECLARE_EVENT_TABLE()
361};
362
363//-----------------------------------------------------------------------------
364// wxListCtrlRenameTimer (internal)
365//-----------------------------------------------------------------------------
366
367wxListCtrlRenameTimer::wxListCtrlRenameTimer( wxListCtrl *owner )
368{
369 m_owner = owner;
370}
371
372void wxListCtrlRenameTimer::Notify()
373{
374 m_owner->OnRenameTimer();
375}
376
377//-----------------------------------------------------------------------------
378// wxListCtrlTextCtrlWrapper (internal)
379//-----------------------------------------------------------------------------
380
381BEGIN_EVENT_TABLE(wxListCtrlTextCtrlWrapper, wxEvtHandler)
382 EVT_CHAR (wxListCtrlTextCtrlWrapper::OnChar)
383 EVT_KEY_UP (wxListCtrlTextCtrlWrapper::OnKeyUp)
384 EVT_KILL_FOCUS (wxListCtrlTextCtrlWrapper::OnKillFocus)
385END_EVENT_TABLE()
386
387wxListCtrlTextCtrlWrapper::wxListCtrlTextCtrlWrapper(wxListCtrl *owner,
388 wxTextCtrl *text,
389 long itemEdit)
390 : m_startValue(owner->GetItemText(itemEdit)),
391 m_itemEdited(itemEdit)
392{
393 m_owner = owner;
394 m_text = text;
395 m_finished = false;
396 m_aboutToFinish = false;
397
398 wxRect rectLabel;
d2af7584 399 int offset = 8;
7ac21a67
KO
400 owner->GetItemRect(itemEdit, rectLabel);
401
402 m_text->Create(owner, wxID_ANY, m_startValue,
d2af7584
KO
403 wxPoint(rectLabel.x+offset,rectLabel.y),
404 wxSize(rectLabel.width-offset,rectLabel.height));
7ac21a67
KO
405 m_text->SetFocus();
406
407 m_text->PushEventHandler(this);
408}
409
410void wxListCtrlTextCtrlWrapper::Finish()
411{
412 if ( !m_finished )
413 {
414 m_finished = true;
415
416 m_text->RemoveEventHandler(this);
417 m_owner->FinishEditing(m_text);
418
419 wxPendingDelete.Append( this );
420 }
421}
422
423bool wxListCtrlTextCtrlWrapper::AcceptChanges()
424{
425 const wxString value = m_text->GetValue();
426
427 if ( value == m_startValue )
428 // nothing changed, always accept
429 return true;
430
431 if ( !m_owner->OnRenameAccept(m_itemEdited, value) )
432 // vetoed by the user
433 return false;
434
435 // accepted, do rename the item
436 m_owner->SetItemText(m_itemEdited, value);
437
438 return true;
439}
440
441void wxListCtrlTextCtrlWrapper::AcceptChangesAndFinish()
442{
443 m_aboutToFinish = true;
444
445 // Notify the owner about the changes
446 AcceptChanges();
447
448 // Even if vetoed, close the control (consistent with MSW)
449 Finish();
450}
451
452void wxListCtrlTextCtrlWrapper::OnChar( wxKeyEvent &event )
453{
454 switch ( event.m_keyCode )
455 {
456 case WXK_RETURN:
457 AcceptChangesAndFinish();
458 break;
459
460 case WXK_ESCAPE:
461 m_owner->OnRenameCancelled( m_itemEdited );
462 Finish();
463 break;
464
465 default:
466 event.Skip();
467 }
468}
469
470void wxListCtrlTextCtrlWrapper::OnKeyUp( wxKeyEvent &event )
471{
472 if (m_finished)
473 {
474 event.Skip();
475 return;
476 }
477
478 // auto-grow the textctrl:
479 wxSize parentSize = m_owner->GetSize();
480 wxPoint myPos = m_text->GetPosition();
481 wxSize mySize = m_text->GetSize();
482 int sx, sy;
483 m_text->GetTextExtent(m_text->GetValue() + _T("MM"), &sx, &sy);
484 if (myPos.x + sx > parentSize.x)
485 sx = parentSize.x - myPos.x;
486 if (mySize.x > sx)
487 sx = mySize.x;
488 m_text->SetSize(sx, wxDefaultCoord);
489
490 event.Skip();
491}
492
493void wxListCtrlTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
494{
495 if ( !m_finished && !m_aboutToFinish )
496 {
497 if ( !AcceptChanges() )
498 m_owner->OnRenameCancelled( m_itemEdited );
499
500 Finish();
501 }
502
503 // We must let the native text control handle focus
504 event.Skip();
505}
506
507BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
508 EVT_LEFT_DOWN(wxListCtrl::OnLeftDown)
509 EVT_LEFT_DCLICK(wxListCtrl::OnDblClick)
7e2ee0bf 510 EVT_MIDDLE_DOWN(wxListCtrl::OnMiddleDown)
ccea21cc 511 EVT_RIGHT_DOWN(wxListCtrl::OnRightDown)
b3ff5a47 512 EVT_CHAR(wxListCtrl::OnChar)
7ac21a67
KO
513END_EVENT_TABLE()
514
e96bbb45
KO
515// ============================================================================
516// implementation
517// ============================================================================
518
519wxMacListControl* wxListCtrl::GetPeer() const
520{
bf9a1615
SC
521 wxMacDataBrowserListCtrlControl *lb = wxDynamicCast(m_peer,wxMacDataBrowserListCtrlControl);
522 return lb ? wx_static_cast(wxMacListControl*,lb) : 0 ;
e96bbb45
KO
523}
524
525// ----------------------------------------------------------------------------
526// wxListCtrl construction
527// ----------------------------------------------------------------------------
528
529void wxListCtrl::Init()
530{
531 m_imageListNormal = NULL;
532 m_imageListSmall = NULL;
533 m_imageListState = NULL;
493e7eb4 534
e96bbb45
KO
535 // keep track of if we created our own image lists, or if they were assigned
536 // to us.
537 m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = false;
538 m_colCount = 0;
539 m_count = 0;
540 m_textCtrl = NULL;
541 m_genericImpl = NULL;
542 m_dbImpl = NULL;
3fd864a1
KO
543 m_compareFunc = NULL;
544 m_compareFuncData = 0;
e9a0cc4b
KO
545 m_colsInfo = wxColumnList();
546 m_textColor = wxNullColour;
547 m_bgColor = wxNullColour;
7ac21a67
KO
548 m_textctrlWrapper = NULL;
549 m_current = -1;
550 m_renameTimer = new wxListCtrlRenameTimer( this );
e96bbb45
KO
551}
552
0100ee7d
RD
553class wxGenericListCtrlHook : public wxGenericListCtrl
554{
555public:
556 wxGenericListCtrlHook(wxListCtrl* parent,
557 wxWindowID id,
558 const wxPoint& pos,
559 const wxSize& size,
560 long style,
561 const wxValidator& validator,
562 const wxString& name)
e330eb46 563 : wxGenericListCtrl(parent, id, pos, size, style, validator, name),
0100ee7d
RD
564 m_nativeListCtrl(parent)
565 {
566 }
567
eea2724a 568protected:
0100ee7d
RD
569 virtual wxListItemAttr * OnGetItemAttr(long item) const
570 {
571 return m_nativeListCtrl->OnGetItemAttr(item);
572 }
573
574 virtual int OnGetItemImage(long item) const
575 {
576 return m_nativeListCtrl->OnGetItemImage(item);
577 }
578
579 virtual int OnGetItemColumnImage(long item, long column) const
580 {
581 return m_nativeListCtrl->OnGetItemColumnImage(item, column);
582 }
583
584 virtual wxString OnGetItemText(long item, long column) const
585 {
586 return m_nativeListCtrl->OnGetItemText(item, column);
587 }
588
0100ee7d
RD
589 wxListCtrl* m_nativeListCtrl;
590
591};
592
7ac21a67
KO
593void wxListCtrl::OnLeftDown(wxMouseEvent& event)
594{
595 if ( m_textctrlWrapper )
596 {
597 m_current = -1;
598 m_textctrlWrapper->AcceptChangesAndFinish();
599 }
0ed77610 600
7ac21a67
KO
601 int hitResult;
602 long current = HitTest(event.GetPosition(), hitResult);
603 if ((current == m_current) &&
604 (hitResult == wxLIST_HITTEST_ONITEM) &&
605 HasFlag(wxLC_EDIT_LABELS) )
606 {
607 m_renameTimer->Start( 100, true );
608 }
609 else
610 {
611 m_current = current;
612 }
613 event.Skip();
614}
615
b3ff5a47
KO
616void wxListCtrl::OnDblClick(wxMouseEvent& event)
617{
618 m_current = -1;
619 event.Skip();
620}
621
622#if wxABI_VERSION >= 20801
ccea21cc
KO
623void wxListCtrl::OnRightDown(wxMouseEvent& event)
624{
1a4b6b97
KO
625 if (m_dbImpl)
626 FireMouseEvent(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition());
7e2ee0bf
KO
627 event.Skip();
628}
629
630void wxListCtrl::OnMiddleDown(wxMouseEvent& event)
631{
1a4b6b97
KO
632 if (m_dbImpl)
633 FireMouseEvent(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, event.GetPosition());
7e2ee0bf
KO
634 event.Skip();
635}
636
637void wxListCtrl::FireMouseEvent(wxEventType eventType, wxPoint position)
638{
639 wxListEvent le( eventType, GetId() );
ccea21cc 640 le.SetEventObject(this);
7e2ee0bf 641 le.m_pointDrag = position;
ccea21cc 642 le.m_itemIndex = -1;
07977ff2 643
ccea21cc 644 int flags;
7e2ee0bf 645 long item = HitTest(position, flags);
ccea21cc
KO
646 if (flags & wxLIST_HITTEST_ONITEM)
647 {
648 le.m_itemIndex = item;
a44a646b
KO
649 le.m_item.m_itemId = item;
650 GetItem(le.m_item);
b3ff5a47 651 GetEventHandler()->ProcessEvent(le);
ccea21cc 652 }
ccea21cc
KO
653}
654
b3ff5a47 655void wxListCtrl::OnChar(wxKeyEvent& event)
7ac21a67 656{
6ff68ce9
KO
657
658
1a4b6b97 659 if (m_dbImpl)
b3ff5a47 660 {
1a4b6b97
KO
661 wxListEvent le( wxEVT_COMMAND_LIST_KEY_DOWN, GetId() );
662 le.SetEventObject(this);
663 le.m_code = event.GetKeyCode();
664 le.m_itemIndex = -1;
6ff68ce9
KO
665
666 if (m_current == -1)
667 {
668 // if m_current isn't set, check if there's been a selection
669 // made before continuing
670 m_current = GetNextItem(-1, wxLIST_NEXT_BELOW, wxLIST_STATE_SELECTED);
671 }
672
673 // We need to determine m_current ourselves when navigation keys
674 // are used. Note that PAGEUP and PAGEDOWN do not alter the current
675 // item on native Mac ListCtrl, so we only handle up and down keys.
676 switch ( event.GetKeyCode() )
677 {
678 case WXK_UP:
679 if ( m_current > 0 )
680 m_current -= 1;
681 else
682 m_current = 0;
683
684 break;
685
686 case WXK_DOWN:
687 if ( m_current < GetItemCount() - 1 )
688 m_current += 1;
689 else
690 m_current = GetItemCount() - 1;
691
692 break;
693 }
07977ff2 694
1a4b6b97 695 if (m_current != -1)
b3ff5a47 696 {
1a4b6b97 697 le.m_itemIndex = m_current;
a44a646b
KO
698 le.m_item.m_itemId = m_current;
699 GetItem(le.m_item);
1a4b6b97 700 GetEventHandler()->ProcessEvent(le);
b3ff5a47 701 }
b3ff5a47 702 }
de387fc9 703 event.Skip();
7ac21a67 704}
b3ff5a47 705#endif
7ac21a67 706
e96bbb45
KO
707bool wxListCtrl::Create(wxWindow *parent,
708 wxWindowID id,
709 const wxPoint& pos,
710 const wxSize& size,
711 long style,
712 const wxValidator& validator,
713 const wxString& name)
714{
715
716 // for now, we'll always use the generic list control for ICON and LIST views,
717 // because they dynamically change the number of columns on resize.
718 // Also, allow the user to set it to use the list ctrl as well.
e330eb46 719 if ( (wxSystemOptions::HasOption( wxMAC_ALWAYS_USE_GENERIC_LISTCTRL )
e96bbb45 720 && (wxSystemOptions::GetOptionInt( wxMAC_ALWAYS_USE_GENERIC_LISTCTRL ) == 1)) ||
7ac21a67 721 (style & wxLC_ICON) || (style & wxLC_SMALL_ICON) || (style & wxLC_LIST) )
e96bbb45
KO
722 {
723 m_macIsUserPane = true;
e330eb46 724
d2af7584
KO
725 long paneStyle = style;
726 paneStyle &= ~wxSIMPLE_BORDER;
727 paneStyle &= ~wxDOUBLE_BORDER;
728 paneStyle &= ~wxSUNKEN_BORDER;
729 paneStyle &= ~wxRAISED_BORDER;
730 paneStyle &= ~wxSTATIC_BORDER;
731 if ( !wxWindow::Create(parent, id, pos, size, paneStyle | wxNO_BORDER, name) )
e96bbb45 732 return false;
f8a98fa2 733
ba3241e6
KO
734 // since the generic control is a child, make sure we position it at 0, 0
735 m_genericImpl = new wxGenericListCtrlHook(this, id, wxPoint(0, 0), size, style, validator, name);
e9a0cc4b 736 m_genericImpl->PushEventHandler( new wxMacListCtrlEventDelegate( this, GetId() ) );
e96bbb45
KO
737 return true;
738 }
e330eb46 739
e96bbb45
KO
740 else
741 {
742 m_macIsUserPane = false;
e0329d24 743 if ( !wxWindow::Create(parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), name) )
e96bbb45
KO
744 return false;
745 m_dbImpl = new wxMacDataBrowserListCtrlControl( this, pos, size, style );
746 m_peer = m_dbImpl;
0ed77610 747
e96bbb45 748 MacPostControlCreate( pos, size );
0ed77610 749
3fd864a1
KO
750 InstallControlEventHandler( m_peer->GetControlRef() , GetwxMacListCtrlEventHandlerUPP(),
751 GetEventTypeCount(eventList), eventList, this,
752 (EventHandlerRef *)&m_macListCtrlEventHandler);
e96bbb45 753 }
e330eb46 754
e96bbb45
KO
755 return true;
756}
757
758wxListCtrl::~wxListCtrl()
e330eb46 759{
e9a0cc4b
KO
760 if (m_genericImpl)
761 {
0ed77610 762 m_genericImpl->PopEventHandler(/* deleteHandler = */ true);
e9a0cc4b 763 }
0ed77610 764
e96bbb45
KO
765 if (m_ownsImageListNormal)
766 delete m_imageListNormal;
767 if (m_ownsImageListSmall)
768 delete m_imageListSmall;
769 if (m_ownsImageListState)
770 delete m_imageListState;
0ed77610 771
7ac21a67 772 delete m_renameTimer;
e96bbb45
KO
773}
774
775// ----------------------------------------------------------------------------
776// set/get/change style
777// ----------------------------------------------------------------------------
778
779// Add or remove a single window style
780void wxListCtrl::SetSingleStyle(long style, bool add)
781{
782 long flag = GetWindowStyleFlag();
783
784 // Get rid of conflicting styles
785 if ( add )
786 {
787 if ( style & wxLC_MASK_TYPE)
788 flag = flag & ~wxLC_MASK_TYPE;
789 if ( style & wxLC_MASK_ALIGN )
790 flag = flag & ~wxLC_MASK_ALIGN;
791 if ( style & wxLC_MASK_SORT )
792 flag = flag & ~wxLC_MASK_SORT;
793 }
794
795 if ( add )
796 flag |= style;
797 else
798 flag &= ~style;
799
800 SetWindowStyleFlag(flag);
801}
802
803// Set the whole window style
804void wxListCtrl::SetWindowStyleFlag(long flag)
805{
806 if ( flag != m_windowStyle )
807 {
808 m_windowStyle = flag;
809
e330eb46
VZ
810 if (m_genericImpl)
811 {
e96bbb45
KO
812 m_genericImpl->SetWindowStyleFlag(flag);
813 }
814
815 Refresh();
816 }
817}
818
e330eb46
VZ
819void wxListCtrl::DoSetSize( int x, int y, int width, int height, int sizeFlags )
820{
e96bbb45 821 wxControl::DoSetSize(x, y, width, height, sizeFlags);
e330eb46 822
e96bbb45 823 if (m_genericImpl)
ba3241e6 824 m_genericImpl->SetSize(0, 0, width, height, sizeFlags);
f0ed40ad
KO
825
826 // determine if we need a horizontal scrollbar, and add it if so
827 if (m_dbImpl)
828 {
829 int totalWidth = 0;
830 for (int column = 0; column < GetColumnCount(); column++)
831 {
832 totalWidth += m_dbImpl->GetColumnWidth( column );
833 }
834
de387fc9
KO
835 if ( !(m_dbImpl->GetFlags() & wxHSCROLL) )
836 {
837 Boolean vertScrollBar;
838 GetDataBrowserHasScrollBars( m_dbImpl->GetControlRef(), NULL, &vertScrollBar );
839 if (totalWidth > width)
840 SetDataBrowserHasScrollBars( m_dbImpl->GetControlRef(), true, vertScrollBar );
841 else
842 SetDataBrowserHasScrollBars( m_dbImpl->GetControlRef(), false, vertScrollBar );
843 }
f0ed40ad 844 }
e96bbb45
KO
845}
846
a6c82d64
KO
847wxSize wxListCtrl::DoGetBestSize() const
848{
a6c82d64
KO
849 return wxWindow::DoGetBestSize();
850}
851
54eb75b5
RD
852bool wxListCtrl::SetFont(const wxFont& font)
853{
e9a0cc4b 854 bool rv = true;
54eb75b5
RD
855 rv = wxControl::SetFont(font);
856 if (m_genericImpl)
857 rv = m_genericImpl->SetFont(font);
858 return rv;
859}
860
861bool wxListCtrl::SetForegroundColour(const wxColour& colour)
862{
e9a0cc4b 863 bool rv = true;
54eb75b5
RD
864 if (m_genericImpl)
865 rv = m_genericImpl->SetForegroundColour(colour);
e9a0cc4b
KO
866 if (m_dbImpl)
867 SetTextColour(colour);
54eb75b5
RD
868 return rv;
869}
870
871bool wxListCtrl::SetBackgroundColour(const wxColour& colour)
872{
e9a0cc4b 873 bool rv = true;
54eb75b5
RD
874 if (m_genericImpl)
875 rv = m_genericImpl->SetBackgroundColour(colour);
e9a0cc4b
KO
876 if (m_dbImpl)
877 m_bgColor = colour;
54eb75b5
RD
878 return rv;
879}
880
e9a0cc4b
KO
881wxColour wxListCtrl::GetBackgroundColour()
882{
883 if (m_genericImpl)
884 return m_genericImpl->GetBackgroundColour();
885 if (m_dbImpl)
886 return m_bgColor;
0ed77610 887
e9a0cc4b
KO
888 return wxNullColour;
889}
890
e96bbb45
KO
891// ----------------------------------------------------------------------------
892// accessors
893// ----------------------------------------------------------------------------
894
895// Gets information about this column
896bool wxListCtrl::GetColumn(int col, wxListItem& item) const
897{
898 if (m_genericImpl)
899 return m_genericImpl->GetColumn(col, item);
900
901 bool success = true;
e330eb46 902
e9a0cc4b 903 if (m_dbImpl)
e96bbb45 904 {
e9a0cc4b
KO
905 wxColumnList::compatibility_iterator node = m_colsInfo.Item( col );
906 wxASSERT_MSG( node, _T("invalid column index in wxMacListCtrlItem") );
907 wxListItem* column = node->GetData();
0ed77610 908
e9a0cc4b
KO
909 long mask = column->GetMask();
910 if (mask & wxLIST_MASK_TEXT)
911 item.SetText(column->GetText());
912 if (mask & wxLIST_MASK_DATA)
913 item.SetData(column->GetData());
914 if (mask & wxLIST_MASK_IMAGE)
915 item.SetImage(column->GetImage());
916 if (mask & wxLIST_MASK_STATE)
917 item.SetState(column->GetState());
918 if (mask & wxLIST_MASK_FORMAT)
919 item.SetAlign(column->GetAlign());
920 if (mask & wxLIST_MASK_WIDTH)
921 item.SetWidth(column->GetWidth());
e96bbb45
KO
922 }
923
e96bbb45
KO
924 return success;
925}
926
927// Sets information about this column
928bool wxListCtrl::SetColumn(int col, wxListItem& item)
929{
930 if (m_genericImpl)
931 return m_genericImpl->SetColumn(col, item);
e330eb46 932
e9a0cc4b
KO
933 if (m_dbImpl)
934 {
f0ed40ad 935 long mask = item.GetMask();
e9a0cc4b
KO
936 if ( col >= (int)m_colsInfo.GetCount() )
937 {
938 wxListItem* listItem = new wxListItem(item);
939 m_colsInfo.Append( listItem );
940 }
941 else
942 {
943 wxListItem listItem;
944 GetColumn( col, listItem );
f0ed40ad 945
e9a0cc4b
KO
946 if (mask & wxLIST_MASK_TEXT)
947 listItem.SetText(item.GetText());
948 if (mask & wxLIST_MASK_DATA)
949 listItem.SetData(item.GetData());
950 if (mask & wxLIST_MASK_IMAGE)
951 listItem.SetImage(item.GetImage());
952 if (mask & wxLIST_MASK_STATE)
953 listItem.SetState(item.GetState());
954 if (mask & wxLIST_MASK_FORMAT)
955 listItem.SetAlign(item.GetAlign());
956 if (mask & wxLIST_MASK_WIDTH)
957 listItem.SetWidth(item.GetWidth());
958 }
0ed77610 959
e9a0cc4b
KO
960 // change the appearance in the databrowser.
961 DataBrowserListViewHeaderDesc columnDesc;
962 columnDesc.version=kDataBrowserListViewLatestHeaderDesc;
963 verify_noerr( m_dbImpl->GetHeaderDesc( kMinColumnId + col, &columnDesc ) );
0ed77610 964
e9a0cc4b
KO
965 /*
966 if (item.GetMask() & wxLIST_MASK_TEXT)
967 {
968 wxFontEncoding enc;
969 if ( m_font.Ok() )
970 enc = m_font.GetEncoding();
971 else
972 enc = wxLocale::GetSystemEncoding();
973 wxMacCFStringHolder cfTitle;
974 cfTitle.Assign( item.GetText() , enc );
0ed77610 975 if(columnDesc.titleString)
e9a0cc4b 976 CFRelease(columnDesc.titleString);
0ed77610 977 columnDesc.titleString = cfTitle;
e9a0cc4b
KO
978 }
979 */
0ed77610 980
e9a0cc4b
KO
981 if (item.GetMask() & wxLIST_MASK_IMAGE && item.GetImage() != -1 )
982 {
983 columnDesc.btnContentInfo.contentType = kControlContentIconRef;
984 wxImageList* imageList = GetImageList(wxIMAGE_LIST_SMALL);
985 if (imageList && imageList->GetImageCount() > 0 )
986 {
987 wxBitmap bmp = imageList->GetBitmap( item.GetImage() );
988 IconRef icon = bmp.GetBitmapData()->GetIconRef();
989 columnDesc.btnContentInfo.u.iconRef = icon;
990 }
991 }
0ed77610 992
e9a0cc4b
KO
993 verify_noerr( m_dbImpl->SetHeaderDesc( kMinColumnId + col, &columnDesc ) );
994
995 }
996 return true;
e96bbb45
KO
997}
998
999int wxListCtrl::GetColumnCount() const
1000{
1001 if (m_genericImpl)
1002 return m_genericImpl->GetColumnCount();
e330eb46
VZ
1003
1004 if (m_dbImpl)
1005 {
e96bbb45
KO
1006 UInt32 count;
1007 m_dbImpl->GetColumnCount(&count);
1008 return count;
1009 }
1010
1011 return m_colCount;
1012}
1013
1014// Gets the column width
1015int wxListCtrl::GetColumnWidth(int col) const
1016{
1017 if (m_genericImpl)
1018 return m_genericImpl->GetColumnWidth(col);
e330eb46
VZ
1019
1020 if (m_dbImpl)
1021 {
e96bbb45
KO
1022 return m_dbImpl->GetColumnWidth(col);
1023 }
1024
1025 return 0;
1026}
1027
1028// Sets the column width
1029bool wxListCtrl::SetColumnWidth(int col, int width)
1030{
1031 if (m_genericImpl)
1032 return m_genericImpl->SetColumnWidth(col, width);
e330eb46 1033
e330eb46
VZ
1034 if (m_dbImpl)
1035 {
54638f9e
KO
1036 int mywidth = width;
1037 if (width == wxLIST_AUTOSIZE || width == wxLIST_AUTOSIZE_USEHEADER)
1038 mywidth = 150;
e330eb46
VZ
1039
1040 if (col == -1)
1041 {
1042 for (int column = 0; column < GetColumnCount(); column++)
1043 {
f0ed40ad
KO
1044 wxListItem colInfo;
1045 GetColumn(col, colInfo);
f8a98fa2 1046
f0ed40ad
KO
1047 colInfo.SetWidth(width);
1048 SetColumn(col, colInfo);
f8a98fa2 1049
54638f9e
KO
1050 m_dbImpl->SetColumnWidth(col, mywidth);
1051 }
1052 }
f0ed40ad
KO
1053 else
1054 {
1055 wxListItem colInfo;
1056 GetColumn(col, colInfo);
07977ff2 1057
f0ed40ad
KO
1058 colInfo.SetWidth(width);
1059 SetColumn(col, colInfo);
54638f9e
KO
1060 m_dbImpl->SetColumnWidth(col, mywidth);
1061 }
1062 return true;
1063 }
e330eb46 1064
e96bbb45
KO
1065 return false;
1066}
1067
1068// Gets the number of items that can fit vertically in the
1069// visible area of the list control (list or report view)
1070// or the total number of items in the list control (icon
1071// or small icon view)
1072int wxListCtrl::GetCountPerPage() const
1073{
1074 if (m_genericImpl)
1075 return m_genericImpl->GetCountPerPage();
e330eb46
VZ
1076
1077 if (m_dbImpl)
1078 {
dcd79bff
KO
1079 UInt16 height = 1;
1080 m_dbImpl->GetDefaultRowHeight( &height );
1081 if (height > 0)
1082 return GetClientSize().y / height;
e96bbb45 1083 }
e330eb46 1084
e96bbb45
KO
1085 return 1;
1086}
1087
1088// Gets the edit control for editing labels.
1089wxTextCtrl* wxListCtrl::GetEditControl() const
1090{
1091 if (m_genericImpl)
1092 return m_genericImpl->GetEditControl();
e330eb46 1093
e96bbb45
KO
1094 return NULL;
1095}
1096
1097// Gets information about the item
1098bool wxListCtrl::GetItem(wxListItem& info) const
1099{
1100 if (m_genericImpl)
1101 return m_genericImpl->GetItem(info);
e330eb46 1102
e96bbb45 1103 if (m_dbImpl)
5b2c1446
KO
1104 {
1105 if (!IsVirtual())
a44a646b 1106 {
ad31e6a2 1107 if (info.m_itemId >= 0 && info.m_itemId < GetItemCount())
8b375198 1108 {
a44a646b 1109 m_dbImpl->MacGetColumnInfo(info.m_itemId, info.m_col, info);
8b375198
JS
1110 if (info.GetMask() & wxLIST_MASK_STATE)
1111 {
1112 DataBrowserItemID id = (DataBrowserItemID)m_dbImpl->GetItemFromLine(info.m_itemId);
1113 if (IsDataBrowserItemSelected( m_dbImpl->GetControlRef(), id ))
1114 info.SetState(info.GetState() | wxLIST_STATE_SELECTED);
1115 }
1116 }
a44a646b 1117 }
5b2c1446
KO
1118 else
1119 {
ad31e6a2 1120 if (info.m_itemId >= 0 && info.m_itemId < GetItemCount())
4cd82e11 1121 {
ad31e6a2
KO
1122 info.SetText( OnGetItemText(info.m_itemId, info.m_col) );
1123 info.SetImage( OnGetItemColumnImage(info.m_itemId, info.m_col) );
1124 if (info.GetMask() & wxLIST_MASK_STATE)
1125 {
1126 if (IsDataBrowserItemSelected( m_dbImpl->GetControlRef(), info.m_itemId+1 ))
1127 info.SetState(info.GetState() | wxLIST_STATE_SELECTED);
1128 }
2f0b521e 1129
ad31e6a2
KO
1130 wxListItemAttr* attrs = OnGetItemAttr( info.m_itemId );
1131 if (attrs)
1132 {
1133 info.SetFont( attrs->GetFont() );
1134 info.SetBackgroundColour( attrs->GetBackgroundColour() );
1135 info.SetTextColour( attrs->GetTextColour() );
1136 }
5b2c1446
KO
1137 }
1138 }
1139 }
e96bbb45
KO
1140 bool success = true;
1141 return success;
1142}
1143
1144// Sets information about the item
1145bool wxListCtrl::SetItem(wxListItem& info)
1146{
1147 if (m_genericImpl)
1148 return m_genericImpl->SetItem(info);
1149
1150 if (m_dbImpl)
1151 m_dbImpl->MacSetColumnInfo( info.m_itemId, info.m_col, &info );
1152
1153 return true;
1154}
1155
1156long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId)
1157{
1158 if (m_genericImpl)
1159 return m_genericImpl->SetItem(index, col, label, imageId);
1160
1161 wxListItem info;
1162 info.m_text = label;
1163 info.m_mask = wxLIST_MASK_TEXT;
1164 info.m_itemId = index;
1165 info.m_col = col;
1166 if ( imageId > -1 )
1167 {
1168 info.m_image = imageId;
1169 info.m_mask |= wxLIST_MASK_IMAGE;
1170 }
1171 return SetItem(info);
1172}
1173
1174
1175// Gets the item state
1176int wxListCtrl::GetItemState(long item, long stateMask) const
1177{
1178 if (m_genericImpl)
1179 return m_genericImpl->GetItemState(item, stateMask);
e330eb46 1180
4cd82e11
KO
1181 if (m_dbImpl)
1182 {
1183 if ( HasFlag(wxLC_VIRTUAL) )
1184 {
1185 if (stateMask == wxLIST_STATE_SELECTED)
2f0b521e
VZ
1186 {
1187 if (IsDataBrowserItemSelected( m_dbImpl->GetControlRef(), item+1 ))
4cd82e11
KO
1188 return wxLIST_STATE_SELECTED;
1189 else
2f0b521e 1190 return 0;
4cd82e11
KO
1191 }
1192 }
1193 else
1194 {
1195 wxListItem info;
e96bbb45 1196
4cd82e11
KO
1197 info.m_mask = wxLIST_MASK_STATE;
1198 info.m_stateMask = stateMask;
1199 info.m_itemId = item;
e96bbb45 1200
4cd82e11
KO
1201 if (!GetItem(info))
1202 return 0;
e96bbb45 1203
4cd82e11
KO
1204 return info.m_state;
1205 }
1206 }
2f0b521e
VZ
1207
1208 return 0;
e96bbb45
KO
1209}
1210
1211// Sets the item state
1212bool wxListCtrl::SetItemState(long item, long state, long stateMask)
1213{
1214 if (m_genericImpl)
1215 return m_genericImpl->SetItemState(item, state, stateMask);
2f0b521e 1216
4cd82e11
KO
1217 if (m_dbImpl)
1218 {
1219 DataBrowserSetOption option = kDataBrowserItemsAdd;
6ff68ce9 1220 if ( (stateMask & wxLIST_STATE_SELECTED) && state == 0 )
4cd82e11 1221 option = kDataBrowserItemsRemove;
2f0b521e 1222
4cd82e11
KO
1223 if (item == -1)
1224 {
1225 if ( HasFlag(wxLC_VIRTUAL) )
1226 {
1227 wxMacDataItemBrowserSelectionSuppressor suppressor(m_dbImpl);
1228 m_dbImpl->SetSelectedAllItems(option);
1229 }
1230 else
1231 {
1232 for(int i = 0; i < GetItemCount();i++)
1233 {
1234 wxListItem info;
1235 info.m_itemId = i;
1236 info.m_mask = wxLIST_MASK_STATE;
1237 info.m_stateMask = stateMask;
1238 info.m_state = state;
1239 SetItem(info);
1240 }
1241 }
1242 }
1243 else
1244 {
1245 if ( HasFlag(wxLC_VIRTUAL) )
1246 {
1247 long itemID = item+1;
6ff68ce9
KO
1248 bool isSelected = IsDataBrowserItemSelected(m_dbImpl->GetControlRef(), (DataBrowserItemID)itemID );
1249 bool isSelectedState = (state == wxLIST_STATE_SELECTED);
1250
1251 // toggle the selection state if wxListInfo state and actual state don't match.
1252 if ( (stateMask & wxLIST_STATE_SELECTED) && isSelected != isSelectedState )
1253 {
4cd82e11
KO
1254 SetDataBrowserSelectedItems(m_dbImpl->GetControlRef(), 1, (DataBrowserItemID*)&itemID, option);
1255 }
6ff68ce9 1256 }
4cd82e11
KO
1257 else
1258 {
1259 wxListItem info;
1260 info.m_itemId = item;
1261 info.m_mask = wxLIST_MASK_STATE;
1262 info.m_stateMask = stateMask;
1263 info.m_state = state;
1264 return SetItem(info);
1265 }
1266 }
1267 }
1268 return true;
e96bbb45
KO
1269}
1270
1271// Sets the item image
1272bool wxListCtrl::SetItemImage(long item, int image, int WXUNUSED(selImage))
1273{
1274 return SetItemColumnImage(item, 0, image);
1275}
1276
1277// Sets the item image
1278bool wxListCtrl::SetItemColumnImage(long item, long column, int image)
1279{
1280 if (m_genericImpl)
1281 return m_genericImpl->SetItemColumnImage(item, column, image);
1282
1283 wxListItem info;
1284
1285 info.m_mask = wxLIST_MASK_IMAGE;
1286 info.m_image = image;
1287 info.m_itemId = item;
1288 info.m_col = column;
1289
1290 return SetItem(info);
1291}
1292
1293// Gets the item text
1294wxString wxListCtrl::GetItemText(long item) const
1295{
1296 if (m_genericImpl)
1297 return m_genericImpl->GetItemText(item);
e330eb46 1298
e96bbb45
KO
1299 wxListItem info;
1300
1301 info.m_mask = wxLIST_MASK_TEXT;
1302 info.m_itemId = item;
1303
1304 if (!GetItem(info))
1305 return wxEmptyString;
1306 return info.m_text;
1307}
1308
1309// Sets the item text
1310void wxListCtrl::SetItemText(long item, const wxString& str)
1311{
1312 if (m_genericImpl)
1313 return m_genericImpl->SetItemText(item, str);
e330eb46 1314
e96bbb45
KO
1315 wxListItem info;
1316
1317 info.m_mask = wxLIST_MASK_TEXT;
1318 info.m_itemId = item;
1319 info.m_text = str;
1320
1321 SetItem(info);
1322}
1323
1324// Gets the item data
1325long wxListCtrl::GetItemData(long item) const
1326{
1327 if (m_genericImpl)
1328 return m_genericImpl->GetItemData(item);
1329
1330 wxListItem info;
1331
1332 info.m_mask = wxLIST_MASK_DATA;
1333 info.m_itemId = item;
1334
1335 if (!GetItem(info))
1336 return 0;
1337 return info.m_data;
1338}
1339
1340// Sets the item data
9fcd0bf7 1341bool wxListCtrl::SetItemPtrData(long item, wxUIntPtr data)
e96bbb45
KO
1342{
1343 if (m_genericImpl)
1344 return m_genericImpl->SetItemData(item, data);
e330eb46 1345
e96bbb45
KO
1346 wxListItem info;
1347
1348 info.m_mask = wxLIST_MASK_DATA;
1349 info.m_itemId = item;
1350 info.m_data = data;
1351
1352 return SetItem(info);
1353}
1354
1355wxRect wxListCtrl::GetViewRect() const
1356{
1357 wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST),
1358 _T("wxListCtrl::GetViewRect() only works in icon mode") );
e330eb46 1359
e96bbb45
KO
1360 if (m_genericImpl)
1361 return m_genericImpl->GetViewRect();
e330eb46 1362
e96bbb45
KO
1363 wxRect rect;
1364 return rect;
1365}
1366
1367// Gets the item rectangle
1368bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const
1369{
1370 if (m_genericImpl)
1371 return m_genericImpl->GetItemRect(item, rect, code);
1372
3ce16a8e
KO
1373
1374 if (m_dbImpl)
1375 {
1376 DataBrowserItemID id;
1377 DataBrowserPropertyID col = kMinColumnId;
1378 Rect bounds;
1379 DataBrowserPropertyPart part = kDataBrowserPropertyEnclosingPart;
1380 if ( code == wxLIST_RECT_LABEL )
1381 part = kDataBrowserPropertyTextPart;
1382 else if ( code == wxLIST_RECT_ICON )
1383 part = kDataBrowserPropertyIconPart;
0ed77610 1384
3ce16a8e
KO
1385 if ( !(GetWindowStyleFlag() & wxLC_VIRTUAL) )
1386 {
1387 wxMacDataItem* thisItem = m_dbImpl->GetItemFromLine(item);
1388 id = (DataBrowserItemID) thisItem;
1389 }
1390 else
d2af7584 1391 id = item+1;
0ed77610 1392
3ce16a8e 1393 GetDataBrowserItemPartBounds( m_dbImpl->GetControlRef(), id, col, part, &bounds );
0ed77610 1394
3ce16a8e
KO
1395 rect.x = bounds.left;
1396 rect.y = bounds.top;
7ac21a67 1397 rect.width = bounds.right - bounds.left; //GetClientSize().x; // we need the width of the whole row, not just the item.
3ce16a8e 1398 rect.height = bounds.bottom - bounds.top;
7ac21a67 1399 //fprintf("id = %d, bounds = %d, %d, %d, %d\n", id, rect.x, rect.y, rect.width, rect.height);
3ce16a8e 1400 }
e330eb46 1401 return true;
e96bbb45
KO
1402}
1403
1404// Gets the item position
1405bool wxListCtrl::GetItemPosition(long item, wxPoint& pos) const
1406{
1407 if (m_genericImpl)
1408 return m_genericImpl->GetItemPosition(item, pos);
1409
1410 bool success = false;
0ed77610 1411
3ce16a8e
KO
1412 if (m_dbImpl)
1413 {
1414 wxRect itemRect;
1415 GetItemRect(item, itemRect);
1416 pos = itemRect.GetPosition();
1417 success = true;
1418 }
e96bbb45
KO
1419
1420 return success;
1421}
1422
1423// Sets the item position.
1424bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos)
1425{
1426 if (m_genericImpl)
1427 return m_genericImpl->SetItemPosition(item, pos);
1428
1429 return false;
1430}
1431
1432// Gets the number of items in the list control
1433int wxListCtrl::GetItemCount() const
1434{
1435 if (m_genericImpl)
1436 return m_genericImpl->GetItemCount();
1437
1438 if (m_dbImpl)
1439 return m_dbImpl->MacGetCount();
e330eb46 1440
e96bbb45
KO
1441 return m_count;
1442}
1443
72bc14da
RD
1444void wxListCtrl::SetItemSpacing( int spacing, bool isSmall )
1445{
1446 if (m_genericImpl)
1447 m_genericImpl->SetItemSpacing(spacing, isSmall);
1448}
1449
e96bbb45
KO
1450wxSize wxListCtrl::GetItemSpacing() const
1451{
1452 if (m_genericImpl)
1453 return m_genericImpl->GetItemSpacing();
1454
1455 return wxSize(0, 0);
1456}
1457
1458void wxListCtrl::SetItemTextColour( long item, const wxColour &col )
1459{
e330eb46
VZ
1460 if (m_genericImpl)
1461 {
e96bbb45 1462 m_genericImpl->SetItemTextColour(item, col);
67650ea0 1463 return;
e96bbb45 1464 }
e330eb46 1465
e96bbb45
KO
1466 wxListItem info;
1467 info.m_itemId = item;
1468 info.SetTextColour( col );
1469 SetItem( info );
1470}
1471
1472wxColour wxListCtrl::GetItemTextColour( long item ) const
1473{
1474 if (m_genericImpl)
1475 return m_genericImpl->GetItemTextColour(item);
e330eb46
VZ
1476
1477 if (m_dbImpl)
1478 {
e96bbb45
KO
1479 wxListItem info;
1480 if (GetItem(info))
1481 return info.GetTextColour();
1482 }
1483 return wxNullColour;
1484}
1485
1486void wxListCtrl::SetItemBackgroundColour( long item, const wxColour &col )
1487{
e330eb46
VZ
1488 if (m_genericImpl)
1489 {
e96bbb45
KO
1490 m_genericImpl->SetItemBackgroundColour(item, col);
1491 return;
1492 }
e330eb46 1493
e96bbb45
KO
1494 wxListItem info;
1495 info.m_itemId = item;
1496 info.SetBackgroundColour( col );
1497 SetItem( info );
1498}
1499
1500wxColour wxListCtrl::GetItemBackgroundColour( long item ) const
1501{
1502 if (m_genericImpl)
1503 return m_genericImpl->GetItemBackgroundColour(item);
e330eb46
VZ
1504
1505 if (m_dbImpl)
1506 {
e96bbb45
KO
1507 wxListItem info;
1508 if (GetItem(info))
1509 return info.GetBackgroundColour();
1510 }
1511 return wxNullColour;
1512}
1513
1514void wxListCtrl::SetItemFont( long item, const wxFont &f )
1515{
e330eb46
VZ
1516 if (m_genericImpl)
1517 {
e96bbb45
KO
1518 m_genericImpl->SetItemFont(item, f);
1519 return;
1520 }
1521
1522 wxListItem info;
1523 info.m_itemId = item;
1524 info.SetFont( f );
1525 SetItem( info );
1526}
1527
1528wxFont wxListCtrl::GetItemFont( long item ) const
1529{
1530 if (m_genericImpl)
1531 return m_genericImpl->GetItemFont(item);
e330eb46
VZ
1532
1533 if (m_dbImpl)
1534 {
e96bbb45
KO
1535 wxListItem info;
1536 if (GetItem(info))
1537 return info.GetFont();
1538 }
1539
1540 return wxNullFont;
1541}
1542
1543// Gets the number of selected items in the list control
1544int wxListCtrl::GetSelectedItemCount() const
1545{
1546 if (m_genericImpl)
1547 return m_genericImpl->GetSelectedItemCount();
1548
1549 if (m_dbImpl)
1550 return m_dbImpl->GetSelectedItemCount(NULL, true);
1551
1552 return 0;
1553}
1554
1555// Gets the text colour of the listview
1556wxColour wxListCtrl::GetTextColour() const
1557{
1558 if (m_genericImpl)
1559 return m_genericImpl->GetTextColour();
1560
1561 // TODO: we need owner drawn list items to customize text color.
1562 if (m_dbImpl)
e9a0cc4b 1563 return m_textColor;
493e7eb4 1564
e330eb46 1565 return wxNullColour;
e96bbb45
KO
1566}
1567
1568// Sets the text colour of the listview
1569void wxListCtrl::SetTextColour(const wxColour& col)
1570{
e330eb46
VZ
1571 if (m_genericImpl)
1572 {
e96bbb45
KO
1573 m_genericImpl->SetTextColour(col);
1574 return;
1575 }
e330eb46 1576
e9a0cc4b
KO
1577 if (m_dbImpl)
1578 m_textColor = col;
e96bbb45
KO
1579}
1580
1581// Gets the index of the topmost visible item when in
1582// list or report view
1583long wxListCtrl::GetTopItem() const
1584{
1585 if (m_genericImpl)
1586 return m_genericImpl->GetTopItem();
e330eb46 1587
02095058
KO
1588 if (m_dbImpl)
1589 {
1590 int flags = 0;
1591 long item = HitTest( wxPoint(1, 1), flags);
1592 if (flags == wxLIST_HITTEST_ONITEM)
1593 return item;
1594 }
1595
e96bbb45
KO
1596 return 0;
1597}
1598
1599// Searches for an item, starting from 'item'.
1600// 'geometry' is one of
1601// wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
1602// 'state' is a state bit flag, one or more of
1603// wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
1604// item can be -1 to find the first item that matches the
1605// specified flags.
1606// Returns the item or -1 if unsuccessful.
1607long wxListCtrl::GetNextItem(long item, int geom, int state) const
1608{
1609 if (m_genericImpl)
1610 return m_genericImpl->GetNextItem(item, geom, state);
1611
e5d3d8ad
KO
1612 // TODO: implement all geometry and state options?
1613 if ( m_dbImpl )
819a3b6f 1614 {
e5d3d8ad 1615 if ( geom == wxLIST_NEXT_ALL || geom == wxLIST_NEXT_BELOW )
819a3b6f 1616 {
e5d3d8ad
KO
1617 long count = m_dbImpl->MacGetCount() ;
1618 for ( long line = item + 1 ; line < count; line++ )
1619 {
255dcbd7
KO
1620 DataBrowserItemID id = line + 1;
1621 if ( !IsVirtual() )
1622 id = (DataBrowserItemID)m_dbImpl->GetItemFromLine(line);
07977ff2 1623
e5d3d8ad
KO
1624 if ( (state == wxLIST_STATE_DONTCARE ) )
1625 return line;
07977ff2 1626
255dcbd7 1627 if ( (state & wxLIST_STATE_SELECTED) && IsDataBrowserItemSelected(m_dbImpl->GetControlRef(), id ) )
e5d3d8ad
KO
1628 return line;
1629 }
1630 }
07977ff2 1631
6ff68ce9 1632 if ( geom == wxLIST_NEXT_ABOVE )
e5d3d8ad
KO
1633 {
1634 int item2 = item;
1635 if ( item2 == -1 )
1636 item2 = m_dbImpl->MacGetCount();
07977ff2 1637
e5d3d8ad
KO
1638 for ( long line = item2 - 1 ; line >= 0; line-- )
1639 {
07977ff2 1640 DataBrowserItemID id = line + 1;
255dcbd7
KO
1641 if ( !IsVirtual() )
1642 id = (DataBrowserItemID)m_dbImpl->GetItemFromLine(line);
07977ff2 1643
e5d3d8ad
KO
1644 if ( (state == wxLIST_STATE_DONTCARE ) )
1645 return line;
07977ff2 1646
255dcbd7 1647 if ( (state & wxLIST_STATE_SELECTED) && IsDataBrowserItemSelected(m_dbImpl->GetControlRef(), id ) )
e5d3d8ad
KO
1648 return line;
1649 }
819a3b6f 1650 }
819a3b6f
SC
1651 }
1652
e5d3d8ad 1653 return -1;
e96bbb45
KO
1654}
1655
1656
1657wxImageList *wxListCtrl::GetImageList(int which) const
1658{
1659 if (m_genericImpl)
1660 return m_genericImpl->GetImageList(which);
1661
1662 if ( which == wxIMAGE_LIST_NORMAL )
1663 {
1664 return m_imageListNormal;
1665 }
1666 else if ( which == wxIMAGE_LIST_SMALL )
1667 {
1668 return m_imageListSmall;
1669 }
1670 else if ( which == wxIMAGE_LIST_STATE )
1671 {
1672 return m_imageListState;
1673 }
1674 return NULL;
1675}
1676
1677void wxListCtrl::SetImageList(wxImageList *imageList, int which)
1678{
e330eb46
VZ
1679 if (m_genericImpl)
1680 {
e96bbb45
KO
1681 m_genericImpl->SetImageList(imageList, which);
1682 return;
1683 }
1684
e96bbb45
KO
1685 if ( which == wxIMAGE_LIST_NORMAL )
1686 {
1687 if (m_ownsImageListNormal) delete m_imageListNormal;
1688 m_imageListNormal = imageList;
1689 m_ownsImageListNormal = false;
1690 }
1691 else if ( which == wxIMAGE_LIST_SMALL )
1692 {
1693 if (m_ownsImageListSmall) delete m_imageListSmall;
1694 m_imageListSmall = imageList;
1695 m_ownsImageListSmall = false;
1696 }
1697 else if ( which == wxIMAGE_LIST_STATE )
1698 {
1699 if (m_ownsImageListState) delete m_imageListState;
1700 m_imageListState = imageList;
1701 m_ownsImageListState = false;
1702 }
1703}
1704
1705void wxListCtrl::AssignImageList(wxImageList *imageList, int which)
1706{
e330eb46
VZ
1707 if (m_genericImpl)
1708 {
e96bbb45
KO
1709 m_genericImpl->AssignImageList(imageList, which);
1710 return;
1711 }
1712
1713 SetImageList(imageList, which);
1714 if ( which == wxIMAGE_LIST_NORMAL )
1715 m_ownsImageListNormal = true;
1716 else if ( which == wxIMAGE_LIST_SMALL )
1717 m_ownsImageListSmall = true;
1718 else if ( which == wxIMAGE_LIST_STATE )
1719 m_ownsImageListState = true;
1720}
1721
1722// ----------------------------------------------------------------------------
1723// Operations
1724// ----------------------------------------------------------------------------
1725
1726// Arranges the items
1727bool wxListCtrl::Arrange(int flag)
1728{
1729 if (m_genericImpl)
1730 return m_genericImpl->Arrange(flag);
1731 return false;
1732}
1733
1734// Deletes an item
1735bool wxListCtrl::DeleteItem(long item)
1736{
1737 if (m_genericImpl)
1738 return m_genericImpl->DeleteItem(item);
e330eb46
VZ
1739
1740 if (m_dbImpl)
1741 {
e96bbb45
KO
1742 m_dbImpl->MacDelete(item);
1743 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ITEM, GetId() );
1744 event.SetEventObject( this );
1745 event.m_itemIndex = item;
493e7eb4 1746 GetEventHandler()->ProcessEvent( event );
e330eb46 1747
e96bbb45
KO
1748 }
1749 return true;
1750}
1751
1752// Deletes all items
1753bool wxListCtrl::DeleteAllItems()
1754{
1755 if (m_genericImpl)
1756 return m_genericImpl->DeleteAllItems();
e330eb46
VZ
1757
1758 if (m_dbImpl)
1759 {
e96bbb45
KO
1760 m_dbImpl->MacClear();
1761 wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, GetId() );
1762 event.SetEventObject( this );
e330eb46 1763 GetEventHandler()->ProcessEvent( event );
e96bbb45
KO
1764 }
1765 return true;
1766}
1767
1768// Deletes all items
1769bool wxListCtrl::DeleteAllColumns()
1770{
1771 if (m_genericImpl)
1772 return m_genericImpl->DeleteAllColumns();
e330eb46
VZ
1773
1774 if (m_dbImpl)
1775 {
e96bbb45
KO
1776 UInt32 cols;
1777 m_dbImpl->GetColumnCount(&cols);
e330eb46
VZ
1778 for (UInt32 col = 0; col < cols; col++)
1779 {
aac75444 1780 DeleteColumn(0);
e330eb46 1781 }
e96bbb45 1782 }
e330eb46 1783
e96bbb45
KO
1784 return true;
1785}
1786
1787// Deletes a column
1788bool wxListCtrl::DeleteColumn(int col)
1789{
1790 if (m_genericImpl)
1791 return m_genericImpl->DeleteColumn(col);
e330eb46
VZ
1792
1793 if (m_dbImpl)
1794 {
e96bbb45
KO
1795 OSStatus err = m_dbImpl->RemoveColumn(col);
1796 return err == noErr;
1797 }
e330eb46 1798
e96bbb45
KO
1799 return true;
1800}
1801
1802// Clears items, and columns if there are any.
1803void wxListCtrl::ClearAll()
1804{
e330eb46
VZ
1805 if (m_genericImpl)
1806 {
e96bbb45
KO
1807 m_genericImpl->ClearAll();
1808 return;
1809 }
e330eb46
VZ
1810
1811 if (m_dbImpl)
1812 {
54638f9e 1813 DeleteAllItems();
e96bbb45 1814 DeleteAllColumns();
54638f9e 1815 }
e96bbb45
KO
1816}
1817
1818wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass)
1819{
1820 if (m_genericImpl)
1821 return m_genericImpl->EditLabel(item, textControlClass);
e330eb46
VZ
1822
1823 if (m_dbImpl)
1824 {
7ac21a67
KO
1825 wxCHECK_MSG( (item >= 0) && ((long)item < GetItemCount()), NULL,
1826 wxT("wrong index in wxListCtrl::EditLabel()") );
1827
1828 wxASSERT_MSG( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)),
1829 wxT("EditLabel() needs a text control") );
1830
7ac21a67
KO
1831 wxListEvent le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, GetParent()->GetId() );
1832 le.SetEventObject( this );
1833 le.m_itemIndex = item;
1834 le.m_col = 0;
1835 GetItem( le.m_item );
1836
1837 if ( GetParent()->GetEventHandler()->ProcessEvent( le ) && !le.IsAllowed() )
1838 {
1839 // vetoed by user code
1840 return NULL;
1841 }
1842
1843 wxTextCtrl * const text = (wxTextCtrl *)textControlClass->CreateObject();
1844 m_textctrlWrapper = new wxListCtrlTextCtrlWrapper(this, text, item);
1845 return m_textctrlWrapper->GetText();
54638f9e 1846 }
e96bbb45
KO
1847 return NULL;
1848}
1849
1850// End label editing, optionally cancelling the edit
89954433 1851bool wxListCtrl::EndEditLabel(bool WXUNUSED(cancel))
e96bbb45
KO
1852{
1853 // TODO: generic impl. doesn't have this method - is it needed for us?
1854 if (m_genericImpl)
54638f9e 1855 return true; // m_genericImpl->EndEditLabel(cancel);
e330eb46 1856
54638f9e
KO
1857 if (m_dbImpl)
1858 verify_noerr( SetDataBrowserEditItem(m_dbImpl->GetControlRef(), kDataBrowserNoItem, kMinColumnId) );
1859 return true;
e96bbb45
KO
1860}
1861
1862// Ensures this item is visible
1863bool wxListCtrl::EnsureVisible(long item)
1864{
1865 if (m_genericImpl)
1866 return m_genericImpl->EnsureVisible(item);
e330eb46
VZ
1867
1868 if (m_dbImpl)
1869 {
e96bbb45
KO
1870 wxMacDataItem* dataItem = m_dbImpl->GetItemFromLine(item);
1871 m_dbImpl->RevealItem(dataItem, kDataBrowserRevealWithoutSelecting);
1872 }
e330eb46 1873
67650ea0 1874 return true;
e96bbb45
KO
1875}
1876
1877// Find an item whose label matches this string, starting from the item after 'start'
1878// or the beginning if 'start' is -1.
1879long wxListCtrl::FindItem(long start, const wxString& str, bool partial)
1880{
1881 if (m_genericImpl)
1882 return m_genericImpl->FindItem(start, str, partial);
1883
7fc5133e
RR
1884 wxString str_upper = str.Upper();
1885
1886 long idx = start;
1887 if (idx < 0)
1888 idx = 0;
1889 long count = GetItemCount();
1890
1891 while (idx < count)
1892 {
1893 wxString line_upper = GetItemText(idx).Upper();
1894 if (!partial)
1895 {
1896 if (line_upper == str_upper )
1897 return idx;
1898 }
1899 else
1900 {
1901 if (line_upper.find(str_upper) == 0)
1902 return idx;
1903 }
2f0b521e 1904
7fc5133e
RR
1905 idx++;
1906 };
1907
1908 return wxNOT_FOUND;
e96bbb45
KO
1909}
1910
1911// Find an item whose data matches this data, starting from the item after 'start'
1912// or the beginning if 'start' is -1.
1913long wxListCtrl::FindItem(long start, long data)
1914{
1915 if (m_genericImpl)
1916 return m_genericImpl->FindItem(start, data);
e330eb46 1917
7fc5133e
RR
1918 long idx = start;
1919 if (idx < 0)
1920 idx = 0;
e96bbb45
KO
1921 long count = GetItemCount();
1922
1923 while (idx < count)
1924 {
1925 if (GetItemData(idx) == data)
1926 return idx;
1927 idx++;
1928 };
1929
7fc5133e 1930 return wxNOT_FOUND;
e96bbb45
KO
1931}
1932
1933// Find an item nearest this position in the specified direction, starting from
1934// the item after 'start' or the beginning if 'start' is -1.
1935long wxListCtrl::FindItem(long start, const wxPoint& pt, int direction)
1936{
1937 if (m_genericImpl)
1938 return m_genericImpl->FindItem(start, pt, direction);
1939 return -1;
1940}
1941
1942// Determines which item (if any) is at the specified point,
1943// giving details in 'flags' (see wxLIST_HITTEST_... flags above)
1944long
1945wxListCtrl::HitTest(const wxPoint& point, int& flags, long *ptrSubItem) const
1946{
1947 if (m_genericImpl)
1948 return m_genericImpl->HitTest(point, flags, ptrSubItem);
1949
3ce16a8e
KO
1950 flags = wxLIST_HITTEST_NOWHERE;
1951 if (m_dbImpl)
1952 {
1953 int colHeaderHeight = 22; // TODO: Find a way to get this value from the db control?
1954 UInt16 rowHeight = 0;
1955 m_dbImpl->GetDefaultRowHeight(&rowHeight);
0ed77610 1956
3ce16a8e 1957 int y = point.y;
7ac21a67
KO
1958 // get the actual row by taking scroll position into account
1959 UInt32 offsetX, offsetY;
1960 m_dbImpl->GetScrollPosition( &offsetY, &offsetX );
1961 y += offsetY;
0ed77610 1962
3ce16a8e
KO
1963 if ( !(GetWindowStyleFlag() & wxLC_NO_HEADER) )
1964 y -= colHeaderHeight;
0ed77610 1965
d2af7584
KO
1966 if ( y < 0 )
1967 return -1;
f8a98fa2 1968
3ce16a8e
KO
1969 int row = y / rowHeight;
1970 DataBrowserItemID id;
1971 m_dbImpl->GetItemID( (DataBrowserTableViewRowIndex) row, &id );
0ed77610 1972
3ce16a8e
KO
1973 // TODO: Use GetDataBrowserItemPartBounds to return if we are in icon or label
1974 if ( !(GetWindowStyleFlag() & wxLC_VIRTUAL ) )
1975 {
1976 wxMacListCtrlItem* lcItem;
1977 lcItem = (wxMacListCtrlItem*) id;
1978 if (lcItem)
1979 {
1980 flags = wxLIST_HITTEST_ONITEM;
1981 return row;
1982 }
1983 }
1984 else
1985 {
1986 if (row < GetItemCount() )
1987 {
1988 flags = wxLIST_HITTEST_ONITEM;
1989 return row;
1990 }
1991 }
0ed77610 1992
3ce16a8e 1993 }
e96bbb45
KO
1994 return -1;
1995}
1996
02095058
KO
1997int wxListCtrl::GetScrollPos(int orient) const
1998{
1999 if (m_genericImpl)
2000 return m_genericImpl->GetScrollPos(orient);
2f0b521e 2001
02095058
KO
2002 if (m_dbImpl)
2003 {
2004 UInt32 offsetX, offsetY;
2005 m_dbImpl->GetScrollPosition( &offsetY, &offsetX );
2006 if ( orient == wxHORIZONTAL )
2007 return offsetX;
2008 else
2009 return offsetY;
2010 }
2011
2012 return 0;
2013}
e96bbb45
KO
2014
2015// Inserts an item, returning the index of the new item if successful,
2016// -1 otherwise.
2017long wxListCtrl::InsertItem(wxListItem& info)
2018{
2019 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
2020
2021 if (m_genericImpl)
2022 return m_genericImpl->InsertItem(info);
e330eb46 2023
3611cec2 2024 if (m_dbImpl && !IsVirtual())
e330eb46 2025 {
e42667e5
KO
2026 int count = GetItemCount();
2027
2028 if (info.m_itemId > count)
2029 info.m_itemId = count;
e330eb46 2030
e96bbb45 2031 m_dbImpl->MacInsertItem(info.m_itemId, &info );
07977ff2 2032
e96bbb45
KO
2033 wxListEvent event( wxEVT_COMMAND_LIST_INSERT_ITEM, GetId() );
2034 event.SetEventObject( this );
2035 event.m_itemIndex = info.m_itemId;
e330eb46 2036 GetEventHandler()->ProcessEvent( event );
3611cec2 2037 return info.m_itemId;
e96bbb45 2038 }
3611cec2 2039 return -1;
e96bbb45
KO
2040}
2041
2042long wxListCtrl::InsertItem(long index, const wxString& label)
2043{
2044 if (m_genericImpl)
2045 return m_genericImpl->InsertItem(index, label);
2046
2047 wxListItem info;
2048 info.m_text = label;
2049 info.m_mask = wxLIST_MASK_TEXT;
2050 info.m_itemId = index;
2051 return InsertItem(info);
2052}
2053
2054// Inserts an image item
2055long wxListCtrl::InsertItem(long index, int imageIndex)
2056{
2057 if (m_genericImpl)
2058 return m_genericImpl->InsertItem(index, imageIndex);
e330eb46 2059
e96bbb45
KO
2060 wxListItem info;
2061 info.m_image = imageIndex;
2062 info.m_mask = wxLIST_MASK_IMAGE;
2063 info.m_itemId = index;
2064 return InsertItem(info);
2065}
2066
2067// Inserts an image/string item
2068long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
2069{
2070 if (m_genericImpl)
2071 return m_genericImpl->InsertItem(index, label, imageIndex);
e330eb46 2072
e96bbb45
KO
2073 wxListItem info;
2074 info.m_image = imageIndex;
2075 info.m_text = label;
2076 info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
2077 info.m_itemId = index;
2078 return InsertItem(info);
2079}
2080
2081// For list view mode (only), inserts a column.
2082long wxListCtrl::InsertColumn(long col, wxListItem& item)
2083{
2084 if (m_genericImpl)
2085 return m_genericImpl->InsertColumn(col, item);
e330eb46
VZ
2086
2087 if (m_dbImpl)
2088 {
e9a0cc4b 2089 int width = item.GetWidth();
e330eb46 2090 if ( !(item.GetMask() & wxLIST_MASK_WIDTH) )
e9a0cc4b 2091 width = 150;
e330eb46 2092
e9a0cc4b 2093 DataBrowserPropertyType type = kDataBrowserCustomType; //kDataBrowserTextType;
e96bbb45 2094 wxImageList* imageList = GetImageList(wxIMAGE_LIST_SMALL);
e330eb46
VZ
2095 if (imageList && imageList->GetImageCount() > 0)
2096 {
e96bbb45 2097 wxBitmap bmp = imageList->GetBitmap(0);
e9a0cc4b
KO
2098 //if (bmp.Ok())
2099 // type = kDataBrowserIconAndTextType;
e96bbb45 2100 }
e330eb46 2101
e96bbb45 2102 SInt16 just = teFlushDefault;
e330eb46
VZ
2103 if (item.GetMask() & wxLIST_MASK_FORMAT)
2104 {
e96bbb45
KO
2105 if (item.GetAlign() == wxLIST_FORMAT_LEFT)
2106 just = teFlushLeft;
2107 else if (item.GetAlign() == wxLIST_FORMAT_CENTER)
2108 just = teCenter;
2109 else if (item.GetAlign() == wxLIST_FORMAT_RIGHT)
2110 just = teFlushRight;
2111 }
e9a0cc4b
KO
2112 m_dbImpl->InsertColumn(col, type, item.GetText(), just, width);
2113 SetColumn(col, item);
e330eb46 2114
3ed1dc0a
KO
2115 // set/remove options based on the wxListCtrl type.
2116 DataBrowserTableViewColumnID id;
2117 m_dbImpl->GetColumnIDFromIndex(col, &id);
2118 DataBrowserPropertyFlags flags;
2119 verify_noerr(m_dbImpl->GetPropertyFlags(id, &flags));
0d2d29b1 2120 if (GetWindowStyleFlag() & wxLC_EDIT_LABELS)
0d2d29b1 2121 flags |= kDataBrowserPropertyIsEditable;
493e7eb4 2122
3ed1dc0a
KO
2123 if (GetWindowStyleFlag() & wxLC_VIRTUAL){
2124 flags &= ~kDataBrowserListViewSortableColumn;
0d2d29b1 2125 }
3ed1dc0a 2126 verify_noerr(m_dbImpl->SetPropertyFlags(id, flags));
e96bbb45 2127 }
e330eb46 2128
e96bbb45
KO
2129 return col;
2130}
2131
2132long wxListCtrl::InsertColumn(long col,
2133 const wxString& heading,
2134 int format,
2135 int width)
2136{
2137 if (m_genericImpl)
2138 return m_genericImpl->InsertColumn(col, heading, format, width);
2139
2140 wxListItem item;
2141 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
2142 item.m_text = heading;
2143 if ( width > -1 )
2144 {
2145 item.m_mask |= wxLIST_MASK_WIDTH;
2146 item.m_width = width;
2147 }
2148 item.m_format = format;
2149
2150 return InsertColumn(col, item);
2151}
2152
2153// scroll the control by the given number of pixels (exception: in list view,
2154// dx is interpreted as number of columns)
2155bool wxListCtrl::ScrollList(int dx, int dy)
2156{
2157 if (m_genericImpl)
2158 return m_genericImpl->ScrollList(dx, dy);
e330eb46
VZ
2159
2160 if (m_dbImpl)
2161 {
e96bbb45
KO
2162 m_dbImpl->SetScrollPosition(dx, dy);
2163 }
2164 return true;
2165}
2166
2167
2168bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
2169{
2170 if (m_genericImpl)
2171 return m_genericImpl->SortItems(fn, data);
0ed77610 2172
3fd864a1
KO
2173 if (m_dbImpl)
2174 {
2175 m_compareFunc = fn;
2176 m_compareFuncData = data;
99b37d67 2177 SortDataBrowserContainer( m_dbImpl->GetControlRef(), kDataBrowserNoItem, true);
07977ff2 2178
99b37d67
KO
2179 // we need to do this after each call, else we get a crash from wxPython when
2180 // SortItems is called the second time.
2181 m_compareFunc = NULL;
2182 m_compareFuncData = 0;
3fd864a1 2183 }
e330eb46 2184
e96bbb45
KO
2185 return true;
2186}
2187
7ac21a67
KO
2188void wxListCtrl::OnRenameTimer()
2189{
2190 wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") );
2191
2192 EditLabel( m_current );
2193}
2194
2195bool wxListCtrl::OnRenameAccept(long itemEdit, const wxString& value)
2196{
2197 wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetId() );
2198 le.SetEventObject( this );
2199 le.m_itemIndex = itemEdit;
2200
2201 GetItem( le.m_item );
2202 le.m_item.m_text = value;
2203 return !GetEventHandler()->ProcessEvent( le ) ||
2204 le.IsAllowed();
2205}
2206
2207void wxListCtrl::OnRenameCancelled(long itemEdit)
2208{
2209 // let owner know that the edit was cancelled
2210 wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
2211
2212 le.SetEditCanceled(true);
2213
2214 le.SetEventObject( this );
2215 le.m_itemIndex = itemEdit;
2216
2217 GetItem( le.m_item );
2218 GetEventHandler()->ProcessEvent( le );
2219}
2220
e96bbb45
KO
2221// ----------------------------------------------------------------------------
2222// virtual list controls
2223// ----------------------------------------------------------------------------
2224
2225wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) const
2226{
2227 // this is a pure virtual function, in fact - which is not really pure
2228 // because the controls which are not virtual don't need to implement it
2229 wxFAIL_MSG( _T("wxListCtrl::OnGetItemText not supposed to be called") );
2230
2231 return wxEmptyString;
2232}
2233
2234int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const
2235{
2236 wxCHECK_MSG(!GetImageList(wxIMAGE_LIST_SMALL),
2237 -1,
2238 wxT("List control has an image list, OnGetItemImage or OnGetItemColumnImage should be overridden."));
2239 return -1;
2240}
2241
2242int wxListCtrl::OnGetItemColumnImage(long item, long column) const
2243{
2244 if (!column)
2245 return OnGetItemImage(item);
2246
2247 return -1;
2248}
2249
2250wxListItemAttr *wxListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const
2251{
2252 wxASSERT_MSG( item >= 0 && item < GetItemCount(),
2253 _T("invalid item index in OnGetItemAttr()") );
2254
2255 // no attributes by default
2256 return NULL;
2257}
2258
2259void wxListCtrl::SetItemCount(long count)
2260{
2261 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
2262
e330eb46
VZ
2263 if (m_genericImpl)
2264 {
e96bbb45
KO
2265 m_genericImpl->SetItemCount(count);
2266 return;
2267 }
e330eb46 2268
67650ea0
KO
2269 if (m_dbImpl)
2270 {
2271 // we need to temporarily disable the new item creation notification
2272 // procedure to speed things up
2273 // FIXME: Even this doesn't seem to help much...
2f0b521e 2274
02095058
KO
2275 // FIXME: Find a more efficient way to do this.
2276 m_dbImpl->MacClear();
2f0b521e 2277
67650ea0
KO
2278 DataBrowserCallbacks callbacks;
2279 DataBrowserItemNotificationUPP itemUPP;
2280 GetDataBrowserCallbacks(m_dbImpl->GetControlRef(), &callbacks);
2281 itemUPP = callbacks.u.v1.itemNotificationCallback;
2282 callbacks.u.v1.itemNotificationCallback = 0;
2283 m_dbImpl->SetCallbacks(&callbacks);
2284 ::AddDataBrowserItems(m_dbImpl->GetControlRef(), kDataBrowserNoItem,
2285 count, NULL, kDataBrowserItemNoProperty);
2286 callbacks.u.v1.itemNotificationCallback = itemUPP;
2287 m_dbImpl->SetCallbacks(&callbacks);
2288 }
e96bbb45
KO
2289 m_count = count;
2290}
2291
2292void wxListCtrl::RefreshItem(long item)
2293{
e330eb46
VZ
2294 if (m_genericImpl)
2295 {
e96bbb45
KO
2296 m_genericImpl->RefreshItem(item);
2297 return;
2298 }
e330eb46 2299
e96bbb45
KO
2300 wxRect rect;
2301 GetItemRect(item, rect);
2302 RefreshRect(rect);
2303}
2304
2305void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
2306{
e330eb46
VZ
2307 if (m_genericImpl)
2308 {
e96bbb45
KO
2309 m_genericImpl->RefreshItems(itemFrom, itemTo);
2310 return;
2311 }
2312
2313 wxRect rect1, rect2;
2314 GetItemRect(itemFrom, rect1);
2315 GetItemRect(itemTo, rect2);
2316
2317 wxRect rect = rect1;
2318 rect.height = rect2.GetBottom() - rect1.GetTop();
2319
2320 RefreshRect(rect);
2321}
2322
02095058
KO
2323void wxListCtrl::SetDropTarget( wxDropTarget *dropTarget )
2324{
2325#if wxUSE_DRAG_AND_DROP
2326 if (m_genericImpl)
2327 m_genericImpl->SetDropTarget( dropTarget );
2f0b521e 2328
02095058
KO
2329 if (m_dbImpl)
2330 wxWindow::SetDropTarget( dropTarget );
2331#endif
2332}
2333
2334wxDropTarget *wxListCtrl::GetDropTarget() const
2335{
2336#if wxUSE_DRAG_AND_DROP
2337 if (m_genericImpl)
2338 return m_genericImpl->GetDropTarget();
2f0b521e 2339
02095058
KO
2340 if (m_dbImpl)
2341 return wxWindow::GetDropTarget();
2342#endif
2343 return NULL;
2344}
e96bbb45 2345
471046b0 2346#if wxABI_VERSION >= 20801
bc63f2c9
KO
2347void wxListCtrl::SetFocus()
2348{
2349 if (m_genericImpl)
2350 {
2351 m_genericImpl->SetFocus();
2352 return;
2353 }
07977ff2 2354
bc63f2c9
KO
2355 wxWindow::SetFocus();
2356}
471046b0 2357#endif
bc63f2c9 2358
e330eb46 2359// wxMac internal data structures
e96bbb45
KO
2360
2361wxMacListCtrlItem::~wxMacListCtrlItem()
2362{
2363}
2364
2365void wxMacListCtrlItem::Notification(wxMacDataItemBrowserControl *owner ,
2366 DataBrowserItemNotification message,
89954433 2367 DataBrowserItemDataRef WXUNUSED(itemData) ) const
e96bbb45
KO
2368{
2369
bf9a1615 2370 wxMacDataBrowserListCtrlControl *lb = wxDynamicCast(owner, wxMacDataBrowserListCtrlControl);
e96bbb45
KO
2371
2372 // we want to depend on as little as possible to make sure tear-down of controls is safe
2373 if ( message == kDataBrowserItemRemoved)
2374 {
2375 if ( lb != NULL && lb->GetClientDataType() == wxClientData_Object )
2376 {
2377 delete (wxClientData*) (m_data);
2378 }
2379
2380 delete this;
2381 return;
2382 }
cb305e1e
SC
2383 else if ( message == kDataBrowserItemAdded )
2384 {
2385 // we don't issue events on adding, the item is not really stored in the list yet, so we
2386 // avoid asserts by gettting out now
2387 return ;
2388 }
e96bbb45 2389
e96bbb45 2390 wxListCtrl *list = wxDynamicCast( owner->GetPeer() , wxListCtrl );
b3aee708 2391 if ( list && lb )
e330eb46 2392 {
e96bbb45 2393 bool trigger = false;
e330eb46 2394
2a81538d 2395 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
eea2724a 2396 bool isSingle = (list->GetWindowStyle() & wxLC_SINGLE_SEL) != 0;
e330eb46 2397
8d700f71
SC
2398 event.SetEventObject( list );
2399 event.m_itemIndex = owner->GetLineFromItem( this ) ;
a44a646b
KO
2400 event.m_item.m_itemId = event.m_itemIndex;
2401 list->GetItem(event.m_item);
e330eb46 2402
e96bbb45
KO
2403 switch (message)
2404 {
2405 case kDataBrowserItemDeselected:
2406 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
2a81538d
SC
2407 if ( !isSingle )
2408 trigger = !lb->IsSelectionSuppressed();
e96bbb45
KO
2409 break;
2410
2411 case kDataBrowserItemSelected:
2a81538d 2412 trigger = !lb->IsSelectionSuppressed();
e96bbb45
KO
2413 break;
2414
2415 case kDataBrowserItemDoubleClicked:
e9a0cc4b 2416 event.SetEventType( wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
e96bbb45
KO
2417 trigger = true;
2418 break;
2419
8d700f71
SC
2420 case kDataBrowserEditStarted :
2421 // TODO : how to veto ?
2422 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
2423 trigger = true ;
2424 break ;
e330eb46 2425
8d700f71
SC
2426 case kDataBrowserEditStopped :
2427 // TODO probably trigger only upon the value store callback, because
2428 // here IIRC we cannot veto
2429 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
2430 trigger = true ;
2431 break ;
2432
e96bbb45
KO
2433 default:
2434 break;
2435 }
2436
2437 if ( trigger )
2438 {
e96bbb45 2439 // direct notification is not always having the listbox GetSelection() having in synch with event
2a81538d 2440 wxPostEvent( list->GetEventHandler(), event );
e96bbb45
KO
2441 }
2442 }
2443
2444}
2445
bf9a1615
SC
2446IMPLEMENT_DYNAMIC_CLASS(wxMacDataBrowserListCtrlControl, wxMacDataItemBrowserControl )
2447
e96bbb45
KO
2448wxMacDataBrowserListCtrlControl::wxMacDataBrowserListCtrlControl( wxWindow *peer, const wxPoint& pos, const wxSize& size, long style)
2449 : wxMacDataItemBrowserControl( peer, pos, size, style )
2450{
2451 OSStatus err = noErr;
2452 m_clientDataItemsType = wxClientData_None;
67650ea0 2453 m_isVirtual = false;
de387fc9 2454 m_flags = 0;
493e7eb4 2455
67650ea0
KO
2456 if ( style & wxLC_VIRTUAL )
2457 m_isVirtual = true;
e96bbb45
KO
2458
2459 DataBrowserSelectionFlags options = kDataBrowserDragSelect;
2460 if ( style & wxLC_SINGLE_SEL )
2461 {
2462 options |= kDataBrowserSelectOnlyOne;
2463 }
2464 else
2465 {
54638f9e 2466 options |= kDataBrowserCmdTogglesSelection;
e96bbb45
KO
2467 }
2468
2469 err = SetSelectionFlags( options );
2470 verify_noerr( err );
0ed77610 2471
e9a0cc4b
KO
2472 DataBrowserCustomCallbacks callbacks;
2473 InitializeDataBrowserCustomCallbacks( &callbacks, kDataBrowserLatestCustomCallbacks );
2474
2475 if ( gDataBrowserDrawItemUPP == NULL )
2476 gDataBrowserDrawItemUPP = NewDataBrowserDrawItemUPP(DataBrowserDrawItemProc);
2477
e9a0cc4b
KO
2478 if ( gDataBrowserHitTestUPP == NULL )
2479 gDataBrowserHitTestUPP = NewDataBrowserHitTestUPP(DataBrowserHitTestProc);
0ed77610 2480
e9a0cc4b 2481 callbacks.u.v1.drawItemCallback = gDataBrowserDrawItemUPP;
e9a0cc4b 2482 callbacks.u.v1.hitTestCallback = gDataBrowserHitTestUPP;
0ed77610 2483
e9a0cc4b 2484 SetDataBrowserCustomCallbacks( GetControlRef(), &callbacks );
e96bbb45 2485
e330eb46
VZ
2486 if ( style & wxLC_LIST )
2487 {
e96bbb45
KO
2488 InsertColumn(0, kDataBrowserIconAndTextType, wxEmptyString, -1, -1);
2489 verify_noerr( AutoSizeColumns() );
e96bbb45 2490 }
e330eb46 2491
54638f9e
KO
2492 if ( style & wxLC_LIST || style & wxLC_NO_HEADER )
2493 verify_noerr( SetHeaderButtonHeight( 0 ) );
e96bbb45 2494
01e935b6
SC
2495 if ( m_isVirtual )
2496 SetSortProperty( kMinColumnId - 1 );
2497 else
2498 SetSortProperty( kMinColumnId );
07977ff2 2499
ccea21cc 2500 m_sortOrder = SortOrder_None;
07977ff2 2501
ccea21cc 2502 if ( style & wxLC_SORT_DESCENDING )
e96bbb45 2503 {
67650ea0 2504 SetSortOrder( kDataBrowserOrderDecreasing );
e96bbb45 2505 }
ccea21cc 2506 else if ( style & wxLC_SORT_ASCENDING )
e96bbb45 2507 {
ccea21cc 2508 SetSortOrder( kDataBrowserOrderIncreasing );
e96bbb45 2509 }
e330eb46
VZ
2510
2511 if ( style & wxLC_VRULES )
2512 {
54638f9e 2513 verify_noerr( DataBrowserChangeAttributes(m_controlRef, kDataBrowserAttributeListViewDrawColumnDividers, kDataBrowserAttributeNone) );
54638f9e 2514 }
e96bbb45 2515
e96bbb45 2516 verify_noerr( SetHiliteStyle(kDataBrowserTableViewFillHilite ) );
de387fc9 2517 verify_noerr( SetHasScrollBars( (style & wxHSCROLL) != 0 , true ) );
e96bbb45
KO
2518}
2519
e9a0cc4b
KO
2520pascal Boolean wxMacDataBrowserListCtrlControl::DataBrowserEditTextProc(
2521 ControlRef browser,
2522 DataBrowserItemID itemID,
2523 DataBrowserPropertyID property,
2524 CFStringRef theString,
2525 Rect *maxEditTextRect,
2526 Boolean *shrinkToFit)
2527{
2528 Boolean result = false;
bf9a1615 2529 wxMacDataBrowserListCtrlControl* ctl = wxDynamicCast(wxMacControl::GetReferenceFromNativeControl( browser ), wxMacDataBrowserListCtrlControl);
e9a0cc4b
KO
2530 if ( ctl != 0 )
2531 {
2532 result = ctl->ConfirmEditText(itemID, property, theString, maxEditTextRect, shrinkToFit);
2533 theString = CFSTR("Hello!");
2534 }
2535 return result;
2536}
2537
2538bool wxMacDataBrowserListCtrlControl::ConfirmEditText(
89954433
VZ
2539 DataBrowserItemID WXUNUSED(itemID),
2540 DataBrowserPropertyID WXUNUSED(property),
2541 CFStringRef WXUNUSED(theString),
2542 Rect *WXUNUSED(maxEditTextRect),
2543 Boolean *WXUNUSED(shrinkToFit))
e9a0cc4b 2544{
e9a0cc4b
KO
2545 return false;
2546}
2547
2548pascal void wxMacDataBrowserListCtrlControl::DataBrowserDrawItemProc(
2549 ControlRef browser,
2550 DataBrowserItemID itemID,
2551 DataBrowserPropertyID property,
2552 DataBrowserItemState itemState,
2553 const Rect *itemRect,
2554 SInt16 gdDepth,
2555 Boolean colorDevice)
2556{
bf9a1615 2557 wxMacDataBrowserListCtrlControl* ctl = wxDynamicCast(wxMacControl::GetReferenceFromNativeControl( browser ), wxMacDataBrowserListCtrlControl);
e9a0cc4b
KO
2558 if ( ctl != 0 )
2559 {
2560 ctl->DrawItem(itemID, property, itemState, itemRect, gdDepth, colorDevice);
2561 }
2562}
2563
2564// routines needed for DrawItem
2565enum
2566{
2567 kIconWidth = 16,
2568 kIconHeight = 16,
2569 kTextBoxHeight = 14,
2570 kIconTextSpacingV = 2,
0ed77610 2571 kItemPadding = 4,
e9a0cc4b
KO
2572 kContentHeight = kIconHeight + kTextBoxHeight + kIconTextSpacingV
2573};
2574
2575static void calculateCGDrawingBounds(CGRect inItemRect, CGRect *outIconRect, CGRect *outTextRect, bool hasIcon = false)
2576{
2577 float textBottom;
2578 float iconH, iconW = 0;
2579 float padding = kItemPadding;
2580 if (hasIcon)
2581 {
2582 iconH = kIconHeight;
2583 iconW = kIconWidth;
2584 padding = padding*2;
2585 }
0ed77610 2586
e9a0cc4b 2587 textBottom = inItemRect.origin.y;
0ed77610
VZ
2588
2589 *outIconRect = CGRectMake(inItemRect.origin.x + kItemPadding,
2590 textBottom + kIconTextSpacingV, kIconWidth,
e9a0cc4b 2591 kIconHeight);
0ed77610
VZ
2592
2593 *outTextRect = CGRectMake(inItemRect.origin.x + padding + iconW,
2594 textBottom + kIconTextSpacingV, inItemRect.size.width - padding - iconW,
e9a0cc4b
KO
2595 inItemRect.size.height - kIconTextSpacingV);
2596}
2597
2598void wxMacDataBrowserListCtrlControl::DrawItem(
2599 DataBrowserItemID itemID,
2600 DataBrowserPropertyID property,
2601 DataBrowserItemState itemState,
89954433 2602 const Rect *WXUNUSED(itemRect),
e9a0cc4b
KO
2603 SInt16 gdDepth,
2604 Boolean colorDevice)
2605{
2606 wxString text;
2607 wxFont font = wxNullFont;
2608 int imgIndex = -1;
2609 short listColumn = property - kMinColumnId;
2610
2611 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
2612 wxMacListCtrlItem* lcItem;
2613 wxColour color = *wxBLACK;
2614 wxColour bgColor = wxNullColour;
2615
2616 if (listColumn >= 0)
2617 {
2618 if (!m_isVirtual)
2619 {
2620 lcItem = (wxMacListCtrlItem*) itemID;
2621 if (lcItem->HasColumnInfo(listColumn)){
2622 wxListItem* item = lcItem->GetColumnInfo(listColumn);
0ed77610 2623
e9a0cc4b
KO
2624 // we always use the 0 column to get font and text/background colors.
2625 if (lcItem->HasColumnInfo(0))
2626 {
2627 wxListItem* firstItem = lcItem->GetColumnInfo(0);
2628 color = firstItem->GetTextColour();
2629 bgColor = firstItem->GetBackgroundColour();
2630 font = firstItem->GetFont();
2631 }
0ed77610 2632
e9a0cc4b
KO
2633 if (item->GetMask() & wxLIST_MASK_TEXT)
2634 text = item->GetText();
2635 if (item->GetMask() & wxLIST_MASK_IMAGE)
2636 imgIndex = item->GetImage();
2637 }
0ed77610 2638
e9a0cc4b
KO
2639 }
2640 else
2641 {
ad31e6a2
KO
2642 long itemNum = (long)itemID-1;
2643 if (itemNum >= 0 && itemNum < list->GetItemCount())
e9a0cc4b 2644 {
ad31e6a2
KO
2645 text = list->OnGetItemText( itemNum, listColumn );
2646 imgIndex = list->OnGetItemColumnImage( itemNum, listColumn );
2647 wxListItemAttr* attrs = list->OnGetItemAttr( itemNum );
2648 if (attrs)
2649 {
2650 if (attrs->HasBackgroundColour())
2651 bgColor = attrs->GetBackgroundColour();
2652 if (attrs->HasTextColour())
2653 color = attrs->GetTextColour();
2654 if (attrs->HasFont())
2655 font = attrs->GetFont();
2656 }
e9a0cc4b
KO
2657 }
2658 }
2659 }
0ed77610 2660
e9a0cc4b
KO
2661 wxColour listBgColor = list->GetBackgroundColour();
2662 if (bgColor == wxNullColour)
2663 bgColor = listBgColor;
0ed77610 2664
e9a0cc4b
KO
2665 wxFont listFont = list->GetFont();
2666 if (font == wxNullFont)
2667 font = listFont;
0ed77610 2668
e9a0cc4b
KO
2669 wxMacCFStringHolder cfString;
2670 cfString.Assign( text, wxLocale::GetSystemEncoding() );
0ed77610 2671
e9a0cc4b
KO
2672 Rect enclosingRect;
2673 CGRect enclosingCGRect, iconCGRect, textCGRect;
2674 Boolean active;
2675 ThemeDrawingState savedState = NULL;
2676 CGContextRef context = (CGContextRef)list->MacGetDrawingContext();
2677 RGBColor labelColor;
02095058
KO
2678 labelColor.red = 0;
2679 labelColor.green = 0;
2680 labelColor.blue = 0;
2681
2682 RGBColor backgroundColor;
2683 backgroundColor.red = 255;
2684 backgroundColor.green = 255;
2685 backgroundColor.blue = 255;
0ed77610
VZ
2686
2687 GetDataBrowserItemPartBounds(GetControlRef(), itemID, property, kDataBrowserPropertyEnclosingPart,
e9a0cc4b 2688 &enclosingRect);
0ed77610
VZ
2689
2690 enclosingCGRect = CGRectMake(enclosingRect.left,
2691 enclosingRect.top,
2692 enclosingRect.right - enclosingRect.left,
e9a0cc4b
KO
2693 enclosingRect.bottom - enclosingRect.top);
2694
f80419c8 2695 bool hasFocus = (wxWindow::FindFocus() == list);
e9a0cc4b 2696 active = IsControlActive(GetControlRef());
f8a98fa2 2697
b3aee708
KO
2698 // don't paint the background over the vertical rule line
2699 if ( list->GetWindowStyleFlag() & wxLC_VRULES )
2700 {
2701 enclosingCGRect.origin.x += 1;
2702 enclosingCGRect.size.width -= 1;
2703 }
e9a0cc4b
KO
2704 if (itemState == kDataBrowserItemIsSelected)
2705 {
0ed77610 2706
e9a0cc4b 2707 GetThemeDrawingState(&savedState);
07977ff2 2708
f80419c8 2709 if (active && hasFocus)
defeae28
KO
2710 {
2711 GetThemeBrushAsColor(kThemeBrushAlternatePrimaryHighlightColor, 32, true, &backgroundColor);
2712 GetThemeTextColor(kThemeTextColorWhite, gdDepth, colorDevice, &labelColor);
2713 }
2714 else
2715 {
2716 GetThemeBrushAsColor(kThemeBrushSecondaryHighlightColor, 32, true, &backgroundColor);
2717 GetThemeTextColor(kThemeTextColorBlack, gdDepth, colorDevice, &labelColor);
2718 }
e9a0cc4b 2719 CGContextSaveGState(context);
0ed77610 2720
02095058
KO
2721 CGContextSetRGBFillColor(context, (float)backgroundColor.red / (float)USHRT_MAX,
2722 (float)backgroundColor.green / (float)USHRT_MAX,
2723 (float)backgroundColor.blue / (float)USHRT_MAX, 1.0);
e9a0cc4b 2724 CGContextFillRect(context, enclosingCGRect);
0ed77610 2725
e9a0cc4b
KO
2726 CGContextRestoreGState(context);
2727 }
2728 else
0ed77610
VZ
2729 {
2730
e9a0cc4b 2731 if (color.Ok())
276ee533 2732 color.GetRGBColor(&labelColor);
e9a0cc4b 2733 else if (list->GetTextColour().Ok())
276ee533 2734 list->GetTextColour().GetRGBColor(&labelColor);
07977ff2 2735
e9a0cc4b
KO
2736 if (bgColor.Ok())
2737 {
276ee533 2738 bgColor.GetRGBColor(&backgroundColor);
e9a0cc4b 2739 CGContextSaveGState(context);
0ed77610 2740
02095058
KO
2741 CGContextSetRGBFillColor(context, (float)backgroundColor.red / (float)USHRT_MAX,
2742 (float)backgroundColor.green / (float)USHRT_MAX,
2743 (float)backgroundColor.blue / (float)USHRT_MAX, 1.0);
e9a0cc4b 2744 CGContextFillRect(context, enclosingCGRect);
0ed77610 2745
e9a0cc4b
KO
2746 CGContextRestoreGState(context);
2747 }
2748 }
0ed77610 2749
e9a0cc4b 2750 calculateCGDrawingBounds(enclosingCGRect, &iconCGRect, &textCGRect, (imgIndex != -1) );
0ed77610 2751
e9a0cc4b
KO
2752 if (imgIndex != -1)
2753 {
2754 wxImageList* imageList = list->GetImageList(wxIMAGE_LIST_SMALL);
2755 if (imageList && imageList->GetImageCount() > 0){
2756 wxBitmap bmp = imageList->GetBitmap(imgIndex);
2757 IconRef icon = bmp.GetBitmapData()->GetIconRef();
0ed77610 2758
3ce16a8e
KO
2759 CGContextSaveGState(context);
2760 CGContextTranslateCTM(context, 0,iconCGRect.origin.y + CGRectGetMaxY(iconCGRect));
2761 CGContextScaleCTM(context,1.0f,-1.0f);
0ed77610 2762 PlotIconRefInContext(context, &iconCGRect, kAlignNone,
02095058 2763 active ? kTransformNone : kTransformDisabled, NULL,
e9a0cc4b 2764 kPlotIconRefNormalFlags, icon);
0ed77610 2765
3ce16a8e 2766 CGContextRestoreGState(context);
e9a0cc4b
KO
2767 }
2768 }
0ed77610 2769
e9a0cc4b 2770 HIThemeTextHorizontalFlush hFlush = kHIThemeTextHorizontalFlushLeft;
6239ee05
SC
2771 HIThemeTextInfo info;
2772
2773#ifdef __LP64__
2774 info.version = kHIThemeTextInfoVersionOne;
2775 info.fontID = kThemeViewsFont;
2776 if (font.Ok())
2777 {
2778 info.fontID = kThemeSpecifiedFont;
2779 info.font = (CTFontRef) font.MacGetCTFont();
2780 }
2781#else
2782 info.version = kHIThemeTextInfoVersionZero;
2783 info.fontID = kThemeViewsFont;
0ed77610 2784
e9a0cc4b
KO
2785 if (font.Ok())
2786 {
2787 if (font.GetFamily() != wxFONTFAMILY_DEFAULT)
6239ee05 2788 info.fontID = font.MacGetThemeFontID();
0ed77610 2789
e9a0cc4b
KO
2790 ::TextSize( (short)(font.MacGetFontSize()) ) ;
2791 ::TextFace( font.MacGetFontStyle() ) ;
e9a0cc4b 2792 }
6239ee05 2793#endif
0ed77610 2794
e9a0cc4b
KO
2795 wxListItem item;
2796 list->GetColumn(listColumn, item);
2797 if (item.GetMask() & wxLIST_MASK_FORMAT)
2798 {
2799 if (item.GetAlign() == wxLIST_FORMAT_LEFT)
0ed77610 2800 hFlush = kHIThemeTextHorizontalFlushLeft;
e9a0cc4b 2801 else if (item.GetAlign() == wxLIST_FORMAT_CENTER)
0ed77610 2802 hFlush = kHIThemeTextHorizontalFlushCenter;
e9a0cc4b
KO
2803 else if (item.GetAlign() == wxLIST_FORMAT_RIGHT)
2804 {
2805 hFlush = kHIThemeTextHorizontalFlushRight;
2806 textCGRect.origin.x -= kItemPadding; // give a little extra paddding
2807 }
2808 }
0ed77610 2809
e9a0cc4b 2810 info.state = active ? kThemeStateActive : kThemeStateInactive;
e9a0cc4b
KO
2811 info.horizontalFlushness = hFlush;
2812 info.verticalFlushness = kHIThemeTextVerticalFlushCenter;
2813 info.options = kHIThemeTextBoxOptionNone;
2814 info.truncationPosition = kHIThemeTextTruncationEnd;
2815 info.truncationMaxLines = 1;
2816
2817 CGContextSaveGState(context);
0ed77610
VZ
2818 CGContextSetRGBFillColor (context, (float)labelColor.red / (float)USHRT_MAX,
2819 (float)labelColor.green / (float)USHRT_MAX,
e9a0cc4b 2820 (float)labelColor.blue / (float)USHRT_MAX, 1.0);
0ed77610
VZ
2821
2822 HIThemeDrawTextBox(cfString, &textCGRect, &info, context, kHIThemeOrientationNormal);
2823
e9a0cc4b 2824 CGContextRestoreGState(context);
0ed77610 2825
6239ee05 2826#ifndef __LP64__
e9a0cc4b
KO
2827 if (savedState != NULL)
2828 SetThemeDrawingState(savedState, true);
6239ee05 2829#endif
e9a0cc4b
KO
2830}
2831
67650ea0
KO
2832OSStatus wxMacDataBrowserListCtrlControl::GetSetItemData(DataBrowserItemID itemID,
2833 DataBrowserPropertyID property,
2834 DataBrowserItemDataRef itemData,
2835 Boolean changeValue )
2836{
2837 wxString text;
2838 int imgIndex = -1;
2839 short listColumn = property - kMinColumnId;
2840
2841 OSStatus err = errDataBrowserPropertyNotSupported;
2842 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
f42e073c 2843 wxMacListCtrlItem* lcItem;
67650ea0
KO
2844
2845 if (listColumn >= 0)
2846 {
2847 if (!m_isVirtual)
2848 {
f42e073c 2849 lcItem = (wxMacListCtrlItem*) itemID;
b3aee708 2850 if (lcItem && lcItem->HasColumnInfo(listColumn)){
67650ea0
KO
2851 wxListItem* item = lcItem->GetColumnInfo(listColumn);
2852 if (item->GetMask() & wxLIST_MASK_TEXT)
2853 text = item->GetText();
2854 if (item->GetMask() & wxLIST_MASK_IMAGE)
2855 imgIndex = item->GetImage();
2856 }
2857 }
2858 else
2859 {
ad31e6a2
KO
2860 long itemNum = (long)itemID-1;
2861 if (itemNum >= 0 && itemNum < list->GetItemCount())
2862 {
2863 text = list->OnGetItemText( itemNum, listColumn );
2864 imgIndex = list->OnGetItemColumnImage( itemNum, listColumn );
2865 }
67650ea0
KO
2866 }
2867 }
2868
2869 if ( !changeValue )
2870 {
2871 switch (property)
2872 {
2873 case kDataBrowserItemIsEditableProperty :
2874 if ( list && list->HasFlag( wxLC_EDIT_LABELS ) )
2875 {
2876 verify_noerr(SetDataBrowserItemDataBooleanValue( itemData, true ));
6239ee05 2877 err = noErr ;
67650ea0
KO
2878 }
2879 break ;
2880 default :
2881 if ( property >= kMinColumnId )
2882 {
6239ee05
SC
2883 wxMacCFStringHolder cfStr;
2884
2885 if (!text.IsEmpty()){
2886 cfStr.Assign( text, wxLocale::GetSystemEncoding() );
2887 err = ::SetDataBrowserItemDataText( itemData, cfStr );
2888 err = noErr;
2889 }
67650ea0 2890
493e7eb4
VZ
2891
2892
67650ea0
KO
2893 if ( imgIndex != -1 )
2894 {
2895 wxImageList* imageList = list->GetImageList(wxIMAGE_LIST_SMALL);
2896 if (imageList && imageList->GetImageCount() > 0){
2897 wxBitmap bmp = imageList->GetBitmap(imgIndex);
2898 IconRef icon = bmp.GetBitmapData()->GetIconRef();
2899 ::SetDataBrowserItemDataIcon(itemData, icon);
2900 }
2901 }
493e7eb4 2902
67650ea0
KO
2903 }
2904 break ;
2905 }
493e7eb4 2906
67650ea0
KO
2907 }
2908 else
2909 {
2910 switch (property)
2911 {
2912 default:
2913 if ( property >= kMinColumnId )
2914 {
2915 short listColumn = property - kMinColumnId;
2916
2917 // TODO probably send the 'end edit' from here, as we
2918 // can then deal with the veto
2919 CFStringRef sr ;
2920 verify_noerr( GetDataBrowserItemDataText( itemData , &sr ) ) ;
2921 wxMacCFStringHolder cfStr(sr) ;;
f42e073c
KO
2922 if (m_isVirtual)
2923 list->SetItem( (long)itemData-1 , listColumn, cfStr.AsString() ) ;
2924 else
2925 {
2926 if (lcItem)
2927 lcItem->SetColumnTextValue( listColumn, cfStr.AsString() );
2928 }
493e7eb4 2929 err = noErr ;
67650ea0
KO
2930 }
2931 break;
2932 }
2933 }
2934 return err;
2935}
2936
2937void wxMacDataBrowserListCtrlControl::ItemNotification(DataBrowserItemID itemID,
2938 DataBrowserItemNotification message,
89954433 2939 DataBrowserItemDataRef WXUNUSED(itemData) )
67650ea0
KO
2940{
2941 // we want to depend on as little as possible to make sure tear-down of controls is safe
2942 if ( message == kDataBrowserItemRemoved)
2943 {
2944 // make sure MacDelete does the proper teardown.
2945 return;
2946 }
2947 else if ( message == kDataBrowserItemAdded )
2948 {
2949 // we don't issue events on adding, the item is not really stored in the list yet, so we
eea2724a 2950 // avoid asserts by getting out now
67650ea0
KO
2951 return ;
2952 }
07977ff2 2953
67650ea0
KO
2954 wxListCtrl *list = wxDynamicCast( GetPeer() , wxListCtrl );
2955 if ( list )
2956 {
2957 bool trigger = false;
493e7eb4 2958
67650ea0 2959 wxListEvent event( wxEVT_COMMAND_LIST_ITEM_SELECTED, list->GetId() );
493e7eb4 2960
67650ea0
KO
2961 event.SetEventObject( list );
2962 if ( !list->IsVirtual() )
2963 {
67650ea0
KO
2964 DataBrowserTableViewRowIndex result = 0;
2965 verify_noerr( GetItemRow( itemID, &result ) ) ;
2966 event.m_itemIndex = result;
67650ea0
KO
2967 }
2968 else
2969 {
c4341187 2970 event.m_itemIndex = (long)itemID-1;
67650ea0 2971 }
a44a646b
KO
2972 event.m_item.m_itemId = event.m_itemIndex;
2973 list->GetItem(event.m_item);
493e7eb4 2974
67650ea0
KO
2975 switch (message)
2976 {
2977 case kDataBrowserItemDeselected:
2978 event.SetEventType(wxEVT_COMMAND_LIST_ITEM_DESELECTED);
6239ee05
SC
2979 // as the generic implementation is also triggering this
2980 // event for single selection, we do the same (different than listbox)
2981 trigger = !IsSelectionSuppressed();
67650ea0
KO
2982 break;
2983
2984 case kDataBrowserItemSelected:
e9a0cc4b 2985 trigger = !IsSelectionSuppressed();
0ed77610 2986
67650ea0
KO
2987 break;
2988
2989 case kDataBrowserItemDoubleClicked:
e9a0cc4b 2990 event.SetEventType( wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
67650ea0
KO
2991 trigger = true;
2992 break;
2993
2994 case kDataBrowserEditStarted :
2995 // TODO : how to veto ?
2996 event.SetEventType( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT ) ;
2997 trigger = true ;
2998 break ;
493e7eb4 2999
67650ea0
KO
3000 case kDataBrowserEditStopped :
3001 // TODO probably trigger only upon the value store callback, because
3002 // here IIRC we cannot veto
3003 event.SetEventType( wxEVT_COMMAND_LIST_END_LABEL_EDIT ) ;
3004 trigger = true ;
3005 break ;
3006
3007 default:
3008 break;
3009 }
3010
3011 if ( trigger )
3012 {
3013 // direct notification is not always having the listbox GetSelection() having in synch with event
3014 wxPostEvent( list->GetEventHandler(), event );
3015 }
3016 }
3017}
3018
3019Boolean wxMacDataBrowserListCtrlControl::CompareItems(DataBrowserItemID itemOneID,
3020 DataBrowserItemID itemTwoID,
3021 DataBrowserPropertyID sortProperty)
3022{
3023
3024 bool retval = false;
3025 wxString itemText;
3026 wxString otherItemText;
bc63f2c9
KO
3027 long itemOrder;
3028 long otherItemOrder;
07977ff2 3029
67650ea0 3030 int colId = sortProperty - kMinColumnId;
493e7eb4 3031
67650ea0 3032 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
493e7eb4 3033
bc63f2c9
KO
3034 DataBrowserSortOrder sort;
3035 verify_noerr(GetSortOrder(&sort));
3036
67650ea0
KO
3037 if (colId >= 0)
3038 {
3039 if (!m_isVirtual)
3040 {
3041 wxMacListCtrlItem* item = (wxMacListCtrlItem*)itemOneID;
3042 wxMacListCtrlItem* otherItem = (wxMacListCtrlItem*)itemTwoID;
2f0b521e 3043
ccea21cc
KO
3044 itemOrder = item->GetOrder();
3045 otherItemOrder = item->GetOrder();
07977ff2 3046
99b37d67
KO
3047 wxListCtrlCompare func = list->GetCompareFunc();
3048 if (func != NULL)
3049 {
3050 long item1 = -1;
3051 long item2 = -1;
3052 if (item && item->HasColumnInfo(0))
3053 item1 = item->GetColumnInfo(0)->GetData();
3054 if (otherItem && otherItem->HasColumnInfo(0))
07977ff2
VZ
3055 item2 = otherItem->GetColumnInfo(0)->GetData();
3056
99b37d67
KO
3057 if (item1 > -1 && item2 > -1)
3058 {
3059 int result = func(item1, item2, list->GetCompareFuncData());
bc63f2c9
KO
3060 if (sort == kDataBrowserOrderIncreasing)
3061 return result >= 0;
3062 else
3063 return result < 0;
99b37d67
KO
3064 }
3065 }
07977ff2 3066
ccea21cc
KO
3067 // we can't use the native control's sorting abilities, so just
3068 // sort by item id.
3069 return itemOrder < otherItemOrder;
67650ea0
KO
3070 }
3071 else
3072 {
f8a98fa2 3073
d2af7584
KO
3074 long itemNum = (long)itemOneID;
3075 long otherItemNum = (long)itemTwoID;
ad31e6a2 3076
bc63f2c9
KO
3077 // virtual listctrls don't support sorting
3078 return itemNum < otherItemNum;
bc63f2c9 3079 }
67650ea0
KO
3080 }
3081 else{
3082 // fallback for undefined cases
3083 retval = itemOneID < itemTwoID;
3084 }
3085
3086 return retval;
3087}
3088
e96bbb45
KO
3089wxMacDataBrowserListCtrlControl::~wxMacDataBrowserListCtrlControl()
3090{
3091}
3092
3093void wxMacDataBrowserListCtrlControl::MacSetColumnInfo( unsigned int row, unsigned int column, wxListItem* item )
493e7eb4 3094{
e96bbb45 3095 wxMacDataItem* dataItem = GetItemFromLine(row);
b3aee708 3096 wxASSERT_MSG( dataItem, _T("could not obtain wxMacDataItem for row in MacSetColumnInfo. Is row a valid wxListCtrl row?") );
e330eb46
VZ
3097 if (item)
3098 {
bf9a1615 3099 wxMacListCtrlItem* listItem = wx_static_cast(wxMacListCtrlItem*,dataItem);
99b37d67 3100 bool hasInfo = listItem->HasColumnInfo( column );
e96bbb45 3101 listItem->SetColumnInfo( column, item );
ccea21cc 3102 listItem->SetOrder(row);
e96bbb45 3103 UpdateState(dataItem, item);
07977ff2 3104
99b37d67 3105 wxListCtrl* list = wxDynamicCast( GetPeer() , wxListCtrl );
07977ff2 3106
99b37d67 3107 // NB: When this call was made before a control was completely shown, it would
07977ff2 3108 // update the item prematurely (i.e. no text would be listed) and, on show,
99b37d67
KO
3109 // only the sorted column would be refreshed, meaning only first column text labels
3110 // would be shown. Making sure not to update items until the control is visible
3111 // seems to fix this issue.
3112 if (hasInfo && list->IsShown())
3113 UpdateItem( wxMacDataBrowserRootContainer, listItem , kMinColumnId + column );
e96bbb45
KO
3114 }
3115}
3116
493e7eb4 3117// apply changes that need to happen immediately, rather than when the
e96bbb45
KO
3118// databrowser control fires a callback.
3119void wxMacDataBrowserListCtrlControl::UpdateState(wxMacDataItem* dataItem, wxListItem* listItem)
3120{
3121 bool isSelected = IsItemSelected( dataItem );
3122 bool isSelectedState = (listItem->GetState() == wxLIST_STATE_SELECTED);
3123
493e7eb4 3124 // toggle the selection state if wxListInfo state and actual state don't match.
dcd79bff 3125 if ( listItem->GetMask() & wxLIST_MASK_STATE && isSelected != isSelectedState )
e330eb46 3126 {
e96bbb45
KO
3127 DataBrowserSetOption options = kDataBrowserItemsAdd;
3128 if (!isSelectedState)
3129 options = kDataBrowserItemsRemove;
e96bbb45
KO
3130 SetSelectedItem(dataItem, options);
3131 }
3132 // TODO: Set column width if item width > than current column width
3133}
3134
3135void wxMacDataBrowserListCtrlControl::MacGetColumnInfo( unsigned int row, unsigned int column, wxListItem& item )
493e7eb4 3136{
e96bbb45 3137 wxMacDataItem* dataItem = GetItemFromLine(row);
b3aee708 3138 wxASSERT_MSG( dataItem, _T("could not obtain wxMacDataItem in MacGetColumnInfo. Is row a valid wxListCtrl row?") );
2a81538d 3139 // CS should this guard against dataItem = 0 ? , as item is not a pointer if (item) is not appropriate
493e7eb4 3140 //if (item)
2a81538d 3141 {
bf9a1615 3142 wxMacListCtrlItem* listItem =wx_static_cast(wxMacListCtrlItem*,dataItem);
f8a98fa2 3143
d2af7584
KO
3144 if (!listItem->HasColumnInfo( column ))
3145 return;
e96bbb45 3146
d2af7584 3147 wxListItem* oldItem = listItem->GetColumnInfo( column );
e96bbb45 3148
d2af7584
KO
3149 if (oldItem)
3150 {
3151 long mask = item.GetMask();
3152 if ( !mask )
3153 // by default, get everything for backwards compatibility
3154 mask = -1;
3155
3156 if ( mask & wxLIST_MASK_TEXT )
3157 item.SetText(oldItem->GetText());
3158 if ( mask & wxLIST_MASK_IMAGE )
3159 item.SetImage(oldItem->GetImage());
3160 if ( mask & wxLIST_MASK_DATA )
3161 item.SetData(oldItem->GetData());
3162 if ( mask & wxLIST_MASK_STATE )
3163 item.SetState(oldItem->GetState());
3164 if ( mask & wxLIST_MASK_WIDTH )
3165 item.SetWidth(oldItem->GetWidth());
3166 if ( mask & wxLIST_MASK_FORMAT )
3167 item.SetAlign(oldItem->GetAlign());
3168
3169 item.SetTextColour(oldItem->GetTextColour());
3170 item.SetBackgroundColour(oldItem->GetBackgroundColour());
3171 item.SetFont(oldItem->GetFont());
3172 }
e96bbb45
KO
3173 }
3174}
3175
3176void wxMacDataBrowserListCtrlControl::MacInsertItem( unsigned int n, wxListItem* item )
3177{
3178 wxMacDataItemBrowserControl::MacInsert(n, item->GetText());
3179 MacSetColumnInfo(n, 0, item);
3180}
3181
9ce05df4 3182wxMacDataItem* wxMacDataBrowserListCtrlControl::CreateItem()
e96bbb45
KO
3183{
3184 return new wxMacListCtrlItem();
3185}
3186
3187wxMacListCtrlItem::wxMacListCtrlItem()
3188{
bc63f2c9 3189 m_rowItems = wxListItemList();
e96bbb45
KO
3190}
3191
3192int wxMacListCtrlItem::GetColumnImageValue( unsigned int column )
3193{
b3aee708
KO
3194 if ( HasColumnInfo(column) )
3195 return GetColumnInfo(column)->GetImage();
f8a98fa2 3196
b3aee708 3197 return -1;
e96bbb45
KO
3198}
3199
3200void wxMacListCtrlItem::SetColumnImageValue( unsigned int column, int imageIndex )
3201{
b3aee708
KO
3202 if ( HasColumnInfo(column) )
3203 GetColumnInfo(column)->SetImage(imageIndex);
e96bbb45
KO
3204}
3205
f8a98fa2 3206wxString wxMacListCtrlItem::GetColumnTextValue( unsigned int column )
e96bbb45
KO
3207{
3208 if ( column == 0 )
3209 return GetLabel();
3210
f8a98fa2 3211 if ( HasColumnInfo(column) )
b3aee708 3212 return GetColumnInfo(column)->GetText();
f8a98fa2 3213
b3aee708 3214 return wxEmptyString;
e96bbb45
KO
3215}
3216
3217void wxMacListCtrlItem::SetColumnTextValue( unsigned int column, const wxString& text )
3218{
b3aee708
KO
3219 if ( HasColumnInfo(column) )
3220 GetColumnInfo(column)->SetText(text);
e330eb46 3221
e96bbb45
KO
3222 // for compatibility with superclass APIs
3223 if ( column == 0 )
3224 SetLabel(text);
3225}
3226
3227wxListItem* wxMacListCtrlItem::GetColumnInfo( unsigned int column )
3228{
bc63f2c9 3229 wxASSERT_MSG( HasColumnInfo(column), _T("invalid column index in wxMacListCtrlItem") );
07977ff2 3230 return m_rowItems[column];
e96bbb45
KO
3231}
3232
3233bool wxMacListCtrlItem::HasColumnInfo( unsigned int column )
3234{
bc63f2c9 3235 return !(m_rowItems.find( column ) == m_rowItems.end());
e96bbb45
KO
3236}
3237
3238void wxMacListCtrlItem::SetColumnInfo( unsigned int column, wxListItem* item )
3239{
3240
b3aee708 3241 if ( !HasColumnInfo(column) )
e330eb46 3242 {
493e7eb4 3243 wxListItem* listItem = new wxListItem(*item);
bc63f2c9 3244 m_rowItems[column] = listItem;
e96bbb45 3245 }
67650ea0
KO
3246 else
3247 {
e96bbb45
KO
3248 wxListItem* listItem = GetColumnInfo( column );
3249 long mask = item->GetMask();
3250 if (mask & wxLIST_MASK_TEXT)
3251 listItem->SetText(item->GetText());
3252 if (mask & wxLIST_MASK_DATA)
3253 listItem->SetData(item->GetData());
3254 if (mask & wxLIST_MASK_IMAGE)
3255 listItem->SetImage(item->GetImage());
3256 if (mask & wxLIST_MASK_STATE)
3257 listItem->SetState(item->GetState());
3258 if (mask & wxLIST_MASK_FORMAT)
3259 listItem->SetAlign(item->GetAlign());
3260 if (mask & wxLIST_MASK_WIDTH)
3261 listItem->SetWidth(item->GetWidth());
0ed77610 3262
d2af7584
KO
3263 if ( item->HasAttributes() )
3264 {
3265 if ( listItem->HasAttributes() )
3266 listItem->GetAttributes()->AssignFrom(*item->GetAttributes());
3267 else
3268 {
3269 listItem->SetTextColour(item->GetTextColour());
3270 listItem->SetBackgroundColour(item->GetBackgroundColour());
3271 listItem->SetFont(item->GetFont());
3272 }
3273 }
e96bbb45
KO
3274 }
3275}
3276
e96bbb45 3277#endif // wxUSE_LISTCTRL
defeae28 3278