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