xref: /aoo4110/main/vcl/aqua/source/window/salmenu.cxx (revision b1cdbd2c)
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