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