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 #include "wrapper.hxx" 25 26 #include <com/sun/star/awt/PosSize.hpp> 27 #include <com/sun/star/awt/XActionListener.hpp> 28 #include <com/sun/star/awt/XButton.hpp> 29 #include <com/sun/star/awt/XCheckBox.hpp> 30 #include <com/sun/star/awt/XRadioButton.hpp> 31 #include <com/sun/star/graphic/XGraphic.hpp> 32 #include <cppuhelper/implbase1.hxx> 33 #include <toolkit/awt/vclxwindow.hxx> 34 #include <toolkit/awt/vclxwindows.hxx> 35 #include <toolkit/helper/convert.hxx> 36 #include <vcl/button.hxx> 37 #include <vcl/event.hxx> 38 #include <vcl/msgbox.hxx> 39 #include <vcl/svapp.hxx> 40 #include <vcl/window.hxx> 41 42 #include <list> 43 44 #include <layout/core/helper.hxx> 45 46 using namespace ::com::sun::star; 47 48 using rtl::OUString; 49 50 namespace layout 51 { 52 53 class ImageImpl 54 { 55 public: 56 uno::Reference< graphic::XGraphic > mxGraphic; 57 ImageImpl( const char *pName ) 58 : mxGraphic( layoutimpl::loadGraphic( pName ) ) 59 { 60 if ( !mxGraphic.is() ) 61 { 62 DBG_ERROR1( "ERROR: failed to load image: `%s'\n", pName ); 63 } 64 } 65 }; 66 67 Image::Image( const char *pName ) 68 : pImpl( new ImageImpl( pName ) ) 69 { 70 } 71 72 Image::~Image() 73 { 74 delete pImpl; 75 } 76 77 class ButtonImpl : public ControlImpl 78 , public ::cppu::WeakImplHelper1< awt::XActionListener > 79 { 80 Link maClickHdl; 81 82 public: 83 uno::Reference< awt::XButton > mxButton; 84 ButtonImpl( Context *context, const PeerHandle &peer, Window *window ) 85 : ControlImpl( context, peer, window ) 86 , mxButton( peer, uno::UNO_QUERY ) 87 { 88 /* We have default action when clicked, always listen. */ 89 mxButton->addActionListener( this ); 90 } 91 92 ~ButtonImpl() 93 { 94 } 95 96 virtual void Click() { /* make me pure virtual? */ }; 97 98 Link& GetClickHdl () 99 { 100 return maClickHdl; 101 } 102 103 virtual void SetClickHdl( Link const& link ) 104 { 105 maClickHdl = link; 106 } 107 108 void SAL_CALL disposing( lang::EventObject const& e ) 109 throw (uno::RuntimeException) 110 { 111 mxButton->removeActionListener( this ); 112 ControlImpl::disposing (e); 113 mxButton.clear (); 114 } 115 116 virtual void SAL_CALL actionPerformed( const awt::ActionEvent& ) 117 throw (uno::RuntimeException) 118 { 119 if ( !maClickHdl ) 120 Click(); 121 else 122 maClickHdl.Call( static_cast<Window *>( mpWindow ) ); 123 } 124 125 bool SetModeImage( uno::Reference< graphic::XGraphic > xGraph ) 126 { 127 setProperty( "Graphic", uno::Any( xGraph ) ); 128 return true; 129 } 130 }; 131 132 Button::~Button () 133 { 134 } 135 136 String Button::GetStandardText (sal_uInt16 button_type) 137 { 138 return ::Button::GetStandardText (button_type); 139 } 140 141 void Button::SetText( OUString const& rStr ) 142 { 143 if ( !getImpl().mxButton.is() ) 144 return; 145 getImpl().mxButton->setLabel( rStr ); 146 } 147 148 void Button::SetClickHdl( const Link& link ) 149 { 150 if (&getImpl () && getImpl().mxButton.is ()) 151 getImpl().SetClickHdl( link ); 152 } 153 154 Link& Button::GetClickHdl () 155 { 156 return getImpl().GetClickHdl (); 157 } 158 159 bool Button::SetModeImage (Image const& image) 160 { 161 return getImpl().SetModeImage (image.getImpl().mxGraphic); 162 } 163 164 bool Button::SetModeImage (::Image const& image, BmpColorMode mode) 165 { 166 return GetButton ()->SetModeImage (image, mode); 167 } 168 169 void Button::SetImageAlign( ImageAlign eAlign ) 170 { 171 getImpl().setProperty( "ImageAlign", uno::Any( (sal_Int16) eAlign ) ); 172 } 173 174 void Button::Click() 175 { 176 } 177 178 IMPL_GET_IMPL( Button ); 179 IMPL_CONSTRUCTORS( Button, Control, "button" ); 180 IMPL_GET_WINDOW (Button); 181 182 class PushButtonImpl : public ButtonImpl 183 , public ::cppu::WeakImplHelper1< awt::XItemListener > 184 { 185 Link maToggleHdl; 186 public: 187 PushButtonImpl( Context *context, const PeerHandle &peer, Window *window ) 188 : ButtonImpl( context, peer, window ) 189 { 190 } 191 192 void SetToggleHdl( const Link& link ) 193 { 194 // XButton doesn't have an explicit event for Toggle. Anyway, it is a 195 // superset of the clicks: all clicks, and explicit toggles 196 if (!link && !!maToggleHdl) 197 mxButton->removeActionListener( this ); 198 else if (!!link && !maToggleHdl) 199 mxButton->addActionListener( this ); 200 maToggleHdl = link; 201 } 202 void SAL_CALL disposing( lang::EventObject const& e ) 203 throw (uno::RuntimeException) 204 { 205 ButtonImpl::disposing (e); 206 } 207 virtual void SAL_CALL actionPerformed( awt::ActionEvent const& e ) 208 throw (uno::RuntimeException) 209 { 210 ButtonImpl::actionPerformed( e ); 211 fireToggle(); 212 } 213 virtual void SAL_CALL itemStateChanged( const awt::ItemEvent& ) 214 throw (uno::RuntimeException) 215 { 216 maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); 217 } 218 void fireToggle() 219 { 220 maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); 221 } 222 223 }; 224 225 PushButton::~PushButton () 226 { 227 SetToggleHdl (Link ()); 228 } 229 230 void PushButton::Check( bool bCheck ) 231 { 232 getImpl().setProperty( "State", uno::Any( (sal_Int16) !!bCheck ) ); 233 // XButton doesn't have explicit toggle event 234 getImpl().fireToggle(); 235 } 236 237 bool PushButton::IsChecked() const 238 { 239 return !!( getImpl().getProperty( "State" ).get< sal_Int16 >() ); 240 } 241 242 void PushButton::Toggle() 243 { 244 Check( true ); 245 } 246 247 void PushButton::SetToggleHdl( const Link& link ) 248 { 249 if (&getImpl () && getImpl().mxButton.is ()) 250 getImpl().SetToggleHdl( link ); 251 } 252 253 IMPL_GET_IMPL( PushButton ); 254 IMPL_CONSTRUCTORS( PushButton, Button, "pushbutton" ); 255 IMPL_GET_WINDOW (PushButton); 256 257 class RadioButtonImpl : public ButtonImpl 258 , public ::cppu::WeakImplHelper1< awt::XItemListener > 259 { 260 Link maToggleHdl; 261 public: 262 uno::Reference< awt::XRadioButton > mxRadioButton; 263 RadioButtonImpl( Context *context, const PeerHandle &peer, Window *window ) 264 : ButtonImpl( context, peer, window ) 265 , mxRadioButton( peer, uno::UNO_QUERY ) 266 { 267 } 268 269 void Check( bool bCheck ) 270 { 271 if ( !mxRadioButton.is() ) 272 return; 273 274 #if 1 275 // Have setState fire item event for 276 // RadioGroups::RadioGroup::itemStateChanged () 277 ::RadioButton *r = static_cast<RadioButton*>(mpWindow)->GetRadioButton (); 278 bool state = r->IsRadioCheckEnabled (); 279 r->EnableRadioCheck(); 280 mxRadioButton->setState( !!bCheck ); 281 r->EnableRadioCheck (state); 282 #else 283 mxRadioButton->setState( !!bCheck ); 284 #endif 285 fireToggle(); 286 } 287 288 bool IsChecked() 289 { 290 if ( !mxRadioButton.is() ) 291 return false; 292 return mxRadioButton->getState(); 293 } 294 295 void SetToggleHdl( const Link& link ) 296 { 297 if (!link && !!maToggleHdl) 298 mxRadioButton->removeItemListener( this ); 299 else if (!!link && !maToggleHdl) 300 mxRadioButton->addItemListener( this ); 301 maToggleHdl = link; 302 } 303 304 inline void fireToggle() 305 { 306 maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); 307 } 308 309 virtual void SetClickHdl( const Link& link ) 310 { 311 // Keep RadioGroups::RadioGroup's actionListener at HEAD 312 // of list. This way, it can handle RadioGroup's button 313 // states before all other callbacks and make sure the 314 // client code has the right state. 315 316 // IWBN to add an XRadioButton2 and layout::VCLXRadioButton 317 // with {get,set}RadioGroup() (and a "radiogroup" property 318 // even) and handle the grouping here in RadioButtonImpl. 319 uno::Reference< uno::XInterface > x = static_cast<VCLXRadioButton*> (mpWindow->GetVCLXWindow ())->getFirstActionListener (); 320 uno::Reference< awt::XActionListener > a = uno::Reference< awt::XActionListener> (x ,uno::UNO_QUERY ); 321 mxButton->removeActionListener (a); 322 ButtonImpl::SetClickHdl (link); 323 mxButton->addActionListener (a); 324 } 325 326 void SAL_CALL disposing( lang::EventObject const& e ) 327 throw (uno::RuntimeException) 328 { 329 ButtonImpl::disposing (e); 330 } 331 332 virtual void SAL_CALL itemStateChanged( const awt::ItemEvent& ) 333 throw (uno::RuntimeException) 334 { 335 maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); 336 } 337 }; 338 339 RadioButton::~RadioButton () 340 { 341 SetToggleHdl (Link ()); 342 } 343 344 void RadioButton::Check( bool bCheck ) 345 { 346 getImpl().Check( bCheck ); 347 } 348 349 bool RadioButton::IsChecked() const 350 { 351 return getImpl().IsChecked(); 352 } 353 354 void RadioButton::SetToggleHdl( const Link& link ) 355 { 356 if (&getImpl () && getImpl().mxRadioButton.is ()) 357 getImpl().SetToggleHdl( link ); 358 } 359 360 IMPL_GET_IMPL( RadioButton ); 361 IMPL_GET_WINDOW( RadioButton ); 362 IMPL_GET_VCLXWINDOW( RadioButton ); 363 IMPL_CONSTRUCTORS( RadioButton, Button, "radiobutton" ); 364 365 class CheckBoxImpl : public ButtonImpl 366 , public ::cppu::WeakImplHelper1< awt::XItemListener > 367 { 368 Link maToggleHdl; 369 public: 370 uno::Reference< awt::XCheckBox > mxCheckBox; 371 CheckBoxImpl( Context *context, const PeerHandle &peer, Window *window ) 372 : ButtonImpl( context, peer, window ) 373 , mxCheckBox( peer, uno::UNO_QUERY ) 374 { 375 } 376 377 void SetToggleHdl( const Link& link ) 378 { 379 if (!link && !!maToggleHdl) 380 mxCheckBox->removeItemListener( this ); 381 else if (!!link && !maToggleHdl) 382 mxCheckBox->addItemListener( this ); 383 maToggleHdl = link; 384 } 385 void SAL_CALL disposing( lang::EventObject const& e ) 386 throw (uno::RuntimeException) 387 { 388 ButtonImpl::disposing (e); 389 } 390 virtual void SAL_CALL itemStateChanged( const awt::ItemEvent& ) 391 throw (uno::RuntimeException) 392 { 393 maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); 394 } 395 }; 396 397 CheckBox::~CheckBox () 398 { 399 SetToggleHdl (Link ()); 400 } 401 402 void CheckBox::Check( bool bCheck ) 403 { 404 if ( !getImpl().mxCheckBox.is() ) 405 return; 406 getImpl().mxCheckBox->setState( !!bCheck ); 407 } 408 409 bool CheckBox::IsChecked() const 410 { 411 if ( !getImpl().mxCheckBox.is() ) 412 return false; 413 return getImpl().mxCheckBox->getState() != 0; 414 } 415 416 void CheckBox::SetToggleHdl( const Link& link ) 417 { 418 if (&getImpl () && getImpl().mxCheckBox.is ()) 419 getImpl().SetToggleHdl( link ); 420 } 421 422 IMPL_GET_IMPL( CheckBox ); 423 IMPL_CONSTRUCTORS( CheckBox, Button, "checkbox" ); 424 425 #define BUTTON_IMPL(t, parent, response) \ 426 class t##Impl : public parent##Impl \ 427 { \ 428 public: \ 429 t##Impl( Context *context, PeerHandle const& peer, Window *window ) \ 430 : parent##Impl( context, peer, window ) \ 431 { \ 432 } \ 433 void Click() \ 434 { \ 435 if (Dialog *d = static_cast<Dialog *> (mpCtx)) \ 436 d->EndDialog( response ); \ 437 } \ 438 } 439 440 /* Common button types currently unavailable in OOo: */ 441 /* mpReset */ 442 /* mpApply */ 443 /* mpAction */ 444 #define RET_RESET 6 445 #define RET_APPLY 7 446 #define BUTTONID_RESET RET_RESET 447 #define BUTTONID_APPLY RET_APPLY 448 449 BUTTON_IMPL( OKButton, PushButton, BUTTONID_OK ); 450 BUTTON_IMPL( CancelButton, PushButton, BUTTONID_CANCEL ); 451 BUTTON_IMPL( YesButton, PushButton, BUTTONID_YES ); 452 BUTTON_IMPL( NoButton, PushButton, BUTTONID_NO ); 453 BUTTON_IMPL( RetryButton, PushButton, BUTTONID_RETRY ); 454 BUTTON_IMPL( IgnoreButton, PushButton, BUTTONID_IGNORE ); 455 BUTTON_IMPL( ResetButton, PushButton, BUTTONID_RESET ); 456 BUTTON_IMPL( ApplyButton, PushButton, BUTTONID_APPLY ); /* Deprecated? */ 457 BUTTON_IMPL( HelpButton, PushButton, BUTTONID_HELP ); 458 459 IMPL_CONSTRUCTORS( OKButton, PushButton, "okbutton" ); 460 IMPL_CONSTRUCTORS( CancelButton, PushButton, "cancelbutton" ); 461 IMPL_CONSTRUCTORS( YesButton, PushButton, "yesbutton" ); 462 IMPL_CONSTRUCTORS( NoButton, PushButton, "nobutton" ); 463 IMPL_CONSTRUCTORS( RetryButton, PushButton, "retrybutton" ); 464 IMPL_CONSTRUCTORS( IgnoreButton, PushButton, "ignorebutton" ); 465 IMPL_CONSTRUCTORS( ResetButton, PushButton, "resetbutton" ); 466 IMPL_CONSTRUCTORS( ApplyButton, PushButton, "applybutton" ); /* Deprecated? */ 467 IMPL_CONSTRUCTORS( HelpButton, PushButton, "helpbutton" ); 468 469 IMPL_IMPL (ImageButton, PushButton) 470 471 472 IMPL_CONSTRUCTORS( ImageButton, PushButton, "imagebutton" ); 473 474 class AdvancedButtonImpl : public PushButtonImpl 475 { 476 protected: 477 bool bAdvancedMode; 478 std::list< Window*> maAdvanced; 479 std::list< Window*> maSimple; 480 481 public: 482 rtl::OUString mAdvancedLabel; 483 rtl::OUString mSimpleLabel; 484 485 protected: 486 Window* Remove( std::list< Window*> lst, Window* w ) 487 { 488 for ( std::list< Window*>::iterator it = maAdvanced.begin(); 489 it != maAdvanced.end(); it++ ) 490 if ( *it == w ) 491 { 492 lst.erase( it ); 493 return *it; 494 } 495 return 0; 496 } 497 498 public: 499 AdvancedButtonImpl( Context *context, PeerHandle const& peer, Window *window ) 500 : PushButtonImpl( context, peer, window ) 501 , bAdvancedMode( false ) 502 // TODO: i18n 503 // Button::GetStandardText( BUTTON_ADVANCED ); 504 // Button::GetStandardText( BUTTON_SIMPLE ); 505 , mAdvancedLabel( rtl::OUString::createFromAscii( "Advanced..." ) ) 506 , mSimpleLabel( rtl::OUString::createFromAscii( "Simple..." ) ) 507 { 508 } 509 void Click() 510 { 511 bAdvancedMode = !bAdvancedMode; 512 if ( bAdvancedMode ) 513 advancedMode(); 514 else 515 simpleMode(); 516 } 517 void setAlign () 518 { 519 ::PushButton *b = static_cast<PushButton*> (mpWindow)->GetPushButton (); 520 b->SetSymbolAlign (SYMBOLALIGN_RIGHT); 521 b->SetSmallSymbol (); 522 //mpWindow->SetStyle (mpWindow->GetStyle() | WB_CENTER); 523 } 524 void advancedMode() 525 { 526 ::PushButton *b = static_cast<PushButton*> (mpWindow)->GetPushButton (); 527 b->SetSymbol (SYMBOL_PAGEUP); 528 setAlign (); 529 if (mSimpleLabel.getLength ()) 530 b->SetText (mSimpleLabel); 531 for ( std::list< Window*>::iterator it = maAdvanced.begin(); 532 it != maAdvanced.end(); it++ ) 533 ( *it )->Show(); 534 for ( std::list< Window*>::iterator it = maSimple.begin(); 535 it != maSimple.end(); it++ ) 536 ( *it )->Hide(); 537 538 redraw (); 539 } 540 void simpleMode() 541 { 542 //mxButton->setLabel( mSimpleLabel ); 543 ::PushButton *b = static_cast<PushButton*> (mpWindow)->GetPushButton (); 544 b->SetSymbol (SYMBOL_PAGEDOWN); 545 if (mAdvancedLabel.getLength ()) 546 b->SetText (mAdvancedLabel); 547 setAlign (); 548 for ( std::list< Window*>::iterator it = maAdvanced.begin(); 549 it != maAdvanced.end(); it++ ) 550 ( *it )->Hide(); 551 for ( std::list< Window*>::iterator it = maSimple.begin(); 552 it != maSimple.end(); it++ ) 553 ( *it )->Show(); 554 555 redraw (true); 556 } 557 void AddAdvanced( Window* w ) 558 { 559 maAdvanced.push_back( w ); 560 if ( !bAdvancedMode ) 561 w->Hide(); 562 } 563 void AddSimple( Window* w ) 564 { 565 maSimple.push_back( w ); 566 if ( bAdvancedMode ) 567 w->Hide(); 568 } 569 void RemoveAdvanced( Window* w ) 570 { 571 Remove( maAdvanced, w ); 572 } 573 void RemoveSimple( Window* w ) 574 { 575 Remove( maSimple, w ); 576 } 577 }; 578 579 void AdvancedButton::AddAdvanced( Window* w ) 580 { 581 getImpl().AddAdvanced( w ); 582 } 583 584 void AdvancedButton::AddSimple( Window* w ) 585 { 586 getImpl().AddSimple( w ); 587 } 588 589 void AdvancedButton::RemoveAdvanced( Window* w ) 590 { 591 getImpl().RemoveAdvanced( w ); 592 } 593 594 void AdvancedButton::RemoveSimple( Window* w ) 595 { 596 getImpl().RemoveSimple( w ); 597 } 598 599 void AdvancedButton::SetAdvancedText (rtl::OUString const& text) 600 { 601 if (text.getLength ()) 602 getImpl ().mAdvancedLabel = text; 603 } 604 605 void AdvancedButton::SetSimpleText (rtl::OUString const& text) 606 { 607 if (text.getLength ()) 608 getImpl ().mSimpleLabel = text; 609 } 610 611 rtl::OUString AdvancedButton::GetAdvancedText () const 612 { 613 return getImpl ().mAdvancedLabel; 614 } 615 616 rtl::OUString AdvancedButton::GetSimpleText () const 617 { 618 return getImpl ().mSimpleLabel; 619 } 620 621 void AdvancedButton::SetDelta (int) 622 { 623 } 624 625 IMPL_CONSTRUCTORS_BODY( AdvancedButton, PushButton, "advancedbutton", getImpl().simpleMode () ); 626 IMPL_GET_IMPL( AdvancedButton ); 627 628 629 class MoreButtonImpl : public AdvancedButtonImpl 630 { 631 public: 632 MoreButtonImpl( Context *context, PeerHandle const& peer, Window *window ) 633 : AdvancedButtonImpl( context, peer, window) 634 { 635 mSimpleLabel = Button::GetStandardText( BUTTON_MORE ); 636 mAdvancedLabel = Button::GetStandardText( BUTTON_LESS ); 637 } 638 void AddWindow( Window* w ) { AddAdvanced( w ); } 639 void RemoveWindow( Window* w ) { RemoveAdvanced( w ); } 640 }; 641 642 // TODO 643 //BUTTON_IMPL( MoreButton, PushButton, 0 ); 644 IMPL_CONSTRUCTORS_BODY( MoreButton, AdvancedButton, "morebutton", getImpl().simpleMode () ); 645 IMPL_GET_IMPL( MoreButton ); 646 647 void MoreButton::AddWindow( Window* w ) 648 { 649 getImpl().AddWindow( w ); 650 } 651 652 void MoreButton::RemoveWindow( Window* w ) 653 { 654 getImpl().RemoveWindow( w ); 655 } 656 657 void MoreButton::SetMoreText (rtl::OUString const& text) 658 { 659 SetAdvancedText (text); 660 } 661 662 void MoreButton::SetLessText (rtl::OUString const& text) 663 { 664 SetSimpleText (text); 665 } 666 667 rtl::OUString MoreButton::GetMoreText () const 668 { 669 return GetAdvancedText (); 670 } 671 672 rtl::OUString MoreButton::GetLessText () const 673 { 674 return GetSimpleText (); 675 } 676 677 } // namespace layout 678