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