//----------------------------------------------------------------------------- // Copyright (c) 2013 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #include "platformOSX/platformOSX.h" #include "platformOSX/osxCocoaUtilities.h" #include "gui/guiCanvas.h" class PlatformPopupMenuData { public: osxPopupMenuController* mController; S32 tag; PlatformPopupMenuData() { mController = NULL; tag = getTag(); } ~PlatformPopupMenuData() { if (mController) [mController release]; mController = NULL; } // We assign each new menu item an arbitrary integer tag. static S32 getTag() { static S32 lastTag = 'TORQ'; return ++lastTag; } }; //----------------------------------------------------------------------------- // Allocates the OS X specific PopupMenuData void PopupMenu::createPlatformPopupMenuData() { mData = new PlatformPopupMenuData; } //----------------------------------------------------------------------------- // Deallocates the OS X specific PopupMenuData void PopupMenu::deletePlatformPopupMenuData() { SAFE_DELETE(mData); } //----------------------------------------------------------------------------- // Called in PopupMenu's constructor, this handles platform specific menu setup void PopupMenu::createPlatformMenu() { mData->mController = [[osxPopupMenuController alloc] init]; [mData->mController setOwner:this]; } //----------------------------------------------------------------------------- S32 PopupMenu::insertItem(S32 pos, const char *title, const char *accel) { NSMenuItem *newItem; newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[NSString stringWithUTF8String:title] action:NULL keyEquivalent:[NSString stringWithUTF8String:accel]]; [newItem setTarget:mData->mController]; [newItem setAction:@selector(handleSelect:)]; [[mData->mController menu] insertItem:newItem atIndex:pos]; [newItem release]; return 0; } //----------------------------------------------------------------------------- S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu) { for(S32 i = 0;i < mSubmenus->size();i++) { if(submenu == (*mSubmenus)[i]) { Con::errorf("PopupMenu::insertSubMenu - Attempting to add submenu twice"); return -1; } } NSMenuItem *newItem; newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[NSString stringWithUTF8String:title] action:NULL keyEquivalent:[NSString stringWithUTF8String:""]]; [newItem setSubmenu:[submenu->mData->mController menu]]; [newItem setTarget:submenu->mData->mController]; [newItem setAction:@selector(handleSelect:)]; [[mData->mController menu] insertItem:newItem atIndex:pos]; [newItem release]; mSubmenus->addObject(submenu); return 0; } //----------------------------------------------------------------------------- void PopupMenu::removeItem(S32 itemPos) { [[mData->mController menu] removeItemAtIndex:itemPos]; } //----------------------------------------------------------------------------- void PopupMenu::enableItem(S32 pos, bool enable) { [[[mData->mController menu] itemAtIndex:pos] setEnabled:enable]; } //----------------------------------------------------------------------------- void PopupMenu::checkItem(S32 pos, bool checked) { [[[mData->mController menu] itemAtIndex:pos] setState:(checked ? NSOnState : NSOffState)]; } //----------------------------------------------------------------------------- void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos) { for(int i = firstPos; i <= lastPos; i++) checkItem( i, false); // check the selected item checkItem( checkPos, true); } //----------------------------------------------------------------------------- bool PopupMenu::isItemChecked(S32 pos) { S32 state = (S32)[[[mData->mController menu] itemAtIndex:pos] state]; return (state == NSOnState); } //----------------------------------------------------------------------------- bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */) { return dAtob(Con::executef(this, 4, "onSelectItem", Con::getIntArg(command), text ? text : "")); } //----------------------------------------------------------------------------- // Not yet implemented or no longer necessary. Will resolve in the next platform update void PopupMenu::showPopup(S32 x /* = -1 */, S32 y /* = -1 */) { // Get the position of the cursor if(x < 0 || y < 0) { Point2I p = Canvas->getCursorPos(); x = p.x; y = p.y; } // Convert to native coordinates //CGPoint native = MacCarbTorqueToNativeCoords(x, y); // Manually click the menu item //U32 result = PopUpMenuSelect(mData->mMenu, native.y, native.x, 0); } //----------------------------------------------------------------------------- void PopupMenu::attachToMenuBar(S32 pos, const char *title) { [[mData->mController menuItem] setTitle:[NSString stringWithUTF8String:title]]; [[mData->mController menu] setTitle:[NSString stringWithUTF8String:title]]; [[NSApp mainMenu] addItem:[mData->mController menuItem]]; } //----------------------------------------------------------------------------- void PopupMenu::removeFromMenuBar() { if ([[NSApp mainMenu] indexOfItem:[mData->mController menuItem]] > -1) [[NSApp mainMenu] removeItem:[mData->mController menuItem]]; }