forked from amazingfate/loongoffice
Also simplify parent/child relationships, get rid of double data (SdrPage/Parent infos in SdrObjects, also in SdrObjList). This is all not needed - when a SdrObject is inserted to a SdrPage, get SdrPage by traveling over parents (no double info, member as soon as inserted, ...). More cleanups/reworks included, will need some more cleanups, too. Stabilizing: SetRectsDirty/DefaultStyleSheet Had to correct the SetRectsDirty stuff for 3D due to going down the hierarchy while the 2D implementation goes the other direction -> endless loops. Added special handling for 3D stuff for now (will be chnaged again when SnapRect is no longer needed at SdrObject level). Also had to adapt how the DefaultStyleSheet is set at incarnated SdrObjects - better: their properties. Since we now always have a SdrModel, it is possible to correctly initialize with the correct default StyleSheet from that SdrModel. This needs to be done after ForceDefaultAttributes and in a way that again deletes Items that are set in the StyleSheet. This leads to an error in CppunitTest_sd_import_tests where I checked tdf100491 - it is okay and thus I change the control instance of the imported, XML-dumped file. The less hard attributes, the better for Styles in general. Cleanup of comments for last two commits Corrected SvxShape::getParent() Needed to get the direct parent, so test for SdrObject first (to get SdrObjGroup/E3DScene), for SdrPage second Fixed CppunitTest_sc_subsequent_export_test Several problems arose. The used SdrCaptionObj was Cloned, but the clone not inserted to a SdrPage. This leads to not being able to access a UNO API imlementation of the SdrPage (SvxPage) on lower levels. It worked before due to SdrObject having a SdrPage* additionally to being added to a SdrPage - this is exactly the main cleanup this change does. Looked for why it is cloned, could see no reasons. The SdrCaptionObj exists during all im/export, not difference to other SdrObjects (that do not get cloned). It is not changed in any way. It *might* be to suppress a crash that happened due to UNO API Service emfio/emfio not being available in the UnitTest scenario. Interestingly it did not crash with the cloned SdrCaptionObj, but the Graphic exported was probably wrong. Fixed by no longer Cloning the SdrCaptionObj and adding emfio/emfio UNO API Service. d139f821a5b39535a3e7b9c6261df7e18f8ae8ac 910e7f4bc628a715fda7545dffaf3369d5e76ea0 ca1de01b723051e09ac37d7ec7bba978beea41c5 3a76da1471dfe75e69847f64a6a3519ad21c8c9c Change-Id: I986586e326b563acebf00d931a7084c6eb09e5f8 Reviewed-on: https://gerrit.libreoffice.org/54689 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
654 lines
22 KiB
C++
654 lines
22 KiB
C++
/* -*- 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 <SelectionHelper.hxx>
|
|
#include <ObjectIdentifier.hxx>
|
|
#include <DiagramHelper.hxx>
|
|
#include <ChartModelHelper.hxx>
|
|
|
|
#include <svx/svdpage.hxx>
|
|
#include <svx/svditer.hxx>
|
|
#include <svx/obj3d.hxx>
|
|
#include <svx/svdopath.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <basegfx/point/b2dpoint.hxx>
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
|
|
namespace chart
|
|
{
|
|
using namespace ::com::sun::star;
|
|
|
|
namespace
|
|
{
|
|
|
|
OUString lcl_getObjectName( SdrObject const * pObj )
|
|
{
|
|
if(pObj)
|
|
return pObj->GetName();
|
|
return OUString();
|
|
}
|
|
|
|
void impl_selectObject( SdrObject* pObjectToSelect, DrawViewWrapper& rDrawViewWrapper )
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
|
|
if(pObjectToSelect)
|
|
{
|
|
SelectionHelper aSelectionHelper( pObjectToSelect );
|
|
SdrObject* pMarkObj = aSelectionHelper.getObjectToMark();
|
|
rDrawViewWrapper.setMarkHandleProvider(&aSelectionHelper);
|
|
rDrawViewWrapper.MarkObject(pMarkObj);
|
|
rDrawViewWrapper.setMarkHandleProvider(nullptr);
|
|
}
|
|
}
|
|
|
|
}//anonymous namespace
|
|
|
|
bool Selection::hasSelection()
|
|
{
|
|
return m_aSelectedOID.isValid();
|
|
}
|
|
|
|
OUString const & Selection::getSelectedCID()
|
|
{
|
|
return m_aSelectedOID.getObjectCID();
|
|
}
|
|
|
|
uno::Reference< drawing::XShape > const & Selection::getSelectedAdditionalShape()
|
|
{
|
|
return m_aSelectedOID.getAdditionalShape();
|
|
}
|
|
|
|
bool Selection::setSelection( const OUString& rCID )
|
|
{
|
|
if ( rCID != m_aSelectedOID.getObjectCID() )
|
|
{
|
|
m_aSelectedOID = ObjectIdentifier( rCID );
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Selection::setSelection( const uno::Reference< drawing::XShape >& xShape )
|
|
{
|
|
if ( !( xShape == m_aSelectedOID.getAdditionalShape() ) )
|
|
{
|
|
clearSelection();
|
|
m_aSelectedOID = ObjectIdentifier( xShape );
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Selection::clearSelection()
|
|
{
|
|
m_aSelectedOID = ObjectIdentifier();
|
|
m_aSelectedOID_beforeMouseDown = ObjectIdentifier();
|
|
m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
|
|
}
|
|
|
|
bool Selection::maybeSwitchSelectionAfterSingleClickWasEnsured()
|
|
{
|
|
if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid()
|
|
&& m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing != m_aSelectedOID )
|
|
{
|
|
m_aSelectedOID = m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing;
|
|
m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Selection::resetPossibleSelectionAfterSingleClickWasEnsured()
|
|
{
|
|
if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
|
|
{
|
|
m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
|
|
}
|
|
}
|
|
|
|
void Selection::remindSelectionBeforeMouseDown()
|
|
{
|
|
m_aSelectedOID_beforeMouseDown = m_aSelectedOID;
|
|
}
|
|
|
|
bool Selection::isSelectionDifferentFromBeforeMouseDown() const
|
|
{
|
|
return ( m_aSelectedOID != m_aSelectedOID_beforeMouseDown );
|
|
}
|
|
|
|
void Selection::applySelection( DrawViewWrapper* pDrawViewWrapper )
|
|
{
|
|
if( pDrawViewWrapper )
|
|
{
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
pDrawViewWrapper->UnmarkAll();
|
|
}
|
|
SdrObject* pObjectToSelect = nullptr;
|
|
if ( m_aSelectedOID.isAutoGeneratedObject() )
|
|
{
|
|
pObjectToSelect = pDrawViewWrapper->getNamedSdrObject( m_aSelectedOID.getObjectCID() );
|
|
}
|
|
else if( m_aSelectedOID.isAdditionalShape() )
|
|
{
|
|
pObjectToSelect = DrawViewWrapper::getSdrObject( m_aSelectedOID.getAdditionalShape() );
|
|
}
|
|
|
|
impl_selectObject( pObjectToSelect, *pDrawViewWrapper );
|
|
}
|
|
}
|
|
|
|
void Selection::adaptSelectionToNewPos( const Point& rMousePos, DrawViewWrapper const * pDrawViewWrapper
|
|
, bool bIsRightMouse, bool bWaitingForDoubleClick )
|
|
{
|
|
if( pDrawViewWrapper )
|
|
{
|
|
//do not toggle multiclick selection if right clicked on the selected object or waiting for double click
|
|
bool bAllowMultiClickSelectionChange = !bIsRightMouse && !bWaitingForDoubleClick;
|
|
|
|
ObjectIdentifier aLastSelectedObject( m_aSelectedOID );
|
|
|
|
SolarMutexGuard aSolarGuard;
|
|
|
|
//bAllowMultiClickSelectionChange==true -> a second click on the same object can lead to a changed selection (e.g. series -> single data point)
|
|
|
|
//get object to select:
|
|
{
|
|
m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
|
|
|
|
//the search for the object to select starts with the hit object deepest in the grouping hierarchy (a leaf in the tree)
|
|
//further we travel along the grouping hierarchy from child to parent
|
|
SdrObject* pNewObj = pDrawViewWrapper->getHitObject(rMousePos);
|
|
m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );//name of pNewObj
|
|
|
|
//ignore handle only objects for hit test
|
|
while( pNewObj && m_aSelectedOID.getObjectCID().match( "HandlesOnly" ) )
|
|
{
|
|
pNewObj->SetMarkProtect(true);
|
|
pNewObj = pDrawViewWrapper->getHitObject(rMousePos);
|
|
m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );
|
|
}
|
|
|
|
//accept only named objects while searching for the object to select
|
|
//this call may change m_aSelectedOID
|
|
if ( SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, true ) )
|
|
{
|
|
//if the so far found object is a multi click object further steps are necessary
|
|
while( ObjectIdentifier::isMultiClickObject( m_aSelectedOID.getObjectCID() ) )
|
|
{
|
|
bool bSameObjectAsLastSelected = ( aLastSelectedObject == m_aSelectedOID );
|
|
if( bSameObjectAsLastSelected )
|
|
{
|
|
//if the same child is clicked again don't go up further
|
|
break;
|
|
}
|
|
if ( ObjectIdentifier::areSiblings( aLastSelectedObject.getObjectCID(), m_aSelectedOID.getObjectCID() ) )
|
|
{
|
|
//if a sibling of the last selected object is clicked don't go up further
|
|
break;
|
|
}
|
|
ObjectIdentifier aLastChild = m_aSelectedOID;
|
|
if ( !SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, false ) )
|
|
{
|
|
//take the one found so far
|
|
break;
|
|
}
|
|
//if the last selected object is found don't go up further
|
|
//but take the last child if selection change is allowed
|
|
if ( aLastSelectedObject == m_aSelectedOID )
|
|
{
|
|
if( bAllowMultiClickSelectionChange )
|
|
{
|
|
m_aSelectedOID = aLastChild;
|
|
}
|
|
else
|
|
m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = aLastChild;
|
|
break;
|
|
}
|
|
}
|
|
|
|
OSL_ENSURE(m_aSelectedOID.isValid(), "somehow lost selected object");
|
|
}
|
|
else
|
|
{
|
|
//maybe an additional shape was hit
|
|
if ( pNewObj )
|
|
{
|
|
m_aSelectedOID = ObjectIdentifier( uno::Reference< drawing::XShape >( pNewObj->getUnoShape(), uno::UNO_QUERY ) );
|
|
}
|
|
else
|
|
{
|
|
m_aSelectedOID = ObjectIdentifier();
|
|
}
|
|
}
|
|
|
|
if ( !m_aSelectedOID.isAdditionalShape() )
|
|
{
|
|
OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) );//@todo read CID from model
|
|
|
|
if ( !m_aSelectedOID.isAutoGeneratedObject() )
|
|
{
|
|
m_aSelectedOID = ObjectIdentifier( aPageCID );
|
|
}
|
|
|
|
//check whether the diagram was hit but not selected (e.g. because it has no filling):
|
|
OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
|
|
OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );//@todo read CID from model
|
|
bool bBackGroundHit = m_aSelectedOID.getObjectCID() == aPageCID || m_aSelectedOID.getObjectCID() == aWallCID || !m_aSelectedOID.isAutoGeneratedObject();
|
|
if( bBackGroundHit )
|
|
{
|
|
//todo: if more than one diagram is available in future do check the list of all diagrams here
|
|
SdrObject* pDiagram = pDrawViewWrapper->getNamedSdrObject( aDiagramCID );
|
|
if( pDiagram )
|
|
{
|
|
if( DrawViewWrapper::IsObjectHit( pDiagram, rMousePos ) )
|
|
{
|
|
m_aSelectedOID = ObjectIdentifier( aDiagramCID );
|
|
}
|
|
}
|
|
}
|
|
//check whether the legend was hit but not selected (e.g. because it has no filling):
|
|
if( bBackGroundHit || m_aSelectedOID.getObjectCID() == aDiagramCID )
|
|
{
|
|
OUString aLegendCID( ObjectIdentifier::createClassifiedIdentifierForParticle( ObjectIdentifier::createParticleForLegend(nullptr) ) );//@todo read CID from model
|
|
SdrObject* pLegend = pDrawViewWrapper->getNamedSdrObject( aLegendCID );
|
|
if( pLegend )
|
|
{
|
|
if( DrawViewWrapper::IsObjectHit( pLegend, rMousePos ) )
|
|
{
|
|
m_aSelectedOID = ObjectIdentifier( aLegendCID );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( bIsRightMouse && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
|
|
{
|
|
m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Selection::isResizeableObjectSelected()
|
|
{
|
|
ObjectType eObjectType = m_aSelectedOID.getObjectType();
|
|
switch( eObjectType )
|
|
{
|
|
case OBJECTTYPE_DIAGRAM:
|
|
case OBJECTTYPE_DIAGRAM_WALL:
|
|
case OBJECTTYPE_SHAPE:
|
|
case OBJECTTYPE_LEGEND:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Selection::isRotateableObjectSelected( const uno::Reference< frame::XModel >& xChartModel )
|
|
{
|
|
return SelectionHelper::isRotateableObject( m_aSelectedOID.getObjectCID(), xChartModel );
|
|
}
|
|
|
|
bool Selection::isDragableObjectSelected()
|
|
{
|
|
return m_aSelectedOID.isDragableObject();
|
|
}
|
|
|
|
bool Selection::isAdditionalShapeSelected() const
|
|
{
|
|
return m_aSelectedOID.isAdditionalShape();
|
|
}
|
|
|
|
bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject
|
|
, OUString& rOutName
|
|
, bool bGivenObjectMayBeResult )
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
//find the deepest named group
|
|
SdrObject* pObj = pInOutObject;
|
|
OUString aName;
|
|
if( bGivenObjectMayBeResult )
|
|
aName = lcl_getObjectName( pObj );
|
|
|
|
while( pObj && !ObjectIdentifier::isCID( aName ) )
|
|
{
|
|
SdrObjList* pObjList = pObj->getParentOfSdrObject();
|
|
if( !pObjList )
|
|
return false;
|
|
SdrObject* pOwner = pObjList->getSdrObjectFromSdrObjList();
|
|
if( !pOwner )
|
|
return false;
|
|
pObj = pOwner;
|
|
aName = lcl_getObjectName( pObj );
|
|
}
|
|
|
|
if(!pObj)
|
|
return false;
|
|
if(aName.isEmpty())
|
|
return false;
|
|
|
|
pInOutObject = pObj;
|
|
rOutName = aName;
|
|
return true;
|
|
}
|
|
|
|
bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject
|
|
, ObjectIdentifier& rOutObject
|
|
, bool bGivenObjectMayBeResult )
|
|
{
|
|
OUString aName;
|
|
if ( findNamedParent( pInOutObject, aName, bGivenObjectMayBeResult ) )
|
|
{
|
|
rOutObject = ObjectIdentifier( aName );
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SelectionHelper::isDragableObjectHitTwice( const Point& rMPos
|
|
, const OUString& rNameOfSelectedObject
|
|
, const DrawViewWrapper& rDrawViewWrapper )
|
|
{
|
|
if(rNameOfSelectedObject.isEmpty())
|
|
return false;
|
|
if( !ObjectIdentifier::isDragableObject(rNameOfSelectedObject) )
|
|
return false;
|
|
SolarMutexGuard aSolarGuard;
|
|
SdrObject* pObj = rDrawViewWrapper.getNamedSdrObject( rNameOfSelectedObject );
|
|
return DrawViewWrapper::IsObjectHit( pObj, rMPos );
|
|
}
|
|
|
|
OUString SelectionHelper::getHitObjectCID(
|
|
const Point& rMPos,
|
|
DrawViewWrapper const & rDrawViewWrapper,
|
|
bool bGetDiagramInsteadOf_Wall )
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
OUString aRet;
|
|
|
|
SdrObject* pNewObj = rDrawViewWrapper.getHitObject(rMPos);
|
|
aRet = lcl_getObjectName( pNewObj );//name of pNewObj
|
|
|
|
//ignore handle only objects for hit test
|
|
while( pNewObj && aRet.match("HandlesOnly") )
|
|
{
|
|
pNewObj->SetMarkProtect(true);
|
|
pNewObj = rDrawViewWrapper.getHitObject(rMPos);
|
|
aRet = lcl_getObjectName( pNewObj );
|
|
}
|
|
|
|
//accept only named objects while searching for the object to select
|
|
if( !findNamedParent( pNewObj, aRet, true ) )
|
|
{
|
|
aRet.clear();
|
|
}
|
|
|
|
OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) );//@todo read CID from model
|
|
//get page when nothing was hit
|
|
if( aRet.isEmpty() && !pNewObj )
|
|
{
|
|
aRet = aPageCID;
|
|
}
|
|
|
|
//get diagram instead wall or page if hit inside diagram
|
|
if( !aRet.isEmpty() )
|
|
{
|
|
if( aRet == aPageCID )
|
|
{
|
|
OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
|
|
//todo: if more than one diagram is available in future do check the list of all diagrams here
|
|
SdrObject* pDiagram = rDrawViewWrapper.getNamedSdrObject( aDiagramCID );
|
|
if( pDiagram )
|
|
{
|
|
if( DrawViewWrapper::IsObjectHit( pDiagram, rMPos ) )
|
|
{
|
|
aRet = aDiagramCID;
|
|
}
|
|
}
|
|
}
|
|
else if( bGetDiagramInsteadOf_Wall )
|
|
{
|
|
OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );//@todo read CID from model
|
|
|
|
if( aRet == aWallCID )
|
|
{
|
|
OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
|
|
aRet = aDiagramCID;
|
|
}
|
|
}
|
|
}
|
|
|
|
return aRet;
|
|
// \\- solar mutex
|
|
}
|
|
|
|
bool SelectionHelper::isRotateableObject( const OUString& rCID
|
|
, const uno::Reference< frame::XModel >& xChartModel )
|
|
{
|
|
if( !ObjectIdentifier::isRotateableObject( rCID ) )
|
|
return false;
|
|
|
|
sal_Int32 nDimensionCount = DiagramHelper::getDimension( ChartModelHelper::findDiagram( xChartModel ) );
|
|
|
|
return nDimensionCount == 3;
|
|
}
|
|
|
|
SelectionHelper::SelectionHelper( SdrObject* pSelectedObj )
|
|
: m_pSelectedObj( pSelectedObj ), m_pMarkObj(nullptr)
|
|
{
|
|
|
|
}
|
|
SelectionHelper::~SelectionHelper()
|
|
{
|
|
}
|
|
|
|
bool SelectionHelper::getFrameDragSingles()
|
|
{
|
|
bool bFrameDragSingles = true;//true == green == surrounding handles
|
|
if( m_pSelectedObj && dynamic_cast<const E3dObject*>( m_pSelectedObj) != nullptr )
|
|
bFrameDragSingles = false;
|
|
return bFrameDragSingles;
|
|
}
|
|
|
|
SdrObject* SelectionHelper::getMarkHandlesObject( SdrObject* pObj )
|
|
{
|
|
if(!pObj)
|
|
return nullptr;
|
|
OUString aName( lcl_getObjectName( pObj ) );
|
|
if( aName.match("MarkHandles") || aName.match("HandlesOnly") )
|
|
return pObj;
|
|
if( !aName.isEmpty() )//don't get the markhandles of a different object
|
|
return nullptr;
|
|
|
|
//search for a child with name "MarkHandles" or "HandlesOnly"
|
|
SolarMutexGuard aSolarGuard;
|
|
SdrObjList* pSubList = pObj->GetSubList();
|
|
if(pSubList)
|
|
{
|
|
SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
|
|
while (aIterator.IsMore())
|
|
{
|
|
SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() );
|
|
if( pMarkHandles )
|
|
return pMarkHandles;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
SdrObject* SelectionHelper::getObjectToMark()
|
|
{
|
|
//return the selected object itself
|
|
//or a specific other object if that exsists
|
|
SdrObject* pObj = m_pSelectedObj;
|
|
m_pMarkObj = pObj;
|
|
|
|
//search for a child with name "MarkHandles" or "HandlesOnly"
|
|
if(pObj)
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
SdrObjList* pSubList = pObj->GetSubList();
|
|
if(pSubList)
|
|
{
|
|
SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
|
|
while (aIterator.IsMore())
|
|
{
|
|
SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() );
|
|
if( pMarkHandles )
|
|
{
|
|
m_pMarkObj = pMarkHandles;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return m_pMarkObj;
|
|
}
|
|
|
|
E3dScene* SelectionHelper::getSceneToRotate( SdrObject* pObj )
|
|
{
|
|
//search whether the object or one of its children is a 3D object
|
|
//if so, return the accessory 3DScene
|
|
|
|
E3dObject* pRotateable = nullptr;
|
|
|
|
if(pObj)
|
|
{
|
|
pRotateable = dynamic_cast<E3dObject*>(pObj);
|
|
if( !pRotateable )
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
SdrObjList* pSubList = pObj->GetSubList();
|
|
if(pSubList)
|
|
{
|
|
SdrObjListIter aIterator(pSubList, SdrIterMode::DeepWithGroups);
|
|
while( aIterator.IsMore() && !pRotateable )
|
|
{
|
|
SdrObject* pSubObj = aIterator.Next();
|
|
pRotateable = dynamic_cast<E3dObject*>(pSubObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
E3dScene* pScene = nullptr;
|
|
if(pRotateable)
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
pScene = pRotateable->GetScene();
|
|
}
|
|
return pScene;
|
|
|
|
}
|
|
|
|
bool SelectionHelper::getMarkHandles( SdrHdlList& rHdlList )
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
|
|
//@todo -> more flexible handle creation
|
|
//2 scenarios possible:
|
|
//1. add an additional invisible shape as a child to the selected object
|
|
//this child needs to be named somehow and handles need to be generated therefrom ...
|
|
//or 2. offer a central service per view where renderer and so can register for handle creation for a special shape
|
|
//.. or 3. feature from drawinglayer to create handles for each shape ... (bad performance ... ?) ?
|
|
|
|
//scenario 1 is now used:
|
|
//if a child with name MarkHandles exsists
|
|
//this child is marked instead of the logical selected object
|
|
|
|
/*
|
|
//if a special mark object was found
|
|
//that object should be used for marking only
|
|
if( m_pMarkObj != m_pSelectedObj)
|
|
return false;
|
|
*/
|
|
//if a special mark object was found
|
|
//that object should be used to create handles from
|
|
if( m_pMarkObj && m_pMarkObj != m_pSelectedObj)
|
|
{
|
|
rHdlList.Clear();
|
|
if( dynamic_cast<const SdrPathObj*>( m_pMarkObj) != nullptr )
|
|
{
|
|
//if th object is a polygon
|
|
//from each point a handle is generated
|
|
const ::basegfx::B2DPolyPolygon& rPolyPolygon = static_cast<SdrPathObj*>(m_pMarkObj)->GetPathPoly();
|
|
for( sal_uInt32 nN = 0; nN < rPolyPolygon.count(); nN++)
|
|
{
|
|
const ::basegfx::B2DPolygon aPolygon(rPolyPolygon.getB2DPolygon(nN));
|
|
for( sal_uInt32 nM = 0; nM < aPolygon.count(); nM++)
|
|
{
|
|
const ::basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(nM));
|
|
SdrHdl* pHdl = new SdrHdl(Point(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY())), SdrHdlKind::Poly);
|
|
rHdlList.AddHdl(pHdl);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
return false; //use the special MarkObject for marking
|
|
}
|
|
|
|
//@todo:
|
|
//add and document good marking defaults ...
|
|
|
|
rHdlList.Clear();
|
|
|
|
SdrObject* pObj = m_pSelectedObj;
|
|
if(!pObj)
|
|
return false;
|
|
SdrObjList* pSubList = pObj->GetSubList();
|
|
if( !pSubList )//no group object !pObj->IsGroupObject()
|
|
return false;
|
|
|
|
OUString aName( lcl_getObjectName( pObj ) );
|
|
ObjectType eObjectType( ObjectIdentifier::getObjectType( aName ) );
|
|
if( eObjectType == OBJECTTYPE_DATA_POINT
|
|
|| eObjectType == OBJECTTYPE_DATA_LABEL
|
|
|| eObjectType == OBJECTTYPE_LEGEND_ENTRY
|
|
|| eObjectType == OBJECTTYPE_AXIS_UNITLABEL )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
|
|
|
|
while (aIterator.IsMore())
|
|
{
|
|
SdrObject* pSubObj = aIterator.Next();
|
|
if( eObjectType == OBJECTTYPE_DATA_SERIES )
|
|
{
|
|
OUString aSubName( lcl_getObjectName( pSubObj ) );
|
|
ObjectType eSubObjectType( ObjectIdentifier::getObjectType( aSubName ) );
|
|
if( eSubObjectType!=OBJECTTYPE_DATA_POINT )
|
|
return false;
|
|
}
|
|
|
|
Point aPos = pSubObj->GetCurrentBoundRect().Center();
|
|
SdrHdl* pHdl = new SdrHdl(aPos,SdrHdlKind::Poly);
|
|
rHdlList.AddHdl(pHdl);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} //namespace chart
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|