Add wxAutoNSAutoreleasePool to SetSelection()
[wxWidgets.git] / src / cocoa / notebook.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        cocoa/notebook.mm
3 // Purpose:     wxNotebook
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2004/04/08
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2004 David Elliott
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13 #ifndef WX_PRECOMP
14     #include "wx/app.h"
15     #include "wx/notebook.h"
16 #endif //WX_PRECOMP
17 #include "wx/imaglist.h"
18
19 #include "wx/cocoa/autorelease.h"
20 #include "wx/cocoa/string.h"
21
22 #import <AppKit/NSTabView.h>
23 #import <AppKit/NSTabViewItem.h>
24 #import <AppKit/NSImage.h>
25
26 // testing:
27 #import <AppKit/NSPasteboard.h>
28 #import <Foundation/NSArray.h>
29
30 // ========================================================================
31 // WXCTabViewImageItem
32 // ========================================================================
33 @interface WXCTabViewImageItem : NSTabViewItem
34 {
35     NSImage *m_image;
36 }
37
38 - (id)init;
39 - (id)initWithIdentifier: (id)identifier;
40 - (void)dealloc;
41
42 - (NSSize)sizeOfLabel:(BOOL)shouldTruncateLabel;
43 - (void)drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)tabRect;
44
45 - (NSImage*)image;
46 - (void)setImage:(NSImage*)image;
47 @end // interface WXCTabViewImageItem : NSTabViewItem
48
49 @implementation WXCTabViewImageItem : NSTabViewItem
50 - (id)init
51 {
52     return [self initWithIdentifier:nil];
53 }
54
55 - (id)initWithIdentifier: (id)identifier;
56 {
57     m_image = nil;
58     return [super initWithIdentifier:identifier];
59 }
60
61 - (void)dealloc
62 {
63     [m_image release];
64 }
65
66 - (NSSize)sizeOfLabel:(BOOL)shouldTruncateLabel
67 {
68     NSSize labelSize = [super sizeOfLabel:shouldTruncateLabel];
69     if(!m_image)
70         return labelSize;
71     NSSize imageSize = [m_image size];
72     // scale image size
73     if(imageSize.height > labelSize.height)
74     {
75         imageSize.width *= labelSize.height/imageSize.height;
76         imageSize.height *= labelSize.height/imageSize.height;
77         [m_image setScalesWhenResized:YES];
78         [m_image setSize: imageSize];
79     }
80     labelSize.width += imageSize.width;
81     return labelSize;
82 }
83
84 - (void)drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)tabRect
85 {
86     if(m_image)
87     {
88         NSSize imageSize = [m_image size];
89         [m_image compositeToPoint:NSMakePoint(tabRect.origin.x,
90                 tabRect.origin.y+imageSize.height)
91             operation:NSCompositeSourceOver];
92         tabRect.size.width -= imageSize.width;
93         tabRect.origin.x += imageSize.width;
94     }
95     [super drawLabel:shouldTruncateLabel inRect:tabRect];
96 }
97
98 - (NSImage*)image
99 {
100     return m_image;
101 }
102
103 - (void)setImage:(NSImage*)image
104 {
105     [image retain];
106     [m_image release];
107     m_image = image;
108     if(!m_image)
109         return;
110     [[NSPasteboard generalPasteboard]
111         declareTypes:[NSArray arrayWithObject:NSTIFFPboardType]
112         owner:nil];
113     [[NSPasteboard generalPasteboard]
114         setData:[m_image TIFFRepresentation]
115         forType:NSTIFFPboardType];
116 }
117
118 @end // implementation WXCTabViewImageItem : NSTabViewItem
119
120 // ========================================================================
121 // wxNotebookEvent
122 // ========================================================================
123 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
124 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
125 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
126
127 // ========================================================================
128 // wxNotebook
129 // ========================================================================
130 IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
131 BEGIN_EVENT_TABLE(wxNotebook, wxNotebookBase)
132 END_EVENT_TABLE()
133 WX_IMPLEMENT_COCOA_OWNER(wxNotebook,NSTabView,NSView,NSView)
134
135 bool wxNotebook::Create(wxWindow *parent, wxWindowID winid,
136            const wxPoint& pos,
137            const wxSize& size,
138            long style,
139            const wxString& name)
140 {
141     wxAutoNSAutoreleasePool pool;
142     if(!CreateControl(parent,winid,pos,size,style,wxDefaultValidator,name))
143         return false;
144     m_cocoaNSView = NULL;
145     SetNSTabView([[NSTabView alloc] initWithFrame:MakeDefaultNSRect(size)]);
146     if(m_parent)
147         m_parent->CocoaAddChild(this);
148     SetInitialFrameRect(pos,size);
149
150     return true;
151 }
152
153 wxNotebook::~wxNotebook()
154 {
155 }
156
157 void wxNotebook::SetPadding(const wxSize& padding)
158 {   // Can't do
159 }
160
161 void wxNotebook::SetTabSize(const wxSize& sz)
162 {   // Can't do
163 }
164
165 void wxNotebook::SetPageSize(const wxSize& size)
166 {
167 }
168
169
170 wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage)
171 {
172     wxNotebookPage *page = wxNotebookBase::DoRemovePage(nPage);
173     if(!page)
174         return NULL;
175     NSTabViewItem *tvitem = [GetNSTabView() tabViewItemAtIndex: nPage];
176     wxASSERT(tvitem);
177     [tvitem retain];
178     [GetNSTabView() removeTabViewItem:tvitem];
179     // Remove the child window as a notebook page
180     wxASSERT([tvitem view] == page->GetNSViewForSuperview());
181     [tvitem setView:nil];
182     [tvitem release];
183     // Make it back into a normal child window
184     [m_cocoaNSView addSubview: page->GetNSViewForSuperview()];
185     
186     return page;
187 }
188
189 bool wxNotebook::DeletePage(size_t nPage)
190 {
191     return wxNotebookBase::DeletePage(nPage);
192 }
193
194 bool wxNotebook::InsertPage( size_t pos,
195                  wxNotebookPage *page, const wxString& title,
196                  bool bSelect, int imageId)
197 {
198     wxAutoNSAutoreleasePool pool;
199     m_pages.Insert(page,pos);
200     NSTabViewItem *tvitem = [[WXCTabViewImageItem alloc] initWithIdentifier:nil];
201     [tvitem setLabel: wxNSStringWithWxString(title)];
202     const wxBitmap *bmp = (imageId!=-1)?m_imageList->GetBitmap(imageId):NULL;
203     if(bmp)
204         [(WXCTabViewImageItem*) tvitem setImage: bmp->GetNSImage(true)];
205
206     NSView *pageNSView = page->GetNSViewForSuperview();
207     // Remove it as a normal child
208     wxASSERT(m_cocoaNSView == [pageNSView superview]);
209     [pageNSView removeFromSuperview];
210     // And make it a notebook page
211     [tvitem setView: pageNSView];
212
213     [GetNSTabView() insertTabViewItem:tvitem atIndex:pos];
214     [tvitem release];
215
216     return true;
217 }
218
219 bool wxNotebook::DeleteAllPages()
220 {
221     while(!m_pages.IsEmpty())
222         DeletePage(0);
223     return true;
224 }
225
226
227 bool wxNotebook::SetPageText(size_t nPage, const wxString& title)
228 {
229     NSTabViewItem *tvitem = [GetNSTabView() tabViewItemAtIndex: nPage];
230     if(!tvitem)
231         return false;
232     [tvitem setLabel: wxNSStringWithWxString(title)];
233     return true;
234 }
235
236 wxString wxNotebook::GetPageText(size_t nPage) const
237 {
238     return wxStringWithNSString([[GetNSTabView() tabViewItemAtIndex: nPage] label]);
239 }
240
241
242 int wxNotebook::GetPageImage(size_t nPage) const
243 {
244     // To do this we'd need to keep track of this, which we don't!
245     return -1;
246 }
247
248 bool wxNotebook::SetPageImage(size_t nPage, int nImage)
249 {
250     const wxBitmap *bmp = nImage!=-1?m_imageList->GetBitmap(nImage):NULL;
251     if(!bmp)
252         return false;
253     NSTabViewItem *tvitem = [GetNSTabView() tabViewItemAtIndex: nPage];
254     if(!tvitem)
255         return false;
256     [(WXCTabViewImageItem*) tvitem setImage: bmp->GetNSImage(true)];
257     return true;
258 }
259
260
261 int wxNotebook::SetSelection(size_t nPage)
262 {
263     wxAutoNSAutoreleasePool pool;
264     [GetNSTabView() selectTabViewItemAtIndex:nPage];
265     return GetSelection();
266 }
267
268 int wxNotebook::GetSelection() const
269 {
270     NSTabViewItem *selectedItem = [GetNSTabView() selectedTabViewItem];
271     if(!selectedItem)
272         return -1;
273     return [GetNSTabView() indexOfTabViewItem:selectedItem];
274 }
275
276 void wxNotebook::CocoaDelegate_tabView_didSelectTabViewItem(WX_NSTabViewItem tabViewItem)
277 {
278     // FIXME: oldSel probably == newSel
279     wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, GetId(),
280         [GetNSTabView() indexOfTabViewItem:tabViewItem], GetSelection());
281     event.SetEventObject(this);
282 }
283
284 bool wxNotebook::CocoaDelegate_tabView_shouldSelectTabViewItem(WX_NSTabViewItem tabViewItem)
285 {
286     wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, GetId(),
287         [GetNSTabView() indexOfTabViewItem:tabViewItem], GetSelection());
288     event.SetEventObject(this);
289     return !GetEventHandler()->ProcessEvent(event) || event.IsAllowed();
290 }
291