/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project .
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2 . 0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice :
*
* 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 .
*/
#include <sal/config.h>
#include <sal/log.hxx>
#include <cassert>
#include <dlged.hxx>
#include <dlgeddef.hxx>
#include <dlgedlist.hxx>
#include <dlgedobj.hxx>
#include <dlgedpage.hxx>
#include <dlgedview.hxx>
#include <localizationmgr.hxx>
#include <strings.hxx>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/form/binding/XBindableValue.hpp>
#include <com/sun/star/form/binding/XValueBinding.hpp>
#include <com/sun/star/form/binding/XListEntrySink.hpp>
#include <com/sun/star/awt/XUnoControlContainer.hpp>
#include <com/sun/star/awt/XVclContainerPeer.hpp>
#include <com/sun/star/container/XContainer.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
#include <com/sun/star/script/XScriptEventsSupplier.hpp>
#include <com/sun/star/table/CellAddress.hpp>
#include <com/sun/star/table/CellRangeAddress.hpp>
#include <cppuhelper/exc_hlp.hxx>
#include <o3tl/functional.hxx>
#include <svx/svdpagv.hxx>
#include <unotools/sharedunocomponent.hxx>
#include <vcl/svapp.hxx>
#include <tools/debug.hxx>
namespace basctl
{
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::script;
DlgEditor& DlgEdObj::GetDialogEditor ()
{
if (DlgEdForm* pFormThis = dynamic_cast <DlgEdForm*>(this ))
return pFormThis->GetDlgEditor();
else
return pDlgEdForm->GetDlgEditor();
}
DlgEdObj::DlgEdObj(SdrModel& rSdrModel)
: SdrUnoObj(rSdrModel, OUString())
,bIsListening(false )
{
}
DlgEdObj::DlgEdObj(SdrModel& rSdrModel, DlgEdObj const & rSource)
: SdrUnoObj(rSdrModel, rSource)
,bIsListening(false )
{
// set parent form
pDlgEdForm = rSource.pDlgEdForm;
// add child to parent form
pDlgEdForm->AddChild( this );
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
if ( xPSet.is() )
{
// set new name
OUString aOUniqueName( GetUniqueName() );
Any aUniqueName;
aUniqueName <<= aOUniqueName;
xPSet->setPropertyValue( DLGED_PROP_NAME, aUniqueName );
Reference< container::XNameContainer > xCont( GetDlgEdForm()->GetUnoControlModel() , UNO_QUERY );
if ( xCont.is() )
{
// set tabindex
Sequence< OUString > aNames = xCont->getElementNames();
xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(static_cast <sal_Int16>(aNames.getLength())) );
// insert control model in dialog model
Reference< awt::XControlModel > xCtrl( xPSet , UNO_QUERY );
xCont->insertByName( aOUniqueName, Any(xCtrl) );
pDlgEdForm->UpdateTabOrderAndGroups();
}
}
// start listening
StartListening();
}
DlgEdObj::DlgEdObj(
SdrModel& rSdrModel,
const OUString& rModelName,
const css::uno::Reference< css::lang::XMultiServiceFactory >& rxSFac)
: SdrUnoObj(rSdrModel, rModelName, rxSFac)
,bIsListening(false )
{
}
DlgEdObj::~DlgEdObj()
{
if ( isListening() )
EndListening(true );
}
namespace
{
/* returns the DlgEdForm which the given DlgEdObj belongs to
( which might in fact be the object itself )
Failure to obtain the form will be reported with an assertion in the non - product
version .
*/
bool lcl_getDlgEdForm( DlgEdObj* _pObject, DlgEdForm*& _out_pDlgEdForm )
{
_out_pDlgEdForm = dynamic_cast < DlgEdForm* >( _pObject );
if ( !_out_pDlgEdForm )
_out_pDlgEdForm = _pObject->GetDlgEdForm();
DBG_ASSERT( _out_pDlgEdForm, "lcl_getDlgEdForm: no form!" );
return ( _out_pDlgEdForm != nullptr );
}
}
uno::Reference< awt::XControl > DlgEdObj::GetControl() const
{
uno::Reference< awt::XControl > xControl;
if (DlgEdForm const * pForm = GetDlgEdForm())
{
DlgEditor const & rEditor = pForm->GetDlgEditor();
xControl = GetUnoControl(rEditor.GetView(), *rEditor.GetWindow().GetOutDev());
}
return xControl;
}
bool DlgEdObj::TransformSdrToControlCoordinates(
sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn,
sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut )
{
// input position and size
Size aPos( nXIn, nYIn );
Size aSize( nWidthIn, nHeightIn );
// form position
DlgEdForm* pForm = nullptr;
if ( !lcl_getDlgEdForm( this , pForm ) )
return false ;
tools::Rectangle aFormRect = pForm->GetSnapRect();
Size aFormPos( aFormRect.Left(), aFormRect.Top() );
// convert 100th_mm to pixel
OutputDevice* pDevice = Application::GetDefaultDevice();
DBG_ASSERT( pDevice, "DlgEdObj::TransformSdrToControlCoordinates: missing default device!" );
if ( !pDevice )
return false ;
aPos = pDevice->LogicToPixel( aPos, MapMode( MapUnit::Map100thMM ) );
aSize = pDevice->LogicToPixel( aSize, MapMode( MapUnit::Map100thMM ) );
aFormPos = pDevice->LogicToPixel( aFormPos, MapMode( MapUnit::Map100thMM ) );
// subtract form position
aPos.AdjustWidth( -(aFormPos.Width()) );
aPos.AdjustHeight( -(aFormPos.Height()) );
// take window borders into account
Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY );
DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" );
if ( !xPSetForm.is() )
return false ;
bool bDecoration = true ;
xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration;
if ( bDecoration )
{
awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo();
aPos.AdjustWidth( -(aDeviceInfo.LeftInset) );
aPos.AdjustHeight( -(aDeviceInfo.TopInset) );
}
// convert pixel to logic units
aPos = pDevice->PixelToLogic(aPos, MapMode(MapUnit::MapAppFont));
aSize = pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapAppFont));
// set out parameters
nXOut = aPos.Width();
nYOut = aPos.Height();
nWidthOut = aSize.Width();
nHeightOut = aSize.Height();
return true ;
}
bool DlgEdObj::TransformSdrToFormCoordinates(
sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn,
sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut )
{
// input position and size
Size aPos( nXIn, nYIn );
Size aSize( nWidthIn, nHeightIn );
// convert 100th_mm to pixel
OutputDevice* pDevice = Application::GetDefaultDevice();
DBG_ASSERT( pDevice, "DlgEdObj::TransformSdrToFormCoordinates: missing default device!" );
if ( !pDevice )
return false ;
aPos = pDevice->LogicToPixel( aPos, MapMode( MapUnit::Map100thMM ) );
aSize = pDevice->LogicToPixel( aSize, MapMode( MapUnit::Map100thMM ) );
// take window borders into account
DlgEdForm* pForm = nullptr;
if ( !lcl_getDlgEdForm( this , pForm ) )
return false ;
// take window borders into account
Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY );
DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" );
if ( !xPSetForm.is() )
return false ;
bool bDecoration = true ;
xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration;
if ( bDecoration )
{
awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo();
aSize.AdjustWidth( -(aDeviceInfo.LeftInset + aDeviceInfo.RightInset) );
aSize.AdjustHeight( -(aDeviceInfo.TopInset + aDeviceInfo.BottomInset) );
}
// convert pixel to logic units
aPos = pDevice->PixelToLogic(aPos, MapMode(MapUnit::MapAppFont));
aSize = pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapAppFont));
// set out parameters
nXOut = aPos.Width();
nYOut = aPos.Height();
nWidthOut = aSize.Width();
nHeightOut = aSize.Height();
return true ;
}
bool DlgEdObj::TransformControlToSdrCoordinates(
sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn,
sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut )
{
// input position and size
Size aPos( nXIn, nYIn );
Size aSize( nWidthIn, nHeightIn );
// form position
DlgEdForm* pForm = nullptr;
if ( !lcl_getDlgEdForm( this , pForm ) )
return false ;
Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY );
DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformControlToSdrCoordinates: no form property set!" );
if ( !xPSetForm.is() )
return false ;
sal_Int32 nFormX = 0 , nFormY = 0 ;
xPSetForm->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nFormX;
xPSetForm->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nFormY;
Size aFormPos( nFormX, nFormY );
// convert logic units to pixel
OutputDevice* pDevice = Application::GetDefaultDevice();
DBG_ASSERT( pDevice, "DlgEdObj::TransformControlToSdrCoordinates: missing default device!" );
if ( !pDevice )
return false ;
aPos = pDevice->LogicToPixel(aPos, MapMode(MapUnit::MapAppFont));
aSize = pDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont));
aFormPos = pDevice->LogicToPixel(aFormPos, MapMode(MapUnit::MapAppFont));
// add form position
aPos.AdjustWidth(aFormPos.Width() );
aPos.AdjustHeight(aFormPos.Height() );
// take window borders into account
bool bDecoration = true ;
xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration;
if ( bDecoration )
{
awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo();
aPos.AdjustWidth(aDeviceInfo.LeftInset );
aPos.AdjustHeight(aDeviceInfo.TopInset );
}
// convert pixel to 100th_mm
aPos = pDevice->PixelToLogic( aPos, MapMode( MapUnit::Map100thMM ) );
aSize = pDevice->PixelToLogic( aSize, MapMode( MapUnit::Map100thMM ) );
// set out parameters
nXOut = aPos.Width();
nYOut = aPos.Height();
nWidthOut = aSize.Width();
nHeightOut = aSize.Height();
return true ;
}
bool DlgEdObj::TransformFormToSdrCoordinates(
sal_Int32 nXIn, sal_Int32 nYIn, sal_Int32 nWidthIn, sal_Int32 nHeightIn,
sal_Int32& nXOut, sal_Int32& nYOut, sal_Int32& nWidthOut, sal_Int32& nHeightOut )
{
// input position and size
Size aPos( nXIn, nYIn );
Size aSize( nWidthIn, nHeightIn );
// convert logic units to pixel
OutputDevice* pDevice = Application::GetDefaultDevice();
DBG_ASSERT( pDevice, "DlgEdObj::TransformFormToSdrCoordinates: missing default device!" );
if ( !pDevice )
return false ;
// take window borders into account
DlgEdForm* pForm = nullptr;
if ( !lcl_getDlgEdForm( this , pForm ) )
return false ;
aPos = pDevice->LogicToPixel(aPos, MapMode(MapUnit::MapAppFont));
aSize = pDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont));
// take window borders into account
Reference< beans::XPropertySet > xPSetForm( pForm->GetUnoControlModel(), UNO_QUERY );
DBG_ASSERT( xPSetForm.is(), "DlgEdObj::TransformFormToSdrCoordinates: no form property set!" );
if ( !xPSetForm.is() )
return false ;
bool bDecoration = true ;
xPSetForm->getPropertyValue( DLGED_PROP_DECORATION ) >>= bDecoration;
if ( bDecoration )
{
awt::DeviceInfo aDeviceInfo = pForm->getDeviceInfo();
aSize.AdjustWidth(aDeviceInfo.LeftInset + aDeviceInfo.RightInset );
aSize.AdjustHeight(aDeviceInfo.TopInset + aDeviceInfo.BottomInset );
}
// convert pixel to 100th_mm
aPos = pDevice->PixelToLogic( aPos, MapMode( MapUnit::Map100thMM ) );
aSize = pDevice->PixelToLogic( aSize, MapMode( MapUnit::Map100thMM ) );
// set out parameters
nXOut = aPos.Width();
nYOut = aPos.Height();
nWidthOut = aSize.Width();
nHeightOut = aSize.Height();
return true ;
}
void DlgEdObj::SetRectFromProps()
{
// get control position and size from properties
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
if ( !xPSet.is() )
return ;
sal_Int32 nXIn = 0 , nYIn = 0 , nWidthIn = 0 , nHeightIn = 0 ;
xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nXIn;
xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nYIn;
xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidthIn;
xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeightIn;
// transform coordinates
sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut;
if ( TransformControlToSdrCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) )
{
// set rectangle position and size
Point aPoint( nXOut, nYOut );
Size aSize( nWidthOut, nHeightOut );
SetSnapRect( tools::Rectangle( aPoint, aSize ) );
}
}
void DlgEdObj::SetPropsFromRect()
{
// get control position and size from rectangle
tools::Rectangle aRect_ = GetSnapRect();
sal_Int32 nXIn = aRect_.Left();
sal_Int32 nYIn = aRect_.Top();
sal_Int32 nWidthIn = aRect_.GetWidth();
sal_Int32 nHeightIn = aRect_.GetHeight();
// transform coordinates
sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut;
if ( TransformSdrToControlCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) )
{
// set properties
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
if ( xPSet.is() )
{
xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nXOut) );
xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nYOut) );
xPSet->setPropertyValue( DLGED_PROP_WIDTH, Any(nWidthOut) );
xPSet->setPropertyValue( DLGED_PROP_HEIGHT, Any(nHeightOut) );
}
}
}
void DlgEdObj::PositionAndSizeChange( const beans::PropertyChangeEvent& evt )
{
DBG_ASSERT( pDlgEdForm, "DlgEdObj::PositionAndSizeChange: no form!" );
DlgEdPage& rPage = pDlgEdForm->GetDlgEditor().GetPage();
{
Size aPageSize = rPage.GetSize();
sal_Int32 nPageWidthIn = aPageSize.Width();
sal_Int32 nPageHeightIn = aPageSize.Height();
sal_Int32 nPageX, nPageY, nPageWidth, nPageHeight;
if ( TransformSdrToControlCoordinates( 0 /*nPageXIn*/, 0/*nPageYIn*/, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) )
{
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
if ( xPSet.is() )
{
sal_Int32 nX = 0 , nY = 0 , nWidth = 0 , nHeight = 0 ;
xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nX;
xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nY;
xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidth;
xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeight;
sal_Int32 nValue = 0 ;
evt.NewValue >>= nValue;
sal_Int32 nNewValue = nValue;
if ( evt.PropertyName == DLGED_PROP_POSITIONX )
{
if ( nNewValue + nWidth > nPageX + nPageWidth )
nNewValue = nPageX + nPageWidth - nWidth;
if ( nNewValue < nPageX )
nNewValue = nPageX;
}
else if ( evt.PropertyName == DLGED_PROP_POSITIONY )
{
if ( nNewValue + nHeight > nPageY + nPageHeight )
nNewValue = nPageY + nPageHeight - nHeight;
if ( nNewValue < nPageY )
nNewValue = nPageY;
}
else if ( evt.PropertyName == DLGED_PROP_WIDTH )
{
if ( nX + nNewValue > nPageX + nPageWidth )
nNewValue = nPageX + nPageWidth - nX;
if ( nNewValue < 1 )
nNewValue = 1 ;
}
else if ( evt.PropertyName == DLGED_PROP_HEIGHT )
{
if ( nY + nNewValue > nPageY + nPageHeight )
nNewValue = nPageY + nPageHeight - nY;
if ( nNewValue < 1 )
nNewValue = 1 ;
}
if ( nNewValue != nValue )
{
EndListening( false );
xPSet->setPropertyValue( evt.PropertyName, Any(nNewValue) );
StartListening();
}
}
}
}
SetRectFromProps();
}
void DlgEdObj::NameChange( const css::beans::PropertyChangeEvent& evt )
{
// get old name
OUString aOldName;
evt.OldValue >>= aOldName;
// get new name
OUString aNewName;
evt.NewValue >>= aNewName;
if ( aNewName == aOldName )
return ;
Reference< container::XNameAccess > xNameAcc((GetDlgEdForm()->GetUnoControlModel()), UNO_QUERY);
if ( !(xNameAcc.is() && xNameAcc->hasByName(aOldName)) )
return ;
if (!xNameAcc->hasByName(aNewName) && !aNewName.isEmpty())
{
// remove the control by the old name and insert the control by the new name in the container
Reference< container::XNameContainer > xCont(xNameAcc, UNO_QUERY );
if ( xCont.is() )
{
Reference< awt::XControlModel > xCtrl = GetUnoControlModel();
Any aAny;
aAny <<= xCtrl;
xCont->removeByName( aOldName );
xCont->insertByName( aNewName , aAny );
LocalizationMgr::renameControlResourceIDsForEditorObject(
&GetDialogEditor(), aAny, aNewName
);
}
}
else
{
// set old name property
EndListening(false );
Reference< beans::XPropertySet > xPSet(GetUnoControlModel(), UNO_QUERY);
xPSet->setPropertyValue( DLGED_PROP_NAME, Any(aOldName) );
StartListening();
}
}
sal_Int32 DlgEdObj::GetStep() const
{
// get step property
sal_Int32 nStep = 0 ;
uno::Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), uno::UNO_QUERY );
if (xPSet.is())
{
xPSet->getPropertyValue( DLGED_PROP_STEP ) >>= nStep;
}
return nStep;
}
void DlgEdObj::UpdateStep()
{
sal_Int32 nCurStep = GetDlgEdForm()->GetStep();
sal_Int32 nStep = GetStep();
SdrLayerAdmin& rLayerAdmin(getSdrModelFromSdrObject().GetLayerAdmin());
SdrLayerID nHiddenLayerId = rLayerAdmin.GetLayerID( u"HiddenLayer" _ustr );
SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName() );
if ( nCurStep )
{
if ( nStep && (nStep != nCurStep) )
{
SetLayer( nHiddenLayerId );
}
else
{
SetLayer( nControlLayerId );
}
}
else
{
SetLayer( nControlLayerId );
}
}
void DlgEdObj::TabIndexChange( const beans::PropertyChangeEvent& evt )
{
DlgEdForm* pForm = GetDlgEdForm();
if ( !pForm )
return ;
// stop listening with all children
std::vector<DlgEdObj*> aChildList = pForm->GetChildren();
for (auto const & child : aChildList)
{
child->EndListening( false );
}
Reference< container::XNameAccess > xNameAcc( pForm->GetUnoControlModel() , UNO_QUERY );
if ( xNameAcc.is() )
{
// get sequence of control names
Sequence< OUString > aNames = xNameAcc->getElementNames();
sal_Int32 nCtrls = aNames.getLength();
// create a map of tab indices and control names, sorted by tab index
IndexToNameMap aIndexToNameMap;
for (auto & aName : aNames)
{
// get tab index
sal_Int16 nTabIndex = -1 ;
Any aCtrl = xNameAcc->getByName( aName );
Reference< beans::XPropertySet > xPSet;
aCtrl >>= xPSet;
if ( xPSet.is() && xPSet == Reference< beans::XPropertySet >( evt.Source, UNO_QUERY ) )
evt.OldValue >>= nTabIndex;
else if ( xPSet.is() )
xPSet->getPropertyValue( DLGED_PROP_TABINDEX ) >>= nTabIndex;
// insert into map
aIndexToNameMap.emplace( nTabIndex, aName );
}
// create a helper list of control names, sorted by tab index
std::vector< OUString > aNameList( aIndexToNameMap.size() );
std::transform(
aIndexToNameMap.begin(), aIndexToNameMap.end(),
aNameList.begin(),
::o3tl::select2nd< IndexToNameMap::value_type >( )
);
// check tab index
sal_Int16 nOldTabIndex = 0 ;
evt.OldValue >>= nOldTabIndex;
sal_Int16 nNewTabIndex = 0 ;
evt.NewValue >>= nNewTabIndex;
if ( nNewTabIndex < 0 )
nNewTabIndex = 0 ;
else if ( nNewTabIndex > nCtrls - 1 )
nNewTabIndex = sal::static_int_cast<sal_Int16>( nCtrls - 1 );
// reorder helper list
OUString aCtrlName = aNameList[nOldTabIndex];
aNameList.erase( aNameList.begin() + nOldTabIndex );
aNameList.insert( aNameList.begin() + nNewTabIndex , aCtrlName );
// set new tab indices
for ( sal_Int32 i = 0 ; i < nCtrls; ++i )
{
Any aCtrl = xNameAcc->getByName( aNameList[i] );
Reference< beans::XPropertySet > xPSet;
aCtrl >>= xPSet;
if ( xPSet.is() )
{
assert(i >= SAL_MIN_INT16);
if (i > SAL_MAX_INT16)
{
SAL_WARN("basctl" , "tab " << i << " > SAL_MAX_INT16" );
continue ;
}
xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(static_cast <sal_Int16>(i)) );
}
}
// reorder objects in drawing page
getSdrModelFromSdrObject().GetPage(0 )->SetObjectOrdNum( nOldTabIndex + 1 , nNewTabIndex + 1 );
pForm->UpdateTabOrderAndGroups();
}
// start listening with all children
for (auto const & child : aChildList)
{
child->StartListening();
}
}
bool DlgEdObj::supportsService( OUString const & serviceName ) const
{
bool bSupports = false ;
Reference< lang::XServiceInfo > xServiceInfo( GetUnoControlModel() , UNO_QUERY );
// TODO: cache xServiceInfo as member?
if ( xServiceInfo.is() )
bSupports = xServiceInfo->supportsService( serviceName );
return bSupports;
}
OUString DlgEdObj::GetDefaultName() const
{
OUString sResId;
OUString aDefaultName;
if ( supportsService( u"com.sun.star.awt.UnoControlDialogModel" _ustr ) )
{
sResId = RID_STR_CLASS_DIALOG;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlButtonModel" _ustr ) )
{
sResId = RID_STR_CLASS_BUTTON;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlRadioButtonModel" _ustr ) )
{
sResId = RID_STR_CLASS_RADIOBUTTON;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlCheckBoxModel" _ustr ) )
{
sResId = RID_STR_CLASS_CHECKBOX;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlListBoxModel" _ustr ) )
{
sResId = RID_STR_CLASS_LISTBOX;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlComboBoxModel" _ustr ) )
{
sResId = RID_STR_CLASS_COMBOBOX;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlGroupBoxModel" _ustr ) )
{
sResId = RID_STR_CLASS_GROUPBOX;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlEditModel" _ustr ) )
{
sResId = RID_STR_CLASS_EDIT;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFixedTextModel" _ustr ) )
{
sResId = RID_STR_CLASS_FIXEDTEXT;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlImageControlModel" _ustr ) )
{
sResId = RID_STR_CLASS_IMAGECONTROL;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlProgressBarModel" _ustr ) )
{
sResId = RID_STR_CLASS_PROGRESSBAR;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlScrollBarModel" _ustr ) )
{
sResId = RID_STR_CLASS_SCROLLBAR;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFixedLineModel" _ustr ) )
{
sResId = RID_STR_CLASS_FIXEDLINE;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlDateFieldModel" _ustr ) )
{
sResId = RID_STR_CLASS_DATEFIELD;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlTimeFieldModel" _ustr ) )
{
sResId = RID_STR_CLASS_TIMEFIELD;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlNumericFieldModel" _ustr ) )
{
sResId = RID_STR_CLASS_NUMERICFIELD;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlCurrencyFieldModel" _ustr ) )
{
sResId = RID_STR_CLASS_CURRENCYFIELD;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFormattedFieldModel" _ustr ) )
{
sResId = RID_STR_CLASS_FORMATTEDFIELD;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlPatternFieldModel" _ustr ) )
{
sResId = RID_STR_CLASS_PATTERNFIELD;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFileControlModel" _ustr ) )
{
sResId = RID_STR_CLASS_FILECONTROL;
}
else if ( supportsService( u"com.sun.star.awt.tree.TreeControlModel" _ustr ) )
{
sResId = RID_STR_CLASS_TREECONTROL;
}
else if ( supportsService( u"com.sun.star.awt.grid.UnoControlGridModel" _ustr ) )
{
sResId = RID_STR_CLASS_GRIDCONTROL;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFixedHyperlinkModel" _ustr ) )
{
sResId = RID_STR_CLASS_HYPERLINKCONTROL;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlSpinButtonModel" _ustr ) )
{
sResId = RID_STR_CLASS_SPINCONTROL;
}
else
{
sResId = RID_STR_CLASS_CONTROL;
}
if (!sResId.isEmpty())
aDefaultName = sResId;
return aDefaultName;
}
OUString DlgEdObj::GetUniqueName() const
{
OUString aUniqueName;
uno::Reference< container::XNameAccess > xNameAcc((GetDlgEdForm()->GetUnoControlModel()), uno::UNO_QUERY);
if ( xNameAcc.is() )
{
sal_Int32 n = 0 ;
OUString aDefaultName = GetDefaultName();
do
{
aUniqueName = aDefaultName + OUString::number(++n);
} while (xNameAcc->hasByName(aUniqueName));
}
return aUniqueName;
}
SdrInventor DlgEdObj::GetObjInventor() const
{
return SdrInventor::BasicDialog;
}
SdrObjKind DlgEdObj::GetObjIdentifier() const
{
if ( supportsService( u"com.sun.star.awt.UnoControlDialogModel" _ustr ))
{
return SdrObjKind::BasicDialogDialog;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlButtonModel" _ustr ))
{
return SdrObjKind::BasicDialogPushButton;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlRadioButtonModel" _ustr ))
{
return SdrObjKind::BasicDialogRadioButton;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlCheckBoxModel" _ustr ))
{
return SdrObjKind::BasicDialogCheckbox;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlListBoxModel" _ustr ))
{
return SdrObjKind::BasicDialogListbox;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlComboBoxModel" _ustr ))
{
return SdrObjKind::BasicDialogCombobox;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlGroupBoxModel" _ustr ))
{
return SdrObjKind::BasicDialogGroupBox;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlEditModel" _ustr ))
{
return SdrObjKind::BasicDialogEdit;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFixedTextModel" _ustr ))
{
return SdrObjKind::BasicDialogFixedText;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlImageControlModel" _ustr ))
{
return SdrObjKind::BasicDialogImageControl;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlProgressBarModel" _ustr ))
{
return SdrObjKind::BasicDialogProgressbar;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlScrollBarModel" _ustr ))
{
return SdrObjKind::BasicDialogHorizontalScrollbar;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFixedLineModel" _ustr ))
{
return SdrObjKind::BasicDialogHorizontalFixedLine;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlDateFieldModel" _ustr ))
{
return SdrObjKind::BasicDialogDateField;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlTimeFieldModel" _ustr ))
{
return SdrObjKind::BasicDialogTimeField;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlNumericFieldModel" _ustr ))
{
return SdrObjKind::BasicDialogNumericField;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlCurrencyFieldModel" _ustr ))
{
return SdrObjKind::BasicDialogCurencyField;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFormattedFieldModel" _ustr ))
{
return SdrObjKind::BasicDialogFormattedField;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlPatternFieldModel" _ustr ))
{
return SdrObjKind::BasicDialogPatternField;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFileControlModel" _ustr ))
{
return SdrObjKind::BasicDialogFileControl;
}
else if ( supportsService( u"com.sun.star.awt.tree.TreeControlModel" _ustr ))
{
return SdrObjKind::BasicDialogTreeControl;
}
else if ( supportsService( u"com.sun.star.awt.grid.UnoControlGridModel" _ustr ))
{
return SdrObjKind::BasicDialogGridControl;
}
else if ( supportsService( u"com.sun.star.awt.UnoControlFixedHyperlinkModel" _ustr ))
{
return SdrObjKind::BasicDialogHyperlinkControl;
}
else
{
return SdrObjKind::BasicDialogControl;
}
}
rtl::Reference<SdrObject> DlgEdObj::CloneSdrObject(SdrModel& rTargetModel) const
{
return new DlgEdObj(rTargetModel, *this );
}
rtl::Reference<SdrObject> DlgEdObj::getFullDragClone() const
{
// no need to really add the clone for dragging, it's a temporary
// object
return rtl::Reference<SdrObject>(new SdrUnoObj(getSdrModelFromSdrObject(), *this ));
}
void DlgEdObj::NbcMove( const Size& rSize )
{
SdrUnoObj::NbcMove( rSize );
// stop listening
EndListening(false );
// set geometry properties
SetPropsFromRect();
// start listening
StartListening();
// dialog model changed
GetDlgEdForm()->GetDlgEditor().SetDialogModelChanged();
}
void DlgEdObj::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract)
{
SdrUnoObj::NbcResize( rRef, xFract, yFract );
// stop listening
EndListening(false );
// set geometry properties
SetPropsFromRect();
// start listening
StartListening();
// dialog model changed
GetDlgEdForm()->GetDlgEditor().SetDialogModelChanged();
}
bool DlgEdObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
{
bool bResult = SdrUnoObj::EndCreate(rStat, eCmd);
// tdf#120674 after interactive creation, the SdrObject (this) has no SdrPage yet
// due to not being inserted. Usually this should be handled in a ::handlePageChange
// implementation. For historical reasons, the SdrPage (which is the DlgEdPage) was
// already set. For now, get it from the SdrDragStat and use it to access and set
// the local pDlgEdForm
if (!pDlgEdForm && nullptr != rStat.GetPageView())
{
const DlgEdPage* pDlgEdPage(dynamic_cast <const DlgEdPage*>(rStat.GetPageView()->GetPage()));
if (nullptr != pDlgEdPage)
{
// set parent form
pDlgEdForm = pDlgEdPage->GetDlgEdForm();
}
}
SetDefaults();
StartListening();
return bResult;
}
void DlgEdObj::SetDefaults()
{
if ( !pDlgEdForm )
return ;
// add child to parent form
pDlgEdForm->AddChild( this );
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
if ( xPSet.is() )
{
// get unique name
OUString aOUniqueName( GetUniqueName() );
// set name property
xPSet->setPropertyValue( DLGED_PROP_NAME, Any(aOUniqueName) );
// set labels
if ( supportsService( u"com.sun.star.awt.UnoControlButtonModel" _ustr ) ||
supportsService( u"com.sun.star.awt.UnoControlRadioButtonModel" _ustr ) ||
supportsService( u"com.sun.star.awt.UnoControlCheckBoxModel" _ustr ) ||
supportsService( u"com.sun.star.awt.UnoControlGroupBoxModel" _ustr ) ||
supportsService( u"com.sun.star.awt.UnoControlFixedTextModel" _ustr ) )
{
xPSet->setPropertyValue( DLGED_PROP_LABEL, Any(aOUniqueName) );
}
// set number formats supplier for formatted field
if ( supportsService( u"com.sun.star.awt.UnoControlFormattedFieldModel" _ustr ) )
{
Reference< util::XNumberFormatsSupplier > xSupplier = GetDlgEdForm()->GetDlgEditor().GetNumberFormatsSupplier();
if ( xSupplier.is() )
{
xPSet->setPropertyValue( DLGED_PROP_FORMATSSUPPLIER, Any(xSupplier) );
}
}
// set geometry properties
SetPropsFromRect();
Reference< container::XNameContainer > xCont( GetDlgEdForm()->GetUnoControlModel() , UNO_QUERY );
if ( xCont.is() )
{
// set tabindex
Sequence< OUString > aNames = xCont->getElementNames();
uno::Any aTabIndex;
aTabIndex <<= static_cast <sal_Int16>(aNames.getLength());
xPSet->setPropertyValue( DLGED_PROP_TABINDEX, aTabIndex );
// set step
Reference< beans::XPropertySet > xPSetForm( xCont, UNO_QUERY );
if ( xPSetForm.is() )
{
Any aStep = xPSetForm->getPropertyValue( DLGED_PROP_STEP );
xPSet->setPropertyValue( DLGED_PROP_STEP, aStep );
}
// insert control model in dialog model
Reference< awt::XControlModel > xCtrl( xPSet , UNO_QUERY );
Any aAny;
aAny <<= xCtrl;
xCont->insertByName( aOUniqueName , aAny );
LocalizationMgr::setControlResourceIDsForNewEditorObject(
&GetDialogEditor(), aAny, aOUniqueName
);
pDlgEdForm->UpdateTabOrderAndGroups();
}
}
// dialog model changed
pDlgEdForm->GetDlgEditor().SetDialogModelChanged();
}
void DlgEdObj::StartListening()
{
DBG_ASSERT(!isListening(), "DlgEdObj::StartListening: already listening!" );
if (isListening())
return ;
bIsListening = true ;
// XPropertyChangeListener
Reference< XPropertySet > xControlModel( GetUnoControlModel() , UNO_QUERY );
if (!m_xPropertyChangeListener.is() && xControlModel.is())
{
// create listener
m_xPropertyChangeListener = new DlgEdPropListenerImpl(*this );
// register listener to properties
xControlModel->addPropertyChangeListener( OUString() , m_xPropertyChangeListener );
}
// XContainerListener
Reference< XScriptEventsSupplier > xEventsSupplier( GetUnoControlModel() , UNO_QUERY );
if ( !m_xContainerListener.is() && xEventsSupplier.is() )
{
// create listener
m_xContainerListener = new DlgEdEvtContListenerImpl(*this );
// register listener to script event container
Reference< XNameContainer > xEventCont = xEventsSupplier->getEvents();
DBG_ASSERT(xEventCont.is(), "DlgEdObj::StartListening: control model has no script event container!" );
Reference< XContainer > xCont( xEventCont , UNO_QUERY );
if (xCont.is())
xCont->addContainerListener( m_xContainerListener );
}
}
void DlgEdObj::EndListening(bool bRemoveListener)
{
DBG_ASSERT(isListening(), "DlgEdObj::EndListening: not listening currently!" );
if (!isListening())
return ;
bIsListening = false ;
if (!bRemoveListener)
return ;
// XPropertyChangeListener
Reference< XPropertySet > xControlModel(GetUnoControlModel(), UNO_QUERY);
if ( m_xPropertyChangeListener.is() && xControlModel.is() )
{
// remove listener
xControlModel->removePropertyChangeListener( OUString() , m_xPropertyChangeListener );
}
m_xPropertyChangeListener.clear();
// XContainerListener
Reference< XScriptEventsSupplier > xEventsSupplier( GetUnoControlModel() , UNO_QUERY );
if ( m_xContainerListener.is() && xEventsSupplier.is() )
{
// remove listener
Reference< XNameContainer > xEventCont = xEventsSupplier->getEvents();
DBG_ASSERT(xEventCont.is(), "DlgEdObj::EndListening: control model has no script event container!" );
Reference< XContainer > xCont( xEventCont , UNO_QUERY );
if (xCont.is())
xCont->removeContainerListener( m_xContainerListener );
}
m_xContainerListener.clear();
}
void DlgEdObj::_propertyChange( const css::beans::PropertyChangeEvent& evt )
{
if (!isListening())
return ;
DlgEdForm* pRealDlgEdForm = dynamic_cast <DlgEdForm*>(this );
if (!pRealDlgEdForm)
pRealDlgEdForm = GetDlgEdForm();
if (!pRealDlgEdForm)
return ;
DlgEditor& rDlgEditor = pRealDlgEdForm->GetDlgEditor();
if (rDlgEditor.isInPaint())
return ;
// dialog model changed
rDlgEditor.SetDialogModelChanged();
// update position and size
if ( evt.PropertyName == DLGED_PROP_POSITIONX || evt.PropertyName == DLGED_PROP_POSITIONY ||
evt.PropertyName == DLGED_PROP_WIDTH || evt.PropertyName == DLGED_PROP_HEIGHT ||
evt.PropertyName == DLGED_PROP_DECORATION )
{
PositionAndSizeChange( evt );
if ( evt.PropertyName == DLGED_PROP_DECORATION )
GetDialogEditor().ResetDialog();
}
// change name of control in dialog model
else if ( evt.PropertyName == DLGED_PROP_NAME )
{
if (!dynamic_cast <DlgEdForm*>(this ))
{
try
{
NameChange(evt);
}
catch (container::NoSuchElementException const &)
{
css::uno::Any anyEx = cppu::getCaughtException();
throw lang::WrappedTargetRuntimeException(u"" _ustr, nullptr,
anyEx);
}
}
}
// update step
else if ( evt.PropertyName == DLGED_PROP_STEP )
{
UpdateStep();
}
// change tabindex
else if ( evt.PropertyName == DLGED_PROP_TABINDEX )
{
if (!dynamic_cast <DlgEdForm*>(this ))
TabIndexChange(evt);
}
}
void DlgEdObj::_elementInserted()
{
if (isListening())
{
// dialog model changed
GetDialogEditor().SetDialogModelChanged();
}
}
void DlgEdObj::_elementReplaced()
{
if (isListening())
{
// dialog model changed
GetDialogEditor().SetDialogModelChanged();
}
}
void DlgEdObj::_elementRemoved()
{
if (isListening())
{
// dialog model changed
GetDialogEditor().SetDialogModelChanged();
}
}
void DlgEdObj::SetLayer(SdrLayerID nLayer)
{
SdrLayerID nOldLayer = GetLayer();
if ( nLayer != nOldLayer )
{
SdrUnoObj::SetLayer( nLayer );
DlgEdHint aHint( DlgEdHint::LAYERCHANGED, this );
GetDlgEdForm()->GetDlgEditor().Broadcast( aHint );
}
}
DlgEdForm::DlgEdForm(
SdrModel& rSdrModel,
DlgEditor& rDlgEditor_)
: DlgEdObj(rSdrModel),
rDlgEditor(rDlgEditor_)
{
}
DlgEdForm::~DlgEdForm()
{
}
void DlgEdForm::SetRectFromProps()
{
// get form position and size from properties
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
if ( !xPSet.is() )
return ;
sal_Int32 nXIn = 0 , nYIn = 0 , nWidthIn = 0 , nHeightIn = 0 ;
xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nXIn;
xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nYIn;
xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidthIn;
xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeightIn;
// transform coordinates
sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut;
if ( TransformFormToSdrCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) )
{
// set rectangle position and size
Point aPoint( nXOut, nYOut );
Size aSize( nWidthOut, nHeightOut );
SetSnapRect( tools::Rectangle( aPoint, aSize ) );
}
}
void DlgEdForm::SetPropsFromRect()
{
// get form position and size from rectangle
tools::Rectangle aRect_ = GetSnapRect();
sal_Int32 nXIn = aRect_.Left();
sal_Int32 nYIn = aRect_.Top();
sal_Int32 nWidthIn = aRect_.GetWidth();
sal_Int32 nHeightIn = aRect_.GetHeight();
// transform coordinates
sal_Int32 nXOut, nYOut, nWidthOut, nHeightOut;
if ( TransformSdrToFormCoordinates( nXIn, nYIn, nWidthIn, nHeightIn, nXOut, nYOut, nWidthOut, nHeightOut ) )
{
// set properties
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY );
if ( xPSet.is() )
{
xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nXOut) );
xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nYOut) );
xPSet->setPropertyValue( DLGED_PROP_WIDTH, Any(nWidthOut) );
xPSet->setPropertyValue( DLGED_PROP_HEIGHT, Any(nHeightOut) );
}
}
}
void DlgEdForm::AddChild( DlgEdObj* pDlgEdObj )
{
pChildren.push_back( pDlgEdObj );
}
void DlgEdForm::RemoveChild( DlgEdObj* pDlgEdObj )
{
std::erase(pChildren, pDlgEdObj);
}
void DlgEdForm::PositionAndSizeChange( const beans::PropertyChangeEvent& evt )
{
DlgEditor& rEditor = GetDlgEditor();
DlgEdPage& rPage = rEditor.GetPage();
sal_Int32 nPageXIn = 0 ;
sal_Int32 nPageYIn = 0 ;
Size aPageSize = rPage.GetSize();
sal_Int32 nPageWidthIn = aPageSize.Width();
sal_Int32 nPageHeightIn = aPageSize.Height();
sal_Int32 nPageX, nPageY, nPageWidth, nPageHeight;
if ( TransformSdrToFormCoordinates( nPageXIn, nPageYIn, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) )
{
Reference< beans::XPropertySet > xPSetForm( GetUnoControlModel(), UNO_QUERY );
if ( xPSetForm.is() )
{
sal_Int32 nValue = 0 ;
evt.NewValue >>= nValue;
sal_Int32 nNewValue = nValue;
if ( evt.PropertyName == DLGED_PROP_POSITIONX )
{
if ( nNewValue < nPageX )
nNewValue = nPageX;
}
else if ( evt.PropertyName == DLGED_PROP_POSITIONY )
{
if ( nNewValue < nPageY )
nNewValue = nPageY;
}
else if ( evt.PropertyName == DLGED_PROP_WIDTH )
{
if ( nNewValue < 1 )
nNewValue = 1 ;
}
else if ( evt.PropertyName == DLGED_PROP_HEIGHT )
{
if ( nNewValue < 1 )
nNewValue = 1 ;
}
if ( nNewValue != nValue )
{
EndListening( false );
xPSetForm->setPropertyValue( evt.PropertyName, Any(nNewValue) );
StartListening();
}
}
}
bool bAdjustedPageSize = rEditor.AdjustPageSize();
SetRectFromProps();
std::vector<DlgEdObj*> const & aChildList = GetChildren();
if ( bAdjustedPageSize )
{
rEditor.InitScrollBars();
aPageSize = rPage.GetSize();
nPageWidthIn = aPageSize.Width();
nPageHeightIn = aPageSize.Height();
if ( TransformSdrToControlCoordinates( nPageXIn, nPageYIn, nPageWidthIn, nPageHeightIn, nPageX, nPageY, nPageWidth, nPageHeight ) )
{
for (auto const & child : aChildList)
{
Reference< beans::XPropertySet > xPSet( child->GetUnoControlModel(), UNO_QUERY );
if ( xPSet.is() )
{
sal_Int32 nX = 0 , nY = 0 , nWidth = 0 , nHeight = 0 ;
xPSet->getPropertyValue( DLGED_PROP_POSITIONX ) >>= nX;
xPSet->getPropertyValue( DLGED_PROP_POSITIONY ) >>= nY;
xPSet->getPropertyValue( DLGED_PROP_WIDTH ) >>= nWidth;
xPSet->getPropertyValue( DLGED_PROP_HEIGHT ) >>= nHeight;
sal_Int32 nNewX = nX;
if ( nX + nWidth > nPageX + nPageWidth )
{
nNewX = nPageX + nPageWidth - nWidth;
if ( nNewX < nPageX )
nNewX = nPageX;
}
if ( nNewX != nX )
{
EndListening( false );
xPSet->setPropertyValue( DLGED_PROP_POSITIONX, Any(nNewX) );
StartListening();
}
sal_Int32 nNewY = nY;
if ( nY + nHeight > nPageY + nPageHeight )
{
nNewY = nPageY + nPageHeight - nHeight;
if ( nNewY < nPageY )
nNewY = nPageY;
}
if ( nNewY != nY )
{
EndListening( false );
xPSet->setPropertyValue( DLGED_PROP_POSITIONY, Any(nNewY) );
StartListening();
}
}
}
}
}
for (auto const & child : aChildList)
child->SetRectFromProps();
}
void DlgEdForm::UpdateStep()
{
SdrPage* pSdrPage = getSdrPageFromSdrObject();
if ( pSdrPage )
{
for (const rtl::Reference<SdrObject>& pObj : *pSdrPage)
{
DlgEdObj* pDlgEdObj = dynamic_cast <DlgEdObj*>(pObj.get());
if (pDlgEdObj && !dynamic_cast <DlgEdForm*>(pDlgEdObj))
pDlgEdObj->UpdateStep();
}
}
}
void DlgEdForm::UpdateTabIndices()
{
// stop listening with all children
for (auto const & child : pChildren)
{
child->EndListening( false );
}
Reference< css::container::XNameAccess > xNameAcc( GetUnoControlModel() , UNO_QUERY );
if ( xNameAcc.is() )
{
// get sequence of control names
// create a map of tab indices and control names, sorted by tab index
IndexToNameMap aIndexToNameMap;
for (auto & aName : xNameAcc->getElementNames())
{
// get tab index
sal_Int16 nTabIndex = -1 ;
Any aCtrl = xNameAcc->getByName( aName );
Reference< css::beans::XPropertySet > xPSet;
aCtrl >>= xPSet;
if ( xPSet.is() )
xPSet->getPropertyValue( DLGED_PROP_TABINDEX ) >>= nTabIndex;
// insert into map
aIndexToNameMap.emplace( nTabIndex, aName );
}
// set new tab indices
sal_Int16 nNewTabIndex = 0 ;
for (auto const & indexToName : aIndexToNameMap)
{
Any aCtrl = xNameAcc->getByName( indexToName.second );
Reference< beans::XPropertySet > xPSet;
aCtrl >>= xPSet;
if ( xPSet.is() )
{
xPSet->setPropertyValue( DLGED_PROP_TABINDEX, Any(nNewTabIndex) );
nNewTabIndex++;
}
}
UpdateTabOrderAndGroups();
}
// start listening with all children
for (auto const & child : pChildren)
{
child->StartListening();
}
}
void DlgEdForm::UpdateTabOrder()
{
// When the tabindex of a control model changes, the dialog control is
// notified about those changes. Due to #109067# (bad performance of
// dialog editor) the dialog control doesn't activate the tab order
// in design mode. When the dialog editor has reordered all
// tabindices, this method allows to activate the taborder afterwards.
Reference< awt::XUnoControlContainer > xCont( GetControl(), UNO_QUERY );
if ( xCont.is() )
{
for (auto & xTabController : xCont->getTabControllers())
xTabController->activateTabOrder();
}
}
void DlgEdForm::UpdateGroups()
{
// The grouping of radio buttons in a dialog is done by vcl.
// In the dialog editor we have two views (=controls) for one
// radio button model. One control is owned by the dialog control,
// but not visible in design mode. The other control is owned by
// the drawing layer object. Whereas the grouping of the first
// control is done by vcl, the grouping of the control in the
// drawing layer has to be done here.
Reference< awt::XTabControllerModel > xTabModel( GetUnoControlModel() , UNO_QUERY );
if ( !xTabModel.is() )
return ;
// create a global list of controls that belong to the dialog
std::vector<DlgEdObj*> aChildList = GetChildren();
sal_uInt32 nSize = aChildList.size();
Sequence< Reference< awt::XControl > > aSeqControls( nSize );
auto * pSeqControlsData = aSeqControls.getArray();
for ( sal_uInt32 i = 0 ; i < nSize; ++i )
pSeqControlsData[i] = aChildList[i]->GetControl();
sal_Int32 nGroupCount = xTabModel->getGroupCount();
for ( sal_Int32 nGroup = 0 ; nGroup < nGroupCount; ++nGroup )
{
// get a list of control models that belong to this group
OUString aName;
Sequence< Reference< awt::XControlModel > > aSeqModels;
xTabModel->getGroup( nGroup, aSeqModels, aName );
sal_Int32 nModelCount = aSeqModels.getLength();
// create a list of peers that belong to this group
Sequence< Reference< awt::XWindow > > aSeqPeers( nModelCount );
auto * pSeqPeersData = aSeqPeers.getArray();
for ( sal_Int32 nModel = 0 ; nModel < nModelCount; ++nModel )
{
// for each control model find the corresponding control in the global list
for (auto & xCtrl : aSeqControls)
{
if ( xCtrl.is() )
{
Reference< awt::XControlModel > xCtrlModel( xCtrl->getModel() );
if (xCtrlModel.get() == aSeqModels[nModel].get())
{
// get the control peer and insert into the list of peers
pSeqPeersData[nModel].set(xCtrl->getPeer(), UNO_QUERY);
break ;
}
}
}
}
// set the group at the dialog peer
Reference< awt::XControl > xDlg = GetControl();
if ( xDlg.is() )
{
Reference< awt::XVclContainerPeer > xDlgPeer( xDlg->getPeer(), UNO_QUERY );
if ( xDlgPeer.is() )
xDlgPeer->setGroup( aSeqPeers );
}
}
}
void DlgEdForm::UpdateTabOrderAndGroups()
{
UpdateTabOrder();
UpdateGroups();
}
void DlgEdForm::NbcMove( const Size& rSize )
{
SdrUnoObj::NbcMove( rSize );
// set geometry properties of form
EndListening(false );
SetPropsFromRect();
StartListening();
// set geometry properties of all children
for (auto const & child : pChildren)
{
child->EndListening(false );
child->SetPropsFromRect();
child->StartListening();
}
// dialog model changed
GetDlgEditor().SetDialogModelChanged();
}
void DlgEdForm::NbcResize(const Point& rRef, const Fraction& xFract, const Fraction& yFract)
{
SdrUnoObj::NbcResize( rRef, xFract, yFract );
// set geometry properties of form
EndListening(false );
SetPropsFromRect();
StartListening();
// set geometry properties of all children
for (auto const & child : pChildren)
{
child->EndListening(false );
child->SetPropsFromRect();
child->StartListening();
}
// dialog model changed
GetDlgEditor().SetDialogModelChanged();
}
bool DlgEdForm::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
{
bool bResult = SdrUnoObj::EndCreate(rStat, eCmd);
// stop listening
EndListening(false );
// set geometry properties
SetPropsFromRect();
// dialog model changed
GetDlgEditor().SetDialogModelChanged();
// start listening
StartListening();
return bResult;
}
awt::DeviceInfo DlgEdForm::getDeviceInfo() const
{
awt::DeviceInfo aDeviceInfo;
DlgEditor& rEditor = GetDlgEditor();
vcl::Window& rWindow = rEditor.GetWindow();
// obtain an XControl
::utl::SharedUNOComponent< awt::XControl > xDialogControl; // ensures auto-disposal, if needed
xDialogControl.reset( GetControl(), ::utl::SharedUNOComponent< awt::XControl >::NoTakeOwnership );
if ( !xDialogControl.is() )
{
// don't create a temporary control all the time, this method here is called
// way too often. Instead, use a cached DeviceInfo.
// #i74065#
if ( !!mpDeviceInfo )
return *mpDeviceInfo;
Reference< awt::XControlContainer > xEditorControlContainer( rEditor.GetWindowControlContainer() );
xDialogControl.reset(
GetTemporaryControlForWindow(rWindow, xEditorControlContainer),
utl::SharedUNOComponent< awt::XControl >::TakeOwnership
);
}
Reference< awt::XDevice > xDialogDevice;
if ( xDialogControl.is() )
xDialogDevice.set( xDialogControl->getPeer(), UNO_QUERY );
DBG_ASSERT( xDialogDevice.is(), "DlgEdForm::getDeviceInfo: no device!" );
if ( xDialogDevice.is() )
aDeviceInfo = xDialogDevice->getInfo();
mpDeviceInfo = aDeviceInfo;
return aDeviceInfo;
}
void DlgEdObj::MakeDataAware( const Reference< frame::XModel >& xModel )
{
// Need to flesh this out, currently we will only support data-aware controls for calc
// and only handle a subset of functionality e.g. linked-cell and cell range data source. Of course later
// we need to disambiguate for writer ( and others ? ) and also support the generic form (db) bindings
// we need some more work in xmlscript to be able to handle that
Reference< lang::XMultiServiceFactory > xFac( xModel, UNO_QUERY );
Reference< form::binding::XBindableValue > xBindable( GetUnoControlModel(), UNO_QUERY );
Reference< form::binding::XListEntrySink > xListEntrySink( GetUnoControlModel(), UNO_QUERY );
if ( !xFac.is() )
return ;
//tdf#90361 and tdf#104011 CellValueBinding and CellRangeListSource are unusable
//without being initialized, so use createInstanceWithArguments with a
//dummy BoundCell and CellRange instead of createInstance. This at least results in
//the dialog editor not falling.
css::beans::NamedValue aCellValue;
aCellValue.Name = "BoundCell" ;
css::table::CellAddress aCellAddress;
aCellValue.Value <<= aCellAddress;
css::beans::NamedValue aCellRange;
aCellRange.Name = "CellRange" ;
css::table::CellRangeAddress aRangeAddress;
aCellRange.Value <<= aRangeAddress;
Sequence< Any > aArgs{ Any(aCellValue), Any(aCellRange) };
if ( xBindable.is() )
{
Reference< form::binding::XValueBinding > xBinding( xFac->createInstanceWithArguments( u"com.sun.star.table.CellValueBinding" _ustr, aArgs ), UNO_QUERY );
xBindable->setValueBinding( xBinding );
}
if ( xListEntrySink.is() )
{
Reference< form::binding::XListEntrySource > xSource( xFac->createInstanceWithArguments( u"com.sun.star.table.CellRangeListSource" _ustr, aArgs ), UNO_QUERY );
xListEntrySink->setListEntrySource( xSource );
}
}
} // namespace basctl
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=92 H=96 G=93
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-09-27)
¤
*© Formatika GbR, Deutschland