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