1*323de322SAndrew Rist/************************************************************** 2cdf0e10cSrcweir * 3*323de322SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*323de322SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*323de322SAndrew Rist * distributed with this work for additional information 6*323de322SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*323de322SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*323de322SAndrew Rist * "License"); you may not use this file except in compliance 9*323de322SAndrew Rist * with the License. You may obtain a copy of the License at 10*323de322SAndrew Rist * 11*323de322SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*323de322SAndrew Rist * 13*323de322SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*323de322SAndrew Rist * software distributed under the License is distributed on an 15*323de322SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*323de322SAndrew Rist * KIND, either express or implied. See the License for the 17*323de322SAndrew Rist * specific language governing permissions and limitations 18*323de322SAndrew Rist * under the License. 19*323de322SAndrew Rist * 20*323de322SAndrew Rist *************************************************************/ 21*323de322SAndrew Rist 22*323de322SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir// MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir#include "precompiled_sfx2.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir#include "unotools/moduleoptions.hxx" 28cdf0e10cSrcweir#include "unotools/dynamicmenuoptions.hxx" 29cdf0e10cSrcweir#include "unotools/historyoptions.hxx" 30cdf0e10cSrcweir#include "tools/urlobj.hxx" 31cdf0e10cSrcweir#include "osl/file.h" 32cdf0e10cSrcweir#include "comphelper/sequenceashashmap.hxx" 33cdf0e10cSrcweir#include "vos/mutex.hxx" 34cdf0e10cSrcweir#include "sfx2/app.hxx" 35cdf0e10cSrcweir#include "app.hrc" 36cdf0e10cSrcweir#define USE_APP_SHORTCUTS 37cdf0e10cSrcweir#include "shutdownicon.hxx" 38cdf0e10cSrcweir 39cdf0e10cSrcweir#include "com/sun/star/util/XStringWidth.hpp" 40cdf0e10cSrcweir 41cdf0e10cSrcweir#include "cppuhelper/implbase1.hxx" 42cdf0e10cSrcweir 43cdf0e10cSrcweir#include <set> 44cdf0e10cSrcweir#include <vector> 45cdf0e10cSrcweir 46cdf0e10cSrcweir#include "premac.h" 47cdf0e10cSrcweir#include <Cocoa/Cocoa.h> 48cdf0e10cSrcweir#include "postmac.h" 49cdf0e10cSrcweir 50cdf0e10cSrcweirusing namespace ::rtl; 51cdf0e10cSrcweirusing namespace ::osl; 52cdf0e10cSrcweirusing namespace ::com::sun::star::uno; 53cdf0e10cSrcweirusing namespace ::com::sun::star::task; 54cdf0e10cSrcweirusing namespace ::com::sun::star::lang; 55cdf0e10cSrcweirusing namespace ::com::sun::star::beans; 56cdf0e10cSrcweirusing namespace ::com::sun::star::util; 57cdf0e10cSrcweir 58cdf0e10cSrcweir#define MI_OPEN 1 59cdf0e10cSrcweir#define MI_WRITER 2 60cdf0e10cSrcweir#define MI_CALC 3 61cdf0e10cSrcweir#define MI_IMPRESS 4 62cdf0e10cSrcweir#define MI_DRAW 5 63cdf0e10cSrcweir#define MI_BASE 6 64cdf0e10cSrcweir#define MI_MATH 7 65cdf0e10cSrcweir#define MI_TEMPLATE 8 66cdf0e10cSrcweir#define MI_STARTMODULE 9 67cdf0e10cSrcweir 68cdf0e10cSrcweir@interface QSMenuExecute : NSObject 69cdf0e10cSrcweir{ 70cdf0e10cSrcweir} 71cdf0e10cSrcweir-(void)executeMenuItem: (NSMenuItem*)pItem; 72cdf0e10cSrcweir-(void)dockIconClicked: (NSObject*)pSender; 73cdf0e10cSrcweir@end 74cdf0e10cSrcweir 75cdf0e10cSrcweir@implementation QSMenuExecute 76cdf0e10cSrcweir-(void)executeMenuItem: (NSMenuItem*)pItem 77cdf0e10cSrcweir{ 78cdf0e10cSrcweir switch( [pItem tag] ) 79cdf0e10cSrcweir { 80cdf0e10cSrcweir case MI_OPEN: 81cdf0e10cSrcweir ShutdownIcon::FileOpen(); 82cdf0e10cSrcweir break; 83cdf0e10cSrcweir case MI_WRITER: 84cdf0e10cSrcweir ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( WRITER_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 85cdf0e10cSrcweir break; 86cdf0e10cSrcweir case MI_CALC: 87cdf0e10cSrcweir ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( CALC_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 88cdf0e10cSrcweir break; 89cdf0e10cSrcweir case MI_IMPRESS: 90cdf0e10cSrcweir ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( IMPRESS_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 91cdf0e10cSrcweir break; 92cdf0e10cSrcweir case MI_DRAW: 93cdf0e10cSrcweir ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( DRAW_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 94cdf0e10cSrcweir break; 95cdf0e10cSrcweir case MI_BASE: 96cdf0e10cSrcweir ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( BASE_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 97cdf0e10cSrcweir break; 98cdf0e10cSrcweir case MI_MATH: 99cdf0e10cSrcweir ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( MATH_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 100cdf0e10cSrcweir break; 101cdf0e10cSrcweir case MI_TEMPLATE: 102cdf0e10cSrcweir ShutdownIcon::FromTemplate(); 103cdf0e10cSrcweir break; 104cdf0e10cSrcweir case MI_STARTMODULE: 105cdf0e10cSrcweir ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( STARTMODULE_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 106cdf0e10cSrcweir break; 107cdf0e10cSrcweir default: 108cdf0e10cSrcweir break; 109cdf0e10cSrcweir } 110cdf0e10cSrcweir} 111cdf0e10cSrcweir 112cdf0e10cSrcweir-(void)dockIconClicked: (NSObject*)pSender 113cdf0e10cSrcweir{ 114cdf0e10cSrcweir (void)pSender; 115cdf0e10cSrcweir // start start module 116cdf0e10cSrcweir ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( STARTMODULE_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 117cdf0e10cSrcweir} 118cdf0e10cSrcweir 119cdf0e10cSrcweir@end 120cdf0e10cSrcweir 121cdf0e10cSrcweirbool ShutdownIcon::IsQuickstarterInstalled() 122cdf0e10cSrcweir{ 123cdf0e10cSrcweir return true; 124cdf0e10cSrcweir} 125cdf0e10cSrcweir 126cdf0e10cSrcweirstatic NSMenuItem* pDefMenu = nil, *pDockSubMenu = nil; 127cdf0e10cSrcweirstatic QSMenuExecute* pExecute = nil; 128cdf0e10cSrcweir 129cdf0e10cSrcweirstatic std::set< OUString > aShortcuts; 130cdf0e10cSrcweir 131cdf0e10cSrcweirstatic NSString* getAutoreleasedString( const rtl::OUString& rStr ) 132cdf0e10cSrcweir{ 133cdf0e10cSrcweir return [[[NSString alloc] initWithCharacters: rStr.getStr() length: rStr.getLength()] autorelease]; 134cdf0e10cSrcweir} 135cdf0e10cSrcweir 136cdf0e10cSrcweirstruct RecentMenuEntry 137cdf0e10cSrcweir{ 138cdf0e10cSrcweir rtl::OUString aURL; 139cdf0e10cSrcweir rtl::OUString aFilter; 140cdf0e10cSrcweir rtl::OUString aTitle; 141cdf0e10cSrcweir rtl::OUString aPassword; 142cdf0e10cSrcweir}; 143cdf0e10cSrcweir 144cdf0e10cSrcweirclass RecentFilesStringLength : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XStringWidth > 145cdf0e10cSrcweir{ 146cdf0e10cSrcweir public: 147cdf0e10cSrcweir RecentFilesStringLength() {} 148cdf0e10cSrcweir virtual ~RecentFilesStringLength() {} 149cdf0e10cSrcweir 150cdf0e10cSrcweir // XStringWidth 151cdf0e10cSrcweir sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString ) 152cdf0e10cSrcweir throw (::com::sun::star::uno::RuntimeException) 153cdf0e10cSrcweir { 154cdf0e10cSrcweir return aString.getLength(); 155cdf0e10cSrcweir } 156cdf0e10cSrcweir}; 157cdf0e10cSrcweir 158cdf0e10cSrcweir@interface RecentMenuDelegate : NSObject 159cdf0e10cSrcweir{ 160cdf0e10cSrcweir std::vector< RecentMenuEntry >* m_pRecentFilesItems; 161cdf0e10cSrcweir} 162cdf0e10cSrcweir-(id)init; 163cdf0e10cSrcweir-(void)dealloc; 164cdf0e10cSrcweir-(void)menuNeedsUpdate:(NSMenu *)menu; 165cdf0e10cSrcweir-(void)executeRecentEntry: (NSMenuItem*)item; 166cdf0e10cSrcweir@end 167cdf0e10cSrcweir 168cdf0e10cSrcweir@implementation RecentMenuDelegate 169cdf0e10cSrcweir-(id)init 170cdf0e10cSrcweir{ 171cdf0e10cSrcweir if( (self = [super init]) ) 172cdf0e10cSrcweir { 173cdf0e10cSrcweir m_pRecentFilesItems = new std::vector< RecentMenuEntry >(); 174cdf0e10cSrcweir } 175cdf0e10cSrcweir return self; 176cdf0e10cSrcweir} 177cdf0e10cSrcweir 178cdf0e10cSrcweir-(void)dealloc 179cdf0e10cSrcweir{ 180cdf0e10cSrcweir delete m_pRecentFilesItems; 181cdf0e10cSrcweir [super dealloc]; 182cdf0e10cSrcweir} 183cdf0e10cSrcweir 184cdf0e10cSrcweir-(void)menuNeedsUpdate:(NSMenu *)menu 185cdf0e10cSrcweir{ 186cdf0e10cSrcweir // clear menu 187cdf0e10cSrcweir int nItems = [menu numberOfItems]; 188cdf0e10cSrcweir while( nItems -- ) 189cdf0e10cSrcweir [menu removeItemAtIndex: 0]; 190cdf0e10cSrcweir 191cdf0e10cSrcweir // update recent item list 192cdf0e10cSrcweir Sequence< Sequence< PropertyValue > > aHistoryList( SvtHistoryOptions().GetList( ePICKLIST ) ); 193cdf0e10cSrcweir 194cdf0e10cSrcweir int nPickListMenuItems = ( aHistoryList.getLength() > 99 ) ? 99 : aHistoryList.getLength(); 195cdf0e10cSrcweir 196cdf0e10cSrcweir m_pRecentFilesItems->clear(); 197cdf0e10cSrcweir if( ( nPickListMenuItems > 0 ) ) 198cdf0e10cSrcweir { 199cdf0e10cSrcweir for ( int i = 0; i < nPickListMenuItems; i++ ) 200cdf0e10cSrcweir { 201cdf0e10cSrcweir Sequence< PropertyValue >& rPickListEntry = aHistoryList[i]; 202cdf0e10cSrcweir RecentMenuEntry aRecentFile; 203cdf0e10cSrcweir 204cdf0e10cSrcweir for ( int j = 0; j < rPickListEntry.getLength(); j++ ) 205cdf0e10cSrcweir { 206cdf0e10cSrcweir Any a = rPickListEntry[j].Value; 207cdf0e10cSrcweir 208cdf0e10cSrcweir if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_URL ) 209cdf0e10cSrcweir a >>= aRecentFile.aURL; 210cdf0e10cSrcweir else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_FILTER ) 211cdf0e10cSrcweir a >>= aRecentFile.aFilter; 212cdf0e10cSrcweir else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_TITLE ) 213cdf0e10cSrcweir a >>= aRecentFile.aTitle; 214cdf0e10cSrcweir else if ( rPickListEntry[j].Name == HISTORY_PROPERTYNAME_PASSWORD ) 215cdf0e10cSrcweir a >>= aRecentFile.aPassword; 216cdf0e10cSrcweir } 217cdf0e10cSrcweir 218cdf0e10cSrcweir m_pRecentFilesItems->push_back( aRecentFile ); 219cdf0e10cSrcweir } 220cdf0e10cSrcweir } 221cdf0e10cSrcweir 222cdf0e10cSrcweir // insert new recent items 223cdf0e10cSrcweir for ( sal_uInt32 i = 0; i < m_pRecentFilesItems->size(); i++ ) 224cdf0e10cSrcweir { 225cdf0e10cSrcweir rtl::OUString aMenuTitle; 226cdf0e10cSrcweir INetURLObject aURL( (*m_pRecentFilesItems)[i].aURL ); 227cdf0e10cSrcweir 228cdf0e10cSrcweir if ( aURL.GetProtocol() == INET_PROT_FILE ) 229cdf0e10cSrcweir { 230cdf0e10cSrcweir // Do handle file URL differently => convert it to a system 231cdf0e10cSrcweir // path and abbreviate it with a special function: 232cdf0e10cSrcweir String aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) ); 233cdf0e10cSrcweir 234cdf0e10cSrcweir ::rtl::OUString aSystemPath( aFileSystemPath ); 235cdf0e10cSrcweir ::rtl::OUString aCompactedSystemPath; 236cdf0e10cSrcweir 237cdf0e10cSrcweir oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL ); 238cdf0e10cSrcweir if ( !nError ) 239cdf0e10cSrcweir aMenuTitle = String( aCompactedSystemPath ); 240cdf0e10cSrcweir else 241cdf0e10cSrcweir aMenuTitle = aSystemPath; 242cdf0e10cSrcweir } 243cdf0e10cSrcweir else 244cdf0e10cSrcweir { 245cdf0e10cSrcweir // Use INetURLObject to abbreviate all other URLs 246cdf0e10cSrcweir Reference< XStringWidth > xStringLength( new RecentFilesStringLength() ); 247cdf0e10cSrcweir aMenuTitle = aURL.getAbbreviated( xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS ); 248cdf0e10cSrcweir } 249cdf0e10cSrcweir 250cdf0e10cSrcweir NSMenuItem* pNewItem = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( aMenuTitle ) 251cdf0e10cSrcweir action: @selector(executeRecentEntry:) 252cdf0e10cSrcweir keyEquivalent: @""]; 253cdf0e10cSrcweir [pNewItem setTag: i]; 254cdf0e10cSrcweir [pNewItem setTarget: self]; 255cdf0e10cSrcweir [pNewItem setEnabled: YES]; 256cdf0e10cSrcweir [menu addItem: pNewItem]; 257cdf0e10cSrcweir [pNewItem autorelease]; 258cdf0e10cSrcweir } 259cdf0e10cSrcweir} 260cdf0e10cSrcweir 261cdf0e10cSrcweir-(void)executeRecentEntry: (NSMenuItem*)item 262cdf0e10cSrcweir{ 263cdf0e10cSrcweir sal_Int32 nIndex = [item tag]; 264cdf0e10cSrcweir if( ( nIndex >= 0 ) && ( nIndex < static_cast<sal_Int32>( m_pRecentFilesItems->size() ) ) ) 265cdf0e10cSrcweir { 266cdf0e10cSrcweir const RecentMenuEntry& rRecentFile = (*m_pRecentFilesItems)[ nIndex ]; 267cdf0e10cSrcweir int NUM_OF_PICKLIST_ARGS = 3; 268cdf0e10cSrcweir Sequence< PropertyValue > aArgsList( NUM_OF_PICKLIST_ARGS ); 269cdf0e10cSrcweir 270cdf0e10cSrcweir aArgsList[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" )); 271cdf0e10cSrcweir aArgsList[0].Value = makeAny( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:user" ) ) ); 272cdf0e10cSrcweir 273cdf0e10cSrcweir // documents in the picklist will never be opened as templates 274cdf0e10cSrcweir aArgsList[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AsTemplate" )); 275cdf0e10cSrcweir aArgsList[1].Value = makeAny( (sal_Bool) sal_False ); 276cdf0e10cSrcweir 277cdf0e10cSrcweir ::rtl::OUString aFilter( rRecentFile.aFilter ); 278cdf0e10cSrcweir sal_Int32 nPos = aFilter.indexOf( '|' ); 279cdf0e10cSrcweir if ( nPos >= 0 ) 280cdf0e10cSrcweir { 281cdf0e10cSrcweir rtl::OUString aFilterOptions; 282cdf0e10cSrcweir 283cdf0e10cSrcweir if ( nPos < ( aFilter.getLength() - 1 ) ) 284cdf0e10cSrcweir aFilterOptions = aFilter.copy( nPos+1 ); 285cdf0e10cSrcweir 286cdf0e10cSrcweir aArgsList[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterOptions" )); 287cdf0e10cSrcweir aArgsList[2].Value = makeAny( aFilterOptions ); 288cdf0e10cSrcweir 289cdf0e10cSrcweir aFilter = aFilter.copy( 0, nPos-1 ); 290cdf0e10cSrcweir aArgsList.realloc( ++NUM_OF_PICKLIST_ARGS ); 291cdf0e10cSrcweir } 292cdf0e10cSrcweir 293cdf0e10cSrcweir aArgsList[NUM_OF_PICKLIST_ARGS-1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )); 294cdf0e10cSrcweir aArgsList[NUM_OF_PICKLIST_ARGS-1].Value = makeAny( aFilter ); 295cdf0e10cSrcweir 296cdf0e10cSrcweir ShutdownIcon::OpenURL( rRecentFile.aURL, OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ), aArgsList ); 297cdf0e10cSrcweir } 298cdf0e10cSrcweir} 299cdf0e10cSrcweir@end 300cdf0e10cSrcweir 301cdf0e10cSrcweirstatic RecentMenuDelegate* pRecentDelegate = nil; 302cdf0e10cSrcweir 303cdf0e10cSrcweirstatic rtl::OUString getShortCut( const rtl::OUString i_rTitle ) 304cdf0e10cSrcweir{ 305cdf0e10cSrcweir // create shortcut 306cdf0e10cSrcweir rtl::OUString aKeyEquiv; 307cdf0e10cSrcweir for( sal_Int32 nIndex = 0; nIndex < i_rTitle.getLength(); nIndex++ ) 308cdf0e10cSrcweir { 309cdf0e10cSrcweir rtl::OUString aShortcut( i_rTitle.copy( nIndex, 1 ).toAsciiLowerCase() ); 310cdf0e10cSrcweir if( aShortcuts.find( aShortcut ) == aShortcuts.end() ) 311cdf0e10cSrcweir { 312cdf0e10cSrcweir aShortcuts.insert( aShortcut ); 313cdf0e10cSrcweir aKeyEquiv = aShortcut; 314cdf0e10cSrcweir break; 315cdf0e10cSrcweir } 316cdf0e10cSrcweir } 317cdf0e10cSrcweir 318cdf0e10cSrcweir return aKeyEquiv; 319cdf0e10cSrcweir} 320cdf0e10cSrcweir 321cdf0e10cSrcweirstatic void appendMenuItem( NSMenu* i_pMenu, NSMenu* i_pDockMenu, const rtl::OUString& i_rTitle, int i_nTag, const rtl::OUString& i_rKeyEquiv ) 322cdf0e10cSrcweir{ 323cdf0e10cSrcweir if( ! i_rTitle.getLength() ) 324cdf0e10cSrcweir return; 325cdf0e10cSrcweir 326cdf0e10cSrcweir NSMenuItem* pItem = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( i_rTitle ) 327cdf0e10cSrcweir action: @selector(executeMenuItem:) 328cdf0e10cSrcweir keyEquivalent: (i_rKeyEquiv.getLength() ? getAutoreleasedString( i_rKeyEquiv ) : @"") 329cdf0e10cSrcweir ]; 330cdf0e10cSrcweir [pItem setTag: i_nTag]; 331cdf0e10cSrcweir [pItem setTarget: pExecute]; 332cdf0e10cSrcweir [pItem setEnabled: YES]; 333cdf0e10cSrcweir [i_pMenu addItem: pItem]; 334cdf0e10cSrcweir 335cdf0e10cSrcweir if( i_pDockMenu ) 336cdf0e10cSrcweir { 337cdf0e10cSrcweir // create a similar entry in the dock menu 338cdf0e10cSrcweir pItem = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( i_rTitle ) 339cdf0e10cSrcweir action: @selector(executeMenuItem:) 340cdf0e10cSrcweir keyEquivalent: @"" 341cdf0e10cSrcweir ]; 342cdf0e10cSrcweir [pItem setTag: i_nTag]; 343cdf0e10cSrcweir [pItem setTarget: pExecute]; 344cdf0e10cSrcweir [pItem setEnabled: YES]; 345cdf0e10cSrcweir [i_pDockMenu addItem: pItem]; 346cdf0e10cSrcweir } 347cdf0e10cSrcweir} 348cdf0e10cSrcweir 349cdf0e10cSrcweirstatic void appendRecentMenu( NSMenu* i_pMenu, NSMenu* i_pDockMenu, const String& i_rTitle ) 350cdf0e10cSrcweir{ 351cdf0e10cSrcweir if( ! pRecentDelegate ) 352cdf0e10cSrcweir pRecentDelegate = [[RecentMenuDelegate alloc] init]; 353cdf0e10cSrcweir 354cdf0e10cSrcweir NSMenuItem* pItem = [i_pMenu addItemWithTitle: getAutoreleasedString( i_rTitle ) 355cdf0e10cSrcweir action: @selector(executeMenuItem:) 356cdf0e10cSrcweir keyEquivalent: @"" 357cdf0e10cSrcweir ]; 358cdf0e10cSrcweir [pItem setEnabled: YES]; 359cdf0e10cSrcweir NSMenu* pRecentMenu = [[NSMenu alloc] initWithTitle: getAutoreleasedString( i_rTitle ) ]; 360cdf0e10cSrcweir [pRecentMenu setDelegate: pRecentDelegate]; 361cdf0e10cSrcweir [pRecentMenu setAutoenablesItems: NO]; 362cdf0e10cSrcweir [pItem setSubmenu: pRecentMenu]; 363cdf0e10cSrcweir 364cdf0e10cSrcweir if( i_pDockMenu ) 365cdf0e10cSrcweir { 366cdf0e10cSrcweir // create a similar entry in the dock menu 367cdf0e10cSrcweir pItem = [i_pDockMenu addItemWithTitle: getAutoreleasedString( i_rTitle ) 368cdf0e10cSrcweir action: @selector(executeMenuItem:) 369cdf0e10cSrcweir keyEquivalent: @"" 370cdf0e10cSrcweir ]; 371cdf0e10cSrcweir [pItem setEnabled: YES]; 372cdf0e10cSrcweir pRecentMenu = [[NSMenu alloc] initWithTitle: getAutoreleasedString( i_rTitle ) ]; 373cdf0e10cSrcweir [pRecentMenu setDelegate: pRecentDelegate]; 374cdf0e10cSrcweir [pRecentMenu setAutoenablesItems: NO]; 375cdf0e10cSrcweir [pItem setSubmenu: pRecentMenu]; 376cdf0e10cSrcweir } 377cdf0e10cSrcweir} 378cdf0e10cSrcweir 379cdf0e10cSrcweir 380cdf0e10cSrcweirextern "C" 381cdf0e10cSrcweir{ 382cdf0e10cSrcweir 383cdf0e10cSrcweirvoid aqua_init_systray() 384cdf0e10cSrcweir{ 385cdf0e10cSrcweir ::vos::OGuard aGuard( Application::GetSolarMutex() ); 386cdf0e10cSrcweir 387cdf0e10cSrcweir ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance(); 388cdf0e10cSrcweir if( ! pShutdownIcon ) 389cdf0e10cSrcweir return; 390cdf0e10cSrcweir 391cdf0e10cSrcweir // disable shutdown 392cdf0e10cSrcweir pShutdownIcon->SetVeto( true ); 393cdf0e10cSrcweir pShutdownIcon->addTerminateListener(); 394cdf0e10cSrcweir 395cdf0e10cSrcweir if( ! pDefMenu ) 396cdf0e10cSrcweir { 397cdf0e10cSrcweir if( [NSApp respondsToSelector: @selector(addFallbackMenuItem:)] ) 398cdf0e10cSrcweir { 399cdf0e10cSrcweir aShortcuts.clear(); 400cdf0e10cSrcweir 401cdf0e10cSrcweir pExecute = [[QSMenuExecute alloc] init]; 402cdf0e10cSrcweir pDefMenu = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( pShutdownIcon->GetResString( STR_QUICKSTART_FILE ) ) action: NULL keyEquivalent: @""]; 403cdf0e10cSrcweir pDockSubMenu = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( pShutdownIcon->GetResString( STR_QUICKSTART_FILE ) ) action: NULL keyEquivalent: @""]; 404cdf0e10cSrcweir NSMenu* pMenu = [[NSMenu alloc] initWithTitle: getAutoreleasedString( pShutdownIcon->GetResString( STR_QUICKSTART_FILE ) )]; 405cdf0e10cSrcweir [pMenu setAutoenablesItems: NO]; 406cdf0e10cSrcweir NSMenu* pDockMenu = [[NSMenu alloc] initWithTitle: getAutoreleasedString( pShutdownIcon->GetResString( STR_QUICKSTART_FILE ) )]; 407cdf0e10cSrcweir [pDockMenu setAutoenablesItems: NO]; 408cdf0e10cSrcweir 409cdf0e10cSrcweir // collect the URLs of the entries in the File/New menu 410cdf0e10cSrcweir SvtModuleOptions aModuleOptions; 411cdf0e10cSrcweir std::set< rtl::OUString > aFileNewAppsAvailable; 412cdf0e10cSrcweir SvtDynamicMenuOptions aOpt; 413cdf0e10cSrcweir Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU ); 414cdf0e10cSrcweir const rtl::OUString sURLKey( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); 415cdf0e10cSrcweir 416cdf0e10cSrcweir const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray(); 417cdf0e10cSrcweir const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength(); 418cdf0e10cSrcweir for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu ) 419cdf0e10cSrcweir { 420cdf0e10cSrcweir comphelper::SequenceAsHashMap aEntryItems( *pNewMenu ); 421cdf0e10cSrcweir rtl::OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, rtl::OUString() ) ); 422cdf0e10cSrcweir if ( sURL.getLength() ) 423cdf0e10cSrcweir aFileNewAppsAvailable.insert( sURL ); 424cdf0e10cSrcweir } 425cdf0e10cSrcweir 426cdf0e10cSrcweir // describe the menu entries for launching the applications 427cdf0e10cSrcweir struct MenuEntryDescriptor 428cdf0e10cSrcweir { 429cdf0e10cSrcweir SvtModuleOptions::EModule eModuleIdentifier; 430cdf0e10cSrcweir int nMenuTag; 431cdf0e10cSrcweir const char* pAsciiURLDescription; 432cdf0e10cSrcweir } aMenuItems[] = 433cdf0e10cSrcweir { 434cdf0e10cSrcweir { SvtModuleOptions::E_SWRITER, MI_WRITER, WRITER_URL }, 435cdf0e10cSrcweir { SvtModuleOptions::E_SCALC, MI_CALC, CALC_URL }, 436cdf0e10cSrcweir { SvtModuleOptions::E_SIMPRESS, MI_IMPRESS, IMPRESS_WIZARD_URL }, 437cdf0e10cSrcweir { SvtModuleOptions::E_SDRAW, MI_DRAW, DRAW_URL }, 438cdf0e10cSrcweir { SvtModuleOptions::E_SDATABASE, MI_BASE, BASE_URL }, 439cdf0e10cSrcweir { SvtModuleOptions::E_SMATH, MI_MATH, MATH_URL } 440cdf0e10cSrcweir }; 441cdf0e10cSrcweir 442cdf0e10cSrcweir // insert entry for startcenter 443cdf0e10cSrcweir if( aModuleOptions.IsModuleInstalled( SvtModuleOptions::E_SSTARTMODULE ) ) 444cdf0e10cSrcweir { 445cdf0e10cSrcweir appendMenuItem( pMenu, nil, pShutdownIcon->GetResString( STR_QUICKSTART_STARTCENTER ), MI_STARTMODULE, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "n" ) ) ); 446cdf0e10cSrcweir if( [NSApp respondsToSelector: @selector(setDockIconClickHandler:)] ) 447cdf0e10cSrcweir [NSApp performSelector:@selector(setDockIconClickHandler:) withObject: pExecute]; 448cdf0e10cSrcweir else 449cdf0e10cSrcweir DBG_ERROR( "setDockIconClickHandler selector failed on NSApp\n" ); 450cdf0e10cSrcweir 451cdf0e10cSrcweir } 452cdf0e10cSrcweir 453cdf0e10cSrcweir // insert the menu entries for launching the applications 454cdf0e10cSrcweir for ( size_t i = 0; i < sizeof( aMenuItems ) / sizeof( aMenuItems[0] ); ++i ) 455cdf0e10cSrcweir { 456cdf0e10cSrcweir if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) ) 457cdf0e10cSrcweir // the complete application is not even installed 458cdf0e10cSrcweir continue; 459cdf0e10cSrcweir 460cdf0e10cSrcweir rtl::OUString sURL( ::rtl::OUString::createFromAscii( aMenuItems[i].pAsciiURLDescription ) ); 461cdf0e10cSrcweir 462cdf0e10cSrcweir if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() ) 463cdf0e10cSrcweir // the application is installed, but the entry has been configured to *not* appear in the File/New 464cdf0e10cSrcweir // menu => also let not appear it in the quickstarter 465cdf0e10cSrcweir continue; 466cdf0e10cSrcweir 467cdf0e10cSrcweir rtl::OUString aKeyEquiv( getShortCut( pShutdownIcon->GetUrlDescription( sURL ) ) ); 468cdf0e10cSrcweir 469cdf0e10cSrcweir appendMenuItem( pMenu, pDockMenu, pShutdownIcon->GetUrlDescription( sURL ), aMenuItems[i].nMenuTag, aKeyEquiv ); 470cdf0e10cSrcweir } 471cdf0e10cSrcweir 472cdf0e10cSrcweir // insert the remaining menu entries 473cdf0e10cSrcweir 474cdf0e10cSrcweir // add recent menu 475cdf0e10cSrcweir appendRecentMenu( pMenu, pDockMenu, pShutdownIcon->GetResString( STR_QUICKSTART_RECENTDOC ) ); 476cdf0e10cSrcweir 477cdf0e10cSrcweir rtl::OUString aTitle( pShutdownIcon->GetResString( STR_QUICKSTART_FROMTEMPLATE ) ); 478cdf0e10cSrcweir rtl::OUString aKeyEquiv( getShortCut( aTitle ) ); 479cdf0e10cSrcweir appendMenuItem( pMenu, pDockMenu, aTitle, MI_TEMPLATE, aKeyEquiv ); 480cdf0e10cSrcweir aTitle = pShutdownIcon->GetResString( STR_QUICKSTART_FILEOPEN ); 481cdf0e10cSrcweir aKeyEquiv = getShortCut( aTitle ); 482cdf0e10cSrcweir appendMenuItem( pMenu, pDockMenu, aTitle, MI_OPEN, aKeyEquiv ); 483cdf0e10cSrcweir 484cdf0e10cSrcweir [pDefMenu setSubmenu: pMenu]; 485cdf0e10cSrcweir [NSApp performSelector:@selector(addFallbackMenuItem:) withObject: pDefMenu]; 486cdf0e10cSrcweir 487cdf0e10cSrcweir if( [NSApp respondsToSelector: @selector(addDockMenuItem:)] ) 488cdf0e10cSrcweir { 489cdf0e10cSrcweir [pDockSubMenu setSubmenu: pDockMenu]; 490cdf0e10cSrcweir // insert a separator to the dock menu 491cdf0e10cSrcweir [NSApp performSelector:@selector(addDockMenuItem:) withObject: [NSMenuItem separatorItem]]; 492cdf0e10cSrcweir // and now add the submenu 493cdf0e10cSrcweir [NSApp performSelector:@selector(addDockMenuItem:) withObject: pDockSubMenu]; 494cdf0e10cSrcweir } 495cdf0e10cSrcweir else 496cdf0e10cSrcweir DBG_ERROR( "addDockMenuItem selector failed on NSApp\n" ); 497cdf0e10cSrcweir } 498cdf0e10cSrcweir else 499cdf0e10cSrcweir DBG_ERROR( "addFallbackMenuItem selector failed on NSApp\n" ); 500cdf0e10cSrcweir } 501cdf0e10cSrcweir} 502cdf0e10cSrcweir 503cdf0e10cSrcweirvoid SAL_DLLPUBLIC_EXPORT aqua_shutdown_systray() 504cdf0e10cSrcweir{ 505cdf0e10cSrcweir} 506cdf0e10cSrcweir 507cdf0e10cSrcweir} 508