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