/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ /* AbiSource Application Framework * Copyright (C) 2003-2004 Hubert Figuiere * Copyright (C) 2004 Francis James Franklin * Copyright (C) 2009 Hubert Figuiere * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #import #include "ut_debugmsg.h" #include "ev_EditMethod.h" #include "ev_CocoaMenuBar.h" #include "xap_CocoaApp.h" #include "xap_CocoaAppController.h" #include "xap_CocoaModule.h" #include "xap_CocoaToolPalette.h" #include "xap_CocoaToolProvider.h" #include "xap_App.h" #include "xap_Frame.h" #include "ie_types.h" #include "ap_Menu_Id.h" struct EV_CocoaKeyEquiv { XAP_Menu_Id menuid; const char * equiv; unsigned int modifier; }; static struct EV_CocoaKeyEquiv KeyEquiv[] = { { AP_MENU_ID_FILE_NEW, "n", NSCommandKeyMask }, // Cmd-N { AP_MENU_ID_FILE_NEW_USING_TEMPLATE, "N", NSCommandKeyMask }, // Cmd-Shift-N { AP_MENU_ID_FILE_OPEN, "o", NSCommandKeyMask }, // Cmd-O { AP_MENU_ID_FILE_SAVE, "s", NSCommandKeyMask }, // Cmd-S { AP_MENU_ID_FILE_SAVEAS, "S", NSCommandKeyMask }, // Cmd-Shift-S { AP_MENU_ID_FILE_CLOSE, "w", NSCommandKeyMask }, // Cmd-W { AP_MENU_ID_FILE_PAGESETUP, "P", NSCommandKeyMask }, // Cmd-Shift-P { AP_MENU_ID_FILE_PRINT, "p", NSCommandKeyMask }, // Cmd-P { AP_MENU_ID_EDIT_UNDO, "z", NSCommandKeyMask }, // Cmd-Z { AP_MENU_ID_EDIT_REDO, "Z", NSCommandKeyMask }, // Cmd-Shift-Z { AP_MENU_ID_EDIT_CUT, "x", NSCommandKeyMask }, // Cmd-X { AP_MENU_ID_EDIT_COPY, "c", NSCommandKeyMask }, // Cmd-C { AP_MENU_ID_EDIT_PASTE, "v", NSCommandKeyMask }, // Cmd-V { AP_MENU_ID_EDIT_PASTE_SPECIAL, "V", NSCommandKeyMask|NSAlternateKeyMask }, // Cmd-Shift-Alt-V { AP_MENU_ID_EDIT_SELECTALL, "a", NSCommandKeyMask }, // Cmd-A { AP_MENU_ID_EDIT_FIND, "f", NSCommandKeyMask }, // Cmd-F { AP_MENU_ID_EDIT_GOTO, "j", NSCommandKeyMask }, // Cmd-J { AP_MENU_ID_VIEW_RULER, "r", NSCommandKeyMask }, // Cmd-R { AP_MENU_ID_FMT_FONT, "t", NSCommandKeyMask }, // Cmd-T { AP_MENU_ID_FMT_BOLD, "b", NSCommandKeyMask }, // Cmd-B { AP_MENU_ID_FMT_ITALIC, "i", NSCommandKeyMask }, // Cmd-I { AP_MENU_ID_FMT_UNDERLINE, "u", NSCommandKeyMask }, // Cmd-U { AP_MENU_ID_TOOLS_SPELL, ":", NSCommandKeyMask }, // Cmd-: { AP_MENU_ID_ALIGN_LEFT, "{", NSCommandKeyMask }, // Cmd-{ { AP_MENU_ID_ALIGN_CENTER, "|", NSCommandKeyMask }, // Cmd-| { AP_MENU_ID_ALIGN_RIGHT, "}", NSCommandKeyMask }, // Cmd-} { 0, 0, 0 } }; @implementation XAP_CocoaApplication - (void)terminate:(id)sender { UT_UNUSED(sender); UT_UCS4String ucs4_empty; ev_EditMethod_invoke("querySaveAndExit", ucs4_empty); } - (void)orderFrontStandardAboutPanel:(id)sender { UT_UNUSED(sender); UT_UCS4String ucs4_empty; ev_EditMethod_invoke("dlgAbout", ucs4_empty); } - (void)orderFrontPreferencesPanel:(id)sender { UT_UNUSED(sender); UT_UCS4String ucs4_empty; ev_EditMethod_invoke("dlgOptions", ucs4_empty); } - (void)openContextHelp:(id)sender { UT_UNUSED(sender); UT_UCS4String ucs4_empty; // Can we use this to override help-contents location? e.g., to bundle help files? [TODO] ev_EditMethod_invoke("helpContents", ucs4_empty); // [TODO: this needs to be redireced to firstResponder] } - (void)sendEvent:(NSEvent *)anEvent { NSWindow * keyWindow = [self keyWindow]; XAP_CocoaAppController * pController = (XAP_CocoaAppController *) [self delegate]; bool bFrameIsActive = pController ? ([pController currentFrame] ? true : false) : false; bool bEventHandled = false; if ([anEvent type] == NSKeyDown) { unsigned int modifierFlags = [anEvent modifierFlags]; if (modifierFlags & NSCommandKeyMask) { if ((bFrameIsActive || !keyWindow) && !(modifierFlags & (NSShiftKeyMask|NSControlKeyMask))) { NSString * str = [anEvent charactersIgnoringModifiers]; if ([str length] == 1) { unichar uc; [str getCharacters:&uc]; if ((uc & 0x7f) == uc) { switch (static_cast(uc)) { case ',': // Cmd-, (preferences) if (!(modifierFlags & NSAlternateKeyMask)) { UT_DEBUGMSG(("[XAP_CocoaApplication -sendEvent: (Cmd-,)]\n")); [self orderFrontPreferencesPanel:self]; bEventHandled = true; } break; case '/': // how to do this, since ? = Shift-/ case '?': // Cmd-? (help) if (!(modifierFlags & NSAlternateKeyMask)) { UT_DEBUGMSG(("[XAP_CocoaApplication -sendEvent: (Cmd-?)]\n")); [self openContextHelp:self]; bEventHandled = true; } break; case 'h': // Alt-Cmd-H (hide others) if (modifierFlags & NSAlternateKeyMask) { UT_DEBUGMSG(("[XAP_CocoaApplication -sendEvent: (Alt-Cmd-H)]\n")); [self hideOtherApplications:self]; bEventHandled = true; } else // Cmd-H (hide application) { UT_DEBUGMSG(("[XAP_CocoaApplication -sendEvent: (Cmd-H)]\n")); [self hide:self]; bEventHandled = true; } break; case 'm': // Cmd-M (minimize current frame/window) if (bFrameIsActive && keyWindow && !(modifierFlags & NSAlternateKeyMask)) { UT_DEBUGMSG(("[XAP_CocoaApplication -sendEvent: (Cmd-M)]\n")); [keyWindow miniaturize:self]; bEventHandled = true; } break; case 'n': // Cmd-N (open untitled) if (pController && !(modifierFlags & NSAlternateKeyMask)) { UT_DEBUGMSG(("[XAP_CocoaApplication -sendEvent: (Cmd-N)]\n")); [pController applicationOpenUntitledFile:self]; bEventHandled = true; } break; case 'o': // Cmd-O (open file) if (pController && !(modifierFlags & NSAlternateKeyMask)) { UT_DEBUGMSG(("[XAP_CocoaApplication -sendEvent: (Cmd-O)]\n")); [pController applicationOpenFile:self]; bEventHandled = true; } break; case 'q': // Cmd-Q (quit) if (!(modifierFlags & NSAlternateKeyMask)) { UT_DEBUGMSG(("[XAP_CocoaApplication -sendEvent: (Cmd-Q)]\n")); [self terminate:self]; bEventHandled = true; } break; default: break; } } } } if (!bEventHandled && false /* m_MenuDelegate */ && bFrameIsActive) { id target; SEL action; if (false /* [m_MenuDelegate menuHasKeyEquivalent:[self mainMenu] forEvent:anEvent target:&target action:&action] */) { [self sendAction:action to:target from:self]; bEventHandled = true; } } else if (!bEventHandled && keyWindow && !bFrameIsActive) { NSString * str = [anEvent charactersIgnoringModifiers]; if ([str length] == 1) { unichar uc; [str getCharacters:&uc]; if ((uc & 0x7f) == uc) switch (static_cast(uc)) { case 'a': // In other applications this would normally be handled by the Edit menu { if (NSResponder * firstResponder = [keyWindow firstResponder]) { [firstResponder selectAll:self]; bEventHandled = true; } break; } case 'c': // In other applications this would normally be handled by the Edit menu { if (NSResponder * firstResponder = [keyWindow firstResponder]) { if ([firstResponder respondsToSelector:@selector(copy:)]) { NSText * textResponder = (NSText *) firstResponder; [textResponder copy:self]; bEventHandled = true; } } break; } case 'v': // In other applications this would normally be handled by the Edit menu { if (NSResponder * firstResponder = [keyWindow firstResponder]) { if ([firstResponder respondsToSelector:@selector(paste:)]) { NSText * textResponder = (NSText *) firstResponder; [textResponder paste:self]; bEventHandled = true; } } break; } case 'x': // In other applications this would normally be handled by the Edit menu { if (NSResponder * firstResponder = [keyWindow firstResponder]) { if ([firstResponder respondsToSelector:@selector(cut:)]) { NSText * textResponder = (NSText *) firstResponder; [textResponder cut:self]; bEventHandled = true; } } break; } default: break; } } } } } if (!bEventHandled) { [super sendEvent:anEvent]; } } @end static XAP_CocoaAppController * XAP_AppController_Instance = nil; @implementation XAP_CocoaAppController + (XAP_CocoaAppController*)sharedAppController // do we really need/want this?? the app controller is instantiated within the application's nib { if (!XAP_AppController_Instance) { UT_DEBUGMSG(("sharedAppController does not exist.\n")); [[XAP_CocoaAppController alloc] init]; } return XAP_AppController_Instance; } - (id)init { UT_DEBUGMSG(("create the XAP_CocoaAppController init\n")); if (XAP_AppController_Instance) { NSLog (@"Attempt to allocate more that one XAP_CocoaAppController"); return nil; } if(![super init]) { return nil; } XAP_AppController_Instance = self; m_FilesRequestedDuringLaunch = [[NSMutableArray alloc] initWithCapacity:8]; m_bApplicationLaunching = YES; m_bAutoLoadPluginsAfterLaunch = NO; m_PanelMenu = [[NSMenu alloc] initWithTitle:@"Panels"]; m_ContextMenu = [[NSMenu alloc] initWithTitle:@"Context Menu"]; m_MenuIDRefDictionary = [[NSMutableDictionary alloc] initWithCapacity:16]; m_Plugins = [[NSMutableArray alloc] initWithCapacity:16]; m_PluginsTools = [[NSMutableArray alloc] initWithCapacity:16]; m_PluginsToolsSeparator = [NSMenuItem separatorItem]; [m_PluginsToolsSeparator retain]; m_ToolProviders = [[NSMutableArray alloc] initWithCapacity:4]; return self; } - (void)dealloc { [m_FilesRequestedDuringLaunch release]; [m_PanelMenu release]; [m_ContextMenu release]; [m_MenuIDRefDictionary release]; [m_Plugins release]; [m_PluginsTools release]; [m_PluginsToolsSeparator release]; [m_ToolProviders release]; [super dealloc]; } - (void)setAutoLoadPluginsAfterLaunch:(BOOL)autoLoadPluginsAfterLaunch { m_bAutoLoadPluginsAfterLaunch = autoLoadPluginsAfterLaunch; } - (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key { UT_UNUSED(sender); return [key isEqualToString:@"orderedDocuments"]; } - (void)applicationWillFinishLaunching:(NSNotification *)aNotification { UT_UNUSED(aNotification); if (const char * home = getenv("HOME")) { NSString * desktop = [[NSString stringWithUTF8String:home] stringByAppendingPathComponent:@"Desktop"]; [[NSFileManager defaultManager] changeCurrentDirectoryPath:desktop]; } if (NSMenu * menu = [NSApp windowsMenu]) { if (NSMenuItem * item = [[NSMenuItem alloc] initWithTitle:@"Panels" action:nil keyEquivalent:@""]) { [menu addItem:item]; [item setSubmenu:m_PanelMenu]; [item release]; } } } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { UT_UNUSED(aNotification); UT_DEBUGMSG(("[XAP_CocoaAppController -applicationDidFinishLaunching:]\n")); m_bApplicationLaunching = NO; UT_DEBUGMSG(("[...FinishLaunching] Constructing standard toolset:\n")); [m_ToolProviders addObject:[XAP_CocoaToolProvider AbiWordToolProvider]]; XAP_CocoaApp * pApp = static_cast(XAP_App::getApp()); if (EV_CocoaMenuBar * pCocoaMenuBar = pApp->getCocoaMenuBar()) { m_AppItem[XAP_CocoaAppMenu_File ] = oMenuItem_File; m_AppItem[XAP_CocoaAppMenu_Edit ] = oMenuItem_Edit; m_AppItem[XAP_CocoaAppMenu_View ] = oMenuItem_View; m_AppItem[XAP_CocoaAppMenu_Insert] = oMenuItem_Insert; m_AppItem[XAP_CocoaAppMenu_Format] = oMenuItem_Format; m_AppItem[XAP_CocoaAppMenu_Tools ] = oMenuItem_Tools; m_AppItem[XAP_CocoaAppMenu_Table ] = oMenuItem_Table; m_AppItem[XAP_CocoaAppMenu_Window] = oMenuItem_Window; m_AppItem[XAP_CocoaAppMenu_Help ] = oMenuItem_Help; m_AppMenu[XAP_CocoaAppMenu_File ] = oMenu_File; m_AppMenu[XAP_CocoaAppMenu_Edit ] = oMenu_Edit; m_AppMenu[XAP_CocoaAppMenu_View ] = oMenu_View; m_AppMenu[XAP_CocoaAppMenu_Insert] = oMenu_Insert; m_AppMenu[XAP_CocoaAppMenu_Format] = oMenu_Format; m_AppMenu[XAP_CocoaAppMenu_Tools ] = oMenu_Tools; m_AppMenu[XAP_CocoaAppMenu_Table ] = oMenu_Table; m_AppMenu[XAP_CocoaAppMenu_Window] = oMenu_Window; m_AppMenu[XAP_CocoaAppMenu_Help ] = oMenu_Help; UT_DEBUGMSG(("[...FinishLaunching] Building application menu:\n")); pCocoaMenuBar->buildAppMenu(); } [XAP_CocoaToolPalette instance:self]; if (m_bAutoLoadPluginsAfterLaunch) { UT_DEBUGMSG(("[...FinishLaunching] Auto-Loading plug-ins:\n")); XAP_CocoaModule::loadAllPlugins(); } BOOL bFileOpenedDuringLaunch = NO; unsigned count = [m_FilesRequestedDuringLaunch count]; for (unsigned i = 0; i < count; i++) // filter out plugins from list and open those first { NSString * filename = (NSString *) [m_FilesRequestedDuringLaunch objectAtIndex:i]; std::string path([filename UTF8String]); if (XAP_CocoaModule::hasPluginExtension(path)) { [self application:NSApp openFile:filename]; } } for (unsigned i = 0; i < count; i++) // open the rest { NSString * filename = (NSString *) [m_FilesRequestedDuringLaunch objectAtIndex:i]; std::string path([filename UTF8String]); if (!XAP_CocoaModule::hasPluginExtension(path)) if ([self application:NSApp openFile:filename]) { bFileOpenedDuringLaunch = YES; } } if (bFileOpenedDuringLaunch == NO) { UT_DEBUGMSG(("[...FinishLaunching] No file opened during launch, so opening untitled document:\n")); [self applicationOpenUntitledFile:NSApp]; } } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender // probably unused now that NSApp's terminate is overridden { UT_UNUSED(sender); UT_DEBUGMSG(("- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender\n")); UT_UCS4String ucs4_empty; bool bQuit = ev_EditMethod_invoke("querySaveAndExit", ucs4_empty); return (bQuit ? NSTerminateNow : NSTerminateCancel); } - (void)applicationWillTerminate:(NSNotification *)aNotification // probably unused now that NSApp's terminate is overridden { UT_UNUSED(aNotification); if ([XAP_CocoaToolPalette instantiated]) { [[XAP_CocoaToolPalette instance:self] close]; } } - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { UT_UNUSED(theApplication); if (m_bApplicationLaunching == YES) { [m_FilesRequestedDuringLaunch addObject:filename]; return YES; } UT_DEBUGMSG(("Requested to open %s\n", [filename UTF8String])); std::string path([filename UTF8String]); if (XAP_CocoaModule::hasPluginExtension(path)) { return (XAP_CocoaModule::loadPlugin(path) ? YES : NO); } XAP_App * pApp = XAP_App::getApp(); XAP_Frame * pNewFrame = pApp->newFrame(); bool result = (UT_OK == pNewFrame->loadDocument([filename UTF8String], IEFT_Unknown)); /* * TODO: check what we should really do now */ if (result) { pNewFrame->show(); } return (result ? YES : NO); } - (BOOL)application:(NSApplication *)theApplication openTempFile:(NSString *)filename { /* TODO: really open temp file. ie, delete it when done */ UT_DEBUGMSG(("Requested to open temp file %s\n", [filename UTF8String])); return [self application:theApplication openFile:filename]; } - (BOOL)application:(NSApplication *)theApplication printFile:(NSString *)filename { /* TODO: really print the file. */ UT_DEBUGMSG(("Requested to print %s\n", [filename UTF8String])); return [self application:theApplication openFile:filename]; } - (BOOL)applicationOpenUntitledFile:(NSApplication *)theApplication { UT_UNUSED(theApplication); if (m_bApplicationLaunching == YES) { return YES; } UT_DEBUGMSG(("Requested to open untitled file...\n")); EV_EditMethodContainer * pEMC = XAP_App::getApp()->getEditMethodContainer(); if (!pEMC) { return NO; } EV_EditMethod * pEM = pEMC->findEditMethodByName("fileNew"); if (!pEM) { return NO; } return (pEM->Fn(0,0) ? YES : NO); } - (BOOL)applicationOpenFile:(NSApplication *)theApplication { UT_UNUSED(theApplication); EV_EditMethodContainer * pEMC = XAP_App::getApp()->getEditMethodContainer(); if (!pEMC) { return NO; } EV_EditMethod * pEM = pEMC->findEditMethodByName("fileOpen"); if (!pEM) { return NO; } return (pEM->Fn(0,0) ? YES : NO); } - (id)dockFileNew:(id)sender { UT_UNUSED(sender); [self applicationOpenUntitledFile:NSApp]; return self; } - (id)dockFileOpen:(id)sender { UT_UNUSED(sender); [self applicationOpenFile:NSApp]; return self; } /* - (NSMenu *)applicationDockMenu:(NSApplication *)sender { XAP_CocoaApp * pCocoaApp = static_cast(XAP_App::getApp()); return (NSMenu *) pCocoaApp->getDockNSMenu (); } */ /* For building the Application Menu */ - (void)setAboutTitle:(NSString *)title { [oMenuItem_AboutAbiWord setTitle:title]; } - (void)setPrefsTitle:(NSString *)title { [oMenuItem_Preferences setTitle:title]; } - (void)setCHelpTitle:(NSString *)title // context-help { [oMenuItem_AbiWordHelp setTitle:title]; } - (void)setTitle:(NSString *)title forMenu:(XAP_CocoaAppMenu_Id)appMenu { switch (appMenu) { case XAP_CocoaAppMenu_File: case XAP_CocoaAppMenu_Edit: case XAP_CocoaAppMenu_View: case XAP_CocoaAppMenu_Insert: case XAP_CocoaAppMenu_Format: case XAP_CocoaAppMenu_Tools: case XAP_CocoaAppMenu_Table: case XAP_CocoaAppMenu_Window: // ?? case XAP_CocoaAppMenu_Help: [m_AppItem[appMenu] setTitle:title]; break; case XAP_CocoaAppMenu_AbiWord: // disallow case XAP_CocoaAppMenu_count__: default: // shouldn't really happen, but... break; } } - (const char *)keyEquivalentForMenuID:(int /* XAP_Menu_Id */)menuid modifierMask:(unsigned int *)mask { const char * equiv = 0; struct EV_CocoaKeyEquiv * pKE = KeyEquiv; while (pKE->equiv) { if (menuid == (int) pKE->menuid) { equiv = pKE->equiv; if ( mask) *mask = pKE->modifier; break; } ++pKE; } return equiv; } - (NSMenu *)panelMenu { return m_PanelMenu; } - (NSMenu *)contextMenu { return m_ContextMenu; } - (void)appendPanelItem:(NSMenuItem *)item { [m_PanelMenu addItem:item]; } - (void)appendContextItem:(NSMenuItem *)item { [m_ContextMenu addItem:item]; } - (void)appendItem:(NSMenuItem *)item toMenu:(XAP_CocoaAppMenu_Id)appMenu { switch (appMenu) { case XAP_CocoaAppMenu_File: case XAP_CocoaAppMenu_Edit: case XAP_CocoaAppMenu_View: case XAP_CocoaAppMenu_Insert: case XAP_CocoaAppMenu_Format: case XAP_CocoaAppMenu_Tools: case XAP_CocoaAppMenu_Table: case XAP_CocoaAppMenu_Help: { // UT_DEBUGMSG(("appendItem: toMenu:\"%s\"\n", [[m_AppItem[appMenu] title] UTF8String])); [m_AppMenu[appMenu] addItem:item]; } break; case XAP_CocoaAppMenu_AbiWord: case XAP_CocoaAppMenu_Window: // these menus treated separately case XAP_CocoaAppMenu_count__: default: // shouldn't really happen, but... break; } } - (void)clearContextMenu { while (int count = [m_ContextMenu numberOfItems]) { [m_ContextMenu removeItemAtIndex:(count - 1)]; } } - (void)clearMenu:(XAP_CocoaAppMenu_Id)appMenu { switch (appMenu) { case XAP_CocoaAppMenu_File: case XAP_CocoaAppMenu_Edit: case XAP_CocoaAppMenu_View: case XAP_CocoaAppMenu_Insert: case XAP_CocoaAppMenu_Format: case XAP_CocoaAppMenu_Tools: case XAP_CocoaAppMenu_Table: while (int count = [m_AppMenu[appMenu] numberOfItems]) { [m_AppMenu[appMenu] removeItemAtIndex:(count - 1)]; } break; case XAP_CocoaAppMenu_Help: while (int count = [m_AppMenu[appMenu] numberOfItems]) { if (count == 1) // the first Help item (context-help) is treated separately break; [m_AppMenu[appMenu] removeItemAtIndex:(count - 1)]; } break; case XAP_CocoaAppMenu_AbiWord: case XAP_CocoaAppMenu_Window: // these menus treated separately case XAP_CocoaAppMenu_count__: default: // shouldn't really happen, but... break; } } - (void)clearAllMenus { // !AbiWord [self clearMenu:XAP_CocoaAppMenu_File ]; [self clearMenu:XAP_CocoaAppMenu_Edit ]; [self clearMenu:XAP_CocoaAppMenu_View ]; [self clearMenu:XAP_CocoaAppMenu_Insert]; [self clearMenu:XAP_CocoaAppMenu_Format]; [self clearMenu:XAP_CocoaAppMenu_Tools ]; [self clearMenu:XAP_CocoaAppMenu_Table ]; // !Windows [self clearMenu:XAP_CocoaAppMenu_Help ]; } - (void)reappendPluginMenuItems { if (unsigned count = [m_PluginsTools count]) { [m_AppMenu[XAP_CocoaAppMenu_Tools] addItem:m_PluginsToolsSeparator]; for (unsigned i = 0; i < count; i++) { NSMenuItem * menuItem = (NSMenuItem *) [m_PluginsTools objectAtIndex:i]; [m_AppMenu[XAP_CocoaAppMenu_Tools] addItem:menuItem]; } } } - (void)appendPluginMenuItem:(NSMenuItem *)menuItem { if (![m_PluginsTools containsObject:menuItem]) { if ([m_PluginsTools count] == 0) { [m_AppMenu[XAP_CocoaAppMenu_Tools] addItem:m_PluginsToolsSeparator]; } [m_AppMenu[XAP_CocoaAppMenu_Tools] addItem:menuItem]; [m_PluginsTools addObject:menuItem]; } } - (void)removePluginMenuItem:(NSMenuItem *)menuItem { if ([m_PluginsTools containsObject:menuItem]) { [m_AppMenu[XAP_CocoaAppMenu_Tools] removeItem:menuItem]; if ([m_PluginsTools count] == 1) { [m_AppMenu[XAP_CocoaAppMenu_Tools] removeItem:m_PluginsToolsSeparator]; } [m_PluginsTools removeObject:menuItem]; } } /* Do we need this? getLastFocussedFrame() should be tracking this now... [TODO!!] */ - (void)setCurrentView:(AV_View *)view inFrame:(XAP_Frame *)frame { if (frame) { XAP_App * pApp = XAP_App::getApp(); pApp->clearLastFocussedFrame(); pApp->rememberFocussedFrame(static_cast(frame)); } m_pViewPrevious = m_pViewCurrent; m_pFramePrevious = m_pFrameCurrent; m_pViewCurrent = view; m_pFrameCurrent = frame; [self notifyFrameViewChange]; } - (void)resetCurrentView:(AV_View *)view inFrame:(XAP_Frame *)frame { // UT_DEBUGMSG(("XAP_CocoaAppController - (void)resetCurrentView:(AV_View *)view inFrame:(XAP_Frame *)frame\n")); if (m_pFrameCurrent == frame) { m_pViewCurrent = view; [self notifyFrameViewChange]; } } - (void)unsetCurrentView:(AV_View *)view inFrame:(XAP_Frame *)frame { XAP_App * pApp = XAP_App::getApp(); if (pApp->getLastFocussedFrame() == frame) { pApp->clearLastFocussedFrame(); } if ((m_pViewCurrent == view) && (m_pFrameCurrent == frame)) { m_pViewCurrent = NULL; m_pFrameCurrent = NULL; } if ((m_pViewPrevious == view) && (m_pFramePrevious == frame)) { m_pViewPrevious = NULL; m_pFramePrevious = NULL; } [self notifyFrameViewChange]; } - (AV_View *)currentView { return m_pViewCurrent; } - (XAP_Frame *)currentFrame { return m_pFrameCurrent; } - (AV_View *)previousView { return m_pViewPrevious; } - (XAP_Frame *)previousFrame { return m_pFramePrevious; } - (void)notifyFrameViewChange { if ([XAP_CocoaToolPalette instantiated]) { [[XAP_CocoaToolPalette instance:self] setCurrentView:m_pViewCurrent inFrame:m_pFrameCurrent]; } unsigned count = [m_Plugins count]; for (unsigned i = 0; i < count; i++) { XAP_CocoaPlugin * plugin = (XAP_CocoaPlugin *) [m_Plugins objectAtIndex:i]; [[plugin delegate] pluginCurrentDocumentHasChanged]; } } /* load .Abi bundle plugin at path, returns nil on failure */ - (XAP_CocoaPlugin *)loadPlugin:(NSString *)path { if (!path) { return nil; } XAP_CocoaPlugin * cocoa_plugin = [[XAP_CocoaPlugin alloc] init]; if (!cocoa_plugin) { return nil; } if ([cocoa_plugin loadBundleWithPath:path]) { [m_Plugins addObject:cocoa_plugin]; } else { [cocoa_plugin release]; cocoa_plugin = nil; } return cocoa_plugin; } /* list of currently loaded plugins */ - (NSArray *)plugins { return m_Plugins; } /* checks to see whether the plugins can deactivate, and, if they can, deactivates them; * returns false if any of the plugins object */ - (BOOL)deactivateAllPlugins { unsigned count = [m_Plugins count]; BOOL bCanDeactivate = YES; for (unsigned i = 0; i < count; i++) { XAP_CocoaPlugin * plugin = (XAP_CocoaPlugin *) [m_Plugins objectAtIndex:i]; bCanDeactivate = [[plugin delegate] pluginCanDeactivate]; if (!bCanDeactivate) break; } if (!bCanDeactivate) { return NO; } for (unsigned i = 0; i < count; i++) { XAP_CocoaPlugin * plugin = (XAP_CocoaPlugin *) [m_Plugins objectAtIndex:i]; [[plugin delegate] pluginDeactivate]; } return YES; } /* checks to see whether the plugins can deactivate, and, if they can, deactivates them; * returns false if the plugin objects, unless override is YES. */ - (BOOL)deactivatePlugin:(XAP_CocoaPlugin *)plugin overridePlugin:(BOOL)override { if (!override) { if (![[plugin delegate] pluginCanDeactivate]) { return NO; } } [[plugin delegate] pluginDeactivate]; return YES; } /* This provides a mechanism for associating XAP_CocoaPlugin_MenuItem objects * with a given menu ID. */ - (void)addRef:(AP_CocoaPlugin_MenuIDRef *)ref forMenuID:(NSNumber *)menuid { [m_MenuIDRefDictionary setObject:ref forKey:menuid]; } /* This provides a mechanism for finding XAP_CocoaPlugin_MenuItem objects associated * with a given menu ID. */ - (AP_CocoaPlugin_MenuIDRef *)refForMenuID:(NSNumber *)menuid { return (AP_CocoaPlugin_MenuIDRef *) [m_MenuIDRefDictionary objectForKey:menuid]; } /* This provides a mechanism for removing XAP_CocoaPlugin_MenuItem objects associated * with a given menu ID. */ - (void)removeRefForMenuID:(NSNumber *)menuid { [m_MenuIDRefDictionary removeObjectForKey:menuid]; } /* Get a list of all the tool providers. * Each tool provider is of type id . */ - (NSArray *)toolProviders { return m_ToolProviders; } /* Find a tool provider by name. * (TODO: If plug-ins are registering tool providers, we need to implement a notification * system to update toolbar systems.) */ - (id )toolProvider:(NSString *)name { id matched_provider = 0; int count = [m_ToolProviders count]; int i; if (!name) return 0; if ([name length] == 0) return 0; for (i = 0; i < count; i++) { id provider = (id ) [m_ToolProviders objectAtIndex:i]; if ([name isEqualToString:[provider name]]) { matched_provider = provider; break; } } return matched_provider; } @end