| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "wrapper.hxx" |
| |
| #include <com/sun/star/awt/PosSize.hpp> |
| #include <com/sun/star/awt/XActionListener.hpp> |
| #include <com/sun/star/awt/XButton.hpp> |
| #include <com/sun/star/awt/XCheckBox.hpp> |
| #include <com/sun/star/awt/XRadioButton.hpp> |
| #include <com/sun/star/graphic/XGraphic.hpp> |
| #include <cppuhelper/implbase1.hxx> |
| #include <toolkit/awt/vclxwindow.hxx> |
| #include <toolkit/awt/vclxwindows.hxx> |
| #include <toolkit/helper/convert.hxx> |
| #include <vcl/button.hxx> |
| #include <vcl/event.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/window.hxx> |
| |
| #include <list> |
| |
| #include <layout/core/helper.hxx> |
| |
| using namespace ::com::sun::star; |
| |
| using rtl::OUString; |
| |
| namespace layout |
| { |
| |
| class ImageImpl |
| { |
| public: |
| uno::Reference< graphic::XGraphic > mxGraphic; |
| ImageImpl( const char *pName ) |
| : mxGraphic( layoutimpl::loadGraphic( pName ) ) |
| { |
| if ( !mxGraphic.is() ) |
| { |
| DBG_ERROR1( "ERROR: failed to load image: `%s'\n", pName ); |
| } |
| } |
| }; |
| |
| Image::Image( const char *pName ) |
| : pImpl( new ImageImpl( pName ) ) |
| { |
| } |
| |
| Image::~Image() |
| { |
| delete pImpl; |
| } |
| |
| class ButtonImpl : public ControlImpl |
| , public ::cppu::WeakImplHelper1< awt::XActionListener > |
| { |
| Link maClickHdl; |
| |
| public: |
| uno::Reference< awt::XButton > mxButton; |
| ButtonImpl( Context *context, const PeerHandle &peer, Window *window ) |
| : ControlImpl( context, peer, window ) |
| , mxButton( peer, uno::UNO_QUERY ) |
| { |
| /* We have default action when clicked, always listen. */ |
| mxButton->addActionListener( this ); |
| } |
| |
| ~ButtonImpl() |
| { |
| } |
| |
| virtual void Click() { /* make me pure virtual? */ }; |
| |
| Link& GetClickHdl () |
| { |
| return maClickHdl; |
| } |
| |
| virtual void SetClickHdl( Link const& link ) |
| { |
| maClickHdl = link; |
| } |
| |
| void SAL_CALL disposing( lang::EventObject const& e ) |
| throw (uno::RuntimeException) |
| { |
| mxButton->removeActionListener( this ); |
| ControlImpl::disposing (e); |
| mxButton.clear (); |
| } |
| |
| virtual void SAL_CALL actionPerformed( const awt::ActionEvent& ) |
| throw (uno::RuntimeException) |
| { |
| if ( !maClickHdl ) |
| Click(); |
| else |
| maClickHdl.Call( static_cast<Window *>( mpWindow ) ); |
| } |
| |
| bool SetModeImage( uno::Reference< graphic::XGraphic > xGraph ) |
| { |
| setProperty( "Graphic", uno::Any( xGraph ) ); |
| return true; |
| } |
| }; |
| |
| Button::~Button () |
| { |
| } |
| |
| String Button::GetStandardText (sal_uInt16 button_type) |
| { |
| return ::Button::GetStandardText (button_type); |
| } |
| |
| void Button::SetText( OUString const& rStr ) |
| { |
| if ( !getImpl().mxButton.is() ) |
| return; |
| getImpl().mxButton->setLabel( rStr ); |
| } |
| |
| void Button::SetClickHdl( const Link& link ) |
| { |
| if (&getImpl () && getImpl().mxButton.is ()) |
| getImpl().SetClickHdl( link ); |
| } |
| |
| Link& Button::GetClickHdl () |
| { |
| return getImpl().GetClickHdl (); |
| } |
| |
| bool Button::SetModeImage (Image const& image) |
| { |
| return getImpl().SetModeImage (image.getImpl().mxGraphic); |
| } |
| |
| bool Button::SetModeImage (::Image const& image, BmpColorMode mode) |
| { |
| return GetButton ()->SetModeImage (image, mode); |
| } |
| |
| void Button::SetImageAlign( ImageAlign eAlign ) |
| { |
| getImpl().setProperty( "ImageAlign", uno::Any( (sal_Int16) eAlign ) ); |
| } |
| |
| void Button::Click() |
| { |
| } |
| |
| IMPL_GET_IMPL( Button ); |
| IMPL_CONSTRUCTORS( Button, Control, "button" ); |
| IMPL_GET_WINDOW (Button); |
| |
| class PushButtonImpl : public ButtonImpl |
| , public ::cppu::WeakImplHelper1< awt::XItemListener > |
| { |
| Link maToggleHdl; |
| public: |
| PushButtonImpl( Context *context, const PeerHandle &peer, Window *window ) |
| : ButtonImpl( context, peer, window ) |
| { |
| } |
| |
| void SetToggleHdl( const Link& link ) |
| { |
| // XButton doesn't have an explicit event for Toggle. Anyway, it is a |
| // superset of the clicks: all clicks, and explicit toggles |
| if (!link && !!maToggleHdl) |
| mxButton->removeActionListener( this ); |
| else if (!!link && !maToggleHdl) |
| mxButton->addActionListener( this ); |
| maToggleHdl = link; |
| } |
| void SAL_CALL disposing( lang::EventObject const& e ) |
| throw (uno::RuntimeException) |
| { |
| ButtonImpl::disposing (e); |
| } |
| virtual void SAL_CALL actionPerformed( awt::ActionEvent const& e ) |
| throw (uno::RuntimeException) |
| { |
| ButtonImpl::actionPerformed( e ); |
| fireToggle(); |
| } |
| virtual void SAL_CALL itemStateChanged( const awt::ItemEvent& ) |
| throw (uno::RuntimeException) |
| { |
| maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); |
| } |
| void fireToggle() |
| { |
| maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); |
| } |
| |
| }; |
| |
| PushButton::~PushButton () |
| { |
| SetToggleHdl (Link ()); |
| } |
| |
| void PushButton::Check( bool bCheck ) |
| { |
| getImpl().setProperty( "State", uno::Any( (sal_Int16) !!bCheck ) ); |
| // XButton doesn't have explicit toggle event |
| getImpl().fireToggle(); |
| } |
| |
| bool PushButton::IsChecked() const |
| { |
| return !!( getImpl().getProperty( "State" ).get< sal_Int16 >() ); |
| } |
| |
| void PushButton::Toggle() |
| { |
| Check( true ); |
| } |
| |
| void PushButton::SetToggleHdl( const Link& link ) |
| { |
| if (&getImpl () && getImpl().mxButton.is ()) |
| getImpl().SetToggleHdl( link ); |
| } |
| |
| IMPL_GET_IMPL( PushButton ); |
| IMPL_CONSTRUCTORS( PushButton, Button, "pushbutton" ); |
| IMPL_GET_WINDOW (PushButton); |
| |
| class RadioButtonImpl : public ButtonImpl |
| , public ::cppu::WeakImplHelper1< awt::XItemListener > |
| { |
| Link maToggleHdl; |
| public: |
| uno::Reference< awt::XRadioButton > mxRadioButton; |
| RadioButtonImpl( Context *context, const PeerHandle &peer, Window *window ) |
| : ButtonImpl( context, peer, window ) |
| , mxRadioButton( peer, uno::UNO_QUERY ) |
| { |
| } |
| |
| void Check( bool bCheck ) |
| { |
| if ( !mxRadioButton.is() ) |
| return; |
| |
| #if 1 |
| // Have setState fire item event for |
| // RadioGroups::RadioGroup::itemStateChanged () |
| ::RadioButton *r = static_cast<RadioButton*>(mpWindow)->GetRadioButton (); |
| bool state = r->IsRadioCheckEnabled (); |
| r->EnableRadioCheck(); |
| mxRadioButton->setState( !!bCheck ); |
| r->EnableRadioCheck (state); |
| #else |
| mxRadioButton->setState( !!bCheck ); |
| #endif |
| fireToggle(); |
| } |
| |
| bool IsChecked() |
| { |
| if ( !mxRadioButton.is() ) |
| return false; |
| return mxRadioButton->getState(); |
| } |
| |
| void SetToggleHdl( const Link& link ) |
| { |
| if (!link && !!maToggleHdl) |
| mxRadioButton->removeItemListener( this ); |
| else if (!!link && !maToggleHdl) |
| mxRadioButton->addItemListener( this ); |
| maToggleHdl = link; |
| } |
| |
| inline void fireToggle() |
| { |
| maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); |
| } |
| |
| virtual void SetClickHdl( const Link& link ) |
| { |
| // Keep RadioGroups::RadioGroup's actionListener at HEAD |
| // of list. This way, it can handle RadioGroup's button |
| // states before all other callbacks and make sure the |
| // client code has the right state. |
| |
| // IWBN to add an XRadioButton2 and layout::VCLXRadioButton |
| // with {get,set}RadioGroup() (and a "radiogroup" property |
| // even) and handle the grouping here in RadioButtonImpl. |
| uno::Reference< uno::XInterface > x = static_cast<VCLXRadioButton*> (mpWindow->GetVCLXWindow ())->getFirstActionListener (); |
| uno::Reference< awt::XActionListener > a = uno::Reference< awt::XActionListener> (x ,uno::UNO_QUERY ); |
| mxButton->removeActionListener (a); |
| ButtonImpl::SetClickHdl (link); |
| mxButton->addActionListener (a); |
| } |
| |
| void SAL_CALL disposing( lang::EventObject const& e ) |
| throw (uno::RuntimeException) |
| { |
| ButtonImpl::disposing (e); |
| } |
| |
| virtual void SAL_CALL itemStateChanged( const awt::ItemEvent& ) |
| throw (uno::RuntimeException) |
| { |
| maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); |
| } |
| }; |
| |
| RadioButton::~RadioButton () |
| { |
| SetToggleHdl (Link ()); |
| } |
| |
| void RadioButton::Check( bool bCheck ) |
| { |
| getImpl().Check( bCheck ); |
| } |
| |
| bool RadioButton::IsChecked() const |
| { |
| return getImpl().IsChecked(); |
| } |
| |
| void RadioButton::SetToggleHdl( const Link& link ) |
| { |
| if (&getImpl () && getImpl().mxRadioButton.is ()) |
| getImpl().SetToggleHdl( link ); |
| } |
| |
| IMPL_GET_IMPL( RadioButton ); |
| IMPL_GET_WINDOW( RadioButton ); |
| IMPL_GET_VCLXWINDOW( RadioButton ); |
| IMPL_CONSTRUCTORS( RadioButton, Button, "radiobutton" ); |
| |
| class CheckBoxImpl : public ButtonImpl |
| , public ::cppu::WeakImplHelper1< awt::XItemListener > |
| { |
| Link maToggleHdl; |
| public: |
| uno::Reference< awt::XCheckBox > mxCheckBox; |
| CheckBoxImpl( Context *context, const PeerHandle &peer, Window *window ) |
| : ButtonImpl( context, peer, window ) |
| , mxCheckBox( peer, uno::UNO_QUERY ) |
| { |
| } |
| |
| void SetToggleHdl( const Link& link ) |
| { |
| if (!link && !!maToggleHdl) |
| mxCheckBox->removeItemListener( this ); |
| else if (!!link && !maToggleHdl) |
| mxCheckBox->addItemListener( this ); |
| maToggleHdl = link; |
| } |
| void SAL_CALL disposing( lang::EventObject const& e ) |
| throw (uno::RuntimeException) |
| { |
| ButtonImpl::disposing (e); |
| } |
| virtual void SAL_CALL itemStateChanged( const awt::ItemEvent& ) |
| throw (uno::RuntimeException) |
| { |
| maToggleHdl.Call( static_cast<Window *>( mpWindow ) ); |
| } |
| }; |
| |
| CheckBox::~CheckBox () |
| { |
| SetToggleHdl (Link ()); |
| } |
| |
| void CheckBox::Check( bool bCheck ) |
| { |
| if ( !getImpl().mxCheckBox.is() ) |
| return; |
| getImpl().mxCheckBox->setState( !!bCheck ); |
| } |
| |
| bool CheckBox::IsChecked() const |
| { |
| if ( !getImpl().mxCheckBox.is() ) |
| return false; |
| return getImpl().mxCheckBox->getState() != 0; |
| } |
| |
| void CheckBox::SetToggleHdl( const Link& link ) |
| { |
| if (&getImpl () && getImpl().mxCheckBox.is ()) |
| getImpl().SetToggleHdl( link ); |
| } |
| |
| IMPL_GET_IMPL( CheckBox ); |
| IMPL_CONSTRUCTORS( CheckBox, Button, "checkbox" ); |
| |
| #define BUTTON_IMPL(t, parent, response) \ |
| class t##Impl : public parent##Impl \ |
| { \ |
| public: \ |
| t##Impl( Context *context, PeerHandle const& peer, Window *window ) \ |
| : parent##Impl( context, peer, window ) \ |
| { \ |
| } \ |
| void Click() \ |
| { \ |
| if (Dialog *d = static_cast<Dialog *> (mpCtx)) \ |
| d->EndDialog( response ); \ |
| } \ |
| } |
| |
| /* Common button types currently unavailable in OOo: */ |
| /* mpReset */ |
| /* mpApply */ |
| /* mpAction */ |
| #define RET_RESET 6 |
| #define RET_APPLY 7 |
| #define BUTTONID_RESET RET_RESET |
| #define BUTTONID_APPLY RET_APPLY |
| |
| BUTTON_IMPL( OKButton, PushButton, BUTTONID_OK ); |
| BUTTON_IMPL( CancelButton, PushButton, BUTTONID_CANCEL ); |
| BUTTON_IMPL( YesButton, PushButton, BUTTONID_YES ); |
| BUTTON_IMPL( NoButton, PushButton, BUTTONID_NO ); |
| BUTTON_IMPL( RetryButton, PushButton, BUTTONID_RETRY ); |
| BUTTON_IMPL( IgnoreButton, PushButton, BUTTONID_IGNORE ); |
| BUTTON_IMPL( ResetButton, PushButton, BUTTONID_RESET ); |
| BUTTON_IMPL( ApplyButton, PushButton, BUTTONID_APPLY ); /* Deprecated? */ |
| BUTTON_IMPL( HelpButton, PushButton, BUTTONID_HELP ); |
| |
| IMPL_CONSTRUCTORS( OKButton, PushButton, "okbutton" ); |
| IMPL_CONSTRUCTORS( CancelButton, PushButton, "cancelbutton" ); |
| IMPL_CONSTRUCTORS( YesButton, PushButton, "yesbutton" ); |
| IMPL_CONSTRUCTORS( NoButton, PushButton, "nobutton" ); |
| IMPL_CONSTRUCTORS( RetryButton, PushButton, "retrybutton" ); |
| IMPL_CONSTRUCTORS( IgnoreButton, PushButton, "ignorebutton" ); |
| IMPL_CONSTRUCTORS( ResetButton, PushButton, "resetbutton" ); |
| IMPL_CONSTRUCTORS( ApplyButton, PushButton, "applybutton" ); /* Deprecated? */ |
| IMPL_CONSTRUCTORS( HelpButton, PushButton, "helpbutton" ); |
| |
| IMPL_IMPL (ImageButton, PushButton) |
| |
| |
| IMPL_CONSTRUCTORS( ImageButton, PushButton, "imagebutton" ); |
| |
| class AdvancedButtonImpl : public PushButtonImpl |
| { |
| protected: |
| bool bAdvancedMode; |
| std::list< Window*> maAdvanced; |
| std::list< Window*> maSimple; |
| |
| public: |
| rtl::OUString mAdvancedLabel; |
| rtl::OUString mSimpleLabel; |
| |
| protected: |
| Window* Remove( std::list< Window*> lst, Window* w ) |
| { |
| for ( std::list< Window*>::iterator it = maAdvanced.begin(); |
| it != maAdvanced.end(); it++ ) |
| if ( *it == w ) |
| { |
| lst.erase( it ); |
| return *it; |
| } |
| return 0; |
| } |
| |
| public: |
| AdvancedButtonImpl( Context *context, PeerHandle const& peer, Window *window ) |
| : PushButtonImpl( context, peer, window ) |
| , bAdvancedMode( false ) |
| // TODO: i18n |
| // Button::GetStandardText( BUTTON_ADVANCED ); |
| // Button::GetStandardText( BUTTON_SIMPLE ); |
| , mAdvancedLabel( rtl::OUString::createFromAscii( "Advanced..." ) ) |
| , mSimpleLabel( rtl::OUString::createFromAscii( "Simple..." ) ) |
| { |
| } |
| void Click() |
| { |
| bAdvancedMode = !bAdvancedMode; |
| if ( bAdvancedMode ) |
| advancedMode(); |
| else |
| simpleMode(); |
| } |
| void setAlign () |
| { |
| ::PushButton *b = static_cast<PushButton*> (mpWindow)->GetPushButton (); |
| b->SetSymbolAlign (SYMBOLALIGN_RIGHT); |
| b->SetSmallSymbol (); |
| //mpWindow->SetStyle (mpWindow->GetStyle() | WB_CENTER); |
| } |
| void advancedMode() |
| { |
| ::PushButton *b = static_cast<PushButton*> (mpWindow)->GetPushButton (); |
| b->SetSymbol (SYMBOL_PAGEUP); |
| setAlign (); |
| if (mSimpleLabel.getLength ()) |
| b->SetText (mSimpleLabel); |
| for ( std::list< Window*>::iterator it = maAdvanced.begin(); |
| it != maAdvanced.end(); it++ ) |
| ( *it )->Show(); |
| for ( std::list< Window*>::iterator it = maSimple.begin(); |
| it != maSimple.end(); it++ ) |
| ( *it )->Hide(); |
| |
| redraw (); |
| } |
| void simpleMode() |
| { |
| //mxButton->setLabel( mSimpleLabel ); |
| ::PushButton *b = static_cast<PushButton*> (mpWindow)->GetPushButton (); |
| b->SetSymbol (SYMBOL_PAGEDOWN); |
| if (mAdvancedLabel.getLength ()) |
| b->SetText (mAdvancedLabel); |
| setAlign (); |
| for ( std::list< Window*>::iterator it = maAdvanced.begin(); |
| it != maAdvanced.end(); it++ ) |
| ( *it )->Hide(); |
| for ( std::list< Window*>::iterator it = maSimple.begin(); |
| it != maSimple.end(); it++ ) |
| ( *it )->Show(); |
| |
| redraw (true); |
| } |
| void AddAdvanced( Window* w ) |
| { |
| maAdvanced.push_back( w ); |
| if ( !bAdvancedMode ) |
| w->Hide(); |
| } |
| void AddSimple( Window* w ) |
| { |
| maSimple.push_back( w ); |
| if ( bAdvancedMode ) |
| w->Hide(); |
| } |
| void RemoveAdvanced( Window* w ) |
| { |
| Remove( maAdvanced, w ); |
| } |
| void RemoveSimple( Window* w ) |
| { |
| Remove( maSimple, w ); |
| } |
| }; |
| |
| void AdvancedButton::AddAdvanced( Window* w ) |
| { |
| getImpl().AddAdvanced( w ); |
| } |
| |
| void AdvancedButton::AddSimple( Window* w ) |
| { |
| getImpl().AddSimple( w ); |
| } |
| |
| void AdvancedButton::RemoveAdvanced( Window* w ) |
| { |
| getImpl().RemoveAdvanced( w ); |
| } |
| |
| void AdvancedButton::RemoveSimple( Window* w ) |
| { |
| getImpl().RemoveSimple( w ); |
| } |
| |
| void AdvancedButton::SetAdvancedText (rtl::OUString const& text) |
| { |
| if (text.getLength ()) |
| getImpl ().mAdvancedLabel = text; |
| } |
| |
| void AdvancedButton::SetSimpleText (rtl::OUString const& text) |
| { |
| if (text.getLength ()) |
| getImpl ().mSimpleLabel = text; |
| } |
| |
| rtl::OUString AdvancedButton::GetAdvancedText () const |
| { |
| return getImpl ().mAdvancedLabel; |
| } |
| |
| rtl::OUString AdvancedButton::GetSimpleText () const |
| { |
| return getImpl ().mSimpleLabel; |
| } |
| |
| void AdvancedButton::SetDelta (int) |
| { |
| } |
| |
| IMPL_CONSTRUCTORS_BODY( AdvancedButton, PushButton, "advancedbutton", getImpl().simpleMode () ); |
| IMPL_GET_IMPL( AdvancedButton ); |
| |
| |
| class MoreButtonImpl : public AdvancedButtonImpl |
| { |
| public: |
| MoreButtonImpl( Context *context, PeerHandle const& peer, Window *window ) |
| : AdvancedButtonImpl( context, peer, window) |
| { |
| mSimpleLabel = Button::GetStandardText( BUTTON_MORE ); |
| mAdvancedLabel = Button::GetStandardText( BUTTON_LESS ); |
| } |
| void AddWindow( Window* w ) { AddAdvanced( w ); } |
| void RemoveWindow( Window* w ) { RemoveAdvanced( w ); } |
| }; |
| |
| // TODO |
| //BUTTON_IMPL( MoreButton, PushButton, 0 ); |
| IMPL_CONSTRUCTORS_BODY( MoreButton, AdvancedButton, "morebutton", getImpl().simpleMode () ); |
| IMPL_GET_IMPL( MoreButton ); |
| |
| void MoreButton::AddWindow( Window* w ) |
| { |
| getImpl().AddWindow( w ); |
| } |
| |
| void MoreButton::RemoveWindow( Window* w ) |
| { |
| getImpl().RemoveWindow( w ); |
| } |
| |
| void MoreButton::SetMoreText (rtl::OUString const& text) |
| { |
| SetAdvancedText (text); |
| } |
| |
| void MoreButton::SetLessText (rtl::OUString const& text) |
| { |
| SetSimpleText (text); |
| } |
| |
| rtl::OUString MoreButton::GetMoreText () const |
| { |
| return GetAdvancedText (); |
| } |
| |
| rtl::OUString MoreButton::GetLessText () const |
| { |
| return GetSimpleText (); |
| } |
| |
| } // namespace layout |