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/langselectionstatusbarcontroller.hxx> 28 #include <classes/fwkresid.hxx> 29 #include <services.h> 30 #include <classes/resource.hrc> 31 #include <vos/mutex.hxx> 32 #include <vcl/svapp.hxx> 33 #include <vcl/window.hxx> 34 #include <vcl/status.hxx> 35 #include <toolkit/helper/convert.hxx> 36 37 #include <com/sun/star/frame/XPopupMenuController.hpp> 38 #include <toolkit/helper/vclunohelper.hxx> 39 #include <com/sun/star/awt/PopupMenuDirection.hpp> 40 #include <svtools/langtab.hxx> 41 #include "sal/types.h" 42 #include <vcl/svapp.hxx> 43 #include <com/sun/star/awt/MenuItemStyle.hpp> 44 #include <com/sun/star/document/XDocumentLanguages.hpp> 45 #include <i18npool/mslangid.hxx> 46 #include <com/sun/star/i18n/ScriptType.hpp> 47 #include <com/sun/star/frame/XModule.hpp> 48 #include <com/sun/star/frame/XModel.hpp> 49 50 #include <classes/fwkresid.hxx> 51 #ifndef __FRAMEWORK_CLASSES_RESOURCE_HRC_ 52 #include <classes/resource.hrc> 53 #endif 54 #include <com/sun/star/frame/XFrame.hpp> 55 #include <com/sun/star/frame/XDispatch.hpp> 56 #include <com/sun/star/frame/XDispatchProvider.hpp> 57 #include <com/sun/star/util/XURLTransformer.hpp> 58 #include <comphelper/processfactory.hxx> 59 60 #include <toolkit/helper/vclunohelper.hxx> 61 #include <tools/gen.hxx> 62 #include <com/sun/star/awt/Command.hpp> 63 #include <svl/languageoptions.hxx> 64 #include <com/sun/star/linguistic2/XLanguageGuessing.hpp> 65 #include <dispatch/uieventloghelper.hxx> 66 67 #include "helper/mischelper.hxx" 68 69 #include <rtl/ustrbuf.hxx> 70 71 #include <map> 72 #include <set> 73 74 using namespace ::cppu; 75 using namespace ::com::sun::star; 76 using namespace ::com::sun::star::uno; 77 using namespace ::com::sun::star::lang; 78 using namespace ::com::sun::star::frame; 79 using namespace ::com::sun::star::i18n; 80 using namespace ::com::sun::star::document; 81 82 using ::rtl::OUString; 83 using ::rtl::OUStringBuffer; 84 85 86 namespace framework 87 { 88 89 DEFINE_XSERVICEINFO_MULTISERVICE ( LangSelectionStatusbarController , 90 OWeakObject , 91 SERVICENAME_STATUSBARCONTROLLER , 92 IMPLEMENTATIONNAME_LANGSELECTIONSTATUSBARCONTROLLER 93 ) 94 95 DEFINE_INIT_SERVICE ( LangSelectionStatusbarController, {} ) 96 97 LangSelectionStatusbarController::LangSelectionStatusbarController( const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) : 98 svt::StatusbarController( xServiceManager, uno::Reference< frame::XFrame >(), OUString(), 0 ), 99 m_bShowMenu( sal_True ), 100 m_nScriptType( LS_SCRIPT_LATIN | LS_SCRIPT_ASIAN | LS_SCRIPT_COMPLEX ), 101 m_aLangGuessHelper( xServiceManager ) 102 { 103 } 104 105 void SAL_CALL LangSelectionStatusbarController::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) 106 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) 107 { 108 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::initialize" ); 109 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 110 111 svt::StatusbarController::initialize( aArguments ); 112 113 if ( m_xStatusbarItem.is() ) 114 { 115 m_xStatusbarItem->setText( String( FwkResId( STR_LANGSTATUS_MULTIPLE_LANGUAGES ) ) ); 116 } 117 } 118 119 void LangSelectionStatusbarController::LangMenu( 120 const ::com::sun::star::awt::Point& aPos ) 121 throw (::com::sun::star::uno::RuntimeException) 122 { 123 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::LangMenu" ); 124 if (!m_bShowMenu) 125 return; 126 127 //add context menu 128 const static OUString s_sPopupMenu(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.PopupMenu")); 129 Reference< awt::XPopupMenu > xPopupMenu( m_xServiceManager->createInstance( s_sPopupMenu ), UNO_QUERY ); 130 //sub menu that contains all items except the last two items: Separator + Set Language for Paragraph 131 Reference< awt::XPopupMenu > subPopupMenu(m_xServiceManager->createInstance( s_sPopupMenu ), UNO_QUERY ); 132 133 SvtLanguageTable aLanguageTable; 134 135 // get languages to be displayed in the menu 136 std::set< OUString > aLangItems; 137 FillLangItems( aLangItems, aLanguageTable, m_xFrame, m_aLangGuessHelper, 138 m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedTextLang ); 139 140 // 141 // add first few entries to main menu 142 // 143 sal_Int16 nItemId = static_cast< sal_Int16 >(MID_LANG_SEL_1); 144 const OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*")); // multiple languages in current selection 145 const OUString sEmpty; // 'no language found' from language guessing 146 std::map< sal_Int16, OUString > aLangMap; 147 std::set< OUString >::const_iterator it; 148 for (it = aLangItems.begin(); it != aLangItems.end(); ++it) 149 { 150 const OUString & rStr( *it ); 151 if ( rStr != OUString( aLanguageTable.GetString( LANGUAGE_NONE ) ) && 152 rStr != sAsterix && 153 rStr != sEmpty) 154 { 155 DBG_ASSERT( MID_LANG_SEL_1 <= nItemId && nItemId <= MID_LANG_SEL_9, 156 "nItemId outside of expected range!" ); 157 xPopupMenu->insertItem( nItemId, rStr, 0, nItemId ); 158 if ( rStr == m_aCurLang ) 159 { 160 //make a sign for the current language 161 xPopupMenu->checkItem( nItemId, sal_True ); 162 } 163 aLangMap[ nItemId ] = rStr; 164 ++nItemId; 165 } 166 } 167 xPopupMenu->insertItem( MID_LANG_SEL_NONE, String( FwkResId( STR_LANGSTATUS_NONE )), 0, MID_LANG_SEL_NONE ); 168 xPopupMenu->insertItem( MID_LANG_SEL_RESET, String( FwkResId( STR_RESET_TO_DEFAULT_LANGUAGE )), 0, MID_LANG_SEL_RESET ); 169 xPopupMenu->insertItem( MID_LANG_SEL_MORE, String( FwkResId( STR_LANGSTATUS_MORE )), 0, MID_LANG_SEL_MORE ); 170 171 // 172 // add entries to submenu ('set language for paragraph') 173 // 174 nItemId = static_cast< sal_Int16 >(MID_LANG_PARA_1); 175 for (it = aLangItems.begin(); it != aLangItems.end(); ++it) 176 { 177 const OUString & rStr( *it ); 178 if( rStr != OUString( aLanguageTable.GetString( LANGUAGE_NONE ) )&& 179 rStr != sAsterix && 180 rStr != sEmpty) 181 { 182 DBG_ASSERT( MID_LANG_PARA_1 <= nItemId && nItemId <= MID_LANG_PARA_9, 183 "nItemId outside of expected range!" ); 184 subPopupMenu->insertItem( nItemId, rStr, 0, nItemId ); 185 aLangMap[nItemId] = rStr; 186 ++nItemId; 187 } 188 } 189 subPopupMenu->insertItem( MID_LANG_PARA_NONE, String( FwkResId( STR_LANGSTATUS_NONE )), 0, MID_LANG_PARA_NONE ); 190 subPopupMenu->insertItem( MID_LANG_PARA_RESET, String( FwkResId( STR_RESET_TO_DEFAULT_LANGUAGE )), 0, MID_LANG_PARA_RESET ); 191 subPopupMenu->insertItem( MID_LANG_PARA_MORE, String( FwkResId( STR_LANGSTATUS_MORE )), 0, MID_LANG_PARA_MORE ); 192 193 // 194 // add last two entries to main menu 195 // 196 xPopupMenu->insertSeparator( MID_LANG_PARA_SEPERATOR ); 197 xPopupMenu->insertItem( MID_LANG_PARA_STRING, String( FwkResId( STR_SET_LANGUAGE_FOR_PARAGRAPH )), 0, MID_LANG_PARA_STRING ); 198 xPopupMenu->setPopupMenu( MID_LANG_PARA_STRING, subPopupMenu ); 199 200 201 // 202 // now display the popup menu and execute every command ... 203 // 204 205 Reference< awt::XWindowPeer > xParent( m_xParentWindow, UNO_QUERY ); 206 com::sun::star::awt::Rectangle aRectangle; 207 aRectangle.X = aPos.X; 208 aRectangle.Y = aPos.Y; 209 sal_Int16 nId = xPopupMenu->execute( xParent, aRectangle, com::sun::star::awt::PopupMenuDirection::EXECUTE_UP+16 ); 210 //click "More..." 211 if ( nId && m_xFrame.is() ) 212 { 213 OUStringBuffer aBuff; 214 //set selected language as current language for selection 215 const OUString aSelectedLang = aLangMap[nId]; 216 217 if (MID_LANG_SEL_1 <= nId && nId <= MID_LANG_SEL_9) 218 { 219 aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( (".uno:LanguageStatus?Language:string=Current_") )); 220 aBuff.append( aSelectedLang ); 221 } 222 else if (nId == MID_LANG_SEL_NONE) 223 { 224 //set None as current language for selection 225 aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( (".uno:LanguageStatus?Language:string=Current_LANGUAGE_NONE") )); 226 } 227 else if (nId == MID_LANG_SEL_RESET) 228 { 229 // reset language attributes for selection 230 aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( (".uno:LanguageStatus?Language:string=Current_RESET_LANGUAGES") )); 231 } 232 else if (nId == MID_LANG_SEL_MORE) 233 { 234 //open the dialog "format/character" for current selection 235 aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( (".uno:FontDialog?Language:string=*") )); 236 } 237 else if (MID_LANG_PARA_1 <= nId && nId <= MID_LANG_PARA_9) 238 { 239 aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( (".uno:LanguageStatus?Language:string=Paragraph_") )); 240 aBuff.append( aSelectedLang ); 241 } 242 else if (nId == MID_LANG_PARA_NONE) 243 { 244 //set None as language for current paragraph 245 aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( (".uno:LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE") )); 246 } 247 else if (nId == MID_LANG_PARA_RESET) 248 { 249 // reset language attributes for paragraph 250 aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( (".uno:LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES") )); 251 } 252 else if (nId == MID_LANG_PARA_MORE) 253 { 254 //open the dialog "format/character" for current paragraph 255 aBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( (".uno:FontDialogForParagraph") )); 256 } 257 258 const Sequence< beans::PropertyValue > aDummyArgs; 259 execute( aBuff.makeStringAndClear(), aDummyArgs ); 260 } 261 } 262 263 void SAL_CALL LangSelectionStatusbarController::command( 264 const ::com::sun::star::awt::Point& aPos, 265 ::sal_Int32 nCommand, 266 ::sal_Bool /*bMouseEvent*/, 267 const ::com::sun::star::uno::Any& /*aData*/ ) 268 throw (::com::sun::star::uno::RuntimeException) 269 { 270 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::command" ); 271 if ( nCommand & ::awt::Command::CONTEXTMENU ) 272 { 273 LangMenu( aPos ); 274 } 275 } 276 277 void SAL_CALL LangSelectionStatusbarController::click( 278 const ::com::sun::star::awt::Point& aPos ) 279 throw (::com::sun::star::uno::RuntimeException) 280 { 281 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::click" ); 282 LangMenu( aPos ); 283 } 284 285 // XStatusListener 286 void SAL_CALL LangSelectionStatusbarController::statusChanged( const FeatureStateEvent& Event ) 287 throw ( RuntimeException ) 288 { 289 // This function will be called when observed data changes, 290 // for example the selection or keyboard language. 291 // - It displays the language in use in the status bar 292 // - and it stores the relevant data for creating the menu 293 // at some later point in the member variables 294 // m_nScriptType, m_aCurLang, m_aKeyboardLang, m_aGuessedText 295 296 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "LangSelectionStatusbarController::statusChanged" ); 297 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 298 299 if ( m_bDisposed ) 300 return; 301 302 m_bShowMenu = sal_True; 303 m_nScriptType = LS_SCRIPT_LATIN | LS_SCRIPT_ASIAN | LS_SCRIPT_COMPLEX; //set the default value 304 305 if ( m_xStatusbarItem.is() ) 306 { 307 OUString aStrValue; 308 Sequence< OUString > aSeq; 309 310 if ( Event.State >>= aStrValue ) 311 m_xStatusbarItem->setText( aStrValue ); 312 else if ( Event.State >>= aSeq ) 313 { 314 if ( aSeq.getLength() == 4 ) 315 { 316 OUString aStatusText = aSeq[0]; 317 if ( 0 == aStatusText.compareToAscii( RTL_CONSTASCII_STRINGPARAM("*") )) 318 { 319 aStatusText = String( FwkResId( STR_LANGSTATUS_MULTIPLE_LANGUAGES ) ); 320 } 321 m_xStatusbarItem->setText( aStatusText ); 322 323 // Retrieve all other values from the sequence and 324 // store it members! 325 m_aCurLang = aSeq[0]; 326 m_nScriptType = static_cast< sal_Int16 >( aSeq[1].toInt32() ); 327 m_aKeyboardLang = aSeq[2]; 328 m_aGuessedTextLang = aSeq[3]; 329 } 330 } 331 else if ( !Event.State.hasValue() ) 332 { 333 m_xStatusbarItem->setText( OUString() ); 334 m_bShowMenu = sal_False; // no language -> no menu 335 } 336 } 337 } 338 339 } 340 341