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