blob: ab901bae0235fa61ac05bdf5a638e3a56ccccf8f [file] [log] [blame]
/**************************************************************
*
* 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