1///////////////////////////////////////////////////////////////////////////// 2// Name: src/cocoa/frame.mm 3// Purpose: wxFrame 4// Author: David Elliott 5// Modified by: 6// Created: 2003/03/16 7// RCS-ID: $Id: frame.mm 47398 2007-07-12 21:17:27Z DE $ 8// Copyright: (c) 2003 David Elliott 9// Licence: wxWidgets licence 10///////////////////////////////////////////////////////////////////////////// 11 12#include "wx/wxprec.h" 13 14#include "wx/frame.h" 15 16#ifndef WX_PRECOMP 17 #include "wx/log.h" 18 #include "wx/app.h" 19 #include "wx/menu.h" 20 #include "wx/toolbar.h" 21 #include "wx/statusbr.h" 22#endif // WX_PRECOMP 23 24#include "wx/cocoa/autorelease.h" 25#include "wx/cocoa/mbarman.h" 26 27#import <AppKit/NSWindow.h> 28#import <AppKit/NSApplication.h> 29#import <AppKit/NSView.h> 30#import <AppKit/NSMenuItem.h> 31 32// wxFrame 33 34BEGIN_EVENT_TABLE(wxFrame, wxFrameBase) 35END_EVENT_TABLE() 36 37IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxTopLevelWindow) 38 39void wxFrame::Init() 40{ 41 m_frameNSView = nil; 42} 43 44bool wxFrame::Create(wxWindow *parent, 45 wxWindowID winid, 46 const wxString& title, 47 const wxPoint& pos, 48 const wxSize& size, 49 long style, 50 const wxString& name) 51{ 52 bool rt = wxTopLevelWindow::Create(parent,winid,title,pos,size,style,name); 53 54 return rt; 55} 56 57wxFrame::~wxFrame() 58{ 59 [m_frameNSView release]; 60} 61 62// ------------------------------------------------------------------- 63// Menubar 64void wxFrame::AttachMenuBar(wxMenuBar *mbar) 65{ 66 wxFrameBase::AttachMenuBar(mbar); 67 wxMenuBarManager::GetInstance()->UpdateMenuBar(); 68} 69 70void wxFrame::DetachMenuBar() 71{ 72 wxFrameBase::DetachMenuBar(); 73 wxMenuBarManager::GetInstance()->UpdateMenuBar(); 74} 75 76void wxFrame::SetMenuBar(wxMenuBar *menubar) 77{ 78 if ( menubar == GetMenuBar() ) 79 { 80 // nothing to do 81 return; 82 } 83 84 wxFrameBase::DetachMenuBar(); 85 wxFrameBase::AttachMenuBar(menubar); 86 wxMenuBarManager::GetInstance()->UpdateMenuBar(); 87} 88 89wxMenuBar* wxFrame::GetAppMenuBar(wxCocoaNSWindow *win) 90{ 91 if(GetMenuBar()) 92 return GetMenuBar(); 93 return wxFrameBase::GetAppMenuBar(win); 94} 95 96void wxFrame::CocoaDelegate_wxMenuItemAction(WX_NSMenuItem menuItem) 97{ 98 wxLogTrace(wxTRACE_COCOA,wxT("wxFrame::wxMenuItemAction")); 99 wxMenuItem *item = wxMenuItem::GetFromCocoa(menuItem); 100 wxCHECK_RET(item,wxT("wxMenuItemAction received but no wxMenuItem exists!")); 101 102 wxMenu *menu = item->GetMenu(); 103 wxCHECK_RET(menu,wxT("wxMenuItemAction received but wxMenuItem is not in a wxMenu!")); 104 105 // Since we're handling the delegate messages there's a very good chance 106 // we'll receive a menu action from an item with a nil target. 107 wxMenuBar *menubar = menu->GetMenuBar(); 108 if(menubar) 109 { 110 wxFrame *frame = menubar->GetFrame(); 111 wxASSERT_MSG(frame==this, wxT("Received wxMenuItemAction in NSWindow delegate from a menu item attached to a different frame.")); 112 frame->ProcessCommand(item->GetId()); 113 } 114 else 115 wxLogDebug(wxT("Received wxMenuItemAction in NSWindow delegate from an unknown menu item.")); 116} 117 118bool wxFrame::CocoaDelegate_validateMenuItem(WX_NSMenuItem menuItem) 119{ 120 SEL itemAction = [menuItem action]; 121 if(itemAction == @selector(wxMenuItemAction:)) 122 { 123 wxMenuItem *item = wxMenuItem::GetFromCocoa(menuItem); 124 wxCHECK_MSG(item,false,wxT("validateMenuItem received but no wxMenuItem exists!")); 125 // TODO: do more sanity checking 126 return item->IsEnabled(); 127 } 128 // TODO: else if cut/copy/paste 129 wxLogDebug(wxT("Asked to validate an unknown menu item")); 130 return false; 131} 132 133// ------------------------------------------------------------------- 134// Origin/Size 135wxPoint wxFrame::GetClientAreaOrigin() const 136{ 137 return wxPoint(0,0); 138} 139 140void wxFrame::CocoaSetWxWindowSize(int width, int height) 141{ 142 if(m_frameStatusBar) 143 height += m_frameStatusBar->GetSize().y; 144#if wxUSE_TOOLBAR 145 if(m_frameToolBar) 146 height += m_frameToolBar->GetSize().y; 147#endif //wxUSE_TOOLBAR 148 wxTopLevelWindow::CocoaSetWxWindowSize(width,height); 149} 150 151// ------------------------------------------------------------------- 152WX_NSView wxFrame::GetNonClientNSView() 153{ 154 if(m_frameNSView) 155 return m_frameNSView; 156 return GetNSViewForSuperview(); 157} 158 159void wxFrame::CocoaReplaceView(WX_NSView oldView, WX_NSView newView) 160{ 161 // If we have the additional toolbar/statbar view, then the 162 // default replaceSubview will work. Otherwise, the old view 163 // should be the content view and should be replaced that way 164 if(m_frameNSView) 165 wxWindow::CocoaReplaceView(oldView, newView); 166 else 167 wxTopLevelWindow::CocoaReplaceView(oldView, newView); 168} 169 170void wxFrame::UpdateFrameNSView() 171{ 172 if(!m_frameNSView) 173 { // NOTE: We only need a plain NSView here since we don't associate it with ourselves. 174 m_frameNSView = [[NSView alloc] initWithFrame:[[m_cocoaNSWindow contentView] frame]]; 175 [m_cocoaNSWindow setContentView: m_frameNSView]; 176 [m_frameNSView addSubview:m_cocoaNSView]; 177 } 178 NSRect frameRect = [m_frameNSView frame]; 179 float tbarheight = 0.0; 180#if wxUSE_TOOLBAR 181 if(m_frameToolBar) 182 { 183 NSView *tbarNSView = m_frameToolBar->GetNSViewForSuperview(); 184 // If the toolbar doesn't have a superview then set it to our 185 // content view. 186 if(![tbarNSView superview]) 187 [m_frameNSView addSubview: tbarNSView]; 188 // Do this after addSubView so that SetSize can work 189 m_frameToolBar->SetSize(m_frameToolBar->DoGetBestSize()); 190 NSRect tbarRect = [tbarNSView frame]; 191 tbarRect.size.width = frameRect.size.width; 192 tbarRect.origin.x = 0.0; 193 tbarRect.origin.y = frameRect.size.height - tbarRect.size.height; 194 [tbarNSView setFrame:tbarRect]; 195 // width expands, bottom margin expands 196 [tbarNSView setAutoresizingMask: NSViewWidthSizable|NSViewMinYMargin]; 197 tbarheight = tbarRect.size.height; 198 } 199#endif //wxUSE_TOOLBAR 200 float sbarheight = 0.0; 201 if(m_frameStatusBar) 202 { 203 NSView *sbarNSView = m_frameStatusBar->GetNSViewForSuperview(); 204 if(![sbarNSView superview]) 205 [m_frameNSView addSubview: sbarNSView]; 206 NSRect sbarRect = [sbarNSView frame]; 207 sbarRect.size.width = frameRect.size.width; 208 sbarRect.origin.x = 0.0; 209 sbarRect.origin.y = 0.0; 210 [sbarNSView setFrame:sbarRect]; 211 // width expands, top margin expands 212 [sbarNSView setAutoresizingMask: NSViewWidthSizable|NSViewMaxYMargin]; 213 sbarheight = sbarRect.size.height; 214 } 215 wxLogTrace(wxTRACE_COCOA,wxT("frame height=%f, tbar=%f, sbar=%f"),frameRect.size.height,tbarheight,sbarheight); 216 NSRect innerRect = [m_cocoaNSView frame]; 217 innerRect.size.height = frameRect.size.height - tbarheight - sbarheight; 218 innerRect.origin.y = sbarheight; 219 [m_cocoaNSView setFrame:innerRect]; 220 [m_cocoaNSView setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; 221 // Don't let the frame get smaller than the toolbar+statusbar height 222 NSRect frameMinRect = [NSWindow frameRectForContentRect: 223 NSMakeRect(0.0,0.0,0.0,tbarheight+sbarheight) 224 styleMask: [m_cocoaNSWindow styleMask]]; 225 [m_cocoaNSWindow setMinSize:frameMinRect.size]; 226} 227 228void wxFrame::SetStatusBar(wxStatusBar *statusbar) 229{ 230 if(m_frameStatusBar) 231 { 232 [m_frameStatusBar->GetNSViewForSuperview() removeFromSuperview]; 233 [m_frameStatusBar->GetNSViewForSuperview() setAutoresizingMask: NSViewMinYMargin]; 234 if(m_frameStatusBar->GetParent()) 235 m_frameStatusBar->GetParent()->CocoaAddChild(m_frameStatusBar); 236 } 237 m_frameStatusBar = statusbar; 238 if(m_frameStatusBar) 239 { 240 m_frameStatusBar->CocoaRemoveFromParent(); 241 } 242 UpdateFrameNSView(); 243} 244 245wxStatusBar* wxFrame::CreateStatusBar(int number, 246 long style, 247 wxWindowID winid, 248 const wxString& name) 249{ 250 wxAutoNSAutoreleasePool pool; 251 wxFrameBase::CreateStatusBar(number,style,winid,name); 252 if(m_frameStatusBar) 253 { 254 m_frameStatusBar->CocoaRemoveFromParent(); 255 } 256 UpdateFrameNSView(); 257 return m_frameStatusBar; 258} 259 260#if wxUSE_TOOLBAR 261void wxFrame::SetToolBar(wxToolBar *toolbar) 262{ 263 if(m_frameToolBar) 264 { 265 m_frameToolBar->SetOwningFrame(NULL); 266 [m_frameToolBar->GetNSViewForSuperview() removeFromSuperview]; 267 [m_frameToolBar->GetNSViewForSuperview() setAutoresizingMask: NSViewMinYMargin]; 268 if(m_frameToolBar->GetParent()) 269 m_frameToolBar->GetParent()->CocoaAddChild(m_frameToolBar); 270 } 271 m_frameToolBar = toolbar; 272 if(m_frameToolBar) 273 { 274 m_frameToolBar->CocoaRemoveFromParent(); 275 m_frameToolBar->SetOwningFrame(this); 276 } 277 UpdateFrameNSView(); 278} 279 280wxToolBar* wxFrame::CreateToolBar(long style, 281 wxWindowID winid, 282 const wxString& name) 283{ 284 wxAutoNSAutoreleasePool pool; 285 return wxFrameBase::CreateToolBar(style,winid,name); 286} 287#endif // wxUSE_TOOLBAR 288 289void wxFrame::PositionStatusBar() 290{ 291} 292