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 
27 #include <uielement/langselectionmenucontroller.hxx>
28 
29 //_________________________________________________________________________________________________________________
30 //	my own includes
31 //_________________________________________________________________________________________________________________
32 #include <threadhelp/resetableguard.hxx>
33 #include "services.h"
34 
35 //_________________________________________________________________________________________________________________
36 //	interface includes
37 //_________________________________________________________________________________________________________________
38 #include <com/sun/star/awt/XDevice.hpp>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/awt/MenuItemStyle.hpp>
41 #include <com/sun/star/frame/XDispatchProvider.hpp>
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 <comphelper/processfactory.hxx>
58 
59 #include <com/sun/star/document/XDocumentLanguages.hpp>
60 #include <com/sun/star/frame/XPopupMenuController.hpp>
61 #include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
62 
63 #include <i18npool/mslangid.hxx>
64 #include <svl/languageoptions.hxx>
65 #include <com/sun/star/awt/MenuItemStyle.hpp>
66 #include <svtools/langtab.hxx>
67 #include <classes/fwlresid.hxx>
68 
69 #ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_
70 #include <classes/resource.hrc>
71 #endif
72 #include <dispatch/uieventloghelper.hxx>
73 
74 #include "helper/mischelper.hxx"
75 #include <vos/mutex.hxx>
76 
77 #include <map>
78 #include <set>
79 
80 //_________________________________________________________________________________________________________________
81 //	Defines
82 //_________________________________________________________________________________________________________________
83 //
84 using namespace ::com::sun::star;
85 using namespace com::sun::star::uno;
86 using namespace com::sun::star::lang;
87 using namespace com::sun::star::frame;
88 using namespace com::sun::star::beans;
89 using namespace com::sun::star::util;
90 
91 using ::rtl::OUString;
92 
93 namespace framework
94 {
95 
DEFINE_XSERVICEINFO_MULTISERVICE(LanguageSelectionMenuController,OWeakObject,SERVICENAME_POPUPMENUCONTROLLER,IMPLEMENTATIONNAME_LANGUAGESELECTIONMENUCONTROLLER)96 DEFINE_XSERVICEINFO_MULTISERVICE        (   LanguageSelectionMenuController			,
97                                             OWeakObject                             ,
98                                             SERVICENAME_POPUPMENUCONTROLLER			,
99 											IMPLEMENTATIONNAME_LANGUAGESELECTIONMENUCONTROLLER
100 										)
101 
102 DEFINE_INIT_SERVICE                     (   LanguageSelectionMenuController, {} )
103 
104 LanguageSelectionMenuController::LanguageSelectionMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) :
105 	svt::PopupMenuControllerBase( xServiceManager ),
106 	m_bShowMenu( sal_True ),
107 	m_aLangGuessHelper( xServiceManager )
108 {
109 }
110 
~LanguageSelectionMenuController()111 LanguageSelectionMenuController::~LanguageSelectionMenuController()
112 {
113 }
114 
115 // XEventListener
disposing(const EventObject &)116 void SAL_CALL LanguageSelectionMenuController::disposing( const EventObject& ) throw ( RuntimeException )
117 {
118 	Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY );
119 
120 	osl::MutexGuard aLock( m_aMutex );
121 	m_xFrame.clear();
122 	m_xDispatch.clear();
123 	m_xLanguageDispatch.clear();
124 	m_xServiceManager.clear();
125 
126 	if ( m_xPopupMenu.is() )
127 		m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY ));
128 	m_xPopupMenu.clear();
129 }
130 
131 // XStatusListener
statusChanged(const FeatureStateEvent & Event)132 void SAL_CALL LanguageSelectionMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException )
133 {
134 	vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
135 
136 	if (rBHelper.bDisposed || rBHelper.bInDispose)
137 		return;
138 
139 	m_bShowMenu = sal_True;
140 	m_nScriptType = LS_SCRIPT_LATIN | LS_SCRIPT_ASIAN | LS_SCRIPT_COMPLEX; // set the default value
141 
142 	OUString               aStrValue;
143 	Sequence< OUString > aSeq;
144 
145 	if ( Event.State >>= aSeq )
146 	{
147 		if ( aSeq.getLength() == 4 )
148 		{
149 			// Retrieve all other values from the sequence and
150 			// store it members!
151 			m_aCurLang          = aSeq[0];
152 			m_nScriptType       = static_cast< sal_Int16 >(aSeq[1].toInt32());
153 			m_aKeyboardLang     = aSeq[2];
154 			m_aGuessedTextLang  = aSeq[3];
155 		}
156 	}
157 	else if ( !Event.State.hasValue() )
158 	{
159 		m_bShowMenu = sal_False;	// no language -> no sub-menu entries -> disable menu
160 	}
161 }
162 
163 // XMenuListener
impl_select(const Reference<XDispatch> & _xDispatch,const::com::sun::star::util::URL & aTargetURL)164 void LanguageSelectionMenuController::impl_select(const Reference< XDispatch >& _xDispatch,const ::com::sun::star::util::URL& aTargetURL)
165 {
166 	Reference< XDispatch > xDispatch = _xDispatch;
167 
168 	if ( aTargetURL.Complete == m_aMenuCommandURL_Font )
169 	{	// open format/character dialog for current selection
170 		xDispatch = m_xMenuDispatch_Font;
171 	}
172 	else if ( aTargetURL.Complete == m_aMenuCommandURL_Lang )
173 	{	// open language tab-page in tools/options dialog
174 		xDispatch = m_xMenuDispatch_Lang;
175 	}
176 	else if ( aTargetURL.Complete == m_aMenuCommandURL_CharDlgForParagraph )
177 	{	// open format/character dialog for current selection
178 		xDispatch = m_xMenuDispatch_CharDlgForParagraph;
179 	}
180 
181 	if ( !xDispatch.is() )
182 	{
183 		Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
184 		if ( xDispatchProvider.is() )
185 			xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
186 	}
187 
188 	if ( xDispatch.is() )
189 	{
190 		Sequence<PropertyValue>	     aArgs;
191 		if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
192 			UiEventLogHelper( OUString::createFromAscii("LanguageSelectionMenuController")).log( m_xServiceManager, m_xFrame, aTargetURL, aArgs );
193 		xDispatch->dispatch( aTargetURL, aArgs );
194 	}
195 }
196 
197 // XPopupMenuController
impl_setPopupMenu()198 void LanguageSelectionMenuController::impl_setPopupMenu()
199 {
200 	Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
201 
202 	com::sun::star::util::URL aTargetURL;
203 
204 	// Register for language updates
205 	aTargetURL.Complete = m_aLangStatusCommandURL;
206 	m_xURLTransformer->parseStrict( aTargetURL );
207 	m_xLanguageDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
208 
209 	// Register for setting languages and opening language dialog
210 	aTargetURL.Complete = m_aMenuCommandURL_Lang;
211 	m_xURLTransformer->parseStrict( aTargetURL );
212 	m_xMenuDispatch_Lang = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
213 
214 	// Register for opening character dialog
215 	aTargetURL.Complete = m_aMenuCommandURL_Font;
216 	m_xURLTransformer->parseStrict( aTargetURL );
217 	m_xMenuDispatch_Font = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
218 
219 	// Register for opening character dialog with preselected paragraph
220 	aTargetURL.Complete = m_aMenuCommandURL_CharDlgForParagraph;
221 	m_xURLTransformer->parseStrict( aTargetURL );
222 	m_xMenuDispatch_CharDlgForParagraph = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
223 }
224 
fillPopupMenu(Reference<css::awt::XPopupMenu> & rPopupMenu,const Mode eMode)225 void LanguageSelectionMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu , const Mode eMode )
226 {
227 	VCLXPopupMenu* pVCLPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu );
228 	PopupMenu*     pPopupMenu    = 0;
229 
230 	vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
231 
232 	resetPopupMenu( rPopupMenu );
233 	if (!m_bShowMenu)
234 		return;
235 
236 	if ( pVCLPopupMenu )
237 		pPopupMenu = (PopupMenu *)pVCLPopupMenu->GetMenu();
238 
239 	String aCmd;
240 	String aCmd_Dialog;
241 	String aCmd_Language;
242 	if( eMode == MODE_SetLanguageSelectionMenu )
243 	{
244 		aCmd_Dialog.AppendAscii(".uno:FontDialog?Language:string=*");
245 		aCmd_Language.AppendAscii(".uno:LanguageStatus?Language:string=Current_");
246 	}
247 	else if ( eMode == MODE_SetLanguageParagraphMenu )
248 	{
249 		aCmd_Dialog.AppendAscii(".uno:FontDialogForParagraph");
250 		aCmd_Language.AppendAscii(".uno:LanguageStatus?Language:string=Paragraph_");
251 	}
252 	else if ( eMode == MODE_SetLanguageAllTextMenu )
253 	{
254 		aCmd_Dialog.AppendAscii(".uno:LanguageStatus?Language:string=*");
255 		aCmd_Language.AppendAscii(".uno:LanguageStatus?Language:string=Default_");
256 	}
257 
258 	SvtLanguageTable    aLanguageTable;
259 
260 	// get languages to be displayed in the menu
261 	std::set< OUString > aLangItems;
262 	FillLangItems( aLangItems, aLanguageTable, m_xFrame, m_aLangGuessHelper,
263 			m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedTextLang );
264 
265 	// now add menu entries
266 	// the different menu purposes will be handled by the different string
267 	// for aCmd_Dialog and aCmd_Language
268 
269 	sal_Int16 nItemId = 1; // in this control the item id is not important for executing the command
270 	const OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*")); // multiple languages in current selection
271 	const OUString sEmpty; // 'no language found' from language guessing
272 	std::map< sal_Int16, OUString > aLangMap;
273 	std::set< OUString >::const_iterator it;
274 	for (it = aLangItems.begin(); it != aLangItems.end(); ++it)
275 	{
276 		const OUString & rStr( *it );
277 		if (rStr != OUString( aLanguageTable.GetString( LANGUAGE_NONE ) )&&
278 			rStr != sAsterix &&
279 			rStr != sEmpty)
280 		{
281 			pPopupMenu->InsertItem( nItemId, rStr );
282 			aCmd = aCmd_Language;
283 			aCmd += String( rStr );
284 			pPopupMenu->SetItemCommand( nItemId, aCmd );
285 			if (rStr == m_aCurLang && eMode == MODE_SetLanguageSelectionMenu )
286 			{
287 				//make a sign for the current language
288 				pPopupMenu->CheckItem( nItemId, sal_True );
289 			}
290 			aLangMap[ nItemId ] = rStr;
291 			++nItemId;
292 		}
293 	}
294 
295 	// entry for LANGUAGE_NONE
296 	++nItemId;
297 	pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_LANGSTATUS_NONE )) );
298 	aCmd=aCmd_Language;
299 	aCmd.AppendAscii("LANGUAGE_NONE");
300 	pPopupMenu->SetItemCommand( nItemId, aCmd );
301 
302 	// entry for 'Reset to default language'
303 	++nItemId;
304 	pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_RESET_TO_DEFAULT_LANGUAGE )) );
305 	aCmd=aCmd_Language;
306 	aCmd.AppendAscii("RESET_LANGUAGES");
307 	pPopupMenu->SetItemCommand( nItemId, aCmd );
308 
309 	// entry for opening the Format/Character dialog
310 	++nItemId;
311 	pPopupMenu->InsertItem( nItemId, String(FwlResId( STR_LANGSTATUS_MORE )));
312 	pPopupMenu->SetItemCommand( nItemId, aCmd_Dialog );
313 }
314 
315 
updatePopupMenu()316 void SAL_CALL LanguageSelectionMenuController::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException )
317 {
318 	svt::PopupMenuControllerBase::updatePopupMenu();
319 
320 	// Force status update to get information about the current languages
321 	osl::ClearableMutexGuard aLock( m_aMutex );
322 	Reference< XDispatch > xDispatch( m_xLanguageDispatch );
323 	com::sun::star::util::URL aTargetURL;
324 	aTargetURL.Complete = m_aLangStatusCommandURL;
325 	m_xURLTransformer->parseStrict( aTargetURL );
326 	aLock.clear();
327 
328 	if ( xDispatch.is() )
329 	{
330 		xDispatch->addStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL );
331 		xDispatch->removeStatusListener( SAL_STATIC_CAST( XStatusListener*, this ), aTargetURL );
332 	}
333 
334 	// TODO: Fill menu with the information retrieved by the status update
335 
336 	if( m_aCommandURL.equalsAscii( ".uno:SetLanguageSelectionMenu" ))
337 	{
338 		fillPopupMenu(m_xPopupMenu, MODE_SetLanguageSelectionMenu );
339 	}
340 	else if( m_aCommandURL.equalsAscii( ".uno:SetLanguageParagraphMenu" ))
341 	{
342 		fillPopupMenu(m_xPopupMenu, MODE_SetLanguageParagraphMenu );
343 	}
344 	else if( m_aCommandURL.equalsAscii( ".uno:SetLanguageAllTextMenu" ))
345 	{
346 		fillPopupMenu(m_xPopupMenu, MODE_SetLanguageAllTextMenu );
347 	}
348 }
349 
350 // XInitialization
initialize(const Sequence<Any> & aArguments)351 void SAL_CALL LanguageSelectionMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
352 {
353 	osl::MutexGuard aLock( m_aMutex );
354 
355 	sal_Bool bInitialized( m_bInitialized );
356 	if ( !bInitialized )
357 	{
358 		svt::PopupMenuControllerBase::initialize(aArguments);
359 
360 		if ( m_bInitialized )
361 		{
362 			m_aLangStatusCommandURL				  = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:LanguageStatus" ));
363 			m_aMenuCommandURL_Lang				  = m_aLangStatusCommandURL;
364 			m_aMenuCommandURL_Font			      = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontDialog" ));
365 			m_aMenuCommandURL_CharDlgForParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FontDialogForParagraph" ));
366 		}
367 	}
368 }
369 
370 }
371 
372 /* vim: set noet sw=4 ts=4: */
373