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