/* -*- 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 .
*/
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 );
}
}
// set out parameters
nXOut = aPos.Width();
nYOut = aPos.Height();
nWidthOut = aSize.Width();
nHeightOut = aSize.Height();
returntrue;
}
void DlgEdObj::SetRectFromProps()
{ // get control position and size from properties
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); if ( !xPSet.is() ) 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();
}
}
// stop listening with all children
std::vector<DlgEdObj*> aChildList = pForm->GetChildren(); for (autoconst& 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; elseif ( 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 >( )
);
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));
}
// 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 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 );
void DlgEdForm::SetRectFromProps()
{ // get form position and size from properties
Reference< beans::XPropertySet > xPSet( GetUnoControlModel(), UNO_QUERY ); if ( !xPSet.is() ) return;
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 (autoconst& 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 (autoconst& 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 (autoconst& 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.
// 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 );
}
}
}
// set geometry properties of form
EndListening(false);
SetPropsFromRect();
StartListening();
// set geometry properties of all children for (autoconst& child : pChildren)
{
child->EndListening(false);
child->SetPropsFromRect();
child->StartListening();
}
// dialog model changed
GetDlgEditor().SetDialogModelChanged();
}
// set geometry properties of form
EndListening(false);
SetPropsFromRect();
StartListening();
// set geometry properties of all children for (autoconst& child : pChildren)
{
child->EndListening(false);
child->SetPropsFromRect();
child->StartListening();
}
// dialog model changed
GetDlgEditor().SetDialogModelChanged();
}
// 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::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;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.