/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at
http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <unotools/moduleoptions.hxx>
#include <unotools/dynamicmenuoptions.hxx>
#include <unotools/historyoptions.hxx>
#include <officecfg/Office/Common.hxx>
#include <rtl/ustring.hxx>
#include <tools/urlobj.hxx>
#include <osl/file.h>
#include <osl/diagnose.h>
#include <comphelper/sequenceashashmap.hxx>
#include <sfx2/app.hxx>
#include <sal/macros.h>
#include <sfx2/sfxresid.hxx>
#include <sfx2/strings.hrc>
#include <vcl/svapp.hxx>
#include <vcl/mnemonic.hxx>
#include <vcl/image.hxx>
#include <svtools/imagemgr.hxx>
#include <shutdownicon.hxx>
#include <com/sun/star/util/XStringWidth.hpp>
#include <cppuhelper/implbase.hxx>
#include <set>
#include <vector>
#include <premac.h>
#include <objc/objc-runtime.h>
#include <Cocoa/Cocoa.h>
#include <postmac.h>
#define MI_OPEN 1
#define MI_WRITER 2
#define MI_CALC 3
#define MI_IMPRESS 4
#define MI_DRAW 5
#define MI_BASE 6
#define MI_MATH 7
#define MI_TEMPLATE 8
#define MI_STARTMODULE 9
#define UNO_TOGGLECURRENTMODULE_COMMAND ".uno:ToggleCurrentModule"
@interface QSMenuExecute : NSObject
{
}
-(void)executeMenuItem: (NSMenuItem*)pItem;
-(void)dockIconClicked: (NSObject*)pSender;
@end
@implementation QSMenuExecute
-(void)executeMenuItem: (NSMenuItem*)pItem
{
SolarMutexGuard aGuard;
switch( [pItem tag] )
{
case MI_OPEN:
ShutdownIcon::FileOpen();
break;
case MI_WRITER:
ShutdownIcon::OpenURL( WRITER_URL, "_default" );
break;
case MI_CALC:
ShutdownIcon::OpenURL( CALC_URL, "_default" );
break;
case MI_IMPRESS:
ShutdownIcon::OpenURL( IMPRESS_URL, "_default" );
break;
case MI_DRAW:
ShutdownIcon::OpenURL( DRAW_URL, "_default" );
break;
case MI_BASE:
ShutdownIcon::OpenURL( BASE_URL, "_default" );
break;
case MI_MATH:
ShutdownIcon::OpenURL( MATH_URL, "_default" );
break;
case MI_TEMPLATE:
ShutdownIcon::FromTemplate();
break;
case MI_STARTMODULE:
ShutdownIcon::OpenURL( STARTMODULE_URL, "_default" );
break;
default:
break;
}
}
-(void)dockIconClicked: (NSObject*)pSender
{
(void)pSender;
SolarMutexGuard aGuard;
// start module
ShutdownIcon::OpenURL( STARTMODULE_URL, "_default" );
}
@end
bool ShutdownIcon::IsQuickstarterInstalled()
{
return true;
}
static NSArray<NSMenuItem*>* pPreferredMenus = nil;
static NSMenuItem* pDefMenu = nil, *pDockSubMenu = nil;
static QSMenuExecute* pExecute = nil;
static std::set< OUString > aShortcuts;
static NSString* getAutoreleasedString( const OUString& rStr )
{
return [[[NSString alloc] initWithCharacters: reinterpret_cast<unichar const *>(rStr.get
Str()) length: rStr.getLength()] autorelease];
}
namespace {
struct RecentMenuEntry
{
OUString aURL;
OUString aFilter;
OUString aTitle;
OUString aPassword;
};
}
@interface QSCommandMenuItem : NSMenuItem
{
OUString m_aCommand;
}
-(void)menuItemTriggered: (id)aSender;
-(void)setCommand: (OUString)aCommand;
@end
@implementation QSCommandMenuItem
-(void)menuItemTriggered: (id)aSender
{
if ( m_aCommand.isEmpty() )
return;
SolarMutexGuard aGuard;
if ( m_aCommand == "vnd.org.libreoffice.recentdocs:ClearRecentFileList" )
{
// Clearing the recent file list requires an extra step
SvtHistoryOptions::Clear( EHistoryType::PickList, false );
}
else if ( m_aCommand == ".uno:Open" )
{
ShutdownIcon::FileOpen();
return;
}
else if ( m_aCommand == ".uno:ConfigureDialog" )
{
// Selecting some menu items will cause a crash if there are
// no visible windows
ShutdownIcon::OpenURL( STARTMODULE_URL, "_default" );
}
else if ( m_aCommand == UNO_TOGGLECURRENTMODULE_COMMAND )
{
bool bIsExclusive = officecfg::Office::Common::History::ShowCurrentModuleOnly::get();
std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
officecfg::Office::Common::History::ShowCurrentModuleOnly::set(!bIsExclusive, batch);
batch->commit();
[self setState: bIsExclusive ? NSControlStateValueOff : NSControlStateValueOn];
return;
}
// "private:" commands are used for menu items in the File > New menu
if ( m_aCommand.startsWith( "private:" ) || m_aCommand == STARTMODULE_URL )
ShutdownIcon::OpenURL( m_aCommand, "_default" );
else
ShutdownIcon::FromCommand( m_aCommand );
}
-(void)setCommand: (OUString)aCommand
{
m_aCommand = aCommand;
}
@end
@interface RecentMenuDelegate : NSObject <NSMenuDelegate>
{
std::vector< RecentMenuEntry >* m_pRecentFilesItems;
}
-(id)init;
-(void)dealloc;
-(void)menuNeedsUpdate:(NSMenu *)menu;
-(void)executeRecentEntry: (NSMenuItem*)item;
@end
@implementation RecentMenuDelegate
-(id)init
{
if( (self = [super init]) )
{
m_pRecentFilesItems = new std::vector< RecentMenuEntry >();
}
return self;
}
-(void)dealloc
{
delete m_pRecentFilesItems;
[super dealloc];
}
-(void)menuNeedsUpdate:(NSMenu *)menu
{
SolarMutexGuard aGuard;
// clear menu
int nItems = [menu numberOfItems];
while( nItems -- )
[menu removeItemAtIndex: 0];
// update recent item list
std::vector< SvtHistoryOptions::HistoryItem > aHistoryList( SvtHistoryOptions::GetList( EHistoryType::PickList ) );
int nPickListMenuItems = ( aHistoryList.size() > 99 ) ? 99 : aHistoryList.size();
m_pRecentFilesItems->clear();
if( nPickListMenuItems > 0 )
{
for ( int i = 0; i < nPickListMenuItems; i++ )
{
const SvtHistoryOptions::HistoryItem & rPickListEntry = aHistoryList[i];
RecentMenuEntry aRecentFile;
aRecentFile.aURL = rPickListEntry.sURL;
aRecentFile.aFilter = rPickListEntry.sFilter;
aRecentFile.aTitle = rPickListEntry.sTitle;
m_pRecentFilesItems->push_back( aRecentFile );
}
}
// insert new recent items
for ( std::vector<RecentMenuEntry>::size_type i = 0; i < m_pRecentFilesItems->size(); i++ )
{
OUStringBuffer aMenuShortCut;
if ( i <= 9 )
{
if ( i == 9 )
aMenuShortCut.append( "1~0. " );
else
{
aMenuShortCut.append( "~N. " );
aMenuShortCut[ 1 ] = sal_Unicode( i + '1' );
}
}
else
{
aMenuShortCut.append( OUString::number(sal_Int32( i + 1 ) ) + ". " );
}
OUString aMenuTitle;
INetURLObject aURL( (*m_pRecentFilesItems)[i].aURL );
NSImage *pImage = nil;
if ( aURL.GetProtocol() == INetProtocol::File )
{
// Do handle file URL differently: don't show the protocol,
// just the file name
aMenuTitle = aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset);
if ( [NSApp respondsToSelector: @selector(createNSImage:)] )
{
BitmapEx aThumbnail(SvFileInformationManager::GetFileImageId(aURL));
Size aBmpSize = aThumbnail.GetSizePixel();
if ( aBmpSize.Width() > 0 && aBmpSize.Height() > 0 )
{
Image aImage( aThumbnail );
NSValue *pImageValue = [NSValue valueWithPointer: &aImage];
pImage = [NSApp performSelector: @selector(createNSImage:) withObject: pImageValue];
}
}
}
else
{
// In all other URLs show the protocol name before the file name
aMenuTitle = INetURLObject::GetSchemeName(aURL.GetProtocol()) + ": " + aURL.getName();
}
aMenuShortCut.append( aMenuTitle );
aMenuTitle = MnemonicGenerator::EraseAllMnemonicChars( aMenuShortCut.makeStringAndClear() );
if ( aMenuTitle.isEmpty() )
continue;
if ( aMenuTitle.endsWith( "...", &aMenuTitle ) )
aMenuTitle += u"\u2026";
NSMenuItem* pNewItem = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( aMenuTitle )
action: @selector(executeRecentEntry:)
keyEquivalent: @""];
[pNewItem setTag: i];
[pNewItem setTarget: self];
[pNewItem setEnabled: YES];
if ( pImage )
{
[pNewItem setImage: pImage];
[pImage release];
}
[menu addItem: pNewItem];
[pNewItem autorelease];
}
if ( [menu numberOfItems] )
{
TranslateId aId( "STR_CLEAR_RECENT_FILES", "Clear List" );
OUString aClearList = Translate::get( aId, Translate::Create("fwk") );
if ( !aClearList.isEmpty() )
{
[menu addItem: [NSMenuItem separatorItem]];
QSCommandMenuItem* pNewItem = [[QSCommandMenuItem alloc] initWithTitle: getAutoreleasedString( aClearList ) action: @selector(menuItemTriggered:) keyEquivalent: @""];
[pNewItem setCommand: "vnd.org.libreoffice.recentdocs:ClearRecentFileList"];
[pNewItem setTarget: pNewItem];
[pNewItem setEnabled: YES];
[menu addItem: pNewItem];
[pNewItem autorelease];
aId = TranslateId( "STR_TOGGLECURRENTMODULE", "Current Module Only" );
OUString aToggleCurrentMode = Translate::get( aId, Translate::Create("fwk") );
if ( !aToggleCurrentMode.isEmpty() )
{
pNewItem = [[QSCommandMenuItem alloc] initWithTitle: getAutoreleasedString( aToggleCurrentMode ) action: @selector(menuItemTriggered:) keyEquivalent: @""];
[pNewItem setCommand: UNO_TOGGLECURRENTMODULE_COMMAND];
[pNewItem setTarget: pNewItem];
[pNewItem setState: officecfg::Office::Common::History::ShowCurrentModuleOnly::get() ? NSControlStateValueOn : NSControlStateValueOff];
[pNewItem setEnabled: YES];
[menu addItem: pNewItem];
[pNewItem autorelease];
}
}
}
else
{
TranslateId aId( "STR_NODOCUMENT", "No Documents" );
OUString aNoDocuments = Translate::get( aId, Translate::Create("fwk") );
if ( !aNoDocuments.isEmpty() )
{
NSMenuItem* pNewItem = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( aNoDocuments ) action: nil keyEquivalent: @""];
[pNewItem setEnabled: YES];
[menu addItem: pNewItem];
[pNewItem autorelease];
}
}
}
-(void)executeRecentEntry: (NSMenuItem*)item
{
sal_Int32 nIndex = [item tag];
if( ( nIndex >= 0 ) && ( nIndex < static_cast<sal_Int32>( m_pRecentFilesItems->size() ) ) )
{
const RecentMenuEntry& rRecentFile = (*m_pRecentFilesItems)[ nIndex ];
int NUM_OF_PICKLIST_ARGS = 3;
css::uno::Sequence< css::beans::PropertyValue > aArgsList( NUM_OF_PICKLIST_ARGS );
css::beans::PropertyValue* pArgsList = aArgsList.getArray();
pArgsList[0].Name = "Referer";
pArgsList[0].Value <<= OUString( "private:user" );
// documents in the picklist will never be opened as templates
pArgsList[1].Name = "AsTemplate";
pArgsList[1].Value <<= false;
OUString aFilter( rRecentFile.aFilter );
sal_Int32 nPos = aFilter.indexOf( '|' );
if ( nPos >= 0 )
{
OUString aFilterOptions;
if ( nPos < ( aFilter.getLength() - 1 ) )
aFilterOptions = aFilter.copy( nPos+1 );
pArgsList[2].Name = "FilterOptions";
pArgsList[2].Value <<= aFilterOptions;
aFilter = aFilter.copy( 0, nPos-1 );
aArgsList.realloc( ++NUM_OF_PICKLIST_ARGS );
pArgsList = aArgsList.getArray();
}
pArgsList[NUM_OF_PICKLIST_ARGS-1].Name = "FilterName";
pArgsList[NUM_OF_PICKLIST_ARGS-1].Value <<= aFilter;
ShutdownIcon::OpenURL( rRecentFile.aURL, "_default", aArgsList );
}
}
@end
static RecentMenuDelegate* pRecentDelegate = nil;
static void appendMenuItem( NSMenu* i_pMenu, NSMenu* i_pDockMenu, const OUString& i_rTitle, int i_nTag, const OUString& i_rKeyEquiv )
{
if( ! i_rTitle.getLength() )
return;
NSMenuItem* pItem = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( i_rTitle )
action: @selector(executeMenuItem:)
keyEquivalent: (i_rKeyEquiv.getLength() ? getAutoreleasedString( i_rKeyEquiv ) : @"")
];
[pItem setTag: i_nTag];
[pItem setTarget: pExecute];
[pItem setEnabled: YES];
[i_pMenu addItem: pItem];
[pItem autorelease];
if( i_pDockMenu )
{
// create a similar entry in the dock menu
pItem = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( i_rTitle )
action: @selector(executeMenuItem:)
keyEquivalent: @""
];
[pItem setTag: i_nTag];
[pItem setTarget: pExecute];
[pItem setEnabled: YES];
[i_pDockMenu addItem: pItem];
[pItem autorelease];
}
}
static void appendRecentMenu( NSMenu* i_pMenu, const OUString& i_rTitle )
{
if( ! pRecentDelegate )
pRecentDelegate = [[RecentMenuDelegate alloc] init];
NSMenuItem* pItem = [i_pMenu addItemWithTitle: getAutoreleasedString( i_rTitle )
action: @selector(executeMenuItem:)
keyEquivalent: @""
];
[pItem setEnabled: YES];
NSMenu* pRecentMenu = [[NSMenu alloc] initWithTitle: getAutoreleasedString( i_rTitle ) ];
[pRecentMenu setDelegate: pRecentDelegate];
[pRecentMenu setAutoenablesItems: NO];
[pItem setSubmenu: pRecentMenu];
}
static void setKeyEquivalent( const vcl::KeyCode &rKeyCode, NSMenuItem *pNSMenuItem )
{
if ( !pNSMenuItem )
return;
sal_uInt16 nKeyCode = rKeyCode.GetCode();
if ( !nKeyCode )
return;
sal_Unicode nCommandKey = 0;
if ((nKeyCode>=KEY_A) && (nKeyCode<=KEY_Z)) // letter A..Z
nCommandKey = nKeyCode - KEY_A + 'a';
else if ((nKeyCode>=KEY_0) && (nKeyCode<=KEY_9)) // numbers 0..9
nCommandKey = nKeyCode - KEY_0 + '0';
else if ((nKeyCode>=KEY_F1) && (nKeyCode<=KEY_F26)) // function keys F1..F26
nCommandKey = nKeyCode - KEY_F1 + NSF1FunctionKey;
if ( !nCommandKey )
return;
sal_uInt16 nModifier = rKeyCode.GetModifier();
int nItemModifier = 0;
if ( nModifier & KEY_SHIFT )
{
nItemModifier |= NSEventModifierFlagShift; // actually useful only for function keys
if ( nKeyCode >= KEY_A && nKeyCode <= KEY_Z )
nCommandKey = nKeyCode - KEY_A + 'A';
}
if ( nModifier & KEY_MOD1 )
nItemModifier |= NSEventModifierFlagCommand;
if ( nModifier & KEY_MOD2 )
nItemModifier |= NSEventModifierFlagOption;
if ( nModifier & KEY_MOD3 )
nItemModifier |= NSEventModifierFlagControl;
// Don’t allow setting the ⌘N shortcut because it would conflict
// with the “Startcenter” menu item which is added explicitly in
// getNSMenuForVCLMenu
if ( nCommandKey == 'n' && nItemModifier == NSEventModifierFlagCommand )
return;
OUString aCommandKey( &nCommandKey, 1 );
NSString *pCommandKey = [NSString stringWithCharacters: reinterpret_cast< unichar const* >(aCommandKey.getStr()) length: aCommandKey.getLength()];
[pNSMenuItem setKeyEquivalent: pCommandKey];
[pNSMenuItem setKeyEquivalentModifierMask: nItemModifier];
}
static NSMenu *getNSMenuForVCLMenu( Menu *pMenu )
{
NSMenu *pRet = nil;
if ( !pMenu )
return pRet;
pMenu->Activate();
sal_uInt16 nItemCount = pMenu->GetItemCount();
if ( nItemCount )
{
pRet = [[[NSMenu alloc] initWithTitle: @""] autorelease];
[pRet setAutoenablesItems: NO];
for ( sal_uInt16 i = 0; i < nItemCount; i++ )
{
sal_uInt16 nId = pMenu->GetItemId( i );
if ( nId && pMenu->IsItemEnabled( nId ) )
{
OUString aText = MnemonicGenerator::EraseAllMnemonicChars( pMenu->GetItemText( nId ) );
if ( aText.isEmpty() )
continue;
if ( aText.endsWith( "...", &aText ) )
aText += u"\u2026";
// Use a custom menu in place of the Start Center's recent
// documents menu so that the list can be dynamically updated
OUString aCommand = pMenu->GetItemCommand( nId );
if ( aCommand == ".uno:RecentFileList" )
{
appendRecentMenu( pRet, aText );
continue;
}
NSString *pText = getAutoreleasedString( aText );
// TODO: use the QSMenuExecute class to connect the command
// string to one of the existing handler functions
QSCommandMenuItem *pNSMenuItem = [[QSCommandMenuItem alloc] initWithTitle: pText action: @selector(menuItemTriggered:) keyEquivalent: @""];
NSMenu *pNSSubmenu = getNSMenuForVCLMenu( pMenu->GetPopupMenu( nId ) );
if ( pNSSubmenu && [pNSSubmenu numberOfItems] )
{
[pNSSubmenu setTitle: pText];
[pNSMenuItem setSubmenu: pNSSubmenu];
if ( aCommand == ".uno:AddDirect" )
{
SvtModuleOptions aModuleOptions;
if ( aModuleOptions.IsModuleInstalled( SvtModuleOptions::EModule::STARTMODULE ) )
{
QSCommandMenuItem *pStartModuleMenuItem = [[QSCommandMenuItem alloc] initWithTitle: getAutoreleasedString( SfxResId( STR_QUICKSTART_STARTCENTER ) ) action: @selector(menuItemTriggered:) keyEquivalent: @"n"];
[pStartModuleMenuItem setTarget: pStartModuleMenuItem];
[pStartModuleMenuItem setCommand: STARTMODULE_URL];
[pNSSubmenu insertItem: pStartModuleMenuItem atIndex: 0];
[pStartModuleMenuItem autorelease];
}
}
}
else if ( !aCommand.isEmpty() )
{
[pNSMenuItem setTarget: pNSMenuItem];
[pNSMenuItem setCommand: aCommand];
setKeyEquivalent( pMenu->GetAccelKey( nId ), pNSMenuItem );
}
[pRet addItem: pNSMenuItem];
[pNSMenuItem autorelease];
}
else if ( pMenu->GetItemType( i ) == MenuItemType::SEPARATOR )
{
[pRet addItem: [NSMenuItem separatorItem]];
}
}
}
pMenu->Deactivate();
return pRet;
}
static void clearDefaultMenuBar()
{
if( ![NSApp respondsToSelector: @selector(removeFallbackMenuItem:)] )
return;
// Remove previous default menu
if ( pDefMenu )
[NSApp performSelector:@selector(removeFallbackMenuItem:) withObject: pDefMenu];
// Remove previous preferred menu
if ( pPreferredMenus && [pPreferredMenus count] )
{
for ( NSMenuItem *pNSMenuItem in pPreferredMenus )
[NSApp performSelector:@selector(removeFallbackMenuItem:) withObject: pNSMenuItem];
}
}
static void resetMenuBar()
{
if( ![NSApp respondsToSelector: @selector(addFallbackMenuItem:)] )
return;
clearDefaultMenuBar();
if ( pPreferredMenus && [pPreferredMenus count] )
{
for ( NSMenuItem *pNSMenuItem in pPreferredMenus )
[NSApp performSelector:@selector(addFallbackMenuItem:) withObject: pNSMenuItem];
}
else if ( pDefMenu )
{
[NSApp performSelector:@selector(addFallbackMenuItem:) withObject: pDefMenu];
}
}
void ShutdownIcon::SetDefaultMenuBar( MenuBar *pMenuBar )
{
if ( !pMenuBar )
return;
SolarMutexGuard aGuard;
clearDefaultMenuBar();
if ( pPreferredMenus )
{
[pPreferredMenus release];
pPreferredMenus = nil;
}
NSMenu *pNSMenu = getNSMenuForVCLMenu( pMenuBar );
if ( pNSMenu && [pNSMenu numberOfItems] )
{
pPreferredMenus = [NSMutableArray arrayWithArray: [pNSMenu itemArray]];
[pNSMenu removeAllItems];
[pPreferredMenus retain];
}
resetMenuBar();
}
extern "C"
{
void aqua_init_systray()
{
SolarMutexGuard aGuard;
ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
if( ! pShutdownIcon )
return;
// disable shutdown
pShutdownIcon->SetVeto( true );
ShutdownIcon::addTerminateListener();
if( ! pDefMenu )
{
if( [NSApp respondsToSelector: @selector(addFallbackMenuItem:)] )
{
aShortcuts.clear();
pExecute = [[QSMenuExecute alloc] init];
pDefMenu = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( SfxResId(STR_QUICKSTART_FILE) ) action: nullptr keyEquivalent: @""];
pDockSubMenu = [[NSMenuItem alloc] initWithTitle: getAutoreleasedString( SfxResId(STR_QUICKSTART_FILE) ) action: nullptr keyEquivalent: @""];
NSMenu* pMenu = [[NSMenu alloc] initWithTitle: getAutoreleasedString( SfxResId(STR_QUICKSTART_FILE) )];
[pMenu setAutoenablesItems: NO];
NSMenu* pDockMenu = [[NSMenu alloc] initWithTitle: getAutoreleasedString( SfxResId(STR_QUICKSTART_FILE) )];
[pDockMenu setAutoenablesItems: NO];
// collect the URLs of the entries in the File/New menu
SvtModuleOptions aModuleOptions;
std::set< OUString > aFileNewAppsAvailable;
std::vector < SvtDynMenuEntry > const aNewMenu = SvtDynamicMenuOptions::GetMenu( EDynamicMenuType::NewMenu );
for ( SvtDynMenuEntry const & newMenuProp : aNewMenu )
{
if ( !newMenuProp.sURL.isEmpty() )
aFileNewAppsAvailable.insert( newMenuProp.sURL );
}
// describe the menu entries for launching the applications
struct MenuEntryDescriptor
{
SvtModuleOptions::EModule eModuleIdentifier;
int nMenuTag;
OUString sURLDescription;
} static constexpr aMenuItems[] =
{
{ SvtModuleOptions::EModule::WRITER, MI_WRITER, WRITER_URL },
{ SvtModuleOptions::EModule::CALC, MI_CALC, CALC_URL },
{ SvtModuleOptions::EModule::IMPRESS, MI_IMPRESS, IMPRESS_WIZARD_URL },
{ SvtModuleOptions::EModule::DRAW, MI_DRAW, DRAW_URL },
{ SvtModuleOptions::EModule::DATABASE, MI_BASE, BASE_URL },
{ SvtModuleOptions::EModule::MATH, MI_MATH, MATH_URL }
};
// insert entry for startcenter
if( aModuleOptions.IsModuleInstalled( SvtModuleOptions::EModule::STARTMODULE ) )
{
appendMenuItem( pMenu, nil, SfxResId(STR_QUICKSTART_STARTCENTER), MI_STARTMODULE, "n" );
if( [NSApp respondsToSelector: @selector(setDockIconClickHandler:)] )
[NSApp performSelector:@selector(setDockIconClickHandler:) withObject: pExecute];
else
OSL_FAIL( "setDockIconClickHandler selector failed on NSApp" );
}
// insert the menu entries for launching the applications
for ( size_t i = 0; i < SAL_N_ELEMENTS( aMenuItems ); ++i )
{
if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) )
// the complete application is not even installed
continue;
const OUString& sURL( aMenuItems[i].sURLDescription );
if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() )
// the application is installed, but the entry has been configured to *not* appear in the File/New
// menu => also let not appear it in the quickstarter
continue;
appendMenuItem( pMenu, pDockMenu, ShutdownIcon::GetUrlDescription( sURL ), aMenuItems[i].nMenuTag, "" );
}
// insert the remaining menu entries
// add recent menu
appendRecentMenu( pMenu, SfxResId(STR_QUICKSTART_RECENTDOC) );
OUString aTitle( SfxResId(STR_QUICKSTART_FROMTEMPLATE) );
appendMenuItem( pMenu, pDockMenu, aTitle, MI_TEMPLATE, "" );
aTitle = SfxResId(STR_QUICKSTART_FILEOPEN);
appendMenuItem( pMenu, pDockMenu, aTitle, MI_OPEN, "" );
[pDefMenu setSubmenu: pMenu];
resetMenuBar();
if( [NSApp respondsToSelector: @selector(addDockMenuItem:)] )
{
[pDockSubMenu setSubmenu: pDockMenu];
// add the submenu
[NSApp performSelector:@selector(addDockMenuItem:) withObject: pDockSubMenu];
}
else
OSL_FAIL( "addDockMenuItem selector failed on NSApp" );
[pMenu autorelease];
[pDockMenu autorelease];
}
else
OSL_FAIL( "addFallbackMenuItem selector failed on NSApp" );
}
}
void SAL_DLLPUBLIC_EXPORT aqua_shutdown_systray()
{
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */