1 /////////////////////////////////////////////////////////////////////////////
2 // Name: cocoa/notebook.mm
4 // Author: David Elliott
8 // Copyright: (c) 2004 David Elliott
9 // Licence: wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
19 #include "wx/notebook.h"
20 #include "wx/imaglist.h"
22 #include "wx/cocoa/autorelease.h"
23 #include "wx/cocoa/string.h"
24 #include "wx/cocoa/objc/objc_uniquifying.h"
26 #import <AppKit/NSTabView.h>
27 #import <AppKit/NSTabViewItem.h>
28 #import <AppKit/NSImage.h>
31 #import <AppKit/NSPasteboard.h>
32 #import <Foundation/NSArray.h>
34 // ========================================================================
35 // WXCTabViewImageItem
36 // ========================================================================
37 @interface WXCTabViewImageItem : NSTabViewItem
43 - (id)initWithIdentifier: (id)identifier;
46 - (NSSize)sizeOfLabel:(BOOL)shouldTruncateLabel;
47 - (void)drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)tabRect;
50 - (void)setImage:(NSImage*)image;
51 @end // interface WXCTabViewImageItem : NSTabViewItem
52 WX_DECLARE_GET_OBJC_CLASS(WXCTabViewImageItem,NSTabViewItem)
54 @implementation WXCTabViewImageItem : NSTabViewItem
57 return [self initWithIdentifier:nil];
60 - (id)initWithIdentifier: (id)identifier;
63 return [super initWithIdentifier:identifier];
72 - (NSSize)sizeOfLabel:(BOOL)shouldTruncateLabel
74 NSSize labelSize = [super sizeOfLabel:shouldTruncateLabel];
77 NSSize imageSize = [m_image size];
79 if(imageSize.height > labelSize.height)
81 imageSize.width *= labelSize.height/imageSize.height;
82 imageSize.height *= labelSize.height/imageSize.height;
83 [m_image setScalesWhenResized:YES];
84 [m_image setSize: imageSize];
86 labelSize.width += imageSize.width;
90 - (void)drawLabel:(BOOL)shouldTruncateLabel inRect:(NSRect)tabRect
94 NSSize imageSize = [m_image size];
95 [m_image compositeToPoint:NSMakePoint(tabRect.origin.x,
96 tabRect.origin.y+imageSize.height)
97 operation:NSCompositeSourceOver];
98 tabRect.size.width -= imageSize.width;
99 tabRect.origin.x += imageSize.width;
101 [super drawLabel:shouldTruncateLabel inRect:tabRect];
109 - (void)setImage:(NSImage*)image
116 [[NSPasteboard generalPasteboard]
117 declareTypes:[NSArray arrayWithObject:NSTIFFPboardType]
119 [[NSPasteboard generalPasteboard]
120 setData:[m_image TIFFRepresentation]
121 forType:NSTIFFPboardType];
124 @end // implementation WXCTabViewImageItem : NSTabViewItem
125 WX_IMPLEMENT_GET_OBJC_CLASS(WXCTabViewImageItem,NSTabViewItem)
127 // ========================================================================
129 // ========================================================================
130 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
131 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
132 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
134 // ========================================================================
136 // ========================================================================
137 IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxBookCtrlBase)
138 BEGIN_EVENT_TABLE(wxNotebook, wxNotebookBase)
140 WX_IMPLEMENT_COCOA_OWNER(wxNotebook,NSTabView,NSView,NSView)
142 bool wxNotebook::Create(wxWindow *parent, wxWindowID winid,
146 const wxString& name)
148 wxAutoNSAutoreleasePool pool;
149 if(!CreateControl(parent,winid,pos,size,style,wxDefaultValidator,name))
151 m_cocoaNSView = NULL;
152 SetNSTabView([[NSTabView alloc] initWithFrame:MakeDefaultNSRect(size)]);
156 NSTabViewType tabViewType;
158 tabViewType = NSTopTabsBezelBorder;
159 else if(style & wxNB_LEFT)
160 tabViewType = NSLeftTabsBezelBorder;
161 else if(style & wxNB_RIGHT)
162 tabViewType = NSRightTabsBezelBorder;
163 else if(style & wxNB_BOTTOM)
164 tabViewType = NSBottomTabsBezelBorder;
167 [GetNSTabView() setTabViewType:tabViewType];
171 m_parent->CocoaAddChild(this);
172 SetInitialFrameRect(pos,size);
177 wxNotebook::~wxNotebook()
181 void wxNotebook::SetPadding(const wxSize& padding)
185 void wxNotebook::SetTabSize(const wxSize& sz)
189 void wxNotebook::SetPageSize(const wxSize& size)
194 wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage)
196 wxNotebookPage *page = wxNotebookBase::DoRemovePage(nPage);
199 NSTabViewItem *tvitem = [GetNSTabView() tabViewItemAtIndex: nPage];
202 [GetNSTabView() removeTabViewItem:tvitem];
203 // Remove the child window as a notebook page
204 wxASSERT(static_cast<NSView*>([tvitem view]) == page->GetNSViewForSuperview());
205 [tvitem setView:nil];
207 // Make it back into a normal child window
208 [m_cocoaNSView addSubview: page->GetNSViewForSuperview()];
213 bool wxNotebook::DeletePage(size_t nPage)
215 return wxNotebookBase::DeletePage(nPage);
218 bool wxNotebook::InsertPage( size_t pos,
219 wxNotebookPage *page, const wxString& title,
220 bool bSelect, int imageId)
222 wxAutoNSAutoreleasePool pool;
223 m_pages.Insert(page,pos);
224 NSTabViewItem *tvitem = [[WX_GET_OBJC_CLASS(WXCTabViewImageItem) alloc] initWithIdentifier:nil];
225 [tvitem setLabel: wxNSStringWithWxString(title)];
226 const wxBitmap *bmp = (imageId!=-1)?m_imageList->GetBitmapPtr(imageId):NULL;
228 [(WXCTabViewImageItem*) tvitem setImage: bmp->GetNSImage(true)];
230 NSView *pageNSView = page->GetNSViewForSuperview();
231 // Remove it as a normal child
232 wxASSERT(m_cocoaNSView == [pageNSView superview]);
233 [pageNSView removeFromSuperview];
234 // And make it a notebook page
235 [tvitem setView: pageNSView];
237 [GetNSTabView() insertTabViewItem:tvitem atIndex:pos];
243 bool wxNotebook::DeleteAllPages()
245 while(!m_pages.IsEmpty())
251 bool wxNotebook::SetPageText(size_t nPage, const wxString& title)
253 NSTabViewItem *tvitem = [GetNSTabView() tabViewItemAtIndex: nPage];
256 [tvitem setLabel: wxNSStringWithWxString(title)];
260 wxString wxNotebook::GetPageText(size_t nPage) const
262 return wxStringWithNSString([[GetNSTabView() tabViewItemAtIndex: nPage] label]);
266 int wxNotebook::GetPageImage(size_t nPage) const
268 // To do this we'd need to keep track of this, which we don't!
272 bool wxNotebook::SetPageImage(size_t nPage, int nImage)
274 const wxBitmap *bmp = nImage!=-1?m_imageList->GetBitmapPtr(nImage):NULL;
277 NSTabViewItem *tvitem = [GetNSTabView() tabViewItemAtIndex: nPage];
280 [(WXCTabViewImageItem*) tvitem setImage: bmp->GetNSImage(true)];
284 int wxNotebook::SetSelection(size_t nPage)
286 const int pageOld = GetSelection();
288 if ( !SendPageChangingEvent(nPage) )
291 int page = ChangeSelection(nPage);
292 if ( page != wxNOT_FOUND )
294 SendPageChangedEvent(pageOld);
300 int wxNotebook::ChangeSelection(size_t nPage)
302 wxAutoNSAutoreleasePool pool;
303 [GetNSTabView() selectTabViewItemAtIndex:nPage];
304 return GetSelection();
307 int wxNotebook::GetSelection() const
309 NSTabViewItem *selectedItem = [GetNSTabView() selectedTabViewItem];
312 return [GetNSTabView() indexOfTabViewItem:selectedItem];
315 void wxNotebook::CocoaDelegate_tabView_didSelectTabViewItem(WX_NSTabViewItem tabViewItem)
317 // FIXME: oldSel probably == newSel
318 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, GetId(),
319 [GetNSTabView() indexOfTabViewItem:tabViewItem], GetSelection());
320 event.SetEventObject(this);
323 bool wxNotebook::CocoaDelegate_tabView_shouldSelectTabViewItem(WX_NSTabViewItem tabViewItem)
325 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, GetId(),
326 [GetNSTabView() indexOfTabViewItem:tabViewItem], GetSelection());
327 event.SetEventObject(this);
328 return !HandleWindowEvent(event) || event.IsAllowed();
331 #endif // wxUSE_NOTEBOOK