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 31 #include <stdio.h> 32 #include <wchar.h> 33 34 #ifndef __FRAMEWORK_UIELEMENT_SPINFIELDTOOLBARCONTROLLER_HXX 35 #include "uielement/spinfieldtoolbarcontroller.hxx" 36 #endif 37 38 //_________________________________________________________________________________________________________________ 39 // my own includes 40 //_________________________________________________________________________________________________________________ 41 42 #ifndef __FRAMEWORK_TOOLBAR_HXX_ 43 #include "uielement/toolbar.hxx" 44 #endif 45 46 //_________________________________________________________________________________________________________________ 47 // interface includes 48 //_________________________________________________________________________________________________________________ 49 #include <com/sun/star/util/XURLTransformer.hpp> 50 #include <com/sun/star/frame/XDispatchProvider.hpp> 51 #include <com/sun/star/beans/PropertyValue.hpp> 52 #include <com/sun/star/frame/status/ItemStatus.hpp> 53 #include <com/sun/star/frame/status/ItemState.hpp> 54 #include <com/sun/star/frame/status/Visibility.hpp> 55 #include <com/sun/star/frame/XControlNotificationListener.hpp> 56 57 //_________________________________________________________________________________________________________________ 58 // other includes 59 //_________________________________________________________________________________________________________________ 60 #include <svtools/toolboxcontroller.hxx> 61 #include <vos/mutex.hxx> 62 #include <vcl/svapp.hxx> 63 #ifndef _VCL_MNEMONIC_HXX_ 64 #include <vcl/mnemonic.hxx> 65 #endif 66 #include <tools/urlobj.hxx> 67 #ifdef WINNT 68 #include <systools/win32/snprintf.h> 69 #endif 70 71 using namespace ::com::sun::star; 72 using namespace ::com::sun::star::uno; 73 using namespace ::com::sun::star::beans; 74 using namespace ::com::sun::star::lang; 75 using namespace ::com::sun::star::frame; 76 using namespace ::com::sun::star::frame::status; 77 using namespace ::com::sun::star::util; 78 79 namespace framework 80 { 81 82 // ------------------------------------------------------------------ 83 84 // Wrapper class to notify controller about events from combobox. 85 // Unfortunaltly the events are notifed through virtual methods instead 86 // of Listeners. 87 88 class SpinfieldControl : public SpinField 89 { 90 public: 91 SpinfieldControl( Window* pParent, WinBits nStyle, ISpinfieldListener* pSpinFieldListener ); 92 virtual ~SpinfieldControl(); 93 94 virtual void Up(); 95 virtual void Down(); 96 virtual void First(); 97 virtual void Last(); 98 virtual void KeyInput( const ::KeyEvent& rKEvt ); 99 virtual void Modify(); 100 virtual void GetFocus(); 101 virtual void LoseFocus(); 102 virtual void StateChanged( StateChangedType nType ); 103 virtual void DataChanged( const DataChangedEvent& rDCEvt ); 104 virtual long PreNotify( NotifyEvent& rNEvt ); 105 106 private: 107 ISpinfieldListener* m_pSpinFieldListener; 108 }; 109 110 SpinfieldControl::SpinfieldControl( Window* pParent, WinBits nStyle, ISpinfieldListener* pSpinFieldListener ) : 111 SpinField( pParent, nStyle ) 112 , m_pSpinFieldListener( pSpinFieldListener ) 113 { 114 } 115 116 SpinfieldControl::~SpinfieldControl() 117 { 118 m_pSpinFieldListener = 0; 119 } 120 121 void SpinfieldControl::Up() 122 { 123 SpinField::Up(); 124 if ( m_pSpinFieldListener ) 125 m_pSpinFieldListener->Up(); 126 } 127 128 void SpinfieldControl::Down() 129 { 130 SpinField::Down(); 131 if ( m_pSpinFieldListener ) 132 m_pSpinFieldListener->Down(); 133 } 134 135 void SpinfieldControl::First() 136 { 137 SpinField::First(); 138 if ( m_pSpinFieldListener ) 139 m_pSpinFieldListener->First(); 140 } 141 142 void SpinfieldControl::Last() 143 { 144 SpinField::First(); 145 if ( m_pSpinFieldListener ) 146 m_pSpinFieldListener->Last(); 147 } 148 149 void SpinfieldControl::KeyInput( const ::KeyEvent& rKEvt ) 150 { 151 SpinField::KeyInput( rKEvt ); 152 if ( m_pSpinFieldListener ) 153 m_pSpinFieldListener->KeyInput( rKEvt ); 154 } 155 156 void SpinfieldControl::Modify() 157 { 158 SpinField::Modify(); 159 if ( m_pSpinFieldListener ) 160 m_pSpinFieldListener->Modify(); 161 } 162 163 void SpinfieldControl::GetFocus() 164 { 165 SpinField::GetFocus(); 166 if ( m_pSpinFieldListener ) 167 m_pSpinFieldListener->GetFocus(); 168 } 169 170 void SpinfieldControl::LoseFocus() 171 { 172 SpinField::GetFocus(); 173 if ( m_pSpinFieldListener ) 174 m_pSpinFieldListener->GetFocus(); 175 } 176 177 void SpinfieldControl::StateChanged( StateChangedType nType ) 178 { 179 SpinField::StateChanged( nType ); 180 if ( m_pSpinFieldListener ) 181 m_pSpinFieldListener->StateChanged( nType ); 182 } 183 184 void SpinfieldControl::DataChanged( const DataChangedEvent& rDCEvt ) 185 { 186 SpinField::DataChanged( rDCEvt ); 187 if ( m_pSpinFieldListener ) 188 m_pSpinFieldListener->DataChanged( rDCEvt ); 189 } 190 191 long SpinfieldControl::PreNotify( NotifyEvent& rNEvt ) 192 { 193 long nRet( 0 ); 194 if ( m_pSpinFieldListener ) 195 nRet = m_pSpinFieldListener->PreNotify( rNEvt ); 196 if ( nRet == 0 ) 197 nRet = SpinField::PreNotify( rNEvt ); 198 199 return nRet; 200 } 201 202 // ------------------------------------------------------------------ 203 204 SpinfieldToolbarController::SpinfieldToolbarController( 205 const Reference< XMultiServiceFactory >& rServiceManager, 206 const Reference< XFrame >& rFrame, 207 ToolBox* pToolbar, 208 sal_uInt16 nID, 209 sal_Int32 nWidth, 210 const ::rtl::OUString& aCommand ) : 211 ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand ) 212 , m_bFloat( false ) 213 , m_bMaxSet( false ) 214 , m_bMinSet( false ) 215 , m_nMax( 0.0 ) 216 , m_nMin( 0.0 ) 217 , m_nValue( 0.0 ) 218 , m_nStep( 0.0 ) 219 , m_pSpinfieldControl( 0 ) 220 { 221 m_pSpinfieldControl = new SpinfieldControl( m_pToolbar, WB_SPIN|WB_BORDER, this ); 222 if ( nWidth == 0 ) 223 nWidth = 100; 224 225 // Calculate height of the spin field according to the application font height 226 sal_Int32 nHeight = getFontSizePixel( m_pSpinfieldControl ) + 5 + 1; 227 228 m_pSpinfieldControl->SetSizePixel( ::Size( nWidth, nHeight )); 229 m_pToolbar->SetItemWindow( m_nID, m_pSpinfieldControl ); 230 } 231 232 // ------------------------------------------------------------------ 233 234 SpinfieldToolbarController::~SpinfieldToolbarController() 235 { 236 } 237 238 // ------------------------------------------------------------------ 239 240 void SAL_CALL SpinfieldToolbarController::dispose() 241 throw ( RuntimeException ) 242 { 243 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); 244 245 m_pToolbar->SetItemWindow( m_nID, 0 ); 246 delete m_pSpinfieldControl; 247 248 ComplexToolbarController::dispose(); 249 250 m_pSpinfieldControl = 0; 251 } 252 253 // ------------------------------------------------------------------ 254 Sequence<PropertyValue> SpinfieldToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const 255 { 256 Sequence<PropertyValue> aArgs( 2 ); 257 ::rtl::OUString aSpinfieldText = m_pSpinfieldControl->GetText(); 258 259 // Add key modifier to argument list 260 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" )); 261 aArgs[0].Value <<= KeyModifier; 262 aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Value" )); 263 if ( m_bFloat ) 264 aArgs[1].Value <<= aSpinfieldText.toDouble(); 265 else 266 aArgs[1].Value <<= aSpinfieldText.toInt32(); 267 return aArgs; 268 } 269 270 // ------------------------------------------------------------------ 271 272 void SpinfieldToolbarController::Up() 273 { 274 double nValue = m_nValue + m_nStep; 275 if ( m_bMaxSet && nValue > m_nMax ) 276 return; 277 278 m_nValue = nValue; 279 280 rtl::OUString aText = impl_formatOutputString( m_nValue ); 281 m_pSpinfieldControl->SetText( aText ); 282 execute( 0 ); 283 } 284 285 void SpinfieldToolbarController::Down() 286 { 287 double nValue = m_nValue - m_nStep; 288 if ( m_bMinSet && nValue < m_nMin ) 289 return; 290 291 m_nValue = nValue; 292 293 rtl::OUString aText = impl_formatOutputString( m_nValue ); 294 m_pSpinfieldControl->SetText( aText ); 295 execute( 0 ); 296 } 297 298 void SpinfieldToolbarController::First() 299 { 300 if ( m_bMinSet ) 301 { 302 m_nValue = m_nMin; 303 304 rtl::OUString aText = impl_formatOutputString( m_nValue ); 305 m_pSpinfieldControl->SetText( aText ); 306 execute( 0 ); 307 } 308 } 309 310 void SpinfieldToolbarController::Last() 311 { 312 if ( m_bMaxSet ) 313 { 314 m_nValue = m_nMax; 315 316 rtl::OUString aText = impl_formatOutputString( m_nValue ); 317 m_pSpinfieldControl->SetText( aText ); 318 execute( 0 ); 319 } 320 } 321 322 void SpinfieldToolbarController::Modify() 323 { 324 notifyTextChanged( m_pSpinfieldControl->GetText() ); 325 } 326 327 void SpinfieldToolbarController::KeyInput( const ::KeyEvent& /*rKEvt*/ ) 328 { 329 } 330 331 void SpinfieldToolbarController::GetFocus() 332 { 333 notifyFocusGet(); 334 } 335 336 void SpinfieldToolbarController::LoseFocus() 337 { 338 notifyFocusLost(); 339 } 340 341 void SpinfieldToolbarController::StateChanged( StateChangedType /*nType*/ ) 342 { 343 } 344 345 void SpinfieldToolbarController::DataChanged( const DataChangedEvent& /*rDCEvt*/ ) 346 { 347 } 348 349 long SpinfieldToolbarController::PreNotify( NotifyEvent& rNEvt ) 350 { 351 if( rNEvt.GetType() == EVENT_KEYINPUT ) 352 { 353 const ::KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); 354 const KeyCode& rKeyCode = pKeyEvent->GetKeyCode(); 355 if(( rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN ) 356 { 357 // Call execute only with non-empty text 358 if ( m_pSpinfieldControl->GetText().Len() > 0 ) 359 execute( rKeyCode.GetModifier() ); 360 return 1; 361 } 362 } 363 364 return 0; 365 } 366 367 // -------------------------------------------------------- 368 369 void SpinfieldToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand ) 370 { 371 rtl::OUString aValue; 372 rtl::OUString aMax; 373 rtl::OUString aMin; 374 rtl::OUString aStep; 375 bool bFloatValue( false ); 376 377 if ( rControlCommand.Command.equalsAsciiL( "SetStep", 7 )) 378 { 379 for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) 380 { 381 sal_Int32 nValue; 382 double fValue; 383 bool bFloat( false ); 384 385 if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Step", 4 )) 386 { 387 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) 388 aStep = bFloat ? ::rtl::OUString::valueOf( fValue ) : 389 ::rtl::OUString::valueOf( nValue ); 390 break; 391 } 392 } 393 } 394 else if ( rControlCommand.Command.equalsAsciiL( "SetValue", 8 )) 395 { 396 for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) 397 { 398 if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Value", 5 )) 399 { 400 sal_Int32 nValue; 401 double fValue; 402 bool bFloat( false ); 403 404 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) 405 { 406 aValue = bFloat ? ::rtl::OUString::valueOf( fValue ) : ::rtl::OUString::valueOf( nValue ); 407 bFloatValue = bFloat; 408 } 409 break; 410 } 411 } 412 } 413 else if ( rControlCommand.Command.equalsAsciiL( "SetValues", 9 )) 414 { 415 for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) 416 { 417 sal_Int32 nValue; 418 double fValue; 419 bool bFloat( false ); 420 421 rtl::OUString aName = rControlCommand.Arguments[i].Name; 422 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) 423 { 424 if ( aName.equalsAsciiL( "Value", 5 )) 425 { 426 aValue = bFloat ? ::rtl::OUString::valueOf( fValue ) : ::rtl::OUString::valueOf( nValue ); 427 bFloatValue = bFloat; 428 } 429 else if ( aName.equalsAsciiL( "Step", 4 )) 430 aStep = bFloat ? ::rtl::OUString::valueOf( fValue ) : 431 ::rtl::OUString::valueOf( nValue ); 432 else if ( aName.equalsAsciiL( "LowerLimit", 10 )) 433 aMin = bFloat ? ::rtl::OUString::valueOf( fValue ) : 434 ::rtl::OUString::valueOf( nValue ); 435 else if ( aName.equalsAsciiL( "UpperLimit", 10 )) 436 aMax = bFloat ? ::rtl::OUString::valueOf( fValue ) : 437 ::rtl::OUString::valueOf( nValue ); 438 } 439 else if ( aName.equalsAsciiL( "OutputFormat", 12 )) 440 rControlCommand.Arguments[i].Value >>= m_aOutFormat; 441 } 442 } 443 else if ( rControlCommand.Command.equalsAsciiL( "SetLowerLimit", 13 )) 444 { 445 for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) 446 { 447 sal_Int32 nValue; 448 double fValue; 449 bool bFloat( false ); 450 451 if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "LowerLimit", 10 )) 452 { 453 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) 454 aMin = bFloat ? ::rtl::OUString::valueOf( fValue ) : 455 ::rtl::OUString::valueOf( nValue ); 456 break; 457 } 458 } 459 } 460 else if ( rControlCommand.Command.equalsAsciiL( "SetUpperLimit", 13 )) 461 { 462 for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) 463 { 464 sal_Int32 nValue; 465 double fValue; 466 bool bFloat( false ); 467 468 if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "UpperLimit", 10 )) 469 { 470 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat )) 471 aMax = bFloat ? ::rtl::OUString::valueOf( fValue ) : 472 ::rtl::OUString::valueOf( nValue ); 473 break; 474 } 475 } 476 } 477 else if ( rControlCommand.Command.equalsAsciiL( "SetOutputFormat", 15 )) 478 { 479 for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ ) 480 { 481 if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "OutputFormat", 10 )) 482 { 483 rControlCommand.Arguments[i].Value >>= m_aOutFormat; 484 break; 485 } 486 } 487 } 488 489 // Check values and set members 490 if ( aValue.getLength() > 0 ) 491 { 492 m_bFloat = bFloatValue; 493 m_nValue = aValue.toDouble(); 494 495 rtl::OUString aOutString = impl_formatOutputString( m_nValue ); 496 m_pSpinfieldControl->SetText( aOutString ); 497 notifyTextChanged( aOutString ); 498 } 499 if ( aMax.getLength() > 0 ) 500 { 501 m_nMax = aMax.toDouble(); 502 m_bMaxSet = true; 503 } 504 if ( aMin.getLength() > 0 ) 505 { 506 m_nMin = aMin.toDouble(); 507 m_bMinSet = true; 508 } 509 if ( aStep.getLength() > 0 ) 510 m_nStep = aStep.toDouble(); 511 } 512 513 bool SpinfieldToolbarController::impl_getValue( 514 const Any& rAny, sal_Int32& nValue, double& fValue, bool& bFloat ) 515 { 516 using ::com::sun::star::uno::TypeClass; 517 518 bool bValueValid( false ); 519 520 bFloat = false; 521 TypeClass aTypeClass = rAny.getValueTypeClass(); 522 if (( aTypeClass == TypeClass( typelib_TypeClass_LONG )) || 523 ( aTypeClass == TypeClass( typelib_TypeClass_SHORT )) || 524 ( aTypeClass == TypeClass( typelib_TypeClass_BYTE ))) 525 bValueValid = rAny >>= nValue; 526 else if (( aTypeClass == TypeClass( typelib_TypeClass_FLOAT )) || 527 ( aTypeClass == TypeClass( typelib_TypeClass_DOUBLE ))) 528 { 529 bValueValid = rAny >>= fValue; 530 bFloat = true; 531 } 532 533 return bValueValid; 534 } 535 536 rtl::OUString SpinfieldToolbarController::impl_formatOutputString( double fValue ) 537 { 538 if ( m_aOutFormat.getLength() == 0 ) 539 { 540 if ( m_bFloat ) 541 return rtl::OUString::valueOf( fValue ); 542 else 543 return rtl::OUString::valueOf( sal_Int32( fValue )); 544 } 545 else 546 { 547 #ifdef WNT 548 sal_Unicode aBuffer[128]; 549 550 aBuffer[0] = 0; 551 if ( m_bFloat ) 552 snwprintf( reinterpret_cast<wchar_t *>(aBuffer), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat.getStr()), fValue ); 553 else 554 snwprintf( reinterpret_cast<wchar_t *>(aBuffer), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat.getStr()), sal_Int32( fValue )); 555 556 sal_Int32 nSize = rtl_ustr_getLength( aBuffer ); 557 return rtl::OUString( aBuffer, nSize ); 558 #else 559 // Currently we have no support for a format string using sal_Unicode. wchar_t 560 // is 32 bit on Unix platform! 561 char aBuffer[128]; 562 563 ::rtl::OString aFormat = OUStringToOString( m_aOutFormat, osl_getThreadTextEncoding() ); 564 if ( m_bFloat ) 565 snprintf( aBuffer, 128, aFormat.getStr(), fValue ); 566 else 567 snprintf( aBuffer, 128, aFormat.getStr(), static_cast<long>( fValue )); 568 569 sal_Int32 nSize = strlen( aBuffer ); 570 rtl::OString aTmp( aBuffer, nSize ); 571 return rtl::OStringToOUString( aTmp, osl_getThreadTextEncoding() ); 572 #endif 573 } 574 } 575 576 } // namespace 577 578