xref: /AOO41X/main/framework/source/uielement/fontsizemenucontroller.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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