1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski #include "rtl/ustrbuf.hxx"
25*b1cdbd2cSJim Jagielski
26*b1cdbd2cSJim Jagielski #include "vcl/cmdevt.hxx"
27*b1cdbd2cSJim Jagielski #include "vcl/floatwin.hxx"
28*b1cdbd2cSJim Jagielski #include "vcl/window.hxx"
29*b1cdbd2cSJim Jagielski #include "vcl/svapp.hxx"
30*b1cdbd2cSJim Jagielski
31*b1cdbd2cSJim Jagielski #include "aqua/saldata.hxx"
32*b1cdbd2cSJim Jagielski #include "aqua/salinst.h"
33*b1cdbd2cSJim Jagielski #include "aqua/salmenu.h"
34*b1cdbd2cSJim Jagielski #include "aqua/salnsmenu.h"
35*b1cdbd2cSJim Jagielski #include "aqua/salframe.h"
36*b1cdbd2cSJim Jagielski #include "aqua/salbmp.h"
37*b1cdbd2cSJim Jagielski #include "aqua/aqua11ywrapper.h"
38*b1cdbd2cSJim Jagielski
39*b1cdbd2cSJim Jagielski #include "svids.hrc"
40*b1cdbd2cSJim Jagielski #include "window.h"
41*b1cdbd2cSJim Jagielski
42*b1cdbd2cSJim Jagielski const AquaSalMenu* AquaSalMenu::pCurrentMenuBar = NULL;
43*b1cdbd2cSJim Jagielski
44*b1cdbd2cSJim Jagielski @interface MainMenuSelector : NSObject
45*b1cdbd2cSJim Jagielski {
46*b1cdbd2cSJim Jagielski }
47*b1cdbd2cSJim Jagielski -(void)showDialog: (int)nDialog;
48*b1cdbd2cSJim Jagielski -(void)showPreferences: (id)sender;
49*b1cdbd2cSJim Jagielski -(void)showAbout: (id)sender;
50*b1cdbd2cSJim Jagielski @end
51*b1cdbd2cSJim Jagielski
52*b1cdbd2cSJim Jagielski @implementation MainMenuSelector
53*b1cdbd2cSJim Jagielski -(void)showDialog: (int)nDialog
54*b1cdbd2cSJim Jagielski {
55*b1cdbd2cSJim Jagielski if( AquaSalMenu::pCurrentMenuBar )
56*b1cdbd2cSJim Jagielski {
57*b1cdbd2cSJim Jagielski const AquaSalFrame* pFrame = AquaSalMenu::pCurrentMenuBar->mpFrame;
58*b1cdbd2cSJim Jagielski if( pFrame && AquaSalFrame::isAlive( pFrame ) )
59*b1cdbd2cSJim Jagielski {
60*b1cdbd2cSJim Jagielski pFrame->CallCallback( SALEVENT_SHOWDIALOG, reinterpret_cast<void*>(nDialog) );
61*b1cdbd2cSJim Jagielski }
62*b1cdbd2cSJim Jagielski }
63*b1cdbd2cSJim Jagielski else
64*b1cdbd2cSJim Jagielski {
65*b1cdbd2cSJim Jagielski String aDialog;
66*b1cdbd2cSJim Jagielski if( nDialog == SHOWDIALOG_ID_ABOUT )
67*b1cdbd2cSJim Jagielski aDialog = String( RTL_CONSTASCII_USTRINGPARAM( "ABOUT" ) );
68*b1cdbd2cSJim Jagielski else if( nDialog == SHOWDIALOG_ID_PREFERENCES )
69*b1cdbd2cSJim Jagielski aDialog = String( RTL_CONSTASCII_USTRINGPARAM( "PREFERENCES" ) );
70*b1cdbd2cSJim Jagielski const ApplicationEvent* pAppEvent = new ApplicationEvent( String(),
71*b1cdbd2cSJim Jagielski ApplicationAddress(),
72*b1cdbd2cSJim Jagielski ByteString( "SHOWDIALOG" ),
73*b1cdbd2cSJim Jagielski aDialog );
74*b1cdbd2cSJim Jagielski AquaSalInstance::aAppEventList.push_back( pAppEvent );
75*b1cdbd2cSJim Jagielski }
76*b1cdbd2cSJim Jagielski }
77*b1cdbd2cSJim Jagielski
78*b1cdbd2cSJim Jagielski -(void)showPreferences: (id) sender
79*b1cdbd2cSJim Jagielski {
80*b1cdbd2cSJim Jagielski (void)sender;
81*b1cdbd2cSJim Jagielski YIELD_GUARD;
82*b1cdbd2cSJim Jagielski
83*b1cdbd2cSJim Jagielski [self showDialog: SHOWDIALOG_ID_PREFERENCES];
84*b1cdbd2cSJim Jagielski }
85*b1cdbd2cSJim Jagielski -(void)showAbout: (id) sender
86*b1cdbd2cSJim Jagielski {
87*b1cdbd2cSJim Jagielski (void)sender;
88*b1cdbd2cSJim Jagielski YIELD_GUARD;
89*b1cdbd2cSJim Jagielski
90*b1cdbd2cSJim Jagielski [self showDialog: SHOWDIALOG_ID_ABOUT];
91*b1cdbd2cSJim Jagielski }
92*b1cdbd2cSJim Jagielski @end
93*b1cdbd2cSJim Jagielski
94*b1cdbd2cSJim Jagielski
95*b1cdbd2cSJim Jagielski // FIXME: currently this is leaked
96*b1cdbd2cSJim Jagielski static MainMenuSelector* pMainMenuSelector = nil;
97*b1cdbd2cSJim Jagielski
initAppMenu()98*b1cdbd2cSJim Jagielski static void initAppMenu()
99*b1cdbd2cSJim Jagielski {
100*b1cdbd2cSJim Jagielski static bool bOnce = true;
101*b1cdbd2cSJim Jagielski if( bOnce )
102*b1cdbd2cSJim Jagielski {
103*b1cdbd2cSJim Jagielski bOnce = false;
104*b1cdbd2cSJim Jagielski
105*b1cdbd2cSJim Jagielski ResMgr* pMgr = ImplGetResMgr();
106*b1cdbd2cSJim Jagielski if( pMgr )
107*b1cdbd2cSJim Jagielski {
108*b1cdbd2cSJim Jagielski // get the main menu
109*b1cdbd2cSJim Jagielski NSMenu* pMainMenu = [NSApp mainMenu];
110*b1cdbd2cSJim Jagielski if( pMainMenu != nil )
111*b1cdbd2cSJim Jagielski {
112*b1cdbd2cSJim Jagielski // create the action selector
113*b1cdbd2cSJim Jagielski pMainMenuSelector = [[MainMenuSelector alloc] init];
114*b1cdbd2cSJim Jagielski
115*b1cdbd2cSJim Jagielski // get the proper submenu
116*b1cdbd2cSJim Jagielski NSMenu* pAppMenu = [[pMainMenu itemAtIndex: 0] submenu];
117*b1cdbd2cSJim Jagielski if( pAppMenu )
118*b1cdbd2cSJim Jagielski {
119*b1cdbd2cSJim Jagielski // insert about entry
120*b1cdbd2cSJim Jagielski String aAbout( ResId( SV_STDTEXT_ABOUT, *pMgr ) );
121*b1cdbd2cSJim Jagielski NSString* pString = CreateNSString( aAbout );
122*b1cdbd2cSJim Jagielski NSMenuItem* pNewItem = [pAppMenu insertItemWithTitle: pString
123*b1cdbd2cSJim Jagielski action: @selector(showAbout:)
124*b1cdbd2cSJim Jagielski keyEquivalent: @""
125*b1cdbd2cSJim Jagielski atIndex: 0];
126*b1cdbd2cSJim Jagielski if (pString)
127*b1cdbd2cSJim Jagielski [pString release];
128*b1cdbd2cSJim Jagielski if( pNewItem )
129*b1cdbd2cSJim Jagielski {
130*b1cdbd2cSJim Jagielski [pNewItem setTarget: pMainMenuSelector];
131*b1cdbd2cSJim Jagielski [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 1];
132*b1cdbd2cSJim Jagielski }
133*b1cdbd2cSJim Jagielski
134*b1cdbd2cSJim Jagielski // insert preferences entry
135*b1cdbd2cSJim Jagielski String aPref( ResId( SV_STDTEXT_PREFERENCES, *pMgr ) );
136*b1cdbd2cSJim Jagielski pString = CreateNSString( aPref );
137*b1cdbd2cSJim Jagielski pNewItem = [pAppMenu insertItemWithTitle: pString
138*b1cdbd2cSJim Jagielski action: @selector(showPreferences:)
139*b1cdbd2cSJim Jagielski keyEquivalent: @","
140*b1cdbd2cSJim Jagielski atIndex: 2];
141*b1cdbd2cSJim Jagielski if (pString)
142*b1cdbd2cSJim Jagielski [pString release];
143*b1cdbd2cSJim Jagielski if( pNewItem )
144*b1cdbd2cSJim Jagielski {
145*b1cdbd2cSJim Jagielski [pNewItem setKeyEquivalentModifierMask: NSCommandKeyMask];
146*b1cdbd2cSJim Jagielski [pNewItem setTarget: pMainMenuSelector];
147*b1cdbd2cSJim Jagielski [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 3];
148*b1cdbd2cSJim Jagielski }
149*b1cdbd2cSJim Jagielski
150*b1cdbd2cSJim Jagielski // WARNING: ultra ugly code ahead
151*b1cdbd2cSJim Jagielski
152*b1cdbd2cSJim Jagielski // rename standard entries
153*b1cdbd2cSJim Jagielski // rename "Services"
154*b1cdbd2cSJim Jagielski pNewItem = [pAppMenu itemAtIndex: 4];
155*b1cdbd2cSJim Jagielski if( pNewItem )
156*b1cdbd2cSJim Jagielski {
157*b1cdbd2cSJim Jagielski pString = CreateNSString( String( ResId( SV_MENU_MAC_SERVICES, *pMgr ) ) );
158*b1cdbd2cSJim Jagielski [pNewItem setTitle: pString];
159*b1cdbd2cSJim Jagielski if( pString )
160*b1cdbd2cSJim Jagielski [pString release];
161*b1cdbd2cSJim Jagielski }
162*b1cdbd2cSJim Jagielski
163*b1cdbd2cSJim Jagielski // rename "Hide NewApplication"
164*b1cdbd2cSJim Jagielski pNewItem = [pAppMenu itemAtIndex: 6];
165*b1cdbd2cSJim Jagielski if( pNewItem )
166*b1cdbd2cSJim Jagielski {
167*b1cdbd2cSJim Jagielski pString = CreateNSString( String( ResId( SV_MENU_MAC_HIDEAPP, *pMgr ) ) );
168*b1cdbd2cSJim Jagielski [pNewItem setTitle: pString];
169*b1cdbd2cSJim Jagielski if( pString )
170*b1cdbd2cSJim Jagielski [pString release];
171*b1cdbd2cSJim Jagielski }
172*b1cdbd2cSJim Jagielski
173*b1cdbd2cSJim Jagielski // rename "Hide Others"
174*b1cdbd2cSJim Jagielski pNewItem = [pAppMenu itemAtIndex: 7];
175*b1cdbd2cSJim Jagielski if( pNewItem )
176*b1cdbd2cSJim Jagielski {
177*b1cdbd2cSJim Jagielski pString = CreateNSString( String( ResId( SV_MENU_MAC_HIDEALL, *pMgr ) ) );
178*b1cdbd2cSJim Jagielski [pNewItem setTitle: pString];
179*b1cdbd2cSJim Jagielski if( pString )
180*b1cdbd2cSJim Jagielski [pString release];
181*b1cdbd2cSJim Jagielski }
182*b1cdbd2cSJim Jagielski
183*b1cdbd2cSJim Jagielski // rename "Show all"
184*b1cdbd2cSJim Jagielski pNewItem = [pAppMenu itemAtIndex: 8];
185*b1cdbd2cSJim Jagielski if( pNewItem )
186*b1cdbd2cSJim Jagielski {
187*b1cdbd2cSJim Jagielski pString = CreateNSString( String( ResId( SV_MENU_MAC_SHOWALL, *pMgr ) ) );
188*b1cdbd2cSJim Jagielski [pNewItem setTitle: pString];
189*b1cdbd2cSJim Jagielski if( pString )
190*b1cdbd2cSJim Jagielski [pString release];
191*b1cdbd2cSJim Jagielski }
192*b1cdbd2cSJim Jagielski
193*b1cdbd2cSJim Jagielski // rename "Quit NewApplication"
194*b1cdbd2cSJim Jagielski pNewItem = [pAppMenu itemAtIndex: 10];
195*b1cdbd2cSJim Jagielski if( pNewItem )
196*b1cdbd2cSJim Jagielski {
197*b1cdbd2cSJim Jagielski pString = CreateNSString( String( ResId( SV_MENU_MAC_QUITAPP, *pMgr ) ) );
198*b1cdbd2cSJim Jagielski [pNewItem setTitle: pString];
199*b1cdbd2cSJim Jagielski if( pString )
200*b1cdbd2cSJim Jagielski [pString release];
201*b1cdbd2cSJim Jagielski }
202*b1cdbd2cSJim Jagielski }
203*b1cdbd2cSJim Jagielski }
204*b1cdbd2cSJim Jagielski }
205*b1cdbd2cSJim Jagielski }
206*b1cdbd2cSJim Jagielski }
207*b1cdbd2cSJim Jagielski
208*b1cdbd2cSJim Jagielski // =======================================================================
209*b1cdbd2cSJim Jagielski
CreateMenu(sal_Bool bMenuBar,Menu * pVCLMenu)210*b1cdbd2cSJim Jagielski SalMenu* AquaSalInstance::CreateMenu( sal_Bool bMenuBar, Menu* pVCLMenu )
211*b1cdbd2cSJim Jagielski {
212*b1cdbd2cSJim Jagielski initAppMenu();
213*b1cdbd2cSJim Jagielski
214*b1cdbd2cSJim Jagielski AquaSalMenu *pAquaSalMenu = new AquaSalMenu( bMenuBar );
215*b1cdbd2cSJim Jagielski pAquaSalMenu->mpVCLMenu = pVCLMenu;
216*b1cdbd2cSJim Jagielski
217*b1cdbd2cSJim Jagielski return pAquaSalMenu;
218*b1cdbd2cSJim Jagielski }
219*b1cdbd2cSJim Jagielski
DestroyMenu(SalMenu * pSalMenu)220*b1cdbd2cSJim Jagielski void AquaSalInstance::DestroyMenu( SalMenu* pSalMenu )
221*b1cdbd2cSJim Jagielski {
222*b1cdbd2cSJim Jagielski delete pSalMenu;
223*b1cdbd2cSJim Jagielski }
224*b1cdbd2cSJim Jagielski
CreateMenuItem(const SalItemParams * pItemData)225*b1cdbd2cSJim Jagielski SalMenuItem* AquaSalInstance::CreateMenuItem( const SalItemParams* pItemData )
226*b1cdbd2cSJim Jagielski {
227*b1cdbd2cSJim Jagielski if( !pItemData )
228*b1cdbd2cSJim Jagielski return NULL;
229*b1cdbd2cSJim Jagielski
230*b1cdbd2cSJim Jagielski AquaSalMenuItem *pSalMenuItem = new AquaSalMenuItem( pItemData );
231*b1cdbd2cSJim Jagielski
232*b1cdbd2cSJim Jagielski return pSalMenuItem;
233*b1cdbd2cSJim Jagielski }
234*b1cdbd2cSJim Jagielski
DestroyMenuItem(SalMenuItem * pSalMenuItem)235*b1cdbd2cSJim Jagielski void AquaSalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem )
236*b1cdbd2cSJim Jagielski {
237*b1cdbd2cSJim Jagielski delete pSalMenuItem;
238*b1cdbd2cSJim Jagielski }
239*b1cdbd2cSJim Jagielski
240*b1cdbd2cSJim Jagielski
241*b1cdbd2cSJim Jagielski // =======================================================================
242*b1cdbd2cSJim Jagielski
243*b1cdbd2cSJim Jagielski
244*b1cdbd2cSJim Jagielski /*
245*b1cdbd2cSJim Jagielski * AquaSalMenu
246*b1cdbd2cSJim Jagielski */
247*b1cdbd2cSJim Jagielski
AquaSalMenu(bool bMenuBar)248*b1cdbd2cSJim Jagielski AquaSalMenu::AquaSalMenu( bool bMenuBar ) :
249*b1cdbd2cSJim Jagielski mbMenuBar( bMenuBar ),
250*b1cdbd2cSJim Jagielski mpMenu( nil ),
251*b1cdbd2cSJim Jagielski mpVCLMenu( NULL ),
252*b1cdbd2cSJim Jagielski mpFrame( NULL ),
253*b1cdbd2cSJim Jagielski mpParentSalMenu( NULL )
254*b1cdbd2cSJim Jagielski {
255*b1cdbd2cSJim Jagielski if( ! mbMenuBar )
256*b1cdbd2cSJim Jagielski {
257*b1cdbd2cSJim Jagielski mpMenu = [[SalNSMenu alloc] initWithMenu: this];
258*b1cdbd2cSJim Jagielski [mpMenu setDelegate: (id<NSMenuDelegate>)mpMenu];
259*b1cdbd2cSJim Jagielski }
260*b1cdbd2cSJim Jagielski else
261*b1cdbd2cSJim Jagielski {
262*b1cdbd2cSJim Jagielski mpMenu = [NSApp mainMenu];
263*b1cdbd2cSJim Jagielski }
264*b1cdbd2cSJim Jagielski [mpMenu setAutoenablesItems: NO];
265*b1cdbd2cSJim Jagielski }
266*b1cdbd2cSJim Jagielski
~AquaSalMenu()267*b1cdbd2cSJim Jagielski AquaSalMenu::~AquaSalMenu()
268*b1cdbd2cSJim Jagielski {
269*b1cdbd2cSJim Jagielski // actually someone should have done AquaSalFrame::SetMenu( NULL )
270*b1cdbd2cSJim Jagielski // on our frame, alas it is not so
271*b1cdbd2cSJim Jagielski if( mpFrame && AquaSalFrame::isAlive( mpFrame ) && mpFrame->mpMenu == this )
272*b1cdbd2cSJim Jagielski const_cast<AquaSalFrame*>(mpFrame)->mpMenu = NULL;
273*b1cdbd2cSJim Jagielski
274*b1cdbd2cSJim Jagielski // this should normally be empty already, but be careful...
275*b1cdbd2cSJim Jagielski for( size_t i = 0; i < maButtons.size(); i++ )
276*b1cdbd2cSJim Jagielski releaseButtonEntry( maButtons[i] );
277*b1cdbd2cSJim Jagielski maButtons.clear();
278*b1cdbd2cSJim Jagielski
279*b1cdbd2cSJim Jagielski // is this leaking in some cases ? the release often leads to a duplicate release
280*b1cdbd2cSJim Jagielski // it seems the parent item gets ownership of the menu
281*b1cdbd2cSJim Jagielski if( mpMenu )
282*b1cdbd2cSJim Jagielski {
283*b1cdbd2cSJim Jagielski if( mbMenuBar )
284*b1cdbd2cSJim Jagielski {
285*b1cdbd2cSJim Jagielski if( pCurrentMenuBar == this )
286*b1cdbd2cSJim Jagielski {
287*b1cdbd2cSJim Jagielski // if the current menubar gets destroyed, set the default menubar
288*b1cdbd2cSJim Jagielski setDefaultMenu();
289*b1cdbd2cSJim Jagielski }
290*b1cdbd2cSJim Jagielski }
291*b1cdbd2cSJim Jagielski else
292*b1cdbd2cSJim Jagielski // the system may still hold a reference on mpMenu
293*b1cdbd2cSJim Jagielski {
294*b1cdbd2cSJim Jagielski // so set the pointer to this AquaSalMenu to NULL
295*b1cdbd2cSJim Jagielski // to protect from calling a dead object
296*b1cdbd2cSJim Jagielski
297*b1cdbd2cSJim Jagielski // in ! mbMenuBar case our mpMenu is actually a SalNSMenu*
298*b1cdbd2cSJim Jagielski // so we can safely cast here
299*b1cdbd2cSJim Jagielski [static_cast<SalNSMenu*>(mpMenu) setSalMenu: NULL];
300*b1cdbd2cSJim Jagielski /* #i89860# FIXME:
301*b1cdbd2cSJim Jagielski using [autorelease] here (and in AquaSalMenuItem::~AquaSalMenuItem)
302*b1cdbd2cSJim Jagielski instead of [release] fixes an occasional crash. That should
303*b1cdbd2cSJim Jagielski indicate that we release menus / menu items in the wrong order
304*b1cdbd2cSJim Jagielski somewhere, but I could not find that case.
305*b1cdbd2cSJim Jagielski */
306*b1cdbd2cSJim Jagielski [mpMenu autorelease];
307*b1cdbd2cSJim Jagielski }
308*b1cdbd2cSJim Jagielski }
309*b1cdbd2cSJim Jagielski }
310*b1cdbd2cSJim Jagielski
removeUnusedItemsRunner(NSMenu * pMenu)311*b1cdbd2cSJim Jagielski sal_Int32 removeUnusedItemsRunner(NSMenu * pMenu)
312*b1cdbd2cSJim Jagielski {
313*b1cdbd2cSJim Jagielski NSArray * elements = [pMenu itemArray];
314*b1cdbd2cSJim Jagielski NSEnumerator * it = [elements objectEnumerator];
315*b1cdbd2cSJim Jagielski id elem;
316*b1cdbd2cSJim Jagielski NSMenuItem * lastDisplayedMenuItem = nil;
317*b1cdbd2cSJim Jagielski sal_Int32 drawnItems = 0;
318*b1cdbd2cSJim Jagielski bool firstEnabledItemIsNoSeparator = false;
319*b1cdbd2cSJim Jagielski while((elem=[it nextObject]) != nil) {
320*b1cdbd2cSJim Jagielski NSMenuItem * item = static_cast<NSMenuItem *>(elem);
321*b1cdbd2cSJim Jagielski if( (![item isEnabled] && ![item isSeparatorItem]) || ([item isSeparatorItem] && (lastDisplayedMenuItem != nil && [lastDisplayedMenuItem isSeparatorItem])) ) {
322*b1cdbd2cSJim Jagielski [[item menu]removeItem:item];
323*b1cdbd2cSJim Jagielski } else {
324*b1cdbd2cSJim Jagielski if( ! firstEnabledItemIsNoSeparator && [item isSeparatorItem] ) {
325*b1cdbd2cSJim Jagielski [[item menu]removeItem:item];
326*b1cdbd2cSJim Jagielski } else {
327*b1cdbd2cSJim Jagielski firstEnabledItemIsNoSeparator = true;
328*b1cdbd2cSJim Jagielski lastDisplayedMenuItem = item;
329*b1cdbd2cSJim Jagielski drawnItems++;
330*b1cdbd2cSJim Jagielski if( [item hasSubmenu] ) {
331*b1cdbd2cSJim Jagielski removeUnusedItemsRunner( [item submenu] );
332*b1cdbd2cSJim Jagielski }
333*b1cdbd2cSJim Jagielski }
334*b1cdbd2cSJim Jagielski }
335*b1cdbd2cSJim Jagielski }
336*b1cdbd2cSJim Jagielski if( lastDisplayedMenuItem != nil && [lastDisplayedMenuItem isSeparatorItem]) {
337*b1cdbd2cSJim Jagielski [[lastDisplayedMenuItem menu]removeItem:lastDisplayedMenuItem];
338*b1cdbd2cSJim Jagielski }
339*b1cdbd2cSJim Jagielski return drawnItems;
340*b1cdbd2cSJim Jagielski }
341*b1cdbd2cSJim Jagielski
ShowNativePopupMenu(FloatingWindow * pWin,const Rectangle & rRect,sal_uLong nFlags)342*b1cdbd2cSJim Jagielski bool AquaSalMenu::ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, sal_uLong nFlags)
343*b1cdbd2cSJim Jagielski {
344*b1cdbd2cSJim Jagielski // do not use native popup menu when AQUA_NATIVE_MENUS is set to sal_False
345*b1cdbd2cSJim Jagielski if( ! VisibleMenuBar() ) {
346*b1cdbd2cSJim Jagielski return false;
347*b1cdbd2cSJim Jagielski }
348*b1cdbd2cSJim Jagielski
349*b1cdbd2cSJim Jagielski // set offsets for positioning
350*b1cdbd2cSJim Jagielski const float offset = 9.0;
351*b1cdbd2cSJim Jagielski
352*b1cdbd2cSJim Jagielski // get the pointers
353*b1cdbd2cSJim Jagielski AquaSalFrame * pParentAquaSalFrame = (AquaSalFrame *) pWin->ImplGetWindowImpl()->mpRealParent->ImplGetFrame();
354*b1cdbd2cSJim Jagielski NSWindow* pParentNSWindow = pParentAquaSalFrame->mpNSWindow;
355*b1cdbd2cSJim Jagielski NSView* pParentNSView = [pParentNSWindow contentView];
356*b1cdbd2cSJim Jagielski NSView* pPopupNSView = ((AquaSalFrame *) pWin->ImplGetWindow()->ImplGetFrame())->mpNSView;
357*b1cdbd2cSJim Jagielski NSRect popupFrame = [pPopupNSView frame];
358*b1cdbd2cSJim Jagielski
359*b1cdbd2cSJim Jagielski // since we manipulate the menu below (removing entries)
360*b1cdbd2cSJim Jagielski // let's rather make a copy here and work with that
361*b1cdbd2cSJim Jagielski NSMenu* pCopyMenu = [mpMenu copy];
362*b1cdbd2cSJim Jagielski
363*b1cdbd2cSJim Jagielski // filter disabled elements
364*b1cdbd2cSJim Jagielski removeUnusedItemsRunner( pCopyMenu );
365*b1cdbd2cSJim Jagielski
366*b1cdbd2cSJim Jagielski // create frame rect
367*b1cdbd2cSJim Jagielski NSRect displayPopupFrame = NSMakeRect( rRect.nLeft+(offset-1), rRect.nTop+(offset+1), popupFrame.size.width, 0 );
368*b1cdbd2cSJim Jagielski pParentAquaSalFrame->VCLToCocoa(displayPopupFrame, false);
369*b1cdbd2cSJim Jagielski
370*b1cdbd2cSJim Jagielski // do the same strange semantics as vcl popup windows to arrive at a frame geometry
371*b1cdbd2cSJim Jagielski // in mirrored UI case; best done by actually executing the same code
372*b1cdbd2cSJim Jagielski sal_uInt16 nArrangeIndex;
373*b1cdbd2cSJim Jagielski pWin->SetPosPixel( pWin->ImplCalcPos( pWin, rRect, nFlags, nArrangeIndex ) );
374*b1cdbd2cSJim Jagielski displayPopupFrame.origin.x = pWin->ImplGetFrame()->maGeometry.nX - pParentAquaSalFrame->maGeometry.nX + offset;
375*b1cdbd2cSJim Jagielski displayPopupFrame.origin.y = pWin->ImplGetFrame()->maGeometry.nY - pParentAquaSalFrame->maGeometry.nY + offset;
376*b1cdbd2cSJim Jagielski pParentAquaSalFrame->VCLToCocoa(displayPopupFrame, false);
377*b1cdbd2cSJim Jagielski
378*b1cdbd2cSJim Jagielski // #i111992# if this menu was opened due to a key event, prevent dispatching that yet again
379*b1cdbd2cSJim Jagielski if( [pParentNSView respondsToSelector: @selector(clearLastEvent)] )
380*b1cdbd2cSJim Jagielski [pParentNSView performSelector:@selector(clearLastEvent)];
381*b1cdbd2cSJim Jagielski
382*b1cdbd2cSJim Jagielski // open popup menu
383*b1cdbd2cSJim Jagielski NSPopUpButtonCell * pPopUpButtonCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO];
384*b1cdbd2cSJim Jagielski [pPopUpButtonCell setMenu: pCopyMenu];
385*b1cdbd2cSJim Jagielski [pPopUpButtonCell selectItem:nil];
386*b1cdbd2cSJim Jagielski [AquaA11yWrapper setPopupMenuOpen: YES];
387*b1cdbd2cSJim Jagielski [pPopUpButtonCell performClickWithFrame:displayPopupFrame inView:pParentNSView];
388*b1cdbd2cSJim Jagielski [pPopUpButtonCell release];
389*b1cdbd2cSJim Jagielski [AquaA11yWrapper setPopupMenuOpen: NO];
390*b1cdbd2cSJim Jagielski
391*b1cdbd2cSJim Jagielski // clean up the copy
392*b1cdbd2cSJim Jagielski [pCopyMenu release];
393*b1cdbd2cSJim Jagielski return true;
394*b1cdbd2cSJim Jagielski }
395*b1cdbd2cSJim Jagielski
getItemIndexByPos(sal_uInt16 nPos) const396*b1cdbd2cSJim Jagielski int AquaSalMenu::getItemIndexByPos( sal_uInt16 nPos ) const
397*b1cdbd2cSJim Jagielski {
398*b1cdbd2cSJim Jagielski int nIndex = 0;
399*b1cdbd2cSJim Jagielski if( nPos == MENU_APPEND )
400*b1cdbd2cSJim Jagielski nIndex = [mpMenu numberOfItems];
401*b1cdbd2cSJim Jagielski else
402*b1cdbd2cSJim Jagielski nIndex = sal::static_int_cast<int>( mbMenuBar ? nPos+1 : nPos );
403*b1cdbd2cSJim Jagielski return nIndex;
404*b1cdbd2cSJim Jagielski }
405*b1cdbd2cSJim Jagielski
getFrame() const406*b1cdbd2cSJim Jagielski const AquaSalFrame* AquaSalMenu::getFrame() const
407*b1cdbd2cSJim Jagielski {
408*b1cdbd2cSJim Jagielski const AquaSalMenu* pMenu = this;
409*b1cdbd2cSJim Jagielski while( pMenu && ! pMenu->mpFrame )
410*b1cdbd2cSJim Jagielski pMenu = pMenu->mpParentSalMenu;
411*b1cdbd2cSJim Jagielski return pMenu ? pMenu->mpFrame : NULL;
412*b1cdbd2cSJim Jagielski }
413*b1cdbd2cSJim Jagielski
unsetMainMenu()414*b1cdbd2cSJim Jagielski void AquaSalMenu::unsetMainMenu()
415*b1cdbd2cSJim Jagielski {
416*b1cdbd2cSJim Jagielski pCurrentMenuBar = NULL;
417*b1cdbd2cSJim Jagielski
418*b1cdbd2cSJim Jagielski // remove items from main menu
419*b1cdbd2cSJim Jagielski NSMenu* pMenu = [NSApp mainMenu];
420*b1cdbd2cSJim Jagielski for( int nItems = [pMenu numberOfItems]; nItems > 1; nItems-- )
421*b1cdbd2cSJim Jagielski [pMenu removeItemAtIndex: 1];
422*b1cdbd2cSJim Jagielski }
423*b1cdbd2cSJim Jagielski
setMainMenu()424*b1cdbd2cSJim Jagielski void AquaSalMenu::setMainMenu()
425*b1cdbd2cSJim Jagielski {
426*b1cdbd2cSJim Jagielski DBG_ASSERT( mbMenuBar, "setMainMenu on non menubar" );
427*b1cdbd2cSJim Jagielski if( mbMenuBar )
428*b1cdbd2cSJim Jagielski {
429*b1cdbd2cSJim Jagielski if( pCurrentMenuBar != this )
430*b1cdbd2cSJim Jagielski {
431*b1cdbd2cSJim Jagielski unsetMainMenu();
432*b1cdbd2cSJim Jagielski // insert our items
433*b1cdbd2cSJim Jagielski for( unsigned int i = 0; i < maItems.size(); i++ )
434*b1cdbd2cSJim Jagielski {
435*b1cdbd2cSJim Jagielski NSMenuItem* pItem = maItems[i]->mpMenuItem;
436*b1cdbd2cSJim Jagielski [mpMenu insertItem: pItem atIndex: i+1];
437*b1cdbd2cSJim Jagielski }
438*b1cdbd2cSJim Jagielski pCurrentMenuBar = this;
439*b1cdbd2cSJim Jagielski
440*b1cdbd2cSJim Jagielski // change status item
441*b1cdbd2cSJim Jagielski statusLayout();
442*b1cdbd2cSJim Jagielski }
443*b1cdbd2cSJim Jagielski enableMainMenu( true );
444*b1cdbd2cSJim Jagielski }
445*b1cdbd2cSJim Jagielski }
446*b1cdbd2cSJim Jagielski
setDefaultMenu()447*b1cdbd2cSJim Jagielski void AquaSalMenu::setDefaultMenu()
448*b1cdbd2cSJim Jagielski {
449*b1cdbd2cSJim Jagielski NSMenu* pMenu = [NSApp mainMenu];
450*b1cdbd2cSJim Jagielski
451*b1cdbd2cSJim Jagielski unsetMainMenu();
452*b1cdbd2cSJim Jagielski
453*b1cdbd2cSJim Jagielski // insert default items
454*b1cdbd2cSJim Jagielski std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu );
455*b1cdbd2cSJim Jagielski for( unsigned int i = 0, nAddItems = rFallbackMenu.size(); i < nAddItems; i++ )
456*b1cdbd2cSJim Jagielski {
457*b1cdbd2cSJim Jagielski NSMenuItem* pItem = rFallbackMenu[i];
458*b1cdbd2cSJim Jagielski if( [pItem menu] == nil )
459*b1cdbd2cSJim Jagielski [pMenu insertItem: pItem atIndex: i+1];
460*b1cdbd2cSJim Jagielski }
461*b1cdbd2cSJim Jagielski }
462*b1cdbd2cSJim Jagielski
enableMainMenu(bool bEnable)463*b1cdbd2cSJim Jagielski void AquaSalMenu::enableMainMenu( bool bEnable )
464*b1cdbd2cSJim Jagielski {
465*b1cdbd2cSJim Jagielski NSMenu* pMainMenu = [NSApp mainMenu];
466*b1cdbd2cSJim Jagielski if( pMainMenu )
467*b1cdbd2cSJim Jagielski {
468*b1cdbd2cSJim Jagielski // enable/disable items from main menu
469*b1cdbd2cSJim Jagielski int nItems = [pMainMenu numberOfItems];
470*b1cdbd2cSJim Jagielski for( int n = 1; n < nItems; n++ )
471*b1cdbd2cSJim Jagielski {
472*b1cdbd2cSJim Jagielski NSMenuItem* pItem = [pMainMenu itemAtIndex: n];
473*b1cdbd2cSJim Jagielski [pItem setEnabled: bEnable ? YES : NO];
474*b1cdbd2cSJim Jagielski }
475*b1cdbd2cSJim Jagielski }
476*b1cdbd2cSJim Jagielski }
477*b1cdbd2cSJim Jagielski
addFallbackMenuItem(NSMenuItem * pNewItem)478*b1cdbd2cSJim Jagielski void AquaSalMenu::addFallbackMenuItem( NSMenuItem* pNewItem )
479*b1cdbd2cSJim Jagielski {
480*b1cdbd2cSJim Jagielski initAppMenu();
481*b1cdbd2cSJim Jagielski
482*b1cdbd2cSJim Jagielski std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu );
483*b1cdbd2cSJim Jagielski
484*b1cdbd2cSJim Jagielski // prevent duplicate insertion
485*b1cdbd2cSJim Jagielski int nItems = rFallbackMenu.size();
486*b1cdbd2cSJim Jagielski for( int i = 0; i < nItems; i++ )
487*b1cdbd2cSJim Jagielski {
488*b1cdbd2cSJim Jagielski if( rFallbackMenu[i] == pNewItem )
489*b1cdbd2cSJim Jagielski return;
490*b1cdbd2cSJim Jagielski }
491*b1cdbd2cSJim Jagielski
492*b1cdbd2cSJim Jagielski // push the item to the back and retain it
493*b1cdbd2cSJim Jagielski [pNewItem retain];
494*b1cdbd2cSJim Jagielski rFallbackMenu.push_back( pNewItem );
495*b1cdbd2cSJim Jagielski
496*b1cdbd2cSJim Jagielski if( pCurrentMenuBar == NULL )
497*b1cdbd2cSJim Jagielski setDefaultMenu();
498*b1cdbd2cSJim Jagielski }
499*b1cdbd2cSJim Jagielski
removeFallbackMenuItem(NSMenuItem * pOldItem)500*b1cdbd2cSJim Jagielski void AquaSalMenu::removeFallbackMenuItem( NSMenuItem* pOldItem )
501*b1cdbd2cSJim Jagielski {
502*b1cdbd2cSJim Jagielski std::vector< NSMenuItem* >& rFallbackMenu( GetSalData()->maFallbackMenu );
503*b1cdbd2cSJim Jagielski
504*b1cdbd2cSJim Jagielski // find item
505*b1cdbd2cSJim Jagielski unsigned int nItems = rFallbackMenu.size();
506*b1cdbd2cSJim Jagielski for( unsigned int i = 0; i < nItems; i++ )
507*b1cdbd2cSJim Jagielski {
508*b1cdbd2cSJim Jagielski if( rFallbackMenu[i] == pOldItem )
509*b1cdbd2cSJim Jagielski {
510*b1cdbd2cSJim Jagielski // remove item and release
511*b1cdbd2cSJim Jagielski rFallbackMenu.erase( rFallbackMenu.begin() + i );
512*b1cdbd2cSJim Jagielski [pOldItem release];
513*b1cdbd2cSJim Jagielski
514*b1cdbd2cSJim Jagielski if( pCurrentMenuBar == NULL )
515*b1cdbd2cSJim Jagielski setDefaultMenu();
516*b1cdbd2cSJim Jagielski
517*b1cdbd2cSJim Jagielski return;
518*b1cdbd2cSJim Jagielski }
519*b1cdbd2cSJim Jagielski }
520*b1cdbd2cSJim Jagielski }
521*b1cdbd2cSJim Jagielski
VisibleMenuBar()522*b1cdbd2cSJim Jagielski sal_Bool AquaSalMenu::VisibleMenuBar()
523*b1cdbd2cSJim Jagielski {
524*b1cdbd2cSJim Jagielski // Enable/disable experimental native menus code?
525*b1cdbd2cSJim Jagielski //
526*b1cdbd2cSJim Jagielski // To disable native menus, set the environment variable AQUA_NATIVE_MENUS to FALSE
527*b1cdbd2cSJim Jagielski
528*b1cdbd2cSJim Jagielski static const char *pExperimental = getenv ("AQUA_NATIVE_MENUS");
529*b1cdbd2cSJim Jagielski
530*b1cdbd2cSJim Jagielski if ( ImplGetSVData()->mbIsTestTool || (pExperimental && !strcasecmp(pExperimental, "FALSE")) )
531*b1cdbd2cSJim Jagielski return sal_False;
532*b1cdbd2cSJim Jagielski
533*b1cdbd2cSJim Jagielski // End of experimental code enable/disable part
534*b1cdbd2cSJim Jagielski
535*b1cdbd2cSJim Jagielski return sal_True;
536*b1cdbd2cSJim Jagielski }
537*b1cdbd2cSJim Jagielski
SetFrame(const SalFrame * pFrame)538*b1cdbd2cSJim Jagielski void AquaSalMenu::SetFrame( const SalFrame *pFrame )
539*b1cdbd2cSJim Jagielski {
540*b1cdbd2cSJim Jagielski mpFrame = static_cast<const AquaSalFrame*>(pFrame);
541*b1cdbd2cSJim Jagielski }
542*b1cdbd2cSJim Jagielski
InsertItem(SalMenuItem * pSalMenuItem,unsigned nPos)543*b1cdbd2cSJim Jagielski void AquaSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
544*b1cdbd2cSJim Jagielski {
545*b1cdbd2cSJim Jagielski AquaSalMenuItem *pAquaSalMenuItem = static_cast<AquaSalMenuItem*>(pSalMenuItem);
546*b1cdbd2cSJim Jagielski
547*b1cdbd2cSJim Jagielski pAquaSalMenuItem->mpParentMenu = this;
548*b1cdbd2cSJim Jagielski DBG_ASSERT( pAquaSalMenuItem->mpVCLMenu == NULL ||
549*b1cdbd2cSJim Jagielski pAquaSalMenuItem->mpVCLMenu == mpVCLMenu ||
550*b1cdbd2cSJim Jagielski mpVCLMenu == NULL,
551*b1cdbd2cSJim Jagielski "resetting menu ?" );
552*b1cdbd2cSJim Jagielski if( pAquaSalMenuItem->mpVCLMenu )
553*b1cdbd2cSJim Jagielski mpVCLMenu = pAquaSalMenuItem->mpVCLMenu;
554*b1cdbd2cSJim Jagielski
555*b1cdbd2cSJim Jagielski if( nPos == MENU_APPEND || nPos == maItems.size() )
556*b1cdbd2cSJim Jagielski maItems.push_back( pAquaSalMenuItem );
557*b1cdbd2cSJim Jagielski else if( nPos < maItems.size() )
558*b1cdbd2cSJim Jagielski maItems.insert( maItems.begin() + nPos, pAquaSalMenuItem );
559*b1cdbd2cSJim Jagielski else
560*b1cdbd2cSJim Jagielski {
561*b1cdbd2cSJim Jagielski DBG_ERROR( "invalid item index in insert" );
562*b1cdbd2cSJim Jagielski return;
563*b1cdbd2cSJim Jagielski }
564*b1cdbd2cSJim Jagielski
565*b1cdbd2cSJim Jagielski if( ! mbMenuBar || pCurrentMenuBar == this )
566*b1cdbd2cSJim Jagielski [mpMenu insertItem: pAquaSalMenuItem->mpMenuItem atIndex: getItemIndexByPos(nPos)];
567*b1cdbd2cSJim Jagielski }
568*b1cdbd2cSJim Jagielski
RemoveItem(unsigned nPos)569*b1cdbd2cSJim Jagielski void AquaSalMenu::RemoveItem( unsigned nPos )
570*b1cdbd2cSJim Jagielski {
571*b1cdbd2cSJim Jagielski AquaSalMenuItem* pRemoveItem = NULL;
572*b1cdbd2cSJim Jagielski if( nPos == MENU_APPEND || nPos == (maItems.size()-1) )
573*b1cdbd2cSJim Jagielski {
574*b1cdbd2cSJim Jagielski pRemoveItem = maItems.back();
575*b1cdbd2cSJim Jagielski maItems.pop_back();
576*b1cdbd2cSJim Jagielski }
577*b1cdbd2cSJim Jagielski else if( nPos < maItems.size() )
578*b1cdbd2cSJim Jagielski {
579*b1cdbd2cSJim Jagielski pRemoveItem = maItems[ nPos ];
580*b1cdbd2cSJim Jagielski maItems.erase( maItems.begin()+nPos );
581*b1cdbd2cSJim Jagielski }
582*b1cdbd2cSJim Jagielski else
583*b1cdbd2cSJim Jagielski {
584*b1cdbd2cSJim Jagielski DBG_ERROR( "invalid item index in remove" );
585*b1cdbd2cSJim Jagielski return;
586*b1cdbd2cSJim Jagielski }
587*b1cdbd2cSJim Jagielski
588*b1cdbd2cSJim Jagielski pRemoveItem->mpParentMenu = NULL;
589*b1cdbd2cSJim Jagielski
590*b1cdbd2cSJim Jagielski if( ! mbMenuBar || pCurrentMenuBar == this )
591*b1cdbd2cSJim Jagielski [mpMenu removeItemAtIndex: getItemIndexByPos(nPos)];
592*b1cdbd2cSJim Jagielski }
593*b1cdbd2cSJim Jagielski
SetSubMenu(SalMenuItem * pSalMenuItem,SalMenu * pSubMenu,unsigned)594*b1cdbd2cSJim Jagielski void AquaSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned /*nPos*/ )
595*b1cdbd2cSJim Jagielski {
596*b1cdbd2cSJim Jagielski AquaSalMenuItem *pAquaSalMenuItem = static_cast<AquaSalMenuItem*>(pSalMenuItem);
597*b1cdbd2cSJim Jagielski AquaSalMenu *subAquaSalMenu = static_cast<AquaSalMenu*>(pSubMenu);
598*b1cdbd2cSJim Jagielski
599*b1cdbd2cSJim Jagielski if (subAquaSalMenu)
600*b1cdbd2cSJim Jagielski {
601*b1cdbd2cSJim Jagielski pAquaSalMenuItem->mpSubMenu = subAquaSalMenu;
602*b1cdbd2cSJim Jagielski if( subAquaSalMenu->mpParentSalMenu == NULL )
603*b1cdbd2cSJim Jagielski {
604*b1cdbd2cSJim Jagielski subAquaSalMenu->mpParentSalMenu = this;
605*b1cdbd2cSJim Jagielski [pAquaSalMenuItem->mpMenuItem setSubmenu: subAquaSalMenu->mpMenu];
606*b1cdbd2cSJim Jagielski
607*b1cdbd2cSJim Jagielski // set title of submenu
608*b1cdbd2cSJim Jagielski [subAquaSalMenu->mpMenu setTitle: [pAquaSalMenuItem->mpMenuItem title]];
609*b1cdbd2cSJim Jagielski }
610*b1cdbd2cSJim Jagielski else if( subAquaSalMenu->mpParentSalMenu != this )
611*b1cdbd2cSJim Jagielski {
612*b1cdbd2cSJim Jagielski // cocoa doesn't allow menus to be submenus of multiple
613*b1cdbd2cSJim Jagielski // menu items, so place a copy in the menu item instead ?
614*b1cdbd2cSJim Jagielski // let's hope that NSMenu copy does the right thing
615*b1cdbd2cSJim Jagielski NSMenu* pCopy = [subAquaSalMenu->mpMenu copy];
616*b1cdbd2cSJim Jagielski [pAquaSalMenuItem->mpMenuItem setSubmenu: pCopy];
617*b1cdbd2cSJim Jagielski
618*b1cdbd2cSJim Jagielski // set title of submenu
619*b1cdbd2cSJim Jagielski [pCopy setTitle: [pAquaSalMenuItem->mpMenuItem title]];
620*b1cdbd2cSJim Jagielski }
621*b1cdbd2cSJim Jagielski }
622*b1cdbd2cSJim Jagielski else
623*b1cdbd2cSJim Jagielski {
624*b1cdbd2cSJim Jagielski if( pAquaSalMenuItem->mpSubMenu )
625*b1cdbd2cSJim Jagielski {
626*b1cdbd2cSJim Jagielski if( pAquaSalMenuItem->mpSubMenu->mpParentSalMenu == this )
627*b1cdbd2cSJim Jagielski pAquaSalMenuItem->mpSubMenu->mpParentSalMenu = NULL;
628*b1cdbd2cSJim Jagielski }
629*b1cdbd2cSJim Jagielski pAquaSalMenuItem->mpSubMenu = NULL;
630*b1cdbd2cSJim Jagielski [pAquaSalMenuItem->mpMenuItem setSubmenu: nil];
631*b1cdbd2cSJim Jagielski }
632*b1cdbd2cSJim Jagielski }
633*b1cdbd2cSJim Jagielski
CheckItem(unsigned nPos,sal_Bool bCheck)634*b1cdbd2cSJim Jagielski void AquaSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck )
635*b1cdbd2cSJim Jagielski {
636*b1cdbd2cSJim Jagielski if( nPos < maItems.size() )
637*b1cdbd2cSJim Jagielski {
638*b1cdbd2cSJim Jagielski NSMenuItem* pItem = maItems[nPos]->mpMenuItem;
639*b1cdbd2cSJim Jagielski [pItem setState: bCheck ? NSOnState : NSOffState];
640*b1cdbd2cSJim Jagielski }
641*b1cdbd2cSJim Jagielski }
642*b1cdbd2cSJim Jagielski
EnableItem(unsigned nPos,sal_Bool bEnable)643*b1cdbd2cSJim Jagielski void AquaSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
644*b1cdbd2cSJim Jagielski {
645*b1cdbd2cSJim Jagielski if( nPos < maItems.size() )
646*b1cdbd2cSJim Jagielski {
647*b1cdbd2cSJim Jagielski NSMenuItem* pItem = maItems[nPos]->mpMenuItem;
648*b1cdbd2cSJim Jagielski [pItem setEnabled: bEnable ? YES : NO];
649*b1cdbd2cSJim Jagielski }
650*b1cdbd2cSJim Jagielski }
651*b1cdbd2cSJim Jagielski
SetItemImage(unsigned,SalMenuItem * pSMI,const Image & rImage)652*b1cdbd2cSJim Jagielski void AquaSalMenu::SetItemImage( unsigned /*nPos*/, SalMenuItem* pSMI, const Image& rImage )
653*b1cdbd2cSJim Jagielski {
654*b1cdbd2cSJim Jagielski AquaSalMenuItem* pSalMenuItem = static_cast<AquaSalMenuItem*>( pSMI );
655*b1cdbd2cSJim Jagielski if( ! pSalMenuItem || ! pSalMenuItem->mpMenuItem )
656*b1cdbd2cSJim Jagielski return;
657*b1cdbd2cSJim Jagielski
658*b1cdbd2cSJim Jagielski NSImage* pImage = CreateNSImage( rImage );
659*b1cdbd2cSJim Jagielski
660*b1cdbd2cSJim Jagielski [pSalMenuItem->mpMenuItem setImage: pImage];
661*b1cdbd2cSJim Jagielski if( pImage )
662*b1cdbd2cSJim Jagielski [pImage release];
663*b1cdbd2cSJim Jagielski }
664*b1cdbd2cSJim Jagielski
SetItemText(unsigned,SalMenuItem * i_pSalMenuItem,const XubString & i_rText)665*b1cdbd2cSJim Jagielski void AquaSalMenu::SetItemText( unsigned /*i_nPos*/, SalMenuItem* i_pSalMenuItem, const XubString& i_rText )
666*b1cdbd2cSJim Jagielski {
667*b1cdbd2cSJim Jagielski if (!i_pSalMenuItem)
668*b1cdbd2cSJim Jagielski return;
669*b1cdbd2cSJim Jagielski
670*b1cdbd2cSJim Jagielski AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) i_pSalMenuItem;
671*b1cdbd2cSJim Jagielski
672*b1cdbd2cSJim Jagielski String aText( i_rText );
673*b1cdbd2cSJim Jagielski
674*b1cdbd2cSJim Jagielski // Delete mnemonics
675*b1cdbd2cSJim Jagielski aText.EraseAllChars( '~' );
676*b1cdbd2cSJim Jagielski
677*b1cdbd2cSJim Jagielski /* #i90015# until there is a correct solution
678*b1cdbd2cSJim Jagielski strip out any appended (.*) in menubar entries
679*b1cdbd2cSJim Jagielski */
680*b1cdbd2cSJim Jagielski if( mbMenuBar )
681*b1cdbd2cSJim Jagielski {
682*b1cdbd2cSJim Jagielski xub_StrLen nPos = aText.SearchBackward( sal_Unicode( '(' ) );
683*b1cdbd2cSJim Jagielski if( nPos != STRING_NOTFOUND )
684*b1cdbd2cSJim Jagielski {
685*b1cdbd2cSJim Jagielski xub_StrLen nPos2 = aText.Search( sal_Unicode( ')' ) );
686*b1cdbd2cSJim Jagielski if( nPos2 != STRING_NOTFOUND )
687*b1cdbd2cSJim Jagielski aText.Erase( nPos, nPos2-nPos+1 );
688*b1cdbd2cSJim Jagielski }
689*b1cdbd2cSJim Jagielski }
690*b1cdbd2cSJim Jagielski
691*b1cdbd2cSJim Jagielski NSString* pString = CreateNSString( aText );
692*b1cdbd2cSJim Jagielski if (pString)
693*b1cdbd2cSJim Jagielski {
694*b1cdbd2cSJim Jagielski [pAquaSalMenuItem->mpMenuItem setTitle: pString];
695*b1cdbd2cSJim Jagielski // if the menu item has a submenu, change its title as well
696*b1cdbd2cSJim Jagielski if (pAquaSalMenuItem->mpSubMenu)
697*b1cdbd2cSJim Jagielski [pAquaSalMenuItem->mpSubMenu->mpMenu setTitle: pString];
698*b1cdbd2cSJim Jagielski [pString release];
699*b1cdbd2cSJim Jagielski }
700*b1cdbd2cSJim Jagielski }
701*b1cdbd2cSJim Jagielski
SetAccelerator(unsigned,SalMenuItem * pSalMenuItem,const KeyCode & rKeyCode,const XubString &)702*b1cdbd2cSJim Jagielski void AquaSalMenu::SetAccelerator( unsigned /*nPos*/, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const XubString& /*rKeyName*/ )
703*b1cdbd2cSJim Jagielski {
704*b1cdbd2cSJim Jagielski sal_uInt16 nModifier;
705*b1cdbd2cSJim Jagielski sal_Unicode nCommandKey = 0;
706*b1cdbd2cSJim Jagielski
707*b1cdbd2cSJim Jagielski sal_uInt16 nKeyCode=rKeyCode.GetCode();
708*b1cdbd2cSJim Jagielski if( nKeyCode )
709*b1cdbd2cSJim Jagielski {
710*b1cdbd2cSJim Jagielski if ((nKeyCode>=KEY_A) && (nKeyCode<=KEY_Z)) // letter A..Z
711*b1cdbd2cSJim Jagielski nCommandKey = nKeyCode-KEY_A + 'a';
712*b1cdbd2cSJim Jagielski else if ((nKeyCode>=KEY_0) && (nKeyCode<=KEY_9)) // numbers 0..9
713*b1cdbd2cSJim Jagielski nCommandKey = nKeyCode-KEY_0 + '0';
714*b1cdbd2cSJim Jagielski else if ((nKeyCode>=KEY_F1) && (nKeyCode<=KEY_F26)) // function keys F1..F26
715*b1cdbd2cSJim Jagielski nCommandKey = nKeyCode-KEY_F1 + NSF1FunctionKey;
716*b1cdbd2cSJim Jagielski else if( nKeyCode == KEY_REPEAT )
717*b1cdbd2cSJim Jagielski nCommandKey = NSRedoFunctionKey;
718*b1cdbd2cSJim Jagielski else if( nKeyCode == KEY_SPACE )
719*b1cdbd2cSJim Jagielski nCommandKey = ' ';
720*b1cdbd2cSJim Jagielski else
721*b1cdbd2cSJim Jagielski {
722*b1cdbd2cSJim Jagielski switch (nKeyCode)
723*b1cdbd2cSJim Jagielski {
724*b1cdbd2cSJim Jagielski case KEY_ADD:
725*b1cdbd2cSJim Jagielski nCommandKey='+';
726*b1cdbd2cSJim Jagielski break;
727*b1cdbd2cSJim Jagielski case KEY_SUBTRACT:
728*b1cdbd2cSJim Jagielski nCommandKey='-';
729*b1cdbd2cSJim Jagielski break;
730*b1cdbd2cSJim Jagielski case KEY_MULTIPLY:
731*b1cdbd2cSJim Jagielski nCommandKey='*';
732*b1cdbd2cSJim Jagielski break;
733*b1cdbd2cSJim Jagielski case KEY_DIVIDE:
734*b1cdbd2cSJim Jagielski nCommandKey='/';
735*b1cdbd2cSJim Jagielski break;
736*b1cdbd2cSJim Jagielski case KEY_POINT:
737*b1cdbd2cSJim Jagielski nCommandKey='.';
738*b1cdbd2cSJim Jagielski break;
739*b1cdbd2cSJim Jagielski case KEY_LESS:
740*b1cdbd2cSJim Jagielski nCommandKey='<';
741*b1cdbd2cSJim Jagielski break;
742*b1cdbd2cSJim Jagielski case KEY_GREATER:
743*b1cdbd2cSJim Jagielski nCommandKey='>';
744*b1cdbd2cSJim Jagielski break;
745*b1cdbd2cSJim Jagielski case KEY_EQUAL:
746*b1cdbd2cSJim Jagielski nCommandKey='=';
747*b1cdbd2cSJim Jagielski break;
748*b1cdbd2cSJim Jagielski }
749*b1cdbd2cSJim Jagielski }
750*b1cdbd2cSJim Jagielski }
751*b1cdbd2cSJim Jagielski else // not even a code ? nonsense -> ignore
752*b1cdbd2cSJim Jagielski return;
753*b1cdbd2cSJim Jagielski
754*b1cdbd2cSJim Jagielski DBG_ASSERT( nCommandKey, "unmapped accelerator key" );
755*b1cdbd2cSJim Jagielski
756*b1cdbd2cSJim Jagielski nModifier=rKeyCode.GetAllModifier();
757*b1cdbd2cSJim Jagielski
758*b1cdbd2cSJim Jagielski // should always use the command key
759*b1cdbd2cSJim Jagielski int nItemModifier = 0;
760*b1cdbd2cSJim Jagielski
761*b1cdbd2cSJim Jagielski if (nModifier & KEY_SHIFT)
762*b1cdbd2cSJim Jagielski {
763*b1cdbd2cSJim Jagielski nItemModifier |= NSShiftKeyMask; // actually useful only for function keys
764*b1cdbd2cSJim Jagielski if( nKeyCode >= KEY_A && nKeyCode <= KEY_Z )
765*b1cdbd2cSJim Jagielski nCommandKey = nKeyCode - KEY_A + 'A';
766*b1cdbd2cSJim Jagielski }
767*b1cdbd2cSJim Jagielski
768*b1cdbd2cSJim Jagielski if (nModifier & KEY_MOD1)
769*b1cdbd2cSJim Jagielski nItemModifier |= NSCommandKeyMask;
770*b1cdbd2cSJim Jagielski
771*b1cdbd2cSJim Jagielski if(nModifier & KEY_MOD2)
772*b1cdbd2cSJim Jagielski nItemModifier |= NSAlternateKeyMask;
773*b1cdbd2cSJim Jagielski
774*b1cdbd2cSJim Jagielski if(nModifier & KEY_MOD3)
775*b1cdbd2cSJim Jagielski nItemModifier |= NSControlKeyMask;
776*b1cdbd2cSJim Jagielski
777*b1cdbd2cSJim Jagielski AquaSalMenuItem *pAquaSalMenuItem = (AquaSalMenuItem *) pSalMenuItem;
778*b1cdbd2cSJim Jagielski NSString* pString = CreateNSString( rtl::OUString( &nCommandKey, 1 ) );
779*b1cdbd2cSJim Jagielski [pAquaSalMenuItem->mpMenuItem setKeyEquivalent: pString];
780*b1cdbd2cSJim Jagielski [pAquaSalMenuItem->mpMenuItem setKeyEquivalentModifierMask: nItemModifier];
781*b1cdbd2cSJim Jagielski if (pString)
782*b1cdbd2cSJim Jagielski [pString release];
783*b1cdbd2cSJim Jagielski }
784*b1cdbd2cSJim Jagielski
GetSystemMenuData(SystemMenuData *)785*b1cdbd2cSJim Jagielski void AquaSalMenu::GetSystemMenuData( SystemMenuData* )
786*b1cdbd2cSJim Jagielski {
787*b1cdbd2cSJim Jagielski }
788*b1cdbd2cSJim Jagielski
findButtonItem(sal_uInt16 i_nItemId)789*b1cdbd2cSJim Jagielski AquaSalMenu::MenuBarButtonEntry* AquaSalMenu::findButtonItem( sal_uInt16 i_nItemId )
790*b1cdbd2cSJim Jagielski {
791*b1cdbd2cSJim Jagielski for( size_t i = 0; i < maButtons.size(); ++i )
792*b1cdbd2cSJim Jagielski {
793*b1cdbd2cSJim Jagielski if( maButtons[i].maButton.mnId == i_nItemId )
794*b1cdbd2cSJim Jagielski return &maButtons[i];
795*b1cdbd2cSJim Jagielski }
796*b1cdbd2cSJim Jagielski return NULL;
797*b1cdbd2cSJim Jagielski }
798*b1cdbd2cSJim Jagielski
statusLayout()799*b1cdbd2cSJim Jagielski void AquaSalMenu::statusLayout()
800*b1cdbd2cSJim Jagielski {
801*b1cdbd2cSJim Jagielski if( GetSalData()->mpStatusItem )
802*b1cdbd2cSJim Jagielski {
803*b1cdbd2cSJim Jagielski NSView* pNSView = [GetSalData()->mpStatusItem view];
804*b1cdbd2cSJim Jagielski if( [pNSView isMemberOfClass: [OOStatusItemView class]] ) // well of course it is
805*b1cdbd2cSJim Jagielski [(OOStatusItemView*)pNSView layout];
806*b1cdbd2cSJim Jagielski else
807*b1cdbd2cSJim Jagielski DBG_ERROR( "someone stole our status view" );
808*b1cdbd2cSJim Jagielski }
809*b1cdbd2cSJim Jagielski }
810*b1cdbd2cSJim Jagielski
releaseButtonEntry(MenuBarButtonEntry & i_rEntry)811*b1cdbd2cSJim Jagielski void AquaSalMenu::releaseButtonEntry( MenuBarButtonEntry& i_rEntry )
812*b1cdbd2cSJim Jagielski {
813*b1cdbd2cSJim Jagielski if( i_rEntry.mpNSImage )
814*b1cdbd2cSJim Jagielski {
815*b1cdbd2cSJim Jagielski [i_rEntry.mpNSImage release];
816*b1cdbd2cSJim Jagielski i_rEntry.mpNSImage = nil;
817*b1cdbd2cSJim Jagielski }
818*b1cdbd2cSJim Jagielski if( i_rEntry.mpToolTipString )
819*b1cdbd2cSJim Jagielski {
820*b1cdbd2cSJim Jagielski [i_rEntry.mpToolTipString release];
821*b1cdbd2cSJim Jagielski i_rEntry.mpToolTipString = nil;
822*b1cdbd2cSJim Jagielski }
823*b1cdbd2cSJim Jagielski }
824*b1cdbd2cSJim Jagielski
AddMenuBarButton(const SalMenuButtonItem & i_rNewItem)825*b1cdbd2cSJim Jagielski bool AquaSalMenu::AddMenuBarButton( const SalMenuButtonItem& i_rNewItem )
826*b1cdbd2cSJim Jagielski {
827*b1cdbd2cSJim Jagielski if( ! mbMenuBar || ! VisibleMenuBar() )
828*b1cdbd2cSJim Jagielski return false;
829*b1cdbd2cSJim Jagielski
830*b1cdbd2cSJim Jagielski MenuBarButtonEntry* pEntry = findButtonItem( i_rNewItem.mnId );
831*b1cdbd2cSJim Jagielski if( pEntry )
832*b1cdbd2cSJim Jagielski {
833*b1cdbd2cSJim Jagielski releaseButtonEntry( *pEntry );
834*b1cdbd2cSJim Jagielski pEntry->maButton = i_rNewItem;
835*b1cdbd2cSJim Jagielski pEntry->mpNSImage = CreateNSImage( i_rNewItem.maImage );
836*b1cdbd2cSJim Jagielski if( i_rNewItem.maToolTipText.getLength() )
837*b1cdbd2cSJim Jagielski pEntry->mpToolTipString = CreateNSString( i_rNewItem.maToolTipText );
838*b1cdbd2cSJim Jagielski }
839*b1cdbd2cSJim Jagielski else
840*b1cdbd2cSJim Jagielski {
841*b1cdbd2cSJim Jagielski maButtons.push_back( MenuBarButtonEntry( i_rNewItem ) );
842*b1cdbd2cSJim Jagielski maButtons.back().mpNSImage = CreateNSImage( i_rNewItem.maImage );
843*b1cdbd2cSJim Jagielski maButtons.back().mpToolTipString = CreateNSString( i_rNewItem.maToolTipText );
844*b1cdbd2cSJim Jagielski }
845*b1cdbd2cSJim Jagielski
846*b1cdbd2cSJim Jagielski // lazy create status item
847*b1cdbd2cSJim Jagielski SalData::getStatusItem();
848*b1cdbd2cSJim Jagielski
849*b1cdbd2cSJim Jagielski if( pCurrentMenuBar == this )
850*b1cdbd2cSJim Jagielski statusLayout();
851*b1cdbd2cSJim Jagielski
852*b1cdbd2cSJim Jagielski return true;
853*b1cdbd2cSJim Jagielski }
854*b1cdbd2cSJim Jagielski
RemoveMenuBarButton(sal_uInt16 i_nId)855*b1cdbd2cSJim Jagielski void AquaSalMenu::RemoveMenuBarButton( sal_uInt16 i_nId )
856*b1cdbd2cSJim Jagielski {
857*b1cdbd2cSJim Jagielski MenuBarButtonEntry* pEntry = findButtonItem( i_nId );
858*b1cdbd2cSJim Jagielski if( pEntry )
859*b1cdbd2cSJim Jagielski {
860*b1cdbd2cSJim Jagielski releaseButtonEntry( *pEntry );
861*b1cdbd2cSJim Jagielski // note: vector guarantees that its contents are in a plain array
862*b1cdbd2cSJim Jagielski maButtons.erase( maButtons.begin() + (pEntry - &maButtons[0]) );
863*b1cdbd2cSJim Jagielski }
864*b1cdbd2cSJim Jagielski
865*b1cdbd2cSJim Jagielski if( pCurrentMenuBar == this )
866*b1cdbd2cSJim Jagielski statusLayout();
867*b1cdbd2cSJim Jagielski }
868*b1cdbd2cSJim Jagielski
GetMenuBarButtonRectPixel(sal_uInt16 i_nItemId,SalFrame * i_pReferenceFrame)869*b1cdbd2cSJim Jagielski Rectangle AquaSalMenu::GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame )
870*b1cdbd2cSJim Jagielski {
871*b1cdbd2cSJim Jagielski if( GetSalData()->mnSystemVersion < OSX_VER_LEOPARD )
872*b1cdbd2cSJim Jagielski return Rectangle( Point( -1, -1 ), Size( 1, 1 ) );
873*b1cdbd2cSJim Jagielski
874*b1cdbd2cSJim Jagielski if( ! i_pReferenceFrame || ! AquaSalFrame::isAlive( static_cast<AquaSalFrame*>(i_pReferenceFrame) ) )
875*b1cdbd2cSJim Jagielski return Rectangle();
876*b1cdbd2cSJim Jagielski
877*b1cdbd2cSJim Jagielski MenuBarButtonEntry* pEntry = findButtonItem( i_nItemId );
878*b1cdbd2cSJim Jagielski
879*b1cdbd2cSJim Jagielski if( ! pEntry )
880*b1cdbd2cSJim Jagielski return Rectangle();
881*b1cdbd2cSJim Jagielski
882*b1cdbd2cSJim Jagielski NSStatusItem* pItem = SalData::getStatusItem();
883*b1cdbd2cSJim Jagielski if( ! pItem )
884*b1cdbd2cSJim Jagielski return Rectangle();
885*b1cdbd2cSJim Jagielski
886*b1cdbd2cSJim Jagielski NSView* pNSView = [pItem view];
887*b1cdbd2cSJim Jagielski if( ! pNSView )
888*b1cdbd2cSJim Jagielski return Rectangle();
889*b1cdbd2cSJim Jagielski NSWindow* pNSWin = [pNSView window];
890*b1cdbd2cSJim Jagielski if( ! pNSWin )
891*b1cdbd2cSJim Jagielski return Rectangle();
892*b1cdbd2cSJim Jagielski
893*b1cdbd2cSJim Jagielski NSRect aRect = [pNSWin frame];
894*b1cdbd2cSJim Jagielski aRect.origin = [pNSWin convertBaseToScreen: NSMakePoint( 0, 0 )];
895*b1cdbd2cSJim Jagielski
896*b1cdbd2cSJim Jagielski // make coordinates relative to reference frame
897*b1cdbd2cSJim Jagielski static_cast<AquaSalFrame*>(i_pReferenceFrame)->CocoaToVCL( aRect.origin );
898*b1cdbd2cSJim Jagielski aRect.origin.x -= i_pReferenceFrame->maGeometry.nX;
899*b1cdbd2cSJim Jagielski aRect.origin.y -= i_pReferenceFrame->maGeometry.nY + aRect.size.height;
900*b1cdbd2cSJim Jagielski
901*b1cdbd2cSJim Jagielski return Rectangle( Point(static_cast<long int>(aRect.origin.x),
902*b1cdbd2cSJim Jagielski static_cast<long int>(aRect.origin.y)
903*b1cdbd2cSJim Jagielski ),
904*b1cdbd2cSJim Jagielski Size( static_cast<long int>(aRect.size.width),
905*b1cdbd2cSJim Jagielski static_cast<long int>(aRect.size.height)
906*b1cdbd2cSJim Jagielski )
907*b1cdbd2cSJim Jagielski );
908*b1cdbd2cSJim Jagielski }
909*b1cdbd2cSJim Jagielski
910*b1cdbd2cSJim Jagielski // =======================================================================
911*b1cdbd2cSJim Jagielski
912*b1cdbd2cSJim Jagielski /*
913*b1cdbd2cSJim Jagielski * SalMenuItem
914*b1cdbd2cSJim Jagielski */
915*b1cdbd2cSJim Jagielski
AquaSalMenuItem(const SalItemParams * pItemData)916*b1cdbd2cSJim Jagielski AquaSalMenuItem::AquaSalMenuItem( const SalItemParams* pItemData ) :
917*b1cdbd2cSJim Jagielski mnId( pItemData->nId ),
918*b1cdbd2cSJim Jagielski mpVCLMenu( pItemData->pMenu ),
919*b1cdbd2cSJim Jagielski mpParentMenu( NULL ),
920*b1cdbd2cSJim Jagielski mpSubMenu( NULL ),
921*b1cdbd2cSJim Jagielski mpMenuItem( nil )
922*b1cdbd2cSJim Jagielski {
923*b1cdbd2cSJim Jagielski String aText( pItemData->aText );
924*b1cdbd2cSJim Jagielski
925*b1cdbd2cSJim Jagielski // Delete mnemonics
926*b1cdbd2cSJim Jagielski aText.EraseAllChars( '~' );
927*b1cdbd2cSJim Jagielski
928*b1cdbd2cSJim Jagielski if (pItemData->eType == MENUITEM_SEPARATOR)
929*b1cdbd2cSJim Jagielski {
930*b1cdbd2cSJim Jagielski mpMenuItem = [NSMenuItem separatorItem];
931*b1cdbd2cSJim Jagielski // these can go occasionally go in and out of a menu, ensure their lifecycle
932*b1cdbd2cSJim Jagielski // also for the release in AquaSalMenuItem destructor
933*b1cdbd2cSJim Jagielski [mpMenuItem retain];
934*b1cdbd2cSJim Jagielski }
935*b1cdbd2cSJim Jagielski else
936*b1cdbd2cSJim Jagielski {
937*b1cdbd2cSJim Jagielski mpMenuItem = [[SalNSMenuItem alloc] initWithMenuItem: this];
938*b1cdbd2cSJim Jagielski [mpMenuItem setEnabled: YES];
939*b1cdbd2cSJim Jagielski NSString* pString = CreateNSString( aText );
940*b1cdbd2cSJim Jagielski if (pString)
941*b1cdbd2cSJim Jagielski {
942*b1cdbd2cSJim Jagielski [mpMenuItem setTitle: pString];
943*b1cdbd2cSJim Jagielski [pString release];
944*b1cdbd2cSJim Jagielski }
945*b1cdbd2cSJim Jagielski // anything but a separator should set a menu to dispatch to
946*b1cdbd2cSJim Jagielski DBG_ASSERT( mpVCLMenu, "no menu" );
947*b1cdbd2cSJim Jagielski }
948*b1cdbd2cSJim Jagielski }
949*b1cdbd2cSJim Jagielski
~AquaSalMenuItem()950*b1cdbd2cSJim Jagielski AquaSalMenuItem::~AquaSalMenuItem()
951*b1cdbd2cSJim Jagielski {
952*b1cdbd2cSJim Jagielski /* #i89860# FIXME:
953*b1cdbd2cSJim Jagielski using [autorelease] here (and in AquaSalMenu:::~AquaSalMenu) instead of
954*b1cdbd2cSJim Jagielski [release] fixes an occasional crash. That should indicate that we release
955*b1cdbd2cSJim Jagielski menus / menu items in the wrong order somewhere, but I
956*b1cdbd2cSJim Jagielski could not find that case.
957*b1cdbd2cSJim Jagielski */
958*b1cdbd2cSJim Jagielski if( mpMenuItem )
959*b1cdbd2cSJim Jagielski [mpMenuItem autorelease];
960*b1cdbd2cSJim Jagielski }
961*b1cdbd2cSJim Jagielski
962*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------
963*b1cdbd2cSJim Jagielski
964