1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_framework.hxx" 26 #include <uielement/fontmenucontroller.hxx> 27 28 //_________________________________________________________________________________________________________________ 29 // my own includes 30 //_________________________________________________________________________________________________________________ 31 #include <threadhelp/resetableguard.hxx> 32 #include "services.h" 33 34 //_________________________________________________________________________________________________________________ 35 // interface includes 36 //_________________________________________________________________________________________________________________ 37 #include <com/sun/star/awt/XDevice.hpp> 38 #include <com/sun/star/beans/PropertyValue.hpp> 39 #include <com/sun/star/awt/MenuItemStyle.hpp> 40 #include <com/sun/star/frame/XDispatchProvider.hpp> 41 42 43 //_________________________________________________________________________________________________________________ 44 // includes of other projects 45 //_________________________________________________________________________________________________________________ 46 47 #ifndef _VCL_MENU_HXX_ 48 #include <vcl/menu.hxx> 49 #endif 50 #include <vcl/svapp.hxx> 51 #include <vcl/i18nhelp.hxx> 52 #include <tools/urlobj.hxx> 53 #include <rtl/ustrbuf.hxx> 54 #ifndef _VCL_MNEMONIC_HXX_ 55 #include <vcl/mnemonic.hxx> 56 #endif 57 #include <dispatch/uieventloghelper.hxx> 58 #include <vos/mutex.hxx> 59 60 //_________________________________________________________________________________________________________________ 61 // Defines 62 //_________________________________________________________________________________________________________________ 63 // 64 65 using namespace com::sun::star::uno; 66 using namespace com::sun::star::lang; 67 using namespace com::sun::star::frame; 68 using namespace com::sun::star::beans; 69 using namespace com::sun::star::util; 70 71 using namespace std; 72 73 bool lcl_I18nCompareString(const rtl::OUString& rStr1, const rtl::OUString& rStr2) 74 { 75 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper(); 76 return rI18nHelper.CompareString( rStr1, rStr2 ) < 0 ? true : false; 77 } 78 79 namespace framework 80 { 81 82 DEFINE_XSERVICEINFO_MULTISERVICE ( FontMenuController , 83 OWeakObject , 84 SERVICENAME_POPUPMENUCONTROLLER , 85 IMPLEMENTATIONNAME_FONTMENUCONTROLLER 86 ) 87 88 DEFINE_INIT_SERVICE ( FontMenuController, {} ) 89 90 FontMenuController::FontMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : 91 svt::PopupMenuControllerBase( xServiceManager ) 92 { 93 } 94 95 FontMenuController::~FontMenuController() 96 { 97 } 98 99 // private function 100 void FontMenuController::fillPopupMenu( const Sequence< ::rtl::OUString >& rFontNameSeq, Reference< css::awt::XPopupMenu >& rPopupMenu ) 101 { 102 const rtl::OUString* pFontNameArray = rFontNameSeq.getConstArray(); 103 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); 104 PopupMenu* pVCLPopupMenu = 0; 105 106 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 107 108 resetPopupMenu( rPopupMenu ); 109 if ( pPopupMenu ) 110 pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); 111 112 if ( pVCLPopupMenu ) 113 { 114 vector<rtl::OUString> aVector; 115 aVector.reserve(rFontNameSeq.getLength()); 116 for ( sal_uInt16 i = 0; i < rFontNameSeq.getLength(); i++ ) 117 { 118 aVector.push_back(MnemonicGenerator::EraseAllMnemonicChars(pFontNameArray[i])); 119 } 120 sort(aVector.begin(), aVector.end(), lcl_I18nCompareString ); 121 122 const rtl::OUString aFontNameCommandPrefix( RTL_CONSTASCII_USTRINGPARAM( ".uno:CharFontName?CharFontName.FamilyName:string=" )); 123 const sal_Int16 nCount = (sal_Int16)aVector.size(); 124 for ( sal_Int16 i = 0; i < nCount; i++ ) 125 { 126 const rtl::OUString& rName = aVector[i]; 127 m_xPopupMenu->insertItem( i+1, rName, css::awt::MenuItemStyle::RADIOCHECK | css::awt::MenuItemStyle::AUTOCHECK, i ); 128 if ( rName == m_aFontFamilyName ) 129 m_xPopupMenu->checkItem( i+1, sal_True ); 130 // use VCL popup menu pointer to set vital information that are not part of the awt implementation 131 rtl::OUStringBuffer aCommandBuffer( aFontNameCommandPrefix ); 132 aCommandBuffer.append( INetURLObject::encode( rName, INetURLObject::PART_HTTP_QUERY, '%', INetURLObject::ENCODE_ALL )); 133 rtl::OUString aFontNameCommand = aCommandBuffer.makeStringAndClear(); 134 pVCLPopupMenu->SetItemCommand( i+1, aFontNameCommand ); // Store font name into item command. 135 } 136 137 } 138 } 139 140 // XEventListener 141 void SAL_CALL FontMenuController::disposing( const EventObject& ) throw ( RuntimeException ) 142 { 143 Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); 144 145 osl::MutexGuard aLock( m_aMutex ); 146 m_xFrame.clear(); 147 m_xDispatch.clear(); 148 m_xFontListDispatch.clear(); 149 m_xServiceManager.clear(); 150 151 if ( m_xPopupMenu.is() ) 152 m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); 153 m_xPopupMenu.clear(); 154 } 155 156 // XStatusListener 157 void SAL_CALL FontMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) 158 { 159 com::sun::star::awt::FontDescriptor aFontDescriptor; 160 Sequence< rtl::OUString > aFontNameSeq; 161 162 if ( Event.State >>= aFontDescriptor ) 163 { 164 osl::MutexGuard aLock( m_aMutex ); 165 m_aFontFamilyName = aFontDescriptor.Name; 166 } 167 else if ( Event.State >>= aFontNameSeq ) 168 { 169 osl::MutexGuard aLock( m_aMutex ); 170 if ( m_xPopupMenu.is() ) 171 fillPopupMenu( aFontNameSeq, m_xPopupMenu ); 172 } 173 } 174 175 // XMenuListener 176 void FontMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL) 177 { 178 Sequence<PropertyValue> aArgs; 179 if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# 180 UiEventLogHelper(::rtl::OUString::createFromAscii("FontMenuController")).log( 181 m_xServiceManager, 182 m_xFrame, 183 aTargetURL, 184 Sequence<PropertyValue>()); 185 OSL_ENSURE(_xDispatch.is(),"FontMenuController::impl_select: No dispatch"); 186 if ( _xDispatch.is() ) 187 _xDispatch->dispatch( aTargetURL, aArgs ); 188 } 189 190 void SAL_CALL FontMenuController::activate( const css::awt::MenuEvent& ) throw (RuntimeException) 191 { 192 osl::MutexGuard aLock( m_aMutex ); 193 194 if ( m_xPopupMenu.is() ) 195 { 196 // find new font name and set check mark! 197 sal_uInt16 nChecked = 0; 198 sal_uInt16 nItemCount = m_xPopupMenu->getItemCount(); 199 rtl::OUString aEmpty; 200 for( sal_uInt16 i = 0; i < nItemCount; i++ ) 201 { 202 sal_uInt16 nItemId = m_xPopupMenu->getItemId( i ); 203 204 if ( m_xPopupMenu->isItemChecked( nItemId ) ) 205 nChecked = nItemId; 206 207 rtl::OUString aText = m_xPopupMenu->getItemText( nItemId ); 208 209 // TODO: must be replaced by implementation of VCL, when available 210 sal_Int32 nIndex = aText.indexOf( (sal_Unicode)'~' ); 211 if ( nIndex >= 0 ) 212 aText = aText.replaceAt( nIndex, 1, aEmpty ); 213 // TODO: must be replaced by implementation of VCL, when available 214 215 if ( aText == m_aFontFamilyName ) 216 { 217 m_xPopupMenu->checkItem( nItemId, sal_True ); 218 return; 219 } 220 } 221 222 if ( nChecked ) 223 m_xPopupMenu->checkItem( nChecked, sal_False ); 224 } 225 } 226 227 // XPopupMenuController 228 void FontMenuController::impl_setPopupMenu() 229 { 230 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); 231 232 com::sun::star::util::URL aTargetURL; 233 // Register for font list updates to get the current font list from the controller 234 aTargetURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontNameList" )); 235 m_xURLTransformer->parseStrict( aTargetURL ); 236 m_xFontListDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); 237 } 238 239 void SAL_CALL FontMenuController::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) 240 { 241 svt::PopupMenuControllerBase::updatePopupMenu(); 242 243 osl::ClearableMutexGuard aLock( m_aMutex ); 244 Reference< XDispatch > xDispatch( m_xFontListDispatch ); 245 com::sun::star::util::URL aTargetURL; 246 aTargetURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontNameList" )); 247 m_xURLTransformer->parseStrict( aTargetURL ); 248 aLock.clear(); 249 250 if ( xDispatch.is() ) 251 { 252 xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 253 xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 254 } 255 } 256 257 } 258 259