c4e649f0cd
There can be some serious rounding errors involved when calculating where to draw the grid lines for the various row heights in a document. This can be especially true for a document that has many different row heights. This results in draw objects appearing to move relative to the grid line at different zoom levels. This patch attempts to fix this problem adjusting the position of the shapes as they are drawn to ensure their position relative to grid appears to be stable. We do this by translating the position of the shape to the corrosponding position of it's cell anchor. Of course not all shapes are cell anchored and in this case we position the shape relative a temporary synthesized cell anchor. The patch essentially does the following a) calculates the offset to be applied for each shape at the current zoom level to ensure that the shape will be drawn relative to the correct cell grid see drwlayer.cxx, drawview.cxx & gridwin3.cxx, svdobj.[ch]xx b) apply the offset in the drawing layer for each of the different drawing primitives see svx/source/sdr/contact/* c) making sure the position and size of the newly created shape ( at any zoom level ) are still as expected when zoom level is changed. see. sc/source/ui/drawfunc/fuco*.cxx & d) making sure that overlays and handles are displayed at the correct position see svx/source/svdraw/* it could also be that a full blown transform might be needed to additionally scale the object ( to ensure that the edges of the object stay stable relative to ajacent grid lines ) If necessary we could do that in a later step. Change-Id: I02232f8ba192d58dbf96b80adf66c281cd0f65e8
1745 lines
60 KiB
C++
1745 lines
60 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 <svx/svdedtv.hxx>
|
|
#include <math.h>
|
|
|
|
#ifndef _MATH_H
|
|
#define _MATH_H
|
|
#endif
|
|
#include <tools/bigint.hxx>
|
|
#include <svl/itemiter.hxx>
|
|
#include <vcl/msgbox.hxx>
|
|
#include <svx/rectenum.hxx>
|
|
#include <svx/svxids.hrc> // for SID_ATTR_TRANSFORM_...
|
|
#include <svx/svdattr.hxx> // for Get/SetGeoAttr
|
|
#include "svx/svditext.hxx"
|
|
#include "svx/svditer.hxx"
|
|
#include <svx/svdtrans.hxx>
|
|
#include <svx/svdundo.hxx>
|
|
#include <svx/svdpage.hxx>
|
|
#include <svx/svdpagv.hxx>
|
|
#include <svx/svdlayer.hxx> // for MergeNotPersistAttr
|
|
#include <svx/svdattrx.hxx> // for MergeNotPersistAttr
|
|
#include <svx/svdetc.hxx> // for SearchOutlinerItems
|
|
#include <svx/svdopath.hxx> // for Crook
|
|
#include "svx/svdstr.hrc" // names taken from the resource
|
|
#include "svx/svdglob.hxx" // StringCache
|
|
#include <editeng/eeitem.hxx>
|
|
#include <svl/aeitem.hxx>
|
|
#include <svl/whiter.hxx>
|
|
#include <svx/sdr/contact/objectcontact.hxx>
|
|
#include <svx/sdr/contact/viewcontact.hxx>
|
|
#include <svx/e3dsceneupdater.hxx>
|
|
#include <svx/obj3d.hxx>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// EditView
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SdrEditView::SetMarkedObjRect(const Rectangle& rRect, sal_Bool bCopy)
|
|
{
|
|
DBG_ASSERT(!rRect.IsEmpty(),"SetMarkedObjRect() with an empty Rect does not make sense.");
|
|
if (rRect.IsEmpty()) return;
|
|
sal_uIntPtr nAnz=GetMarkedObjectCount();
|
|
if (nAnz==0) return;
|
|
Rectangle aR0(GetMarkedObjRect());
|
|
DBG_ASSERT(!aR0.IsEmpty(),"SetMarkedObjRect(): GetMarkedObjRect() is empty.");
|
|
if (aR0.IsEmpty()) return;
|
|
long x0=aR0.Left();
|
|
long y0=aR0.Top();
|
|
long w0=aR0.Right()-x0;
|
|
long h0=aR0.Bottom()-y0;
|
|
long x1=rRect.Left();
|
|
long y1=rRect.Top();
|
|
long w1=rRect.Right()-x1;
|
|
long h1=rRect.Bottom()-y1;
|
|
XubString aStr;
|
|
ImpTakeDescriptionStr(STR_EditPosSize,aStr);
|
|
if (bCopy)
|
|
aStr+=ImpGetResStr(STR_EditWithCopy);
|
|
|
|
const bool bUndo = IsUndoEnabled();
|
|
if( bUndo )
|
|
BegUndo(aStr);
|
|
|
|
if (bCopy)
|
|
CopyMarkedObj();
|
|
|
|
for (sal_uIntPtr nm=0; nm<nAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pO=pM->GetMarkedSdrObj();
|
|
if( bUndo )
|
|
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
|
|
|
|
Rectangle aR1(pO->GetSnapRect());
|
|
if (!aR1.IsEmpty())
|
|
{
|
|
if (aR1==aR0)
|
|
{
|
|
aR1=rRect;
|
|
}
|
|
else
|
|
{ // transform aR1 to aR0 after rRect
|
|
aR1.Move(-x0,-y0);
|
|
BigInt l(aR1.Left());
|
|
BigInt r(aR1.Right());
|
|
BigInt t(aR1.Top());
|
|
BigInt b(aR1.Bottom());
|
|
if (w0!=0) {
|
|
l*=w1; l/=w0;
|
|
r*=w1; r/=w0;
|
|
} else {
|
|
l=0; r=w1;
|
|
}
|
|
if (h0!=0) {
|
|
t*=h1; t/=h0;
|
|
b*=h1; b/=h0;
|
|
} else {
|
|
t=0; b=h1;
|
|
}
|
|
aR1.Left ()=long(l);
|
|
aR1.Right ()=long(r);
|
|
aR1.Top ()=long(t);
|
|
aR1.Bottom()=long(b);
|
|
aR1.Move(x1,y1);
|
|
}
|
|
pO->SetSnapRect(aR1);
|
|
} else {
|
|
OSL_FAIL("SetMarkedObjRect(): pObj->GetSnapRect() returns empty Rect");
|
|
}
|
|
}
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
std::vector< SdrUndoAction* > SdrEditView::CreateConnectorUndo( SdrObject& rO )
|
|
{
|
|
std::vector< SdrUndoAction* > vUndoActions;
|
|
|
|
if ( rO.GetBroadcaster() )
|
|
{
|
|
const SdrPage* pPage = rO.GetPage();
|
|
if ( pPage )
|
|
{
|
|
SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
|
|
while( aIter.IsMore() )
|
|
{
|
|
SdrObject* pPartObj = aIter.Next();
|
|
if ( pPartObj->ISA( SdrEdgeObj ) )
|
|
{
|
|
if ( ( pPartObj->GetConnectedNode( sal_False ) == &rO ) ||
|
|
( pPartObj->GetConnectedNode( sal_True ) == &rO ) )
|
|
{
|
|
vUndoActions.push_back( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pPartObj ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return vUndoActions;
|
|
}
|
|
|
|
void SdrEditView::AddUndoActions( std::vector< SdrUndoAction* >& rUndoActions )
|
|
{
|
|
std::vector< SdrUndoAction* >::iterator aUndoActionIter( rUndoActions.begin() );
|
|
while( aUndoActionIter != rUndoActions.end() )
|
|
AddUndo( *aUndoActionIter++ );
|
|
}
|
|
|
|
void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy)
|
|
{
|
|
const bool bUndo = IsUndoEnabled();
|
|
|
|
if( bUndo )
|
|
{
|
|
XubString aStr(ImpGetResStr(STR_EditMove));
|
|
if (bCopy)
|
|
aStr+=ImpGetResStr(STR_EditWithCopy);
|
|
// meeds its own UndoGroup because of its parameters
|
|
BegUndo(aStr,GetDescriptionOfMarkedObjects(),SDRREPFUNC_OBJ_MOVE);
|
|
}
|
|
|
|
if (bCopy)
|
|
CopyMarkedObj();
|
|
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pO=pM->GetMarkedSdrObj();
|
|
if( bUndo )
|
|
{
|
|
std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
|
|
AddUndoActions( vConnectorUndoActions );
|
|
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,rSiz));
|
|
}
|
|
pO->Move(rSiz);
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy)
|
|
{
|
|
const bool bUndo = IsUndoEnabled();
|
|
if( bUndo )
|
|
{
|
|
XubString aStr;
|
|
ImpTakeDescriptionStr(STR_EditResize,aStr);
|
|
if (bCopy)
|
|
aStr+=ImpGetResStr(STR_EditWithCopy);
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
if (bCopy)
|
|
CopyMarkedObj();
|
|
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pO=pM->GetMarkedSdrObj();
|
|
if( bUndo )
|
|
{
|
|
std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
|
|
AddUndoActions( vConnectorUndoActions );
|
|
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
|
|
}
|
|
pO->Resize(rRef,xFact,yFact);
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
long SdrEditView::GetMarkedObjRotate() const
|
|
{
|
|
sal_Bool b1st=sal_True;
|
|
sal_Bool bOk=sal_True;
|
|
long nWink=0;
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz && bOk; nm++) {
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pO=pM->GetMarkedSdrObj();
|
|
long nWink2=pO->GetRotateAngle();
|
|
if (b1st) nWink=nWink2;
|
|
else if (nWink2!=nWink) bOk=sal_False;
|
|
b1st=sal_False;
|
|
}
|
|
if (!bOk) nWink=0;
|
|
return nWink;
|
|
}
|
|
|
|
void SdrEditView::RotateMarkedObj(const Point& rRef, long nWink, bool bCopy)
|
|
{
|
|
const bool bUndo = IsUndoEnabled();
|
|
if( bUndo )
|
|
{
|
|
XubString aStr;
|
|
ImpTakeDescriptionStr(STR_EditRotate,aStr);
|
|
if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
if (bCopy)
|
|
CopyMarkedObj();
|
|
|
|
double nSin=sin(nWink*nPi180);
|
|
double nCos=cos(nWink*nPi180);
|
|
const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
|
|
|
|
if(nMarkAnz)
|
|
{
|
|
std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
|
|
|
|
for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM = GetSdrMarkByIndex(nm);
|
|
SdrObject* pO = pM->GetMarkedSdrObj();
|
|
|
|
if( bUndo )
|
|
{
|
|
// extra undo actions for changed connector which now may hold its laid out path (SJ)
|
|
std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
|
|
AddUndoActions( vConnectorUndoActions );
|
|
|
|
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
|
|
}
|
|
|
|
// set up a scene updater if object is a 3d object
|
|
if(dynamic_cast< E3dObject* >(pO))
|
|
{
|
|
aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
|
|
}
|
|
|
|
pO->Rotate(rRef,nWink,nSin,nCos);
|
|
}
|
|
|
|
// fire scene updaters
|
|
while(!aUpdaters.empty())
|
|
{
|
|
delete aUpdaters.back();
|
|
aUpdaters.pop_back();
|
|
}
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool bCopy)
|
|
{
|
|
const bool bUndo = IsUndoEnabled();
|
|
|
|
if( bUndo )
|
|
{
|
|
XubString aStr;
|
|
Point aDif(rRef2-rRef1);
|
|
if (aDif.X()==0) ImpTakeDescriptionStr(STR_EditMirrorHori,aStr);
|
|
else if (aDif.Y()==0) ImpTakeDescriptionStr(STR_EditMirrorVert,aStr);
|
|
else if (Abs(aDif.X())==Abs(aDif.Y())) ImpTakeDescriptionStr(STR_EditMirrorDiag,aStr);
|
|
else ImpTakeDescriptionStr(STR_EditMirrorFree,aStr);
|
|
if (bCopy) aStr+=ImpGetResStr(STR_EditWithCopy);
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
if (bCopy)
|
|
CopyMarkedObj();
|
|
|
|
const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
|
|
|
|
if(nMarkAnz)
|
|
{
|
|
std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
|
|
|
|
for(sal_uInt32 nm(0); nm < nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM = GetSdrMarkByIndex(nm);
|
|
SdrObject* pO = pM->GetMarkedSdrObj();
|
|
|
|
if( bUndo )
|
|
{
|
|
// extra undo actions for changed connector which now may hold its laid out path (SJ)
|
|
std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
|
|
AddUndoActions( vConnectorUndoActions );
|
|
|
|
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
|
|
}
|
|
|
|
// set up a scene updater if object is a 3d object
|
|
if(dynamic_cast< E3dObject* >(pO))
|
|
{
|
|
aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
|
|
}
|
|
|
|
pO->Mirror(rRef1,rRef2);
|
|
}
|
|
|
|
// fire scene updaters
|
|
while(!aUpdaters.empty())
|
|
{
|
|
delete aUpdaters.back();
|
|
aUpdaters.pop_back();
|
|
}
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
void SdrEditView::MirrorMarkedObjHorizontal(sal_Bool bCopy)
|
|
{
|
|
Point aCenter(GetMarkedObjRect().Center());
|
|
Point aPt2(aCenter);
|
|
aPt2.Y()++;
|
|
MirrorMarkedObj(aCenter,aPt2,bCopy);
|
|
}
|
|
|
|
void SdrEditView::MirrorMarkedObjVertical(sal_Bool bCopy)
|
|
{
|
|
Point aCenter(GetMarkedObjRect().Center());
|
|
Point aPt2(aCenter);
|
|
aPt2.X()++;
|
|
MirrorMarkedObj(aCenter,aPt2,bCopy);
|
|
}
|
|
|
|
long SdrEditView::GetMarkedObjShear() const
|
|
{
|
|
sal_Bool b1st=sal_True;
|
|
sal_Bool bOk=sal_True;
|
|
long nWink=0;
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz && bOk; nm++) {
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pO=pM->GetMarkedSdrObj();
|
|
long nWink2=pO->GetShearAngle();
|
|
if (b1st) nWink=nWink2;
|
|
else if (nWink2!=nWink) bOk=sal_False;
|
|
b1st=sal_False;
|
|
}
|
|
if (nWink>SDRMAXSHEAR) nWink=SDRMAXSHEAR;
|
|
if (nWink<-SDRMAXSHEAR) nWink=-SDRMAXSHEAR;
|
|
if (!bOk) nWink=0;
|
|
return nWink;
|
|
}
|
|
|
|
void SdrEditView::ShearMarkedObj(const Point& rRef, long nWink, bool bVShear, bool bCopy)
|
|
{
|
|
const bool bUndo = IsUndoEnabled();
|
|
|
|
if( bUndo )
|
|
{
|
|
XubString aStr;
|
|
ImpTakeDescriptionStr(STR_EditShear,aStr);
|
|
if (bCopy)
|
|
aStr+=ImpGetResStr(STR_EditWithCopy);
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
if (bCopy)
|
|
CopyMarkedObj();
|
|
|
|
double nTan=tan(nWink*nPi180);
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pO=pM->GetMarkedSdrObj();
|
|
if( bUndo )
|
|
{
|
|
std::vector< SdrUndoAction* > vConnectorUndoActions( CreateConnectorUndo( *pO ) );
|
|
AddUndoActions( vConnectorUndoActions );
|
|
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
|
|
}
|
|
pO->Shear(rRef,nWink,nTan,bVShear);
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRad,
|
|
SdrCrookMode eMode, sal_Bool bVertical, sal_Bool bNoContortion, sal_Bool bRotate, const Rectangle& rMarkRect)
|
|
{
|
|
SdrPathObj* pPath=PTR_CAST(SdrPathObj,pO);
|
|
sal_Bool bDone = sal_False;
|
|
|
|
if(pPath!=NULL && !bNoContortion)
|
|
{
|
|
XPolyPolygon aXPP(pPath->GetPathPoly());
|
|
switch (eMode) {
|
|
case SDRCROOK_ROTATE : CrookRotatePoly (aXPP,rRef,rRad,bVertical); break;
|
|
case SDRCROOK_SLANT : CrookSlantPoly (aXPP,rRef,rRad,bVertical); break;
|
|
case SDRCROOK_STRETCH: CrookStretchPoly(aXPP,rRef,rRad,bVertical,rMarkRect); break;
|
|
} // switch
|
|
pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
|
|
bDone = sal_True;
|
|
}
|
|
|
|
if(!bDone && !pPath && pO->IsPolyObj() && 0L != pO->GetPointCount())
|
|
{
|
|
// for PolyObj's, but NOT for SdrPathObj's, e.g. the measurement object
|
|
sal_uInt32 nPtAnz(pO->GetPointCount());
|
|
XPolygon aXP((sal_uInt16)nPtAnz);
|
|
sal_uInt32 nPtNum;
|
|
|
|
for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
|
|
{
|
|
Point aPt(pO->GetPoint(nPtNum));
|
|
aXP[(sal_uInt16)nPtNum]=aPt;
|
|
}
|
|
|
|
switch (eMode)
|
|
{
|
|
case SDRCROOK_ROTATE : CrookRotatePoly (aXP,rRef,rRad,bVertical); break;
|
|
case SDRCROOK_SLANT : CrookSlantPoly (aXP,rRef,rRad,bVertical); break;
|
|
case SDRCROOK_STRETCH: CrookStretchPoly(aXP,rRef,rRad,bVertical,rMarkRect); break;
|
|
}
|
|
|
|
for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
|
|
{
|
|
// broadcasting could be optimized here, but for the
|
|
// current two points of the measurement object, it's fine
|
|
pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
|
|
}
|
|
|
|
bDone = sal_True;
|
|
}
|
|
|
|
if(!bDone)
|
|
{
|
|
// for all others or if bNoContortion
|
|
Point aCtr0(pO->GetSnapRect().Center());
|
|
Point aCtr1(aCtr0);
|
|
sal_Bool bRotOk(sal_False);
|
|
double nSin(0.0), nCos(1.0);
|
|
double nWink(0.0);
|
|
|
|
if(0 != rRad.X() && 0 != rRad.Y())
|
|
{
|
|
bRotOk = bRotate;
|
|
|
|
switch (eMode)
|
|
{
|
|
case SDRCROOK_ROTATE : nWink=CrookRotateXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); bRotOk=bRotate; break;
|
|
case SDRCROOK_SLANT : nWink=CrookSlantXPoint (aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical); break;
|
|
case SDRCROOK_STRETCH: nWink=CrookStretchXPoint(aCtr1,NULL,NULL,rRef,rRad,nSin,nCos,bVertical,rMarkRect); break;
|
|
}
|
|
}
|
|
|
|
aCtr1 -= aCtr0;
|
|
|
|
if(bRotOk)
|
|
pO->Rotate(aCtr0, Round(nWink/nPi180), nSin, nCos);
|
|
|
|
pO->Move(Size(aCtr1.X(),aCtr1.Y()));
|
|
}
|
|
}
|
|
|
|
void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookMode eMode,
|
|
bool bVertical, bool bNoContortion, bool bCopy)
|
|
{
|
|
Rectangle aMarkRect(GetMarkedObjRect());
|
|
const bool bUndo = IsUndoEnabled();
|
|
|
|
bool bRotate=bNoContortion && eMode==SDRCROOK_ROTATE && IsRotateAllowed(sal_False);
|
|
|
|
if( bUndo )
|
|
{
|
|
XubString aStr;
|
|
ImpTakeDescriptionStr(bNoContortion?STR_EditCrook:STR_EditCrookContortion,aStr);
|
|
if (bCopy)
|
|
aStr+=ImpGetResStr(STR_EditWithCopy);
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
if (bCopy)
|
|
CopyMarkedObj();
|
|
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pO=pM->GetMarkedSdrObj();
|
|
if( bUndo )
|
|
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
|
|
|
|
const SdrObjList* pOL=pO->GetSubList();
|
|
if (bNoContortion || pOL==NULL) {
|
|
ImpCrookObj(pO,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
|
|
} else {
|
|
SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
|
|
while (aIter.IsMore()) {
|
|
SdrObject* pO1=aIter.Next();
|
|
ImpCrookObj(pO1,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
void SdrEditView::ImpDistortObj(SdrObject* pO, const Rectangle& rRef, const XPolygon& rDistortedRect, sal_Bool bNoContortion)
|
|
{
|
|
SdrPathObj* pPath = PTR_CAST(SdrPathObj, pO);
|
|
|
|
if(!bNoContortion && pPath)
|
|
{
|
|
XPolyPolygon aXPP(pPath->GetPathPoly());
|
|
aXPP.Distort(rRef, rDistortedRect);
|
|
pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
|
|
}
|
|
else if(pO->IsPolyObj())
|
|
{
|
|
// e. g. for the measurement object
|
|
sal_uInt32 nPtAnz(pO->GetPointCount());
|
|
XPolygon aXP((sal_uInt16)nPtAnz);
|
|
sal_uInt32 nPtNum;
|
|
|
|
for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
|
|
{
|
|
Point aPt(pO->GetPoint(nPtNum));
|
|
aXP[(sal_uInt16)nPtNum]=aPt;
|
|
}
|
|
|
|
aXP.Distort(rRef, rDistortedRect);
|
|
|
|
for(nPtNum = 0L; nPtNum < nPtAnz; nPtNum++)
|
|
{
|
|
// broadcasting could be optimized here, but for the
|
|
// current two points of the measurement object it's fine
|
|
pO->SetPoint(aXP[(sal_uInt16)nPtNum],nPtNum);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdrEditView::DistortMarkedObj(const Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion, bool bCopy)
|
|
{
|
|
const bool bUndo = IsUndoEnabled();
|
|
|
|
if( bUndo )
|
|
{
|
|
XubString aStr;
|
|
ImpTakeDescriptionStr(STR_EditDistort,aStr);
|
|
if (bCopy)
|
|
aStr+=ImpGetResStr(STR_EditWithCopy);
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
if (bCopy)
|
|
CopyMarkedObj();
|
|
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pO=pM->GetMarkedSdrObj();
|
|
if( bUndo )
|
|
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
|
|
|
|
Rectangle aRefRect(rRef);
|
|
XPolygon aRefPoly(rDistortedRect);
|
|
const SdrObjList* pOL=pO->GetSubList();
|
|
if (bNoContortion || pOL==NULL) {
|
|
ImpDistortObj(pO,aRefRect,aRefPoly,bNoContortion);
|
|
} else {
|
|
SdrObjListIter aIter(*pOL,IM_DEEPNOGROUPS);
|
|
while (aIter.IsMore()) {
|
|
SdrObject* pO1=aIter.Next();
|
|
ImpDistortObj(pO1,aRefRect,aRefPoly,bNoContortion);
|
|
}
|
|
}
|
|
}
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SdrEditView::SetNotPersistAttrToMarked(const SfxItemSet& rAttr, sal_Bool /*bReplaceAll*/)
|
|
{
|
|
// bReplaceAll has no effect here
|
|
Rectangle aAllSnapRect(GetMarkedObjRect());
|
|
const SfxPoolItem *pPoolItem=NULL;
|
|
if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
long n=((const SdrTransformRef1XItem*)pPoolItem)->GetValue();
|
|
SetRef1(Point(n,GetRef1().Y()));
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
long n=((const SdrTransformRef1YItem*)pPoolItem)->GetValue();
|
|
SetRef1(Point(GetRef1().X(),n));
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
long n=((const SdrTransformRef2XItem*)pPoolItem)->GetValue();
|
|
SetRef2(Point(n,GetRef2().Y()));
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
long n=((const SdrTransformRef2YItem*)pPoolItem)->GetValue();
|
|
SetRef2(Point(GetRef2().X(),n));
|
|
}
|
|
long nAllPosX=0; sal_Bool bAllPosX=sal_False;
|
|
long nAllPosY=0; sal_Bool bAllPosY=sal_False;
|
|
long nAllWdt=0; sal_Bool bAllWdt=sal_False;
|
|
long nAllHgt=0; sal_Bool bAllHgt=sal_False;
|
|
sal_Bool bDoIt=sal_False;
|
|
if (rAttr.GetItemState(SDRATTR_ALLPOSITIONX,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
nAllPosX=((const SdrAllPositionXItem*)pPoolItem)->GetValue();
|
|
bAllPosX=sal_True; bDoIt=sal_True;
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_ALLPOSITIONY,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
nAllPosY=((const SdrAllPositionYItem*)pPoolItem)->GetValue();
|
|
bAllPosY=sal_True; bDoIt=sal_True;
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_ALLSIZEWIDTH,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
nAllWdt=((const SdrAllSizeWidthItem*)pPoolItem)->GetValue();
|
|
bAllWdt=sal_True; bDoIt=sal_True;
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_ALLSIZEHEIGHT,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
nAllHgt=((const SdrAllSizeHeightItem*)pPoolItem)->GetValue();
|
|
bAllHgt=sal_True; bDoIt=sal_True;
|
|
}
|
|
if (bDoIt) {
|
|
Rectangle aRect(aAllSnapRect); // TODO: change this for PolyPt's and GluePt's!!!
|
|
if (bAllPosX) aRect.Move(nAllPosX-aRect.Left(),0);
|
|
if (bAllPosY) aRect.Move(0,nAllPosY-aRect.Top());
|
|
if (bAllWdt) aRect.Right()=aAllSnapRect.Left()+nAllWdt;
|
|
if (bAllHgt) aRect.Bottom()=aAllSnapRect.Top()+nAllHgt;
|
|
SetMarkedObjRect(aRect);
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_RESIZEXALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
Fraction aXFact=((const SdrResizeXAllItem*)pPoolItem)->GetValue();
|
|
ResizeMarkedObj(aAllSnapRect.TopLeft(),aXFact,Fraction(1,1));
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_RESIZEYALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
Fraction aYFact=((const SdrResizeYAllItem*)pPoolItem)->GetValue();
|
|
ResizeMarkedObj(aAllSnapRect.TopLeft(),Fraction(1,1),aYFact);
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_ROTATEALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
long nAngle=((const SdrRotateAllItem*)pPoolItem)->GetValue();
|
|
RotateMarkedObj(aAllSnapRect.Center(),nAngle);
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_HORZSHEARALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
long nAngle=((const SdrHorzShearAllItem*)pPoolItem)->GetValue();
|
|
ShearMarkedObj(aAllSnapRect.Center(),nAngle,sal_False);
|
|
}
|
|
if (rAttr.GetItemState(SDRATTR_VERTSHEARALL,sal_True,&pPoolItem)==SFX_ITEM_SET) {
|
|
long nAngle=((const SdrVertShearAllItem*)pPoolItem)->GetValue();
|
|
ShearMarkedObj(aAllSnapRect.Center(),nAngle,sal_True);
|
|
}
|
|
|
|
const bool bUndo = IsUndoEnabled();
|
|
|
|
// TODO: check if WhichRange is necessary.
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
const SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pObj=pM->GetMarkedSdrObj();
|
|
if( bUndo )
|
|
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
|
|
|
|
pObj->ApplyNotPersistAttr(rAttr);
|
|
}
|
|
}
|
|
|
|
void SdrEditView::MergeNotPersistAttrFromMarked(SfxItemSet& rAttr, sal_Bool /*bOnlyHardAttr*/) const
|
|
{
|
|
// bOnlyHardAttr has no effect here.
|
|
// TODO: Take into account the origin and PvPos.
|
|
Rectangle aAllSnapRect(GetMarkedObjRect()); // TODO: change this for PolyPt's and GluePt's!!!
|
|
long nAllSnapPosX=aAllSnapRect.Left();
|
|
long nAllSnapPosY=aAllSnapRect.Top();
|
|
long nAllSnapWdt=aAllSnapRect.GetWidth()-1;
|
|
long nAllSnapHgt=aAllSnapRect.GetHeight()-1;
|
|
// TODO: could go into CheckPossibilities
|
|
bool bMovProtect = false, bMovProtectDC = false;
|
|
bool bSizProtect = false, bSizProtectDC = false;
|
|
bool bPrintable = true, bPrintableDC = false;
|
|
bool bVisible = true, bVisibleDC = false;
|
|
SdrLayerID nLayerId=0; sal_Bool bLayerDC=sal_False;
|
|
rtl::OUString aObjName;
|
|
sal_Bool bObjNameDC=sal_False,bObjNameSet=sal_False;
|
|
long nSnapPosX=0; sal_Bool bSnapPosXDC=sal_False;
|
|
long nSnapPosY=0; sal_Bool bSnapPosYDC=sal_False;
|
|
long nSnapWdt=0; sal_Bool bSnapWdtDC=sal_False;
|
|
long nSnapHgt=0; sal_Bool bSnapHgtDC=sal_False;
|
|
long nLogicWdt=0; sal_Bool bLogicWdtDC=sal_False,bLogicWdtDiff=sal_False;
|
|
long nLogicHgt=0; sal_Bool bLogicHgtDC=sal_False,bLogicHgtDiff=sal_False;
|
|
long nRotAngle=0; sal_Bool bRotAngleDC=sal_False;
|
|
long nShrAngle=0; sal_Bool bShrAngleDC=sal_False;
|
|
Rectangle aSnapRect;
|
|
Rectangle aLogicRect;
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++) {
|
|
const SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
const SdrObject* pObj=pM->GetMarkedSdrObj();
|
|
if (nm==0) {
|
|
nLayerId=pObj->GetLayer();
|
|
bMovProtect=pObj->IsMoveProtect();
|
|
bSizProtect=pObj->IsResizeProtect();
|
|
bPrintable =pObj->IsPrintable();
|
|
bVisible = pObj->IsVisible();
|
|
Rectangle aSnapRect2(pObj->GetSnapRect());
|
|
Rectangle aLogicRect2(pObj->GetLogicRect());
|
|
nSnapPosX=aSnapRect2.Left();
|
|
nSnapPosY=aSnapRect2.Top();
|
|
nSnapWdt=aSnapRect2.GetWidth()-1;
|
|
nSnapHgt=aSnapRect2.GetHeight()-1;
|
|
nLogicWdt=aLogicRect2.GetWidth()-1;
|
|
nLogicHgt=aLogicRect2.GetHeight()-1;
|
|
bLogicWdtDiff=nLogicWdt!=nSnapWdt;
|
|
bLogicHgtDiff=nLogicHgt!=nSnapHgt;
|
|
nRotAngle=pObj->GetRotateAngle();
|
|
nShrAngle=pObj->GetShearAngle();
|
|
} else {
|
|
if (!bLayerDC && nLayerId !=pObj->GetLayer()) bLayerDC = true;
|
|
if (!bMovProtectDC && bMovProtect!=pObj->IsMoveProtect()) bMovProtectDC = true;
|
|
if (!bSizProtectDC && bSizProtect!=pObj->IsResizeProtect()) bSizProtectDC = true;
|
|
if (!bPrintableDC && bPrintable !=pObj->IsPrintable()) bPrintableDC = true;
|
|
if (!bVisibleDC && bVisible !=pObj->IsVisible()) bVisibleDC=true;
|
|
if (!bRotAngleDC && nRotAngle !=pObj->GetRotateAngle()) bRotAngleDC=sal_True;
|
|
if (!bShrAngleDC && nShrAngle !=pObj->GetShearAngle()) bShrAngleDC=sal_True;
|
|
if (!bSnapWdtDC || !bSnapHgtDC || !bSnapPosXDC || !bSnapPosYDC || !bLogicWdtDiff || !bLogicHgtDiff) {
|
|
aSnapRect=pObj->GetSnapRect();
|
|
if (nSnapPosX!=aSnapRect.Left()) bSnapPosXDC=sal_True;
|
|
if (nSnapPosY!=aSnapRect.Top()) bSnapPosYDC=sal_True;
|
|
if (nSnapWdt!=aSnapRect.GetWidth()-1) bSnapWdtDC=sal_True;
|
|
if (nSnapHgt!=aSnapRect.GetHeight()-1) bSnapHgtDC=sal_True;
|
|
}
|
|
if (!bLogicWdtDC || !bLogicHgtDC || !bLogicWdtDiff || !bLogicHgtDiff) {
|
|
aLogicRect=pObj->GetLogicRect();
|
|
if (nLogicWdt!=aLogicRect.GetWidth()-1) bLogicWdtDC=sal_True;
|
|
if (nLogicHgt!=aLogicRect.GetHeight()-1) bLogicHgtDC=sal_True;
|
|
if (!bLogicWdtDiff && aSnapRect.GetWidth()!=aLogicRect.GetWidth()) bLogicWdtDiff=sal_True;
|
|
if (!bLogicHgtDiff && aSnapRect.GetHeight()!=aLogicRect.GetHeight()) bLogicHgtDiff=sal_True;
|
|
}
|
|
}
|
|
if (!bObjNameDC ) {
|
|
if (!bObjNameSet) {
|
|
aObjName=pObj->GetName();
|
|
} else {
|
|
if (!aObjName.equals(pObj->GetName()))
|
|
bObjNameDC = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bSnapPosXDC || nAllSnapPosX!=nSnapPosX) rAttr.Put(SdrAllPositionXItem(nAllSnapPosX));
|
|
if (bSnapPosYDC || nAllSnapPosY!=nSnapPosY) rAttr.Put(SdrAllPositionYItem(nAllSnapPosY));
|
|
if (bSnapWdtDC || nAllSnapWdt !=nSnapWdt ) rAttr.Put(SdrAllSizeWidthItem(nAllSnapWdt));
|
|
if (bSnapHgtDC || nAllSnapHgt !=nSnapHgt ) rAttr.Put(SdrAllSizeHeightItem(nAllSnapHgt));
|
|
|
|
// items for pure transformations
|
|
rAttr.Put(SdrMoveXItem());
|
|
rAttr.Put(SdrMoveYItem());
|
|
rAttr.Put(SdrResizeXOneItem());
|
|
rAttr.Put(SdrResizeYOneItem());
|
|
rAttr.Put(SdrRotateOneItem());
|
|
rAttr.Put(SdrHorzShearOneItem());
|
|
rAttr.Put(SdrVertShearOneItem());
|
|
|
|
if (nMarkAnz>1) {
|
|
rAttr.Put(SdrResizeXAllItem());
|
|
rAttr.Put(SdrResizeYAllItem());
|
|
rAttr.Put(SdrRotateAllItem());
|
|
rAttr.Put(SdrHorzShearAllItem());
|
|
rAttr.Put(SdrVertShearAllItem());
|
|
}
|
|
|
|
if(eDragMode == SDRDRAG_ROTATE || eDragMode == SDRDRAG_MIRROR)
|
|
{
|
|
rAttr.Put(SdrTransformRef1XItem(GetRef1().X()));
|
|
rAttr.Put(SdrTransformRef1YItem(GetRef1().Y()));
|
|
}
|
|
|
|
if(eDragMode == SDRDRAG_MIRROR)
|
|
{
|
|
rAttr.Put(SdrTransformRef2XItem(GetRef2().X()));
|
|
rAttr.Put(SdrTransformRef2YItem(GetRef2().Y()));
|
|
}
|
|
}
|
|
|
|
SfxItemSet SdrEditView::GetAttrFromMarked(sal_Bool bOnlyHardAttr) const
|
|
{
|
|
SfxItemSet aSet(pMod->GetItemPool());
|
|
MergeAttrFromMarked(aSet,bOnlyHardAttr);
|
|
//the EE_FEATURE items should not be set with SetAttrToMarked (see error message there)
|
|
//so we do not set them here
|
|
// #i32448#
|
|
// Do not disable, but clear the items.
|
|
aSet.ClearItem(EE_FEATURE_TAB);
|
|
aSet.ClearItem(EE_FEATURE_LINEBR);
|
|
aSet.ClearItem(EE_FEATURE_NOTCONV);
|
|
aSet.ClearItem(EE_FEATURE_FIELD);
|
|
return aSet;
|
|
}
|
|
|
|
void SdrEditView::MergeAttrFromMarked(SfxItemSet& rAttr, sal_Bool bOnlyHardAttr) const
|
|
{
|
|
sal_uInt32 nMarkAnz(GetMarkedObjectCount());
|
|
|
|
for(sal_uInt32 a(0); a < nMarkAnz; a++)
|
|
{
|
|
// #80277# merging was done wrong in the prev version
|
|
const SfxItemSet& rSet = GetMarkedObjectByIndex(a)->GetMergedItemSet();
|
|
SfxWhichIter aIter(rSet);
|
|
sal_uInt16 nWhich(aIter.FirstWhich());
|
|
|
|
while(nWhich)
|
|
{
|
|
if(!bOnlyHardAttr)
|
|
{
|
|
if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, sal_False))
|
|
rAttr.InvalidateItem(nWhich);
|
|
else
|
|
rAttr.MergeValue(rSet.Get(nWhich), sal_True);
|
|
}
|
|
else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, sal_False))
|
|
{
|
|
const SfxPoolItem& rItem = rSet.Get(nWhich);
|
|
rAttr.MergeValue(rItem, sal_True);
|
|
}
|
|
|
|
nWhich = aIter.NextWhich();
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, sal_Bool bReplaceAll)
|
|
{
|
|
if (AreObjectsMarked())
|
|
{
|
|
#ifdef DBG_UTIL
|
|
{
|
|
sal_Bool bHasEEFeatureItems=sal_False;
|
|
SfxItemIter aIter(rAttr);
|
|
const SfxPoolItem* pItem=aIter.FirstItem();
|
|
while (!bHasEEFeatureItems && pItem!=NULL) {
|
|
if (!IsInvalidItem(pItem)) {
|
|
sal_uInt16 nW=pItem->Which();
|
|
if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=sal_True;
|
|
}
|
|
pItem=aIter.NextItem();
|
|
}
|
|
if(bHasEEFeatureItems)
|
|
{
|
|
String aMessage;
|
|
aMessage.AppendAscii("SdrEditView::SetAttrToMarked(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents.");
|
|
InfoBox(NULL, aMessage).Execute();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// #103836# if the user thets character attributes to the complete shape,
|
|
// we want to remove all hard set character attributes with same
|
|
// which ids from the text. We do that later but here we remember
|
|
// all character attribute which id's that are set.
|
|
std::vector<sal_uInt16> aCharWhichIds;
|
|
{
|
|
SfxItemIter aIter(rAttr);
|
|
const SfxPoolItem* pItem=aIter.FirstItem();
|
|
while( pItem!=NULL )
|
|
{
|
|
if (!IsInvalidItem(pItem))
|
|
{
|
|
sal_uInt16 nWhich = pItem->Which();
|
|
if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END)
|
|
aCharWhichIds.push_back( nWhich );
|
|
}
|
|
pItem=aIter.NextItem();
|
|
}
|
|
}
|
|
|
|
// To make Undo reconstruct text attributes correctly after Format.Standard
|
|
sal_Bool bHasEEItems=SearchOutlinerItems(rAttr,bReplaceAll);
|
|
|
|
// save additional geometry information when paragraph or character attributes
|
|
// are changed and the geometrical shape of the text object might be changed
|
|
sal_Bool bPossibleGeomChange(sal_False);
|
|
SfxWhichIter aIter(rAttr);
|
|
sal_uInt16 nWhich = aIter.FirstWhich();
|
|
while(!bPossibleGeomChange && nWhich)
|
|
{
|
|
SfxItemState eState = rAttr.GetItemState(nWhich);
|
|
if(eState == SFX_ITEM_SET)
|
|
{
|
|
if((nWhich >= SDRATTR_TEXT_MINFRAMEHEIGHT && nWhich <= SDRATTR_TEXT_CONTOURFRAME)
|
|
|| nWhich == SDRATTR_3DOBJ_PERCENT_DIAGONAL
|
|
|| nWhich == SDRATTR_3DOBJ_BACKSCALE
|
|
|| nWhich == SDRATTR_3DOBJ_DEPTH
|
|
|| nWhich == SDRATTR_3DOBJ_END_ANGLE
|
|
|| nWhich == SDRATTR_3DSCENE_DISTANCE)
|
|
{
|
|
bPossibleGeomChange = sal_True;
|
|
}
|
|
}
|
|
nWhich = aIter.NextWhich();
|
|
}
|
|
|
|
const bool bUndo = IsUndoEnabled();
|
|
if( bUndo )
|
|
{
|
|
XubString aStr;
|
|
ImpTakeDescriptionStr(STR_EditSetAttributes,aStr);
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
const sal_uInt32 nMarkAnz(GetMarkedObjectCount());
|
|
std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
|
|
|
|
// create ItemSet without SFX_ITEM_DONTCARE. Put()
|
|
// uses its second parameter (bInvalidAsDefault) to
|
|
// remove all such items to set them to default.
|
|
SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
|
|
aAttr.Put(rAttr, sal_True);
|
|
|
|
// #i38135#
|
|
bool bResetAnimationTimer(false);
|
|
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pObj = pM->GetMarkedSdrObj();
|
|
|
|
if( bUndo )
|
|
{
|
|
std::vector< SdrUndoAction* > vConnectorUndoActions;
|
|
SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj );
|
|
if ( pEdgeObj )
|
|
bPossibleGeomChange = sal_True;
|
|
else if( bUndo )
|
|
vConnectorUndoActions = CreateConnectorUndo( *pObj );
|
|
|
|
AddUndoActions( vConnectorUndoActions );
|
|
}
|
|
|
|
// new geometry undo
|
|
if(bPossibleGeomChange && bUndo)
|
|
{
|
|
// save position and size of object, too
|
|
AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
|
|
}
|
|
|
|
if( bUndo )
|
|
{
|
|
// #i8508#
|
|
// If this is a text object also rescue the OutlinerParaObject since
|
|
// applying attributes to the object may change text layout when
|
|
// multiple portions exist with multiple formats. If a OutlinerParaObject
|
|
// really exists and needs to be rescued is evaluated in the undo
|
|
// implementation itself.
|
|
const bool bRescueText = dynamic_cast< SdrTextObj* >(pObj) != 0;
|
|
|
|
// add attribute undo
|
|
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj,sal_False,bHasEEItems || bPossibleGeomChange || bRescueText));
|
|
}
|
|
|
|
// set up a scene updater if object is a 3d object
|
|
if(dynamic_cast< E3dObject* >(pObj))
|
|
{
|
|
aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
|
|
}
|
|
|
|
// set attributes at object
|
|
pObj->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
|
|
|
|
if(pObj->ISA(SdrTextObj))
|
|
{
|
|
SdrTextObj* pTextObj = ((SdrTextObj*)pObj);
|
|
|
|
if(!aCharWhichIds.empty())
|
|
{
|
|
Rectangle aOldBoundRect = pTextObj->GetLastBoundRect();
|
|
|
|
// #110094#-14 pTextObj->SendRepaintBroadcast(pTextObj->GetBoundRect());
|
|
pTextObj->RemoveOutlinerCharacterAttribs( aCharWhichIds );
|
|
|
|
// object has changed, should be called from
|
|
// RemoveOutlinerCharacterAttribs. This will change when the text
|
|
// object implementation changes.
|
|
pTextObj->SetChanged();
|
|
|
|
pTextObj->BroadcastObjectChange();
|
|
pTextObj->SendUserCall(SDRUSERCALL_CHGATTR, aOldBoundRect);
|
|
}
|
|
}
|
|
|
|
// #i38495#
|
|
if(!bResetAnimationTimer)
|
|
{
|
|
if(pObj->GetViewContact().isAnimatedInAnyViewObjectContact())
|
|
{
|
|
bResetAnimationTimer = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// fire scene updaters
|
|
while(!aUpdaters.empty())
|
|
{
|
|
delete aUpdaters.back();
|
|
aUpdaters.pop_back();
|
|
}
|
|
|
|
// #i38135#
|
|
if(bResetAnimationTimer)
|
|
{
|
|
SetAnimationTimer(0L);
|
|
}
|
|
|
|
// better check before what to do:
|
|
// pObj->SetAttr() or SetNotPersistAttr()
|
|
// TODO: missing implementation!
|
|
SetNotPersistAttrToMarked(rAttr,bReplaceAll);
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
}
|
|
|
|
SfxStyleSheet* SdrEditView::GetStyleSheetFromMarked() const
|
|
{
|
|
SfxStyleSheet* pRet=NULL;
|
|
sal_Bool b1st=sal_True;
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++) {
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SfxStyleSheet* pSS=pM->GetMarkedSdrObj()->GetStyleSheet();
|
|
if (b1st) pRet=pSS;
|
|
else if (pRet!=pSS) return NULL; // different stylesheets
|
|
b1st=sal_False;
|
|
}
|
|
return pRet;
|
|
}
|
|
|
|
void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, sal_Bool bDontRemoveHardAttr)
|
|
{
|
|
if (AreObjectsMarked())
|
|
{
|
|
const bool bUndo = IsUndoEnabled();
|
|
|
|
if( bUndo )
|
|
{
|
|
XubString aStr;
|
|
if (pStyleSheet!=NULL)
|
|
ImpTakeDescriptionStr(STR_EditSetStylesheet,aStr);
|
|
else
|
|
ImpTakeDescriptionStr(STR_EditDelStylesheet,aStr);
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
for (sal_uIntPtr nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
if( bUndo )
|
|
{
|
|
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pM->GetMarkedSdrObj()));
|
|
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pM->GetMarkedSdrObj(),true,true));
|
|
}
|
|
pM->GetMarkedSdrObj()->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
sal_Bool SdrEditView::GetAttributes(SfxItemSet& rTargetSet, sal_Bool bOnlyHardAttr) const
|
|
{
|
|
if(GetMarkedObjectCount())
|
|
{
|
|
rTargetSet.Put(GetAttrFromMarked(bOnlyHardAttr), sal_False);
|
|
return sal_True;
|
|
}
|
|
else
|
|
{
|
|
return SdrMarkView::GetAttributes(rTargetSet, bOnlyHardAttr);
|
|
}
|
|
}
|
|
|
|
sal_Bool SdrEditView::SetAttributes(const SfxItemSet& rSet, sal_Bool bReplaceAll)
|
|
{
|
|
if (GetMarkedObjectCount()!=0) {
|
|
SetAttrToMarked(rSet,bReplaceAll);
|
|
return sal_True;
|
|
} else {
|
|
return SdrMarkView::SetAttributes(rSet,bReplaceAll);
|
|
}
|
|
}
|
|
|
|
SfxStyleSheet* SdrEditView::GetStyleSheet() const
|
|
{
|
|
if (GetMarkedObjectCount()!=0) {
|
|
return GetStyleSheetFromMarked();
|
|
} else {
|
|
return SdrMarkView::GetStyleSheet();
|
|
}
|
|
}
|
|
|
|
sal_Bool SdrEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, sal_Bool bDontRemoveHardAttr)
|
|
{
|
|
if (GetMarkedObjectCount()!=0) {
|
|
SetStyleSheetToMarked(pStyleSheet,bDontRemoveHardAttr);
|
|
return sal_True;
|
|
} else {
|
|
return SdrMarkView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
SfxItemSet SdrEditView::GetGeoAttrFromMarked() const
|
|
{
|
|
SfxItemSet aRetSet(pMod->GetItemPool(), // SID_ATTR_TRANSFORM_... from s:svxids.hrc
|
|
SID_ATTR_TRANSFORM_POS_X,SID_ATTR_TRANSFORM_ANGLE,
|
|
SID_ATTR_TRANSFORM_PROTECT_POS,SID_ATTR_TRANSFORM_AUTOHEIGHT,
|
|
SDRATTR_ECKENRADIUS,SDRATTR_ECKENRADIUS,
|
|
0);
|
|
if (AreObjectsMarked()) {
|
|
SfxItemSet aMarkAttr(GetAttrFromMarked(sal_False)); // because of AutoGrowHeight and corner radius
|
|
Rectangle aRect(GetMarkedObjRect() );
|
|
// restore position to that before calc hack
|
|
aRect -= GetGridOffset();
|
|
|
|
if(GetSdrPageView())
|
|
{
|
|
GetSdrPageView()->LogicToPagePos(aRect);
|
|
}
|
|
|
|
// position
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X,aRect.Left()));
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y,aRect.Top()));
|
|
|
|
// size
|
|
long nResizeRefX=aRect.Left();
|
|
long nResizeRefY=aRect.Top();
|
|
if (eDragMode==SDRDRAG_ROTATE) { // use rotation axis as a reference for resizing, too
|
|
nResizeRefX=aRef1.X();
|
|
nResizeRefY=aRef1.Y();
|
|
}
|
|
aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTH,aRect.Right()-aRect.Left()));
|
|
aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHT,aRect.Bottom()-aRect.Top()));
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_X,nResizeRefX));
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_Y,nResizeRefY));
|
|
|
|
Point aRotateAxe(aRef1);
|
|
|
|
if(GetSdrPageView())
|
|
{
|
|
GetSdrPageView()->LogicToPagePos(aRotateAxe);
|
|
}
|
|
|
|
// rotation
|
|
long nRotateRefX=aRect.Center().X();
|
|
long nRotateRefY=aRect.Center().Y();
|
|
if (eDragMode==SDRDRAG_ROTATE) {
|
|
nRotateRefX=aRotateAxe.X();
|
|
nRotateRefY=aRotateAxe.Y();
|
|
}
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLE,GetMarkedObjRotate()));
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_X,nRotateRefX));
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_Y,nRotateRefY));
|
|
|
|
// shearing
|
|
long nShearRefX=aRect.Left();
|
|
long nShearRefY=aRect.Bottom();
|
|
if (eDragMode==SDRDRAG_ROTATE) { // use rotation axis as a reference for shearing, too
|
|
nShearRefX=aRotateAxe.X();
|
|
nShearRefY=aRotateAxe.Y();
|
|
}
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR,GetMarkedObjShear()));
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X,nShearRefX));
|
|
aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y,nShearRefY));
|
|
|
|
// check every object whether it is protected
|
|
const SdrMarkList& rMarkList=GetMarkedObjectList();
|
|
sal_uIntPtr nMarkCount=rMarkList.GetMarkCount();
|
|
SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
|
|
bool bPosProt=pObj->IsMoveProtect();
|
|
bool bSizProt=pObj->IsResizeProtect();
|
|
bool bPosProtDontCare=false;
|
|
bool bSizProtDontCare=false;
|
|
for (sal_uIntPtr i=1; i<nMarkCount && (!bPosProtDontCare || !bSizProtDontCare); i++) {
|
|
pObj=rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if (bPosProt!=pObj->IsMoveProtect()) bPosProtDontCare=true;
|
|
if (bSizProt!=pObj->IsResizeProtect()) bSizProtDontCare=true;
|
|
}
|
|
|
|
// InvalidateItem sets item to DONT_CARE
|
|
if (bPosProtDontCare) {
|
|
aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_POS);
|
|
} else {
|
|
aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_POS,bPosProt));
|
|
}
|
|
if (bSizProtDontCare) {
|
|
aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_SIZE);
|
|
} else {
|
|
aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_SIZE,bSizProt));
|
|
}
|
|
|
|
SfxItemState eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWWIDTH);
|
|
sal_Bool bAutoGrow=((SdrTextAutoGrowWidthItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue();
|
|
if (eState==SFX_ITEM_DONTCARE) {
|
|
aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOWIDTH);
|
|
} else if (eState==SFX_ITEM_SET) {
|
|
aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOWIDTH,bAutoGrow));
|
|
}
|
|
|
|
eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWHEIGHT);
|
|
bAutoGrow=((SdrTextAutoGrowHeightItem&)(aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
|
|
if (eState==SFX_ITEM_DONTCARE) {
|
|
aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOHEIGHT);
|
|
} else if (eState==SFX_ITEM_SET) {
|
|
aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOHEIGHT,bAutoGrow));
|
|
}
|
|
|
|
eState=aMarkAttr.GetItemState(SDRATTR_ECKENRADIUS);
|
|
long nRadius=((SdrEckenradiusItem&)(aMarkAttr.Get(SDRATTR_ECKENRADIUS))).GetValue();
|
|
if (eState==SFX_ITEM_DONTCARE) {
|
|
aRetSet.InvalidateItem(SDRATTR_ECKENRADIUS);
|
|
} else if (eState==SFX_ITEM_SET) {
|
|
aRetSet.Put(SdrEckenradiusItem(nRadius));
|
|
}
|
|
|
|
}
|
|
return aRetSet;
|
|
}
|
|
|
|
Point ImpGetPoint(Rectangle aRect, RECT_POINT eRP)
|
|
{
|
|
switch(eRP) {
|
|
case RP_LT: return aRect.TopLeft();
|
|
case RP_MT: return aRect.TopCenter();
|
|
case RP_RT: return aRect.TopRight();
|
|
case RP_LM: return aRect.LeftCenter();
|
|
case RP_MM: return aRect.Center();
|
|
case RP_RM: return aRect.RightCenter();
|
|
case RP_LB: return aRect.BottomLeft();
|
|
case RP_MB: return aRect.BottomCenter();
|
|
case RP_RB: return aRect.BottomRight();
|
|
}
|
|
return Point(); // Should not happen!
|
|
}
|
|
|
|
void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr)
|
|
{
|
|
Rectangle aRect(GetMarkedObjRect());
|
|
|
|
if(GetSdrPageView())
|
|
{
|
|
GetSdrPageView()->LogicToPagePos(aRect);
|
|
}
|
|
|
|
long nOldRotateAngle=GetMarkedObjRotate();
|
|
long nOldShearAngle=GetMarkedObjShear();
|
|
const SdrMarkList& rMarkList=GetMarkedObjectList();
|
|
sal_uIntPtr nMarkCount=rMarkList.GetMarkCount();
|
|
SdrObject* pObj=NULL;
|
|
|
|
RECT_POINT eSizePoint=RP_MM;
|
|
long nPosDX=0;
|
|
long nPosDY=0;
|
|
long nSizX=0;
|
|
long nSizY=0;
|
|
long nRotateAngle=0;
|
|
|
|
sal_Bool bModeIsRotate(eDragMode == SDRDRAG_ROTATE);
|
|
long nRotateX(0);
|
|
long nRotateY(0);
|
|
long nOldRotateX(0);
|
|
long nOldRotateY(0);
|
|
if(bModeIsRotate)
|
|
{
|
|
Point aRotateAxe(aRef1);
|
|
|
|
if(GetSdrPageView())
|
|
{
|
|
GetSdrPageView()->LogicToPagePos(aRotateAxe);
|
|
}
|
|
|
|
nRotateX = nOldRotateX = aRotateAxe.X();
|
|
nRotateY = nOldRotateY = aRotateAxe.Y();
|
|
}
|
|
|
|
long nShearAngle=0;
|
|
long nShearX=0;
|
|
long nShearY=0;
|
|
sal_Bool bShearVert=sal_False;
|
|
|
|
sal_Bool bChgPos=sal_False;
|
|
sal_Bool bChgSiz=sal_False;
|
|
sal_Bool bRotate=sal_False;
|
|
sal_Bool bShear =sal_False;
|
|
|
|
sal_Bool bSetAttr=sal_False;
|
|
SfxItemSet aSetAttr(pMod->GetItemPool());
|
|
|
|
const SfxPoolItem* pPoolItem=NULL;
|
|
|
|
// position
|
|
if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_X,sal_True,&pPoolItem)) {
|
|
nPosDX=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Left();
|
|
bChgPos=sal_True;
|
|
}
|
|
if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_Y,sal_True,&pPoolItem)){
|
|
nPosDY=((const SfxInt32Item*)pPoolItem)->GetValue()-aRect.Top();
|
|
bChgPos=sal_True;
|
|
}
|
|
// size
|
|
if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_WIDTH,sal_True,&pPoolItem)) {
|
|
nSizX=((const SfxUInt32Item*)pPoolItem)->GetValue();
|
|
bChgSiz=sal_True;
|
|
}
|
|
if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_HEIGHT,sal_True,&pPoolItem)) {
|
|
nSizY=((const SfxUInt32Item*)pPoolItem)->GetValue();
|
|
bChgSiz=sal_True;
|
|
}
|
|
if (bChgSiz) {
|
|
eSizePoint=(RECT_POINT)((const SfxAllEnumItem&)rAttr.Get(SID_ATTR_TRANSFORM_SIZE_POINT)).GetValue();
|
|
}
|
|
|
|
// rotation
|
|
if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ANGLE,sal_True,&pPoolItem)) {
|
|
nRotateAngle=((const SfxInt32Item*)pPoolItem)->GetValue()-nOldRotateAngle;
|
|
bRotate = (nRotateAngle != 0);
|
|
}
|
|
|
|
// position rotation point x
|
|
if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_X, sal_True ,&pPoolItem))
|
|
nRotateX = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_X)).GetValue();
|
|
|
|
// position rotation point y
|
|
if(bRotate || SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_Y, sal_True ,&pPoolItem))
|
|
nRotateY = ((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_ROT_Y)).GetValue();
|
|
|
|
// shearing
|
|
if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_SHEAR,sal_True,&pPoolItem)) {
|
|
long nNewShearAngle=((const SfxInt32Item*)pPoolItem)->GetValue();
|
|
if (nNewShearAngle>SDRMAXSHEAR) nNewShearAngle=SDRMAXSHEAR;
|
|
if (nNewShearAngle<-SDRMAXSHEAR) nNewShearAngle=-SDRMAXSHEAR;
|
|
if (nNewShearAngle!=nOldShearAngle) {
|
|
bShearVert=((const SfxBoolItem&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_VERTICAL)).GetValue();
|
|
if (bShearVert) {
|
|
nShearAngle=nNewShearAngle;
|
|
} else {
|
|
if (nNewShearAngle!=0 && nOldShearAngle!=0) {
|
|
// bug fix
|
|
double nOld=tan((double)nOldShearAngle*nPi180);
|
|
double nNew=tan((double)nNewShearAngle*nPi180);
|
|
nNew-=nOld;
|
|
nNew=atan(nNew)/nPi180;
|
|
nShearAngle=Round(nNew);
|
|
} else {
|
|
nShearAngle=nNewShearAngle-nOldShearAngle;
|
|
}
|
|
}
|
|
bShear=nShearAngle!=0;
|
|
if (bShear) {
|
|
nShearX=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_X)).GetValue();
|
|
nShearY=((const SfxInt32Item&)rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_Y)).GetValue();
|
|
}
|
|
}
|
|
}
|
|
|
|
// AutoGrow
|
|
if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOWIDTH,sal_True,&pPoolItem)) {
|
|
sal_Bool bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue();
|
|
aSetAttr.Put(SdrTextAutoGrowWidthItem(bAutoGrow));
|
|
bSetAttr=sal_True;
|
|
}
|
|
|
|
if (SFX_ITEM_SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOHEIGHT,sal_True,&pPoolItem)) {
|
|
sal_Bool bAutoGrow=((const SfxBoolItem*)pPoolItem)->GetValue();
|
|
aSetAttr.Put(SdrTextAutoGrowHeightItem(bAutoGrow));
|
|
bSetAttr=sal_True;
|
|
}
|
|
|
|
// corner radius
|
|
if (bEdgeRadiusAllowed && SFX_ITEM_SET==rAttr.GetItemState(SDRATTR_ECKENRADIUS,sal_True,&pPoolItem)) {
|
|
long nRadius=((SdrEckenradiusItem*)pPoolItem)->GetValue();
|
|
aSetAttr.Put(SdrEckenradiusItem(nRadius));
|
|
bSetAttr=sal_True;
|
|
}
|
|
|
|
ForcePossibilities();
|
|
|
|
BegUndo(ImpGetResStr(STR_EditTransform),GetDescriptionOfMarkedObjects());
|
|
|
|
if (bSetAttr) {
|
|
SetAttrToMarked(aSetAttr,sal_False);
|
|
}
|
|
|
|
// change size and height
|
|
if (bChgSiz && (bResizeFreeAllowed || bResizePropAllowed)) {
|
|
Fraction aWdt(nSizX,aRect.Right()-aRect.Left());
|
|
Fraction aHgt(nSizY,aRect.Bottom()-aRect.Top());
|
|
Point aRef(ImpGetPoint(aRect,eSizePoint));
|
|
|
|
if(GetSdrPageView())
|
|
{
|
|
GetSdrPageView()->PagePosToLogic(aRef);
|
|
}
|
|
|
|
ResizeMarkedObj(aRef,aWdt,aHgt);
|
|
}
|
|
|
|
// rotate
|
|
if (bRotate && (bRotateFreeAllowed || bRotate90Allowed)) {
|
|
Point aRef(nRotateX,nRotateY);
|
|
|
|
if(GetSdrPageView())
|
|
{
|
|
GetSdrPageView()->PagePosToLogic(aRef);
|
|
}
|
|
|
|
RotateMarkedObj(aRef,nRotateAngle);
|
|
}
|
|
|
|
// set rotation point position
|
|
if(bModeIsRotate && (nRotateX != nOldRotateX || nRotateY != nOldRotateY))
|
|
{
|
|
Point aNewRef1(nRotateX, nRotateY);
|
|
|
|
if(GetSdrPageView())
|
|
{
|
|
GetSdrPageView()->PagePosToLogic(aNewRef1);
|
|
}
|
|
|
|
SetRef1(aNewRef1);
|
|
}
|
|
|
|
// shear
|
|
if (bShear && bShearAllowed) {
|
|
Point aRef(nShearX,nShearY);
|
|
|
|
if(GetSdrPageView())
|
|
{
|
|
GetSdrPageView()->PagePosToLogic(aRef);
|
|
}
|
|
|
|
ShearMarkedObj(aRef,nShearAngle,bShearVert);
|
|
|
|
// #i74358#
|
|
// ShearMarkedObj creates a linear combination of the existing transformation and
|
|
// the new shear to apply. If the object is already transformed (e.g. rotated) the
|
|
// linear combination will not decompose to the same start values again, but to a
|
|
// new combination. Thus it makes no sense to check if the wanted shear is reached
|
|
// or not. Taking out.
|
|
}
|
|
|
|
// change position
|
|
if (bChgPos && bMoveAllowed) {
|
|
MoveMarkedObj(Size(nPosDX,nPosDY));
|
|
}
|
|
|
|
// protect position
|
|
if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_POS, sal_True, &pPoolItem))
|
|
{
|
|
const bool bProtPos(((const SfxBoolItem*)pPoolItem)->GetValue());
|
|
bool bChanged(false);
|
|
|
|
for(sal_uInt32 i(0); i < nMarkCount; i++)
|
|
{
|
|
pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
|
|
if(pObj->IsMoveProtect() != bProtPos)
|
|
{
|
|
bChanged = true;
|
|
pObj->SetMoveProtect(bProtPos);
|
|
|
|
if(bProtPos)
|
|
{
|
|
pObj->SetResizeProtect(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(bChanged)
|
|
{
|
|
bMoveProtect = bProtPos;
|
|
|
|
if(bProtPos)
|
|
{
|
|
bResizeProtect = true;
|
|
}
|
|
|
|
// #i77187# there is no simple method to get the toolbars updated
|
|
// in the application. The App is listening to selection change and i
|
|
// will use it here (even if not true). It's acceptable since changing
|
|
// this model data is pretty rare and only possible using the F4 dialog
|
|
MarkListHasChanged();
|
|
}
|
|
}
|
|
|
|
if(!bMoveProtect)
|
|
{
|
|
// protect size
|
|
if(SFX_ITEM_SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_SIZE, sal_True, &pPoolItem))
|
|
{
|
|
const bool bProtSize(((const SfxBoolItem*)pPoolItem)->GetValue());
|
|
bool bChanged(false);
|
|
|
|
for(sal_uInt32 i(0); i < nMarkCount; i++)
|
|
{
|
|
pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
|
|
if(pObj->IsResizeProtect() != bProtSize)
|
|
{
|
|
bChanged = true;
|
|
pObj->SetResizeProtect(bProtSize);
|
|
}
|
|
}
|
|
|
|
if(bChanged)
|
|
{
|
|
bResizeProtect = bProtSize;
|
|
|
|
// #i77187# see above
|
|
MarkListHasChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
EndUndo();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
sal_Bool SdrEditView::IsAlignPossible() const
|
|
{ // at least two selected objects, at least one of them movable
|
|
ForcePossibilities();
|
|
sal_uIntPtr nAnz=GetMarkedObjectCount();
|
|
if (nAnz==0) return sal_False; // nothing selected!
|
|
if (nAnz==1) return bMoveAllowed; // align single object to page
|
|
return bOneOrMoreMovable; // otherwise: MarkCount>=2
|
|
}
|
|
|
|
void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert, sal_Bool bBoundRects)
|
|
{
|
|
if (eHor==SDRHALIGN_NONE && eVert==SDRVALIGN_NONE)
|
|
return;
|
|
|
|
SortMarkedObjects();
|
|
if (GetMarkedObjectCount()<1)
|
|
return;
|
|
|
|
const bool bUndo = IsUndoEnabled();
|
|
if( bUndo )
|
|
{
|
|
XubString aStr(GetDescriptionOfMarkedObjects());
|
|
if (eHor==SDRHALIGN_NONE)
|
|
{
|
|
switch (eVert)
|
|
{
|
|
case SDRVALIGN_TOP : ImpTakeDescriptionStr(STR_EditAlignVTop ,aStr); break;
|
|
case SDRVALIGN_BOTTOM: ImpTakeDescriptionStr(STR_EditAlignVBottom,aStr); break;
|
|
case SDRVALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignVCenter,aStr); break;
|
|
default: break;
|
|
}
|
|
}
|
|
else if (eVert==SDRVALIGN_NONE)
|
|
{
|
|
switch (eHor)
|
|
{
|
|
case SDRHALIGN_LEFT : ImpTakeDescriptionStr(STR_EditAlignHLeft ,aStr); break;
|
|
case SDRHALIGN_RIGHT : ImpTakeDescriptionStr(STR_EditAlignHRight ,aStr); break;
|
|
case SDRHALIGN_CENTER: ImpTakeDescriptionStr(STR_EditAlignHCenter,aStr); break;
|
|
default: break;
|
|
}
|
|
}
|
|
else if (eHor==SDRHALIGN_CENTER && eVert==SDRVALIGN_CENTER)
|
|
{
|
|
ImpTakeDescriptionStr(STR_EditAlignCenter,aStr);
|
|
}
|
|
else
|
|
{
|
|
ImpTakeDescriptionStr(STR_EditAlign,aStr);
|
|
}
|
|
BegUndo(aStr);
|
|
}
|
|
|
|
Rectangle aBound;
|
|
sal_uIntPtr nMarkAnz=GetMarkedObjectCount();
|
|
sal_uIntPtr nm;
|
|
sal_Bool bHasFixed=sal_False;
|
|
for (nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pObj=pM->GetMarkedSdrObj();
|
|
SdrObjTransformInfoRec aInfo;
|
|
pObj->TakeObjInfo(aInfo);
|
|
if (!aInfo.bMoveAllowed || pObj->IsMoveProtect())
|
|
{
|
|
Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
|
|
aBound.Union(aObjRect);
|
|
bHasFixed=sal_True;
|
|
}
|
|
}
|
|
if (!bHasFixed)
|
|
{
|
|
if (nMarkAnz==1)
|
|
{ // align single object to page
|
|
const SdrObject* pObj=GetMarkedObjectByIndex(0L);
|
|
const SdrPage* pPage=pObj->GetPage();
|
|
const SdrPageGridFrameList* pGFL=pPage->GetGridFrameList(GetSdrPageViewOfMarkedByIndex(0),&(pObj->GetSnapRect()));
|
|
const SdrPageGridFrame* pFrame=NULL;
|
|
if (pGFL!=NULL && pGFL->GetCount()!=0)
|
|
{ // Writer
|
|
pFrame=&((*pGFL)[0]);
|
|
}
|
|
|
|
if (pFrame!=NULL)
|
|
{ // Writer
|
|
aBound=pFrame->GetUserArea();
|
|
}
|
|
else
|
|
{
|
|
aBound=Rectangle(pPage->GetLftBorder(),pPage->GetUppBorder(),
|
|
pPage->GetWdt()-pPage->GetRgtBorder(),
|
|
pPage->GetHgt()-pPage->GetLwrBorder());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bBoundRects)
|
|
aBound=GetMarkedObjBoundRect();
|
|
else
|
|
aBound=GetMarkedObjRect();
|
|
}
|
|
}
|
|
Point aCenter(aBound.Center());
|
|
for (nm=0; nm<nMarkAnz; nm++)
|
|
{
|
|
SdrMark* pM=GetSdrMarkByIndex(nm);
|
|
SdrObject* pObj=pM->GetMarkedSdrObj();
|
|
SdrObjTransformInfoRec aInfo;
|
|
pObj->TakeObjInfo(aInfo);
|
|
if (aInfo.bMoveAllowed && !pObj->IsMoveProtect())
|
|
{
|
|
long nXMov=0;
|
|
long nYMov=0;
|
|
Rectangle aObjRect(bBoundRects?pObj->GetCurrentBoundRect():pObj->GetSnapRect());
|
|
switch (eVert)
|
|
{
|
|
case SDRVALIGN_TOP : nYMov=aBound.Top() -aObjRect.Top() ; break;
|
|
case SDRVALIGN_BOTTOM: nYMov=aBound.Bottom()-aObjRect.Bottom() ; break;
|
|
case SDRVALIGN_CENTER: nYMov=aCenter.Y() -aObjRect.Center().Y(); break;
|
|
default: break;
|
|
}
|
|
switch (eHor)
|
|
{
|
|
case SDRHALIGN_LEFT : nXMov=aBound.Left() -aObjRect.Left() ; break;
|
|
case SDRHALIGN_RIGHT : nXMov=aBound.Right() -aObjRect.Right() ; break;
|
|
case SDRHALIGN_CENTER: nXMov=aCenter.X() -aObjRect.Center().X(); break;
|
|
default: break;
|
|
}
|
|
if (nXMov!=0 || nYMov!=0)
|
|
{
|
|
// SdrEdgeObj needs an extra SdrUndoGeoObj since the
|
|
// connections may need to be saved
|
|
if( bUndo )
|
|
{
|
|
if( dynamic_cast<SdrEdgeObj*>(pObj) )
|
|
{
|
|
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
|
|
}
|
|
|
|
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,Size(nXMov,nYMov)));
|
|
}
|
|
|
|
pObj->Move(Size(nXMov,nYMov));
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|