1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 
3 /* AbiSource Application Framework
4  * Copyright (C) 1998 AbiSource, Inc.
5  * Copyright (C) 2001-2004 Hubert Figuiere
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301 USA.
21  */
22 
23 
24 #import <Cocoa/Cocoa.h>
25 
26 #import "ut_debugmsg.h"
27 #import "ut_assert.h"
28 #import "ut_sleep.h"
29 
30 #import "fv_View.h"
31 #import "ev_EditMethod.h"
32 #import "ev_CocoaKeyboard.h"
33 #import "ev_CocoaMouse.h"
34 #import "ev_CocoaMenu.h"
35 #import "ev_CocoaMenuBar.h"
36 #import "ev_CocoaMenuPopup.h"
37 #import "ev_CocoaToolbar.h"
38 #import "ev_Toolbar.h"
39 #import "gr_CocoaCairoGraphics.h"
40 #import "xap_App.h"
41 #import "xap_CocoaApp.h"
42 #import "xap_CocoaAppController.h"
43 #import "xap_CocoaFrameImpl.h"
44 #import "xap_CocoaTextView.h"
45 #import "xap_CocoaTimer.h"
46 #import "xap_CocoaToolbarWindow.h"
47 #import "xap_CocoaToolPalette.h"
48 #import "xap_FrameImpl.h"
49 #import "xap_Frame.h"
50 #import "xap_FrameNSWindow.h"
51 
52 /*****************************************************************/
53 
54 #define ENSUREP(p)		do { UT_ASSERT(p); if (!p) goto Cleanup; } while (0)
55 
56 
57 NSString* XAP_CocoaFrameImpl::XAP_FrameNeedToolbar = @"XAP_FrameNeedToolbar";
58 NSString* XAP_CocoaFrameImpl::XAP_FrameReleaseToolbar = @"XAP_FrameReleaseToolbar";
59 
60 
61 /*****************************************************************/
62 
XAP_CocoaFrameImpl(XAP_Frame * frame)63 XAP_CocoaFrameImpl::XAP_CocoaFrameImpl(XAP_Frame* frame)
64 	: XAP_FrameImpl (frame),
65 	  m_dialogFactory(XAP_App::getApp(), frame),
66 	  m_pCocoaPopup(NULL),
67 	  m_frameController(nil)
68 {
69 //	m_pView = NULL;
70 
71 	// dirty hack to make sure the frame is compiled in as the class is only
72 	// referenced from a nib.
73 	XAP_FrameNSWindow *p = nil;
74 	if (0) {
75 		p = [[[XAP_FrameNSWindow alloc] init] autorelease];
76 	}
77 }
78 
79 // TODO when cloning a new frame from an existing one
80 // TODO should we also clone any frame-persistent
81 // TODO dialog data ??
82 /*
83 XAP_CocoaFrameImpl::XAP_CocoaFrameImpl(XAP_CocoaFrameImpl * f)
84 	: XAP_FrameImpl(f),
85 	  m_dialogFactory(XAP_App::getApp(), f->m_pFrame),
86 	  m_pCocoaMenu(NULL),
87 	  m_pCocoaPopup(NULL),
88 	  m_frameController(nil)
89 {
90 	m_pView = NULL;
91 }
92 */
93 
~XAP_CocoaFrameImpl(void)94 XAP_CocoaFrameImpl::~XAP_CocoaFrameImpl(void)
95 {
96 	// only delete the things we created...
97 	if 	(m_frameController != nil) {
98 		[m_frameController release];
99 	}
100 
101 	DELETEP(m_pCocoaPopup);
102 }
103 
104 /*
105 bool XAP_CocoaFrameImpl::initialize(const char * szKeyBindingsKey, const char * szKeyBindingsDefaultValue,
106 								  const char * szMenuLayoutKey, const char * szMenuLayoutDefaultValue,
107 								  const char * szMenuLabelSetKey, const char * szMenuLabelSetDefaultValue,
108 								  const char * szToolbarLayoutsKey, const char * szToolbarLayoutsDefaultValue,
109 								  const char * szToolbarLabelSetKey, const char * szToolbarLabelSetDefaultValue)
110 {
111 	bool bResult;
112 
113 	// invoke our base class first.
114 
115 	bResult = XAP_Frame::initialize(szKeyBindingsKey, szKeyBindingsDefaultValue,
116 									szMenuLayoutKey, szMenuLayoutDefaultValue,
117 									szMenuLabelSetKey, szMenuLabelSetDefaultValue,
118 									szToolbarLayoutsKey, szToolbarLayoutsDefaultValue,
119 									szToolbarLabelSetKey, szToolbarLabelSetDefaultValue);
120 	UT_ASSERT(bResult);
121 */
_initialize()122 void XAP_CocoaFrameImpl::_initialize()
123 {
124    	// get a handle to our keyboard binding mechanism
125 	// and to our mouse binding mechanism.
126 
127 	EV_EditEventMapper * pEEM = XAP_App::getApp()->getEditEventMapper();
128 	UT_ASSERT(pEEM);
129 
130 	m_pKeyboard = new ev_CocoaKeyboard(pEEM);
131 	UT_ASSERT(m_pKeyboard);
132 
133 	m_pMouse = new EV_CocoaMouse(pEEM);
134 	UT_ASSERT(m_pMouse);
135 }
136 
notifyViewChanged(AV_View * pView)137 void XAP_CocoaFrameImpl::notifyViewChanged(AV_View * pView) // called from XAP_Frame::setView(pView)
138 {
139 	if (XAP_Frame * pFrame = getFrame())
140 		{
141 			XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [NSApp delegate];
142 			[pController resetCurrentView:pView inFrame:pFrame];
143 		}
144 }
145 
_setInputMode(const char * szName)146 UT_sint32 XAP_CocoaFrameImpl::_setInputMode(const char * szName)
147 {
148 	UT_sint32 result = XAP_App::getApp()->setInputMode(szName);
149 	if (result == 1)
150 	{
151 		// if it actually changed we need to update keyboard and mouse
152 
153 		EV_EditEventMapper * pEEM = XAP_App::getApp()->getEditEventMapper();
154 		UT_ASSERT(pEEM);
155 
156 		m_pKeyboard->setEditEventMap(pEEM);
157 		m_pMouse->setEditEventMap(pEEM);
158 	}
159 
160 	return result;
161 }
162 
getTopLevelWindow(void) const163 NSWindow * XAP_CocoaFrameImpl::getTopLevelWindow(void) const
164 {
165 	UT_ASSERT (m_frameController);
166 	return [m_frameController window];
167 }
168 
getVBoxWidget(void) const169 NSView * XAP_CocoaFrameImpl::getVBoxWidget(void) const
170 {
171 	UT_ASSERT (m_frameController);
172 	return [m_frameController getMainView];
173 }
174 
_getDialogFactory(void)175 XAP_DialogFactory * XAP_CocoaFrameImpl::_getDialogFactory(void)
176 {
177 	return &m_dialogFactory;
178 }
179 
_nullUpdate() const180 void XAP_CocoaFrameImpl::_nullUpdate() const
181 {
182 	/* FIXME: do this more propperly if there is any chance...*/
183 	[[m_frameController window] displayIfNeeded];
184 }
185 
186 static UT_uint32	s_iNewFrameOffsetX = 0;
187 static UT_uint32	s_iNewFrameOffsetY = 0;
188 
_createTopLevelWindow(void)189 void XAP_CocoaFrameImpl::_createTopLevelWindow(void)
190 {
191 	// create a top-level window for us.
192 	m_frameController = _createController();
193 	UT_ASSERT (m_frameController);
194 
195 	NSWindow * theWindow = [m_frameController window];
196 	UT_ASSERT (theWindow);
197 	[theWindow setTitle:[NSString stringWithUTF8String:XAP_App::getApp()->getApplicationTitleForTitleBar()]];
198 
199 	// create a toolbar instance for each toolbar listed in our base class.
200 
201 	_createToolbars();
202 
203 	// Let the app-specific frame code create the contents of
204 	// the child area of the window (between the toolbars and
205 	// the status bar).
206 	_createDocumentWindow();
207 
208 	// Let the app-specific frame code create the status bar
209 	// if it wants to.  we will put it below the document
210 	// window (a peer with toolbars and the overall sunkenbox)
211 	// so that it will appear outside of the scrollbars.
212 	_createStatusBarWindow([m_frameController getStatusBar]);
213 
214 	// set the icon
215 	_setWindowIcon();
216 
217 	// set geometry hints as the user requested
218 	int x, y;
219 	UT_uint32 width, height;
220 	XAP_CocoaApp::windowGeometryFlags f;
221 
222 	dynamic_cast<XAP_CocoaApp*>(XAP_App::getApp())->getGeometry(&x, &y, &width, &height, &f);
223 
224 	// Set the size if requested
225 	NSSize userSize;
226 	// userSize.width  = (width  < 300.0f) ? 300.0f : static_cast<float>(width);
227 	// userSize.height = (height < 300.0f) ? 300.0f : static_cast<float>(height);
228 
229 	if (f & XAP_CocoaApp::GEOMETRY_FLAG_SIZE)
230 	{
231 		NSRect screenFrame = [[NSScreen mainScreen] visibleFrame];
232 
233 		screenFrame.size.height -= [[XAP_CocoaToolbarWindow_Controller sharedToolbar] height];
234 
235 		if ([XAP_CocoaToolPalette instantiated])
236 		{
237 			NSWindow * palettePanel = [[XAP_CocoaToolPalette instance:theWindow] window];
238 			if ([palettePanel isVisible])
239 			{
240 				NSRect paletteFrame = [palettePanel frame];
241 				if (paletteFrame.origin.x < screenFrame.origin.x + 10.0f) // panel at left
242 				{
243 					screenFrame.origin.x   += paletteFrame.size.width;
244 					screenFrame.size.width -= paletteFrame.size.width;
245 				}
246 				else if (paletteFrame.origin.x + paletteFrame.size.width > screenFrame.origin.x + screenFrame.size.width - 10.0f) // panel at right
247 				{
248 					screenFrame.size.width -= paletteFrame.size.width;
249 				}
250 			}
251 		}
252 
253 		userSize.height = screenFrame.size.height;
254 		userSize.width  = rintf(screenFrame.size.height * 0.9f);
255 
256 		if (XAP_App::getApp()->getFrameCount() == 1)
257 		{
258 			s_iNewFrameOffsetX = 0;
259 			s_iNewFrameOffsetY = 0;
260 		}
261 
262 		screenFrame.origin.x    += s_iNewFrameOffsetX;
263 		screenFrame.size.height -= s_iNewFrameOffsetY;
264 
265 		s_iNewFrameOffsetX = (s_iNewFrameOffsetX <= 128) ? (s_iNewFrameOffsetX + 32) : 0;
266 		s_iNewFrameOffsetY = (s_iNewFrameOffsetY <  128) ? (s_iNewFrameOffsetY + 32) : 0;
267 
268 		NSRect windowFrame;
269 		windowFrame.size.width  = UT_MIN(screenFrame.size.width,  userSize.width ); // 813);
270 		windowFrame.size.height = UT_MIN(screenFrame.size.height, userSize.height); // 836);
271 		windowFrame.origin.x = screenFrame.origin.x;
272 		windowFrame.origin.y = screenFrame.origin.y + screenFrame.size.height - windowFrame.size.height;
273 
274 		[theWindow setFrame:windowFrame display:YES];
275 	}
276 }
277 
278 
_rebuildMenus()279 void XAP_CocoaFrameImpl::_rebuildMenus()
280 {
281 #if 0
282 	// destroy old menu
283 	m_pUnixMenu->destroy();
284 	DELETEP(m_pUnixMenu);
285 
286 	// build new one.
287 	m_pUnixMenu = new EV_CocoaMenuBar(static_cast<XAP_UnixApp*>(XAP_App::getApp()), getFrame(),
288 					 m_szMenuLayoutName,
289 					 m_szMenuLabelSetName);
290 	UT_return_if_fail(m_pUnixMenu);
291 	bool bResult = m_pUnixMenu->rebuildMenuBar();
292 	UT_ASSERT_HARMLESS(bResult);
293 #endif
294 	UT_ASSERT(UT_NOT_IMPLEMENTED);
295 }
296 
297 
298 /*!
299  * This code is used by the dynamic toolbar API to rebuild a toolbar after a
300  * a change in the toolbar structure.
301  */
_rebuildToolbar(UT_uint32 ibar)302 void XAP_CocoaFrameImpl::_rebuildToolbar(UT_uint32 ibar)
303 {
304 	XAP_Frame* pFrame = getFrame();
305 //
306 // Destroy the old toolbar
307 //
308 	EV_Toolbar * pToolbar = (EV_Toolbar *) m_vecToolbars.getNthItem(ibar);
309 	const char * szTBName = (const char *) m_vecToolbarLayoutNames.getNthItem(ibar);
310 	EV_CocoaToolbar * pUTB = static_cast<EV_CocoaToolbar *>( pToolbar);
311 	UT_sint32 oldpos = pUTB->destroy();
312 //
313 // Delete the old class
314 //
315 	delete pToolbar;
316 	if(oldpos < 0)
317 	{
318 		return;
319 	}
320 //
321 // Build a new one.
322 //
323 	pToolbar = _newToolbar(pFrame, szTBName,
324 						   (const char *) m_szToolbarLabelSetName);
325 	static_cast<EV_CocoaToolbar *>(pToolbar)->rebuildToolbar(oldpos);
326 	m_vecToolbars.setNthItem(ibar, pToolbar, NULL);
327 //
328 // Refill the framedata pointers
329 //
330 	pFrame->refillToolbarsInFrameData();
331 	pFrame->repopulateCombos();
332 }
333 
_close()334 bool XAP_CocoaFrameImpl::_close()
335 {
336 	UT_DEBUGMSG (("XAP_CocoaFrame::close()\n"));
337 	[m_frameController close];
338 	[[NSNotificationCenter defaultCenter] postNotificationName:XAP_FrameReleaseToolbar object:m_frameController];
339 	return true;
340 }
341 
_raise()342 bool XAP_CocoaFrameImpl::_raise()
343 {
344 	UT_DEBUGMSG (("XAP_CocoaFrame::raise()\n"));
345 	[[m_frameController window] makeKeyAndOrderFront:m_frameController];
346 	[[NSNotificationCenter defaultCenter] postNotificationName:XAP_FrameNeedToolbar object:m_frameController];
347 	return true;
348 }
349 
_show()350 bool XAP_CocoaFrameImpl::_show()
351 {
352 	UT_DEBUGMSG (("XAP_CocoaFrame::show()\n"));
353 	[[m_frameController window] makeKeyAndOrderFront:m_frameController];
354 	[[NSNotificationCenter defaultCenter] postNotificationName:XAP_FrameNeedToolbar object:m_frameController];
355 
356 	XAP_CocoaTextView * textView = (XAP_CocoaTextView *) [m_frameController textView];
357 	[textView hasBeenResized:nil];
358 
359 	return true;
360 }
361 
362 
getColorSelBackground() const363 UT_RGBColor XAP_CocoaFrameImpl::getColorSelBackground () const
364 {
365 	/* this code is disabled as the NSColor returned is not RGB compatible. */
366 	static UT_RGBColor * c = NULL;
367 	if (c == NULL) {
368 		c = new UT_RGBColor();
369 		GR_CocoaCairoGraphics::_utNSColorToRGBColor ([[NSColor selectedTextBackgroundColor]
370 					colorUsingColorSpaceName:NSCalibratedRGBColorSpace], *c);
371 	}
372 	return *c;
373 }
374 
375 
_updateTitle()376 bool XAP_CocoaFrameImpl::_updateTitle()
377 {
378 	if (!XAP_FrameImpl::_updateTitle())
379 	{
380 		// no relevant change, so skip it
381 		return false;
382 	}
383 
384 	NSWindow * theWindow = [m_frameController window];
385 	UT_ASSERT (theWindow);
386 	if (theWindow)
387 		{
388 			const char * szTitle    = getFrame()->getNonDecoratedTitle();
389 			const char * szFilename = getFrame()->getFilename();
390 
391 			[theWindow setTitle:[NSString stringWithUTF8String:szTitle]];
392 			if (szFilename)
393 				[theWindow setRepresentedFilename:[NSString stringWithUTF8String:szFilename]];
394 
395 			[theWindow setDocumentEdited:(getFrame()->isDirty() ? YES : NO)];
396 		}
397 	return true;
398 }
399 
400 /*****************************************************************/
_runModalContextMenu(AV_View *,const char * szMenuName,UT_sint32,UT_sint32)401 bool XAP_CocoaFrameImpl::_runModalContextMenu(AV_View * /* pView */, const char * szMenuName,
402 										   UT_sint32 /*x*/, UT_sint32 /*y*/)
403 {
404 	bool bResult = true;
405 
406 	UT_ASSERT(!m_pCocoaPopup);
407 
408 	m_pCocoaPopup = new EV_CocoaMenuPopup(szMenuName, m_szMenuLabelSetName);
409 	if (m_pCocoaPopup && m_pCocoaPopup->synthesizeMenuPopup()) {
410 		NSEvent *evt = [NSApp currentEvent];
411 		[NSMenu popUpContextMenu:m_pCocoaPopup->getMenuHandle() withEvent:evt forView:[m_frameController getMainView]];
412 	}
413 	XAP_Frame * pFrame = (XAP_Frame *)getFrame();
414 	if (pFrame->getCurrentView()) {
415 		pFrame->getCurrentView()->focusChange( AV_FOCUS_HERE);
416 	}
417 	DELETEP(m_pCocoaPopup);
418 	return bResult;
419 }
420 
setTimeOfLastEvent(NSTimeInterval timestamp)421 void XAP_CocoaFrameImpl::setTimeOfLastEvent(NSTimeInterval timestamp)
422 {
423 	dynamic_cast<XAP_CocoaApp*>(XAP_App::getApp())->setTimeOfLastEvent(timestamp);
424 }
425 
_newToolbar(XAP_Frame * frame,const char * szLayout,const char * szLanguage)426 EV_Toolbar * XAP_CocoaFrameImpl::_newToolbar(XAP_Frame *frame,
427 											 const char *szLayout,
428 											 const char *szLanguage)
429 {
430 	return (new EV_CocoaToolbar((AP_CocoaFrame *)frame,
431 								szLayout, szLanguage));
432 }
433 
_queue_resize()434 void XAP_CocoaFrameImpl::_queue_resize()
435 {
436 	UT_DEBUGMSG(("XAP_CocoaFrameImpl::queue_resize\n"));
437 	UT_ASSERT (UT_NOT_IMPLEMENTED);
438 //	gtk_widget_queue_resize(m_wTopLevelWindow);
439 }
440 
441 
_getMainMenu()442 EV_Menu* XAP_CocoaFrameImpl::_getMainMenu()
443 {
444 	return dynamic_cast<XAP_CocoaApp*>(XAP_App::getApp())->getCocoaMenuBar();
445 }
446 
447 
_setController(XAP_CocoaFrameController * ctrl)448 void XAP_CocoaFrameImpl::_setController (XAP_CocoaFrameController * ctrl)
449 {
450 	if ((m_frameController) && (ctrl != m_frameController)){
451 		[m_frameController release];
452 	}
453 	m_frameController = ctrl;
454 }
455 
setToolbarRect(const NSRect & r)456 void XAP_CocoaFrameImpl::setToolbarRect(const NSRect &r)
457 {
458 	UT_uint32 frameCount = XAP_App::getApp()->getFrameCount();
459 	UT_uint32 i;
460 
461 	for (i = 0; i < frameCount; i++) {
462 		XAP_CocoaFrameImpl* impl = dynamic_cast<XAP_CocoaFrameImpl*>(XAP_App::getApp()->getFrame(i)->getFrameImpl());
463 		XAP_CocoaFrameController* ctrl  = impl->_getController();
464 		NSRect frame = [[ctrl window] frame];
465 		if (NSIntersectsRect(frame, r)) {
466 			if (frame.origin.y + frame.size.height > r.origin.y) {
467 				UT_DEBUGMSG(("original frame is %f %f %f %f\n", frame.origin.x, frame.origin.y,
468 									frame.size.width, frame.size.height));
469 				frame.size.height = r.origin.y - frame.origin.y;
470 				[[ctrl window] setFrame:frame display:YES];
471 				UT_DEBUGMSG(("resized frame is %f %f %f %f\n", frame.origin.x, frame.origin.y,
472 									frame.size.width, frame.size.height));
473 			}
474 		}
475 	}
476 }
477 
478 
479 /* Objective C section */
480 
481 @implementation XAP_CocoaFrameController
482 
483 - (BOOL)windowShouldClose:(id)sender
484 {
485 	UT_UNUSED(sender);
486 	UT_DEBUGMSG (("shouldCloseDocument\n"));
487 	UT_ASSERT (m_frame);
488 	XAP_App * pApp = XAP_App::getApp();
489 	UT_ASSERT(pApp);
490 
491 	const EV_EditMethodContainer * pEMC = pApp->getEditMethodContainer();
492 	UT_ASSERT(pEMC);
493 
494 	const EV_EditMethod * pEM = pEMC->findEditMethodByName("closeWindowX");
495 	UT_ASSERT(pEM);
496 
497 	if (pEM)
498 	{
499 		XAP_Frame * pFrame = m_frame->getFrame ();
500 		UT_ASSERT(pFrame);
501 		AV_View * pView = pFrame->getCurrentView();
502 		UT_ASSERT(pView);
503 		if (pEM->Fn(m_frame->getFrame()->getCurrentView(),NULL))
504 		{
505 			// returning YES means close the window
506 			// but first let's warn the app controller not to assume our existence
507 
508 			XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [NSApp delegate];
509 			[pController unsetCurrentView:pView inFrame:pFrame];
510 
511 			return YES;
512 		}
513 	}
514 
515 	// returning NO means do NOT close the window
516 	return NO;
517 }
518 
519 - (void)keyDown:(NSEvent *)theEvent
520 {
521 	xxx_UT_DEBUGMSG(("keyDown in window '%s'\n", [[[self window] title] UTF8String]));
522 	[m_textView interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
523 #if 0
524 	XAP_Frame * pFrame = m_frame->getFrame();
525 //  	pFrame->setTimeOfLastEvent([theEvent timestamp]);
526 	AV_View * pView = pFrame->getCurrentView();
527 	ev_CocoaKeyboard * pCocoaKeyboard = static_cast<ev_CocoaKeyboard *>
528 		(pFrame->getKeyboard());
529 
530 	if (pView)
531 		pCocoaKeyboard->keyPressEvent(pView, theEvent);
532 #endif
533 }
534 
535 - (void)windowDidBecomeKey:(NSNotification *)aNotification
536 {
537 	UT_UNUSED(aNotification);
538 	UT_DEBUGMSG(("windowDidBecomeKey: '%s'\n", [[[self window] title] UTF8String]));
539 
540 	XAP_Frame * pFrame = m_frame->getFrame ();
541 	AV_View * pView = pFrame->getCurrentView();
542 
543 	XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [NSApp delegate];
544 	[pController setCurrentView:pView inFrame:pFrame];
545 
546 	[[NSNotificationCenter defaultCenter] postNotificationName:XAP_CocoaFrameImpl::XAP_FrameNeedToolbar
547 			object:self];
548 }
549 
550 - (void)windowDidExpose:(NSNotification *)aNotification
551 {
552 	UT_UNUSED(aNotification);
553 	UT_DEBUGMSG(("windowDidExpose:\n"));
554 //	[[NSNotificationCenter defaultCenter] postNotificationName:XAP_CocoaFrameImpl::XAP_FrameNeedToolbar
555 //			object:self];
556 }
557 
558 - (void)windowDidResignKey:(NSNotification *)aNotification
559 {
560 	UT_UNUSED(aNotification);
561 	UT_DEBUGMSG(("windowDidResignKey: '%s'\n", [[[self window] title] UTF8String]));
562 
563 	XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [NSApp delegate];
564 	[pController setCurrentView:0 inFrame:0];
565 
566 //	[[NSNotificationCenter defaultCenter] postNotificationName:XAP_CocoaFrameImpl::XAP_FrameReleaseToolbar
567 //			object:self];
568 }
569 
570 
571 /*!
572 	Returns an instance.
573  */
574 + (XAP_CocoaFrameController*)createFrom:(XAP_CocoaFrameImpl *)frame
575 {
576 	UT_DEBUGMSG (("Cocoa: createFrom:frame\n"));
577 	XAP_CocoaFrameController *obj = [[XAP_CocoaFrameController alloc] initWith:frame];
578 	return [obj autorelease];
579 }
580 
581 - (id)initWith:(XAP_CocoaFrameImpl *)frame
582 {
583 	UT_DEBUGMSG (("Cocoa: @XAP_CocoaFrameController initWith:frame\n"));
584 	if(![self initWithWindowNibName:frame->_getNibName()]) {	/* this one will make the call to [super init]  */
585 		return nil;
586 	}
587 	m_frame = frame;
588 	[[self window] setAcceptsMouseMovedEvents:YES];		/* can't we set that from IB (FIXME) */
589 	[[self window] makeFirstResponder:self];
590 	return self;
591 }
592 
593 - (NSView *)getMainView
594 {
595 	return mainView;
596 }
597 
598 
599 - (XAP_CocoaNSStatusBar *)getStatusBar
600 {
601 	return statusBar;
602 }
603 
604 - (XAP_CocoaFrameImpl *)frameImpl
605 {
606 	return m_frame;
607 }
608 
609 - (void)setTextView:(NSView <NSTextInput>*)tv
610 {
611 	m_textView = tv;
612 }
613 
614 - (NSView <NSTextInput>*)textView
615 {
616 	return m_textView;
617 }
618 
619 - (NSArray*)getToolbars
620 {
621 	NSMutableArray*	array = [NSMutableArray array];
622 	const UT_GenericVector<EV_Toolbar*> & toolbars = m_frame->_getToolbars();
623 	UT_uint32 count = toolbars.getItemCount();
624 	for (UT_uint32 i = 0; i < count; i++) {
625 		const EV_CocoaToolbar* tlbr = static_cast<const EV_CocoaToolbar*>(toolbars[i]);
626 		UT_ASSERT(tlbr);
627 		if (!tlbr->isHidden()) {
628 			[array addObject:tlbr->_getToolbarView()];
629 		}
630 	}
631 	return array;
632 }
633 
634 - (NSString *)getToolbarSummaryID
635 {
636 	UT_UTF8String SummaryID;
637 
638 	const UT_GenericVector<EV_Toolbar *> & toolbars = m_frame->_getToolbars();
639 
640 	UT_uint32 count = toolbars.getItemCount();
641 
642 	for (UT_uint32 i = 0; i < count; i++) {
643 		const EV_CocoaToolbar * tlbr = static_cast<const EV_CocoaToolbar *>(toolbars[i]);
644 		UT_ASSERT(tlbr);
645 
646 		if (!tlbr->isHidden()) {
647 			SummaryID += "+";
648 		}
649 		else {
650 			SummaryID += "-";
651 		}
652 	}
653 	return [NSString stringWithUTF8String:(SummaryID.utf8_str())];
654 }
655 
656 @end
657