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/fontsizemenucontroller.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 #include <com/sun/star/view/XPrintable.hpp> 42 43 //_________________________________________________________________________________________________________________ 44 // includes of other projects 45 //_________________________________________________________________________________________________________________ 46 47 #ifndef _VCL_MENU_HXX_ 48 #include <vcl/menu.hxx> 49 #endif 50 #include <tools/mapunit.hxx> 51 #ifndef _VCL_SVAPP_HXX_ 52 #include <vcl/svapp.hxx> 53 #endif 54 #include <vcl/i18nhelp.hxx> 55 #ifndef _VCL_OUTPUTDEVICE_HXX_ 56 #include <vcl/outdev.hxx> 57 #endif 58 #include <vcl/print.hxx> 59 #ifndef _SVTOOLS_CTRLTOOL_HXX_ 60 #include <svtools/ctrltool.hxx> 61 #endif 62 #include <dispatch/uieventloghelper.hxx> 63 #include <vos/mutex.hxx> 64 65 //_________________________________________________________________________________________________________________ 66 // Defines 67 //_________________________________________________________________________________________________________________ 68 // 69 70 using namespace com::sun::star::uno; 71 using namespace com::sun::star::lang; 72 using namespace com::sun::star::frame; 73 using namespace com::sun::star::beans; 74 using namespace com::sun::star::util; 75 using namespace com::sun::star::view; 76 using namespace com::sun::star::beans; 77 78 namespace framework 79 { 80 81 DEFINE_XSERVICEINFO_MULTISERVICE ( FontSizeMenuController , 82 OWeakObject , 83 SERVICENAME_POPUPMENUCONTROLLER , 84 IMPLEMENTATIONNAME_FONTSIZEMENUCONTROLLER 85 ) 86 87 DEFINE_INIT_SERVICE ( FontSizeMenuController, {} ) 88 89 FontSizeMenuController::FontSizeMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) : 90 svt::PopupMenuControllerBase( xServiceManager ), 91 m_pHeightArray( 0 ), 92 m_bRebuildMenu( sal_True ) 93 { 94 } 95 96 FontSizeMenuController::~FontSizeMenuController() 97 { 98 delete []m_pHeightArray; 99 } 100 101 // private function 102 rtl::OUString FontSizeMenuController::retrievePrinterName( com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& rFrame ) 103 { 104 rtl::OUString aPrinterName; 105 106 if ( rFrame.is() ) 107 { 108 Reference< XController > xController = m_xFrame->getController(); 109 if ( xController.is() ) 110 { 111 Reference< XPrintable > xPrintable( xController->getModel(), UNO_QUERY ); 112 if ( xPrintable.is() ) 113 { 114 Sequence< PropertyValue > aPrinterSeq = xPrintable->getPrinter(); 115 for ( int i = 0; i < aPrinterSeq.getLength(); i++ ) 116 { 117 if ( aPrinterSeq[i].Name.equalsAscii( "Name" )) 118 { 119 aPrinterSeq[i].Value >>= aPrinterName; 120 break; 121 } 122 } 123 } 124 } 125 } 126 127 return aPrinterName; 128 } 129 130 // private function 131 void FontSizeMenuController::setCurHeight( long nHeight, Reference< css::awt::XPopupMenu >& rPopupMenu ) 132 { 133 // check menu item 134 rtl::OUString aHeight = Application::GetSettings().GetUILocaleI18nHelper().GetNum( nHeight, 1, sal_True, sal_False ); 135 sal_uInt16 nChecked = 0; 136 sal_uInt16 nItemCount = rPopupMenu->getItemCount(); 137 for( sal_uInt16 i = 0; i < nItemCount; i++ ) 138 { 139 sal_uInt16 nItemId = rPopupMenu->getItemId( i ); 140 141 if ( m_pHeightArray[i] == nHeight ) 142 { 143 rPopupMenu->checkItem( nItemId, sal_True ); 144 return; 145 } 146 147 if ( rPopupMenu->isItemChecked( nItemId ) ) 148 nChecked = nItemId; 149 } 150 151 if ( nChecked ) 152 rPopupMenu->checkItem( nChecked, sal_False ); 153 } 154 155 // private function 156 void FontSizeMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu ) 157 { 158 const rtl::OUString aFontNameCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontHeight?FontHeight=" )); 159 VCLXPopupMenu* pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); 160 PopupMenu* pVCLPopupMenu = 0; 161 162 resetPopupMenu( rPopupMenu ); 163 if ( pPopupMenu ) 164 pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); 165 166 if ( pVCLPopupMenu ) 167 { 168 FontList* pFontList = 0; 169 Printer* pInfoPrinter = 0; 170 rtl::OUString aPrinterName; 171 172 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 173 174 // try to retrieve printer name of document 175 aPrinterName = retrievePrinterName( m_xFrame ); 176 if ( aPrinterName.getLength() > 0 ) 177 { 178 pInfoPrinter = new Printer( aPrinterName ); 179 if ( pInfoPrinter && pInfoPrinter->GetDevFontCount() > 0 ) 180 pFontList = new FontList( pInfoPrinter ); 181 } 182 183 if ( pFontList == 0 ) 184 pFontList = new FontList( Application::GetDefaultDevice() ); 185 186 FontInfo aFntInfo = pFontList->Get( m_aFontDescriptor.Name, m_aFontDescriptor.StyleName ); 187 188 // setup font size array 189 if ( m_pHeightArray ) 190 delete m_pHeightArray; 191 192 const long* pTempAry; 193 const long* pAry = pFontList->GetSizeAry( aFntInfo ); 194 sal_uInt16 nSizeCount = 0; 195 while ( pAry[nSizeCount] ) 196 nSizeCount++; 197 198 sal_uInt16 nPos = 0; 199 const rtl::OUString aFontHeightCommand( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontHeight?FontHeight.Height:float=" )); 200 201 // first insert font size names (for simplified/traditional chinese) 202 float fPoint; 203 rtl::OUString aHeightString; 204 FontSizeNames aFontSizeNames( Application::GetSettings().GetUILanguage() ); 205 m_pHeightArray = new long[nSizeCount+aFontSizeNames.Count()]; 206 rtl::OUString aCommand; 207 208 if ( !aFontSizeNames.IsEmpty() ) 209 { 210 if ( pAry == pFontList->GetStdSizeAry() ) 211 { 212 // for scalable fonts all font size names 213 sal_uLong nCount = aFontSizeNames.Count(); 214 for( sal_uLong i = 0; i < nCount; i++ ) 215 { 216 String aSizeName = aFontSizeNames.GetIndexName( i ); 217 long nSize = aFontSizeNames.GetIndexSize( i ); 218 m_pHeightArray[nPos] = nSize; 219 nPos++; // Id is nPos+1 220 pVCLPopupMenu->InsertItem( nPos, aSizeName, MIB_RADIOCHECK | MIB_AUTOCHECK ); 221 fPoint = float( m_pHeightArray[nPos-1] ) / 10; 222 223 // Create dispatchable .uno command and set it 224 aCommand = aFontHeightCommand + rtl::OUString::valueOf( fPoint ); 225 pVCLPopupMenu->SetItemCommand( nPos, aCommand ); 226 } 227 } 228 else 229 { 230 // for fixed size fonts only selectable font size names 231 pTempAry = pAry; 232 while ( *pTempAry ) 233 { 234 String aSizeName = aFontSizeNames.Size2Name( *pTempAry ); 235 if ( aSizeName.Len() ) 236 { 237 m_pHeightArray[nPos] = *pTempAry; 238 nPos++; // Id is nPos+1 239 pVCLPopupMenu->InsertItem( nPos, aSizeName, MIB_RADIOCHECK | MIB_AUTOCHECK ); 240 fPoint = float( m_pHeightArray[nPos-1] ) / 10; 241 242 // Create dispatchable .uno command and set it 243 aCommand = aFontHeightCommand + rtl::OUString::valueOf( fPoint ); 244 pVCLPopupMenu->SetItemCommand( nPos, aCommand ); 245 } 246 pTempAry++; 247 } 248 } 249 } 250 251 // then insert numerical font size values 252 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper(); 253 pTempAry = pAry; 254 while ( *pTempAry ) 255 { 256 m_pHeightArray[nPos] = *pTempAry; 257 nPos++; // Id is nPos+1 258 pVCLPopupMenu->InsertItem( nPos, rI18nHelper.GetNum( *pTempAry, 1, sal_True, sal_False ), MIB_RADIOCHECK | MIB_AUTOCHECK ); 259 fPoint = float( m_pHeightArray[nPos-1] ) / 10; 260 261 // Create dispatchable .uno command and set it 262 aCommand = aFontHeightCommand + rtl::OUString::valueOf( fPoint ); 263 pVCLPopupMenu->SetItemCommand( nPos, aCommand ); 264 265 pTempAry++; 266 } 267 268 setCurHeight( long( m_aFontHeight.Height * 10), rPopupMenu ); 269 270 delete pFontList; 271 delete pInfoPrinter; 272 } 273 } 274 275 // XEventListener 276 void SAL_CALL FontSizeMenuController::disposing( const EventObject& ) throw ( RuntimeException ) 277 { 278 Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY ); 279 280 osl::MutexGuard aLock( m_aMutex ); 281 m_xFrame.clear(); 282 m_xDispatch.clear(); 283 m_xCurrentFontDispatch.clear(); 284 if ( m_xPopupMenu.is() ) 285 m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY )); 286 m_xPopupMenu.clear(); 287 } 288 289 // XStatusListener 290 void SAL_CALL FontSizeMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException ) 291 { 292 com::sun::star::awt::FontDescriptor aFontDescriptor; 293 ::com::sun::star::frame::status::FontHeight aFontHeight; 294 295 if ( Event.State >>= aFontDescriptor ) 296 { 297 osl::MutexGuard aLock( m_aMutex ); 298 m_aFontDescriptor = aFontDescriptor; 299 300 if ( m_xPopupMenu.is() ) 301 fillPopupMenu( m_xPopupMenu ); 302 303 } 304 else if ( Event.State >>= aFontHeight ) 305 { 306 osl::MutexGuard aLock( m_aMutex ); 307 m_aFontHeight = aFontHeight; 308 309 if ( m_xPopupMenu.is() ) 310 { 311 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 312 setCurHeight( long( m_aFontHeight.Height * 10), m_xPopupMenu ); 313 } 314 } 315 } 316 317 // XMenuListener 318 void FontSizeMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL) 319 { 320 Sequence<PropertyValue> aArgs; 321 if(::comphelper::UiEventsLogger::isEnabled()) //#i88653# 322 UiEventLogHelper(::rtl::OUString::createFromAscii("FontSizeMenuController")).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs); 323 OSL_ENSURE(_xDispatch.is(),"FontSizeMenuController::impl_select: No dispatch"); 324 if ( _xDispatch.is() ) 325 _xDispatch->dispatch( aTargetURL, aArgs ); 326 } 327 328 // XPopupMenuController 329 void FontSizeMenuController::impl_setPopupMenu() 330 { 331 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); 332 com::sun::star::util::URL aTargetURL; 333 // Register for font name updates which gives us info about the current font! 334 aTargetURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:CharFontName" )); 335 m_xURLTransformer->parseStrict( aTargetURL ); 336 m_xCurrentFontDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); 337 } 338 339 void SAL_CALL FontSizeMenuController::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) 340 { 341 osl::ClearableMutexGuard aLock( m_aMutex ); 342 343 throwIfDisposed(); 344 345 Reference< XDispatch > xDispatch( m_xCurrentFontDispatch ); 346 com::sun::star::util::URL aTargetURL; 347 aTargetURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:CharFontName" )); 348 m_xURLTransformer->parseStrict( aTargetURL ); 349 aLock.clear(); 350 351 if ( xDispatch.is() ) 352 { 353 xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 354 xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL ); 355 } 356 357 svt::PopupMenuControllerBase::updatePopupMenu(); 358 } 359 } 360