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/headermenucontroller.hxx>
31 
32 //_________________________________________________________________________________________________________________
33 //	my own includes
34 //_________________________________________________________________________________________________________________
35 #include <threadhelp/resetableguard.hxx>
36 #include "services.h"
37 
38 #ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_
39 #include <classes/resource.hrc>
40 #endif
41 #include <classes/fwlresid.hxx>
42 
43 //_________________________________________________________________________________________________________________
44 //	interface includes
45 //_________________________________________________________________________________________________________________
46 #include <com/sun/star/awt/XDevice.hpp>
47 #include <com/sun/star/beans/PropertyValue.hpp>
48 #include <com/sun/star/awt/MenuItemStyle.hpp>
49 #include <com/sun/star/frame/XDispatchProvider.hpp>
50 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
51 #include <com/sun/star/container/XNameContainer.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 
54 //_________________________________________________________________________________________________________________
55 //	includes of other projects
56 //_________________________________________________________________________________________________________________
57 
58 #ifndef _VCL_MENU_HXX_
59 #include <vcl/menu.hxx>
60 #endif
61 #include <vcl/svapp.hxx>
62 #include <vcl/i18nhelp.hxx>
63 #include <tools/urlobj.hxx>
64 #include <rtl/ustrbuf.hxx>
65 //#include <tools/solar.hrc>
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::style;
80 using namespace com::sun::star::container;
81 
82 // Copied from Writer module
83 //#define RID_SW_SHELLRES (RID_SW_START + 1250 + 1)
84 //#define STR_ALLPAGE_HEADFOOT 14
85 
86 const sal_uInt16 ALL_MENUITEM_ID = 1;
87 
88 namespace framework
89 {
90 
91 DEFINE_XSERVICEINFO_MULTISERVICE        (   HeaderMenuController				    ,
92                                             OWeakObject                             ,
93                                             SERVICENAME_POPUPMENUCONTROLLER		    ,
94 											IMPLEMENTATIONNAME_HEADERMENUCONTROLLER
95 										)
96 
97 DEFINE_INIT_SERVICE                     (   HeaderMenuController, {} )
98 
99 HeaderMenuController::HeaderMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager,bool _bFooter ) :
100 	svt::PopupMenuControllerBase( xServiceManager )
101     ,m_bFooter(_bFooter)
102 {
103 }
104 
105 HeaderMenuController::~HeaderMenuController()
106 {
107 }
108 
109 // private function
110 void HeaderMenuController::fillPopupMenu( const Reference< ::com::sun::star::frame::XModel >& rModel, Reference< css::awt::XPopupMenu >& rPopupMenu )
111 {
112     VCLXPopupMenu*                                     pPopupMenu        = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu );
113     PopupMenu*                                         pVCLPopupMenu     = 0;
114 
115     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
116 
117     resetPopupMenu( rPopupMenu );
118     if ( pPopupMenu )
119         pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu();
120 
121     Reference< XStyleFamiliesSupplier > xStyleFamiliesSupplier( rModel, UNO_QUERY );
122     if ( pVCLPopupMenu && xStyleFamiliesSupplier.is())
123     {
124         Reference< XNameAccess > xStyleFamilies = xStyleFamiliesSupplier->getStyleFamilies();
125 
126         rtl::OUString aCmd( RTL_CONSTASCII_USTRINGPARAM( ".uno:InsertPageHeader" ));
127         rtl::OUString aHeaderFooterIsOnStr(RTL_CONSTASCII_USTRINGPARAM( "HeaderIsOn" ));
128         if ( m_bFooter )
129         {
130             aCmd = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:InsertPageFooter" ));
131             aHeaderFooterIsOnStr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FooterIsOn" ));
132         }
133         const rtl::OUString aIsPhysicalStr( RTL_CONSTASCII_USTRINGPARAM( "IsPhysical" ));
134         const rtl::OUString aDisplayNameStr( RTL_CONSTASCII_USTRINGPARAM( "DisplayName" ));
135 
136         try
137         {
138             Reference< XNameContainer > xNameContainer;
139             if ( xStyleFamilies->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageStyles" ))) >>= xNameContainer )
140             {
141                 Sequence< rtl::OUString > aSeqNames = xNameContainer->getElementNames();
142 
143                 sal_uInt16   nId = 2;
144                 sal_uInt16  nCount = 0;
145                 sal_Bool bAllOneState( sal_True );
146                 sal_Bool bLastCheck( sal_True );
147                 sal_Bool bFirstChecked( sal_False );
148                 sal_Bool bFirstItemInserted( sal_False );
149                 for ( sal_Int32 n = 0; n < aSeqNames.getLength(); n++ )
150                 {
151                     rtl::OUString aName = aSeqNames[n];
152                     Reference< XPropertySet > xPropSet( xNameContainer->getByName( aName ), UNO_QUERY );
153                     if ( xPropSet.is() )
154                     {
155                         sal_Bool bIsPhysical( sal_False );
156                         if (( xPropSet->getPropertyValue( aIsPhysicalStr ) >>= bIsPhysical ) && bIsPhysical )
157                         {
158                             rtl::OUString aDisplayName;
159                             sal_Bool      bHeaderIsOn( sal_False );
160                             xPropSet->getPropertyValue( aDisplayNameStr ) >>= aDisplayName;
161                             xPropSet->getPropertyValue( aHeaderFooterIsOnStr ) >>= bHeaderIsOn;
162 
163                             rtl::OUStringBuffer aStrBuf( aCmd );
164                             aStrBuf.appendAscii( "?PageStyle:string=");
165                             aStrBuf.append( aDisplayName );
166                             aStrBuf.appendAscii( "&On:bool=" );
167                             if ( !bHeaderIsOn )
168                                 aStrBuf.appendAscii( "true" );
169                             else
170                                 aStrBuf.appendAscii( "false" );
171                             rtl::OUString aCommand( aStrBuf.makeStringAndClear() );
172                             pVCLPopupMenu->InsertItem( nId, aDisplayName, MIB_CHECKABLE );
173                             if ( !bFirstItemInserted )
174                             {
175                                 bFirstItemInserted = sal_True;
176                                 bFirstChecked      = bHeaderIsOn;
177                             }
178 
179                             pVCLPopupMenu->SetItemCommand( nId, aCommand );
180 
181                             if ( bHeaderIsOn )
182                                 pVCLPopupMenu->CheckItem( nId, sal_True );
183                             ++nId;
184 
185                             // Check if all entries have the same state
186                             if( bAllOneState && n && bHeaderIsOn != bLastCheck )
187 				                bAllOneState = sal_False;
188                             bLastCheck = bHeaderIsOn;
189                             ++nCount;
190                         }
191                     }
192                 }
193 
194                 if ( bAllOneState && ( nCount > 1 ))
195                 {
196                     // Insert special item for all command
197                     pVCLPopupMenu->InsertItem( ALL_MENUITEM_ID, String( FwlResId( STR_MENU_HEADFOOTALL )), 0, 0 );
198 
199                     rtl::OUStringBuffer aStrBuf( aCmd );
200                     aStrBuf.appendAscii( "?On:bool=" );
201 
202                     // Command depends on check state of first menu item entry
203                     if ( !bFirstChecked )
204                         aStrBuf.appendAscii( "true" );
205                     else
206                         aStrBuf.appendAscii( "false" );
207 
208                     pVCLPopupMenu->SetItemCommand( 1, aStrBuf.makeStringAndClear() );
209 				    pVCLPopupMenu->InsertSeparator( 1 );
210                 }
211             }
212         }
213         catch ( com::sun::star::container::NoSuchElementException& )
214         {
215         }
216     }
217 }
218 
219 // XEventListener
220 void SAL_CALL HeaderMenuController::disposing( const EventObject& ) throw ( RuntimeException )
221 {
222     Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY );
223 
224     osl::MutexGuard aLock( m_aMutex );
225     m_xFrame.clear();
226     m_xDispatch.clear();
227     m_xServiceManager.clear();
228 
229     if ( m_xPopupMenu.is() )
230         m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY ));
231     m_xPopupMenu.clear();
232 }
233 
234 // XStatusListener
235 void SAL_CALL HeaderMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException )
236 {
237     Reference< com::sun::star::frame::XModel > xModel;
238 
239     if ( Event.State >>= xModel )
240     {
241         osl::MutexGuard aLock( m_aMutex );
242         m_xModel = xModel;
243         if ( m_xPopupMenu.is() )
244             fillPopupMenu( xModel, m_xPopupMenu );
245     }
246 }
247 
248 // XMenuListener
249 void HeaderMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL)
250 {
251     Sequence<PropertyValue>	     aArgs;
252     if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
253         UiEventLogHelper(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(m_bFooter ? "FooterMenuController" : "HeaderMenuController"))).log(m_xServiceManager, m_xFrame, aTargetURL, aArgs);
254 	OSL_ENSURE(_xDispatch.is(),"HeaderMenuController::impl_select: No dispatch");
255 	if ( _xDispatch.is() )
256 		_xDispatch->dispatch( aTargetURL, aArgs );
257 }
258 
259 void SAL_CALL HeaderMenuController::updatePopupMenu() throw (::com::sun::star::uno::RuntimeException)
260 {
261     osl::ResettableMutexGuard aLock( m_aMutex );
262 
263 	throwIfDisposed();
264 
265     Reference< com::sun::star::frame::XModel > xModel( m_xModel );
266     aLock.clear();
267 
268     if ( !xModel.is() )
269 		svt::PopupMenuControllerBase::updatePopupMenu();
270 
271     aLock.reset();
272     if ( m_xPopupMenu.is() && m_xModel.is() )
273         fillPopupMenu( m_xModel, m_xPopupMenu );
274 }
275 
276 }
277