summaryrefslogtreecommitdiff
path: root/sw/source/core/draw/dview.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/draw/dview.cxx')
-rw-r--r--sw/source/core/draw/dview.cxx1071
1 files changed, 1071 insertions, 0 deletions
diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
new file mode 100644
index 000000000000..4827627f6ef1
--- /dev/null
+++ b/sw/source/core/draw/dview.cxx
@@ -0,0 +1,1071 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include <editeng/protitem.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/fmmodel.hxx>
+#include <sot/exchange.hxx>
+
+#include "swtypes.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "flyfrm.hxx"
+#include "frmfmt.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "frmatr.hxx"
+#include "viewsh.hxx"
+#include "viewimp.hxx"
+#include "dview.hxx"
+#include "dpage.hxx"
+#include "doc.hxx"
+#include "mdiexp.hxx"
+#include <ndole.hxx>
+#include <fmtanchr.hxx>
+#include "shellres.hxx"
+#include <IDocumentUndoRedo.hxx>
+
+// #i7672#
+#include <editeng/outliner.hxx>
+
+#include <com/sun/star/embed/EmbedMisc.hpp>
+
+#include <vector>
+// --> OD 2004-06-24 #i28701#
+#include <sortedobjs.hxx>
+#include <flyfrms.hxx>
+// <--
+
+
+using namespace com::sun::star;
+
+
+class SwSdrHdl : public SdrHdl
+{
+public:
+ SwSdrHdl(const Point& rPnt, bool bTopRight ) :
+ SdrHdl( rPnt, bTopRight ? HDL_ANCHOR_TR : HDL_ANCHOR ) {}
+ virtual sal_Bool IsFocusHdl() const;
+};
+
+sal_Bool SwSdrHdl::IsFocusHdl() const
+{
+ if( HDL_ANCHOR == eKind || HDL_ANCHOR_TR == eKind )
+ return sal_True;
+ return SdrHdl::IsFocusHdl();
+}
+
+const SwFrm *lcl_FindAnchor( const SdrObject *pObj, sal_Bool bAll )
+{
+ const SwVirtFlyDrawObj *pVirt = pObj->ISA(SwVirtFlyDrawObj) ?
+ (SwVirtFlyDrawObj*)pObj : 0;
+ if ( pVirt )
+ {
+ if ( bAll || !pVirt->GetFlyFrm()->IsFlyInCntFrm() )
+ return pVirt->GetFlyFrm()->GetAnchorFrm();
+ }
+ else
+ {
+ const SwDrawContact *pCont = (const SwDrawContact*)GetUserCall(pObj);
+ if ( pCont )
+ return pCont->GetAnchorFrm( pObj );
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::Ctor
+|*
+*************************************************************************/
+
+
+
+SwDrawView::SwDrawView( SwViewImp &rI, SdrModel *pMd, OutputDevice *pOutDev) :
+ FmFormView( (FmFormModel*)pMd, pOutDev ),
+ rImp( rI )
+{
+ SetPageVisible( sal_False );
+ SetBordVisible( sal_False );
+ SetGridVisible( sal_False );
+ SetHlplVisible( sal_False );
+ SetGlueVisible( sal_False );
+ SetFrameDragSingles( sal_True );
+ SetVirtualObjectBundling( sal_True );
+ SetSwapAsynchron( sal_True );
+
+ EnableExtendedKeyInputDispatcher( sal_False );
+ EnableExtendedMouseEventDispatcher( sal_False );
+ EnableExtendedCommandEventDispatcher( sal_False );
+
+ SetHitTolerancePixel( GetMarkHdlSizePixel()/2 );
+
+ SetPrintPreview( rI.GetShell()->IsPreView() );
+
+ // #i73602# Use default from the configuration
+ SetBufferedOverlayAllowed(getOptionsDrawinglayer().IsOverlayBuffer_Writer());
+
+ // #i74769#, #i75172# Use default from the configuration
+ SetBufferedOutputAllowed(getOptionsDrawinglayer().IsPaintBuffer_Writer());
+}
+
+// --> OD 2009-03-05 #i99665#
+sal_Bool SwDrawView::IsAntiAliasing() const
+{
+ return getOptionsDrawinglayer().IsAntiAliasing();
+}
+// <--
+
+//////////////////////////////////////////////////////////////////////////////
+
+SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol, const SdrMarkList &rMrkList)
+{
+ if(!nTol)
+ {
+ // the old method forced back to outer bounds test when nTol == 0, so
+ // do not try to correct when nTol is not set (used from HelpContent)
+ }
+ else
+ {
+ // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since
+ // the SdrObject-specific CheckHit implementations are now replaced with primitives and
+ // 'tricks' like in the old implementation (e.g. using a view from a model-data class to
+ // detect if object is selected) are no longer valid.
+ // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old
+ // implementation reduced this excluding the inner bound when the object was not selected.
+ SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(pRetval);
+
+ if(pSwVirtFlyDrawObj)
+ {
+ if(pSwVirtFlyDrawObj->GetFlyFrm()->Lower() && pSwVirtFlyDrawObj->GetFlyFrm()->Lower()->IsNoTxtFrm())
+ {
+ // the old method used IsNoTxtFrm (should be for SW's own OLE and
+ // graphic's) to accept hit only based on outer bounds; nothing to do
+ }
+ else
+ {
+ // check if the object is selected in this view
+ const sal_uInt32 nMarkCount(rMrkList.GetMarkCount());
+ bool bSelected(false);
+
+ for(sal_uInt32 a(0); !bSelected && a < nMarkCount; a++)
+ {
+ if(pSwVirtFlyDrawObj == rMrkList.GetMark(a)->GetMarkedSdrObj())
+ {
+ bSelected = true;
+ }
+ }
+
+ if(!bSelected)
+ {
+ // when not selected, the object is not hit when hit position is inside
+ // inner range. Get and shrink inner range
+ basegfx::B2DRange aInnerBound(pSwVirtFlyDrawObj->getInnerBound());
+
+ aInnerBound.grow(-1.0 * nTol);
+
+ if(aInnerBound.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y())))
+ {
+ // exclude this hit
+ pRetval = 0;
+ }
+ }
+ }
+ }
+ }
+
+ return pRetval;
+}
+
+SdrObject* SwDrawView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, sal_uLong nOptions, const SetOfByte* pMVisLay) const
+{
+ // call parent
+ SdrObject* pRetval = FmFormView::CheckSingleSdrObjectHit(rPnt, nTol, pObj, pPV, nOptions, pMVisLay);
+
+ if(pRetval)
+ {
+ // overloaded to allow extra handling when picking SwVirtFlyDrawObj's
+ pRetval = impLocalHitCorrection(pRetval, rPnt, nTol, GetMarkedObjectList());
+ }
+
+ return pRetval;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::AddCustomHdl()
+|*
+|* Gets called every time the handles need to be build
+|*
+*************************************************************************/
+
+void SwDrawView::AddCustomHdl()
+{
+ const SdrMarkList &rMrkList = GetMarkedObjectList();
+
+ if(rMrkList.GetMarkCount() != 1 || !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()))
+ return;
+
+ SdrObject *pObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
+ // make code robust
+ SwFrmFmt* pFrmFmt( ::FindFrmFmt( pObj ) );
+ if ( !pFrmFmt )
+ {
+ OSL_FAIL( "<SwDrawView::AddCustomHdl()> - missing frame format!" );
+ return;
+ }
+ const SwFmtAnchor &rAnchor = pFrmFmt->GetAnchor();
+
+ if (FLY_AS_CHAR == rAnchor.GetAnchorId())
+ return;
+
+ const SwFrm* pAnch;
+ if(0 == (pAnch = CalcAnchor()))
+ return;
+
+ Point aPos(aAnchorPoint);
+
+ if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
+ {
+ // --> OD 2004-06-24 #i28701# - use last character rectangle saved at object
+ // in order to avoid a format of the anchor frame
+ SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
+ SwRect aAutoPos = pAnchoredObj->GetLastCharRect();
+ if ( aAutoPos.Height() )
+ {
+ aPos = aAutoPos.Pos();
+ }
+ }
+
+ // add anchor handle:
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ aHdl.AddHdl( new SwSdrHdl( aPos, ( pAnch->IsVertical() && !pAnch->IsVertLR() ) ||
+ pAnch->IsRightToLeft() ) );
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::GetMaxToTopObj(), _GetMaxToTopObj()
+|*
+*************************************************************************/
+
+
+SdrObject* SwDrawView::GetMaxToTopObj( SdrObject* pObj ) const
+{
+ if ( GetUserCall(pObj) )
+ {
+ const SwFrm *pAnch = ::lcl_FindAnchor( pObj, sal_False );
+ if ( pAnch )
+ {
+ //Das oberste Obj innerhalb des Ankers darf nicht ueberholt
+ //werden.
+ const SwFlyFrm *pFly = pAnch->FindFlyFrm();
+ if ( pFly )
+ {
+ const SwPageFrm *pPage = pFly->FindPageFrm();
+ if ( pPage->GetSortedObjs() )
+ {
+ sal_uInt32 nOrdNum = 0;
+ for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i )
+ {
+ const SdrObject *pO =
+ (*pPage->GetSortedObjs())[i]->GetDrawObj();
+
+ if ( pO->GetOrdNumDirect() > nOrdNum )
+ {
+ const SwFrm *pTmpAnch = ::lcl_FindAnchor( pO, sal_False );
+ if ( pFly->IsAnLower( pTmpAnch ) )
+ {
+ nOrdNum = pO->GetOrdNumDirect();
+ }
+ }
+ }
+ if ( nOrdNum )
+ {
+ SdrPage *pTmpPage = GetModel()->GetPage( 0 );
+ ++nOrdNum;
+ if ( nOrdNum < pTmpPage->GetObjCount() )
+ {
+ return pTmpPage->GetObj( nOrdNum );
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::GetMaxToBtmObj()
+|*
+*************************************************************************/
+
+
+SdrObject* SwDrawView::GetMaxToBtmObj(SdrObject* pObj) const
+{
+ if ( GetUserCall(pObj) )
+ {
+ const SwFrm *pAnch = ::lcl_FindAnchor( pObj, sal_False );
+ if ( pAnch )
+ {
+ //Der Fly des Ankers darf nicht "unterflogen" werden.
+ const SwFlyFrm *pFly = pAnch->FindFlyFrm();
+ if ( pFly )
+ {
+ SdrObject *pRet = (SdrObject*)pFly->GetVirtDrawObj();
+ return pRet != pObj ? pRet : 0;
+ }
+ }
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::ObjOrderChanged()
+|*
+*************************************************************************/
+
+inline sal_Bool lcl_IsChild( SdrObject *pParent, SdrObject *pChild )
+{
+ if ( pParent->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFrm *pAnch = lcl_FindAnchor( pChild, sal_False );
+ if ( pAnch && ((SwVirtFlyDrawObj*)pParent)->GetFlyFrm()->IsAnLower( pAnch ))
+ {
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+inline SdrObject *lcl_FindParent( SdrObject *pObj )
+{
+ const SwFrm *pAnch = lcl_FindAnchor( pObj, sal_False );
+ if ( pAnch && pAnch->IsInFly() )
+ return (SdrObject*)pAnch->FindFlyFrm()->GetVirtDrawObj();
+ return 0;
+}
+
+/** determine maximal order number for a 'child' object of given 'parent' object
+
+ @author OD
+*/
+sal_uInt32 SwDrawView::_GetMaxChildOrdNum( const SwFlyFrm& _rParentObj,
+ const SdrObject* _pExclChildObj ) const
+{
+ sal_uInt32 nMaxChildOrdNum = _rParentObj.GetDrawObj()->GetOrdNum();
+
+ const SdrPage* pDrawPage = _rParentObj.GetDrawObj()->GetPage();
+ OSL_ENSURE( pDrawPage,
+ "<SwDrawView::_GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!" );
+
+ sal_uInt32 nObjCount = pDrawPage->GetObjCount();
+ for ( sal_uInt32 i = nObjCount-1; i > _rParentObj.GetDrawObj()->GetOrdNum() ; --i )
+ {
+ const SdrObject* pObj = pDrawPage->GetObj( i );
+
+ // Don't consider 'child' object <_pExclChildObj>
+ if ( pObj == _pExclChildObj )
+ {
+ continue;
+ }
+
+ if ( pObj->GetOrdNum() > nMaxChildOrdNum &&
+ _rParentObj.IsAnLower( lcl_FindAnchor( pObj, sal_True ) ) )
+ {
+ nMaxChildOrdNum = pObj->GetOrdNum();
+ break;
+ }
+ }
+
+ return nMaxChildOrdNum;
+}
+
+/** method to move 'repeated' objects of the given moved object to the
+ according level
+
+ @author OD
+*/
+void SwDrawView::_MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj,
+ const std::vector<SdrObject*>& _rMovedChildObjs ) const
+{
+ // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
+ std::list<SwAnchoredObject*> aAnchoredObjs;
+ {
+ const SwContact* pContact = ::GetUserCall( _rMovedAnchoredObj.GetDrawObj() );
+ OSL_ENSURE( pContact,
+ "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash." );
+ pContact->GetAnchoredObjs( aAnchoredObjs );
+ }
+
+ // check, if 'repeated' objects exists.
+ if ( aAnchoredObjs.size() > 1 )
+ {
+ SdrPage* pDrawPage = GetModel()->GetPage( 0 );
+
+ // move 'repeated' ones to the same order number as the already moved one.
+ sal_uInt32 nNewPos = _rMovedAnchoredObj.GetDrawObj()->GetOrdNum();
+ while ( !aAnchoredObjs.empty() )
+ {
+ SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
+ if ( pAnchoredObj != &_rMovedAnchoredObj )
+ {
+ pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
+ nNewPos );
+ pDrawPage->RecalcObjOrdNums();
+ // adjustments for accessibility API
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj);
+ rImp.DisposeAccessibleFrm( pTmpFlyFrm );
+ rImp.AddAccessibleFrm( pTmpFlyFrm );
+ }
+ else
+ {
+ rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() );
+ rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
+ }
+ }
+ aAnchoredObjs.pop_back();
+ }
+
+ // move 'repeated' ones of 'child' objects
+ for ( std::vector<SdrObject*>::const_iterator aObjIter = _rMovedChildObjs.begin();
+ aObjIter != _rMovedChildObjs.end(); ++aObjIter )
+ {
+ SdrObject* pChildObj = (*aObjIter);
+ {
+ const SwContact* pContact = ::GetUserCall( pChildObj );
+ OSL_ENSURE( pContact,
+ "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash." );
+ pContact->GetAnchoredObjs( aAnchoredObjs );
+ }
+ // move 'repeated' ones to the same order number as the already moved one.
+ const sal_uInt32 nTmpNewPos = pChildObj->GetOrdNum();
+ while ( !aAnchoredObjs.empty() )
+ {
+ SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
+ if ( pAnchoredObj->GetDrawObj() != pChildObj )
+ {
+ pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
+ nTmpNewPos );
+ pDrawPage->RecalcObjOrdNums();
+ // adjustments for accessibility API
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj);
+ rImp.DisposeAccessibleFrm( pTmpFlyFrm );
+ rImp.AddAccessibleFrm( pTmpFlyFrm );
+ }
+ else
+ {
+ rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() );
+ rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
+ }
+ }
+ aAnchoredObjs.pop_back();
+ }
+ }
+ }
+}
+
+// --> adjustment and re-factoring of method
+void SwDrawView::ObjOrderChanged( SdrObject* pObj, sal_uLong nOldPos,
+ sal_uLong nNewPos )
+{
+ // nothing to do for group members
+ if ( pObj->GetUpGroup() )
+ {
+ return;
+ }
+
+ // determine drawing page and assure that the order numbers are correct.
+ SdrPage* pDrawPage = GetModel()->GetPage( 0 );
+ if ( pDrawPage->IsObjOrdNumsDirty() )
+ pDrawPage->RecalcObjOrdNums();
+ const sal_uInt32 nObjCount = pDrawPage->GetObjCount();
+
+ SwAnchoredObject* pMovedAnchoredObj =
+ ::GetUserCall( pObj )->GetAnchoredObj( pObj );
+ const SwFlyFrm* pParentAnchoredObj =
+ pMovedAnchoredObj->GetAnchorFrm()->FindFlyFrm();
+
+ const bool bMovedForward = nOldPos < nNewPos;
+
+ // assure for a 'child' object, that it doesn't exceed the limits of its 'parent'
+ if ( pParentAnchoredObj )
+ {
+ if ( bMovedForward )
+ {
+ sal_uInt32 nMaxChildOrdNumWithoutMoved =
+ _GetMaxChildOrdNum( *pParentAnchoredObj, pMovedAnchoredObj->GetDrawObj() );
+ if ( nNewPos > nMaxChildOrdNumWithoutMoved+1 )
+ {
+ // set position to the top of the 'child' object group
+ pDrawPage->SetObjectOrdNum( nNewPos, nMaxChildOrdNumWithoutMoved+1 );
+ nNewPos = nMaxChildOrdNumWithoutMoved+1;
+ }
+ }
+ else
+ {
+ const sal_uInt32 nParentOrdNum = pParentAnchoredObj->GetDrawObj()->GetOrdNum();
+ if ( nNewPos < nParentOrdNum )
+ {
+ // set position to the bottom of the 'child' object group
+ pDrawPage->SetObjectOrdNum( nNewPos, nParentOrdNum );
+ nNewPos = nParentOrdNum;
+ }
+ }
+ if ( pDrawPage->IsObjOrdNumsDirty() )
+ pDrawPage->RecalcObjOrdNums();
+ }
+
+ // Assure, that object isn't positioned between 'repeated' ones
+ if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
+ ( !bMovedForward && nNewPos > 0 ) )
+ {
+ const SdrObject* pTmpObj =
+ pDrawPage->GetObj( bMovedForward ? nNewPos - 1 : nNewPos + 1 );
+ if ( pTmpObj )
+ {
+ sal_uInt32 nTmpNewPos( nNewPos );
+ if ( bMovedForward )
+ {
+ // move before the top 'repeated' object
+ const sal_uInt32 nTmpMaxOrdNum =
+ ::GetUserCall( pTmpObj )->GetMaxOrdNum();
+ if ( nTmpMaxOrdNum > nNewPos )
+ nTmpNewPos = nTmpMaxOrdNum;
+ }
+ else
+ {
+ // move behind the bottom 'repeated' object
+ const sal_uInt32 nTmpMinOrdNum =
+ ::GetUserCall( pTmpObj )->GetMinOrdNum();
+ if ( nTmpMinOrdNum < nNewPos )
+ nTmpNewPos = nTmpMinOrdNum;
+ }
+ if ( nTmpNewPos != nNewPos )
+ {
+ pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
+ nNewPos = nTmpNewPos;
+ pDrawPage->RecalcObjOrdNums();
+ }
+ }
+ }
+
+ // On move forward, assure that object is moved before its own childs.
+ // Only Writer fly frames can have childs.
+ if ( pMovedAnchoredObj->ISA(SwFlyFrm) &&
+ bMovedForward && nNewPos < nObjCount - 1 )
+ {
+ sal_uInt32 nMaxChildOrdNum =
+ _GetMaxChildOrdNum( *(static_cast<const SwFlyFrm*>(pMovedAnchoredObj)) );
+ if ( nNewPos < nMaxChildOrdNum )
+ {
+ // determine position before the object before its top 'child' object
+ const SdrObject* pTmpObj = pDrawPage->GetObj( nMaxChildOrdNum );
+ sal_uInt32 nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum() + 1;
+ if ( nTmpNewPos >= nObjCount )
+ {
+ --nTmpNewPos;
+ }
+ // assure, that determined position isn't between 'repeated' objects
+ pTmpObj = pDrawPage->GetObj( nTmpNewPos );
+ nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
+ // apply new position
+ pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
+ nNewPos = nTmpNewPos;
+ pDrawPage->RecalcObjOrdNums();
+ }
+ }
+
+ // Assure, that object isn't positioned between nested objects
+ if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
+ ( !bMovedForward && nNewPos > 0 ) )
+ {
+ sal_uInt32 nTmpNewPos( nNewPos );
+ const SwFrmFmt* pParentFrmFmt =
+ pParentAnchoredObj ? &(pParentAnchoredObj->GetFrmFmt()) : 0L;
+ const SdrObject* pTmpObj = pDrawPage->GetObj( nNewPos + 1 );
+ while ( pTmpObj )
+ {
+ // --> OD 2004-12-07 #i38563# - assure, that anchor frame exists.
+ // If object is anchored inside a invisible part of the document
+ // (e.g. page header, whose page style isn't applied, or hidden
+ // section), no anchor frame exists.
+ const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, sal_True );
+ const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm
+ ? pTmpAnchorFrm->FindFlyFrm() : 0L;
+ // <--
+ if ( pTmpParentObj &&
+ &(pTmpParentObj->GetFrmFmt()) != pParentFrmFmt )
+ {
+ if ( bMovedForward )
+ {
+ nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
+ pTmpObj = pDrawPage->GetObj( nTmpNewPos + 1 );
+ }
+ else
+ {
+ nTmpNewPos = ::GetUserCall( pTmpParentObj->GetDrawObj() )
+ ->GetMinOrdNum();
+ pTmpObj = pTmpParentObj->GetDrawObj();
+ }
+ }
+ else
+ break;
+ }
+ if ( nTmpNewPos != nNewPos )
+ {
+ pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
+ nNewPos = nTmpNewPos;
+ pDrawPage->RecalcObjOrdNums();
+ }
+ }
+
+ // setup collection of moved 'child' objects to move its 'repeated' objects.
+ std::vector< SdrObject* > aMovedChildObjs;
+
+ // move 'childs' accordingly
+ if ( pMovedAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pMovedAnchoredObj);
+
+ // adjustments for accessibility API
+ rImp.DisposeAccessibleFrm( pFlyFrm );
+ rImp.AddAccessibleFrm( pFlyFrm );
+
+ const sal_uInt32 nChildNewPos = bMovedForward ? nNewPos : nNewPos+1;
+ sal_uInt32 i = bMovedForward ? nOldPos : nObjCount-1;
+ do
+ {
+ SdrObject* pTmpObj = pDrawPage->GetObj( i );
+ if ( pTmpObj == pObj )
+ break;
+
+ // --> OD 2004-12-07 #i38563# - assure, that anchor frame exists.
+ // If object is anchored inside a invisible part of the document
+ // (e.g. page header, whose page style isn't applied, or hidden
+ // section), no anchor frame exists.
+ const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, sal_True );
+ const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm
+ ? pTmpAnchorFrm->FindFlyFrm() : 0L;
+ // <--
+ if ( pTmpParentObj &&
+ ( ( pTmpParentObj == pFlyFrm ) ||
+ ( pFlyFrm->IsUpperOf( *pTmpParentObj ) ) ) )
+ {
+ // move child object.,
+ pDrawPage->SetObjectOrdNum( i, nChildNewPos );
+ pDrawPage->RecalcObjOrdNums();
+ // collect 'child' object
+ aMovedChildObjs.push_back( pTmpObj );
+ // adjustments for accessibility API
+ if ( pTmpObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm *pTmpFlyFrm =
+ static_cast<SwVirtFlyDrawObj*>(pTmpObj)->GetFlyFrm();
+ rImp.DisposeAccessibleFrm( pTmpFlyFrm );
+ rImp.AddAccessibleFrm( pTmpFlyFrm );
+ }
+ else
+ {
+ rImp.DisposeAccessibleObj( pTmpObj );
+ rImp.AddAccessibleObj( pTmpObj );
+ }
+ }
+ else
+ {
+ // adjust loop counter
+ if ( bMovedForward )
+ ++i;
+ else if ( !bMovedForward && i > 0 )
+ --i;
+ }
+
+ } while ( ( bMovedForward && i < ( nObjCount - aMovedChildObjs.size() ) ) ||
+ ( !bMovedForward && i > ( nNewPos + aMovedChildObjs.size() ) ) );
+ }
+ else
+ {
+ // adjustments for accessibility API
+ rImp.DisposeAccessibleObj( pObj );
+ rImp.AddAccessibleObj( pObj );
+ }
+
+ _MoveRepeatedObjs( *pMovedAnchoredObj, aMovedChildObjs );
+}
+// <--
+
+/*************************************************************************
+|*
+|* SwDrawView::TakeDragLimit()
+|*
+*************************************************************************/
+
+
+sal_Bool SwDrawView::TakeDragLimit( SdrDragMode eMode,
+ Rectangle& rRect ) const
+{
+ const SdrMarkList &rMrkList = GetMarkedObjectList();
+ sal_Bool bRet = sal_False;
+ if( 1 == rMrkList.GetMarkCount() )
+ {
+ const SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ SwRect aRect;
+ if( ::CalcClipRect( pObj, aRect, eMode == SDRDRAG_MOVE ) )
+ {
+ rRect = aRect.SVRect();
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::CalcAnchor()
+|*
+*************************************************************************/
+
+
+const SwFrm* SwDrawView::CalcAnchor()
+{
+ const SdrMarkList &rMrkList = GetMarkedObjectList();
+ if ( rMrkList.GetMarkCount() != 1 )
+ return NULL;
+
+ SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ //Fuer Absatzgebundene Objekte suchen, andernfalls einfach nur
+ //der aktuelle Anker. Nur suchen wenn wir gerade draggen.
+ const SwFrm* pAnch;
+ Rectangle aMyRect;
+ const sal_Bool bFly = pObj->ISA(SwVirtFlyDrawObj);
+ if ( bFly )
+ {
+ pAnch = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetAnchorFrm();
+ aMyRect = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->Frm().SVRect();
+ }
+ else
+ {
+ SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
+ // determine correct anchor position for 'virtual' drawing objects.
+ // #i26791#
+ pAnch = pC->GetAnchorFrm( pObj );
+ if( !pAnch )
+ {
+ pC->ConnectToLayout();
+ // determine correct anchor position for 'virtual' drawing objects.
+ // #i26791#
+ pAnch = pC->GetAnchorFrm( pObj );
+ }
+ aMyRect = pObj->GetSnapRect();
+ }
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ const sal_Bool bTopRight = pAnch && ( ( pAnch->IsVertical() &&
+ !pAnch->IsVertLR() ) ||
+ pAnch->IsRightToLeft() );
+ const Point aMyPt = bTopRight ? aMyRect.TopRight() : aMyRect.TopLeft();
+
+ Point aPt;
+ if ( IsAction() )
+ {
+ if ( !TakeDragObjAnchorPos( aPt, bTopRight ) )
+ return NULL;
+ }
+ else
+ {
+ Rectangle aRect = pObj->GetSnapRect();
+ aPt = bTopRight ? aRect.TopRight() : aRect.TopLeft();
+ }
+
+ if ( aPt != aMyPt )
+ {
+ if ( pAnch->IsCntntFrm() )
+ {
+ // allow drawing objects in header/footer,
+ // but exclude control objects.
+ bool bBodyOnly = CheckControlLayer( pObj );
+ pAnch = ::FindAnchor( (SwCntntFrm*)pAnch, aPt, bBodyOnly );
+ }
+ else if ( !bFly )
+ {
+ const SwRect aRect( aPt.X(), aPt.Y(), 1, 1 );
+
+ SwDrawContact* pContact = (SwDrawContact*)GetUserCall(pObj);
+ if ( pContact->GetAnchorFrm( pObj ) &&
+ pContact->GetAnchorFrm( pObj )->IsPageFrm() )
+ pAnch = pContact->GetPageFrm();
+ else
+ pAnch = pContact->FindPage( aRect );
+ }
+ }
+ if( pAnch && !pAnch->IsProtected() )
+ aAnchorPoint = pAnch->GetFrmAnchorPos( ::HasWrap( pObj ) );
+ else
+ pAnch = 0;
+ return pAnch;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::ShowDragXor(), HideDragXor()
+|*
+*************************************************************************/
+
+
+void SwDrawView::ShowDragAnchor()
+{
+ SdrHdl* pHdl = aHdl.GetHdl(HDL_ANCHOR);
+ if ( ! pHdl )
+ pHdl = aHdl.GetHdl(HDL_ANCHOR_TR);
+
+ if(pHdl)
+ {
+ CalcAnchor();
+ pHdl->SetPos(aAnchorPoint);
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::MarkListHasChanged()
+|*
+*************************************************************************/
+
+
+void SwDrawView::MarkListHasChanged()
+{
+ Imp().GetShell()->DrawSelChanged();
+ FmFormView::MarkListHasChanged();
+}
+
+// #i7672#
+void SwDrawView::ModelHasChanged()
+{
+ // The ModelHasChanged() call in DrawingLayer also updates
+ // a eventually active text edit view (OutlinerView). This also leads
+ // to newly setting the background color for that edit view. Thus,
+ // this method rescues the current background color if a OutlinerView
+ // exists and re-establishes it then. To be more safe, the OutlinerView
+ // will be fetched again (maybe textedit has ended).
+ OutlinerView* pView = GetTextEditOutlinerView();
+ Color aBackColor;
+ sal_Bool bColorWasSaved(sal_False);
+
+ if(pView)
+ {
+ aBackColor = pView->GetBackgroundColor();
+ bColorWasSaved = sal_True;
+ }
+
+ // call parent
+ FmFormView::ModelHasChanged();
+
+ if(bColorWasSaved)
+ {
+ pView = GetTextEditOutlinerView();
+
+ if(pView)
+ {
+ pView->SetBackgroundColor(aBackColor);
+ }
+ }
+}
+
+void SwDrawView::MakeVisible( const Rectangle &rRect, Window & )
+{
+ OSL_ENSURE( rImp.GetShell()->GetWin(), "MakeVisible, unknown Window");
+ rImp.GetShell()->MakeVisible( SwRect( rRect ) );
+}
+
+void SwDrawView::CheckPossibilities()
+{
+ FmFormView::CheckPossibilities();
+
+ //Zusaetzlich zu den bestehenden Flags der Objekte selbst, die von der
+ //DrawingEngine ausgewertet werden, koennen weitere Umstaende zu einem
+ //Schutz fuehren.
+ //Objekte, die in Rahmen verankert sind, muessen genau dann geschuetzt
+ //sein, wenn der Inhalt des Rahmens geschuetzt ist.
+ //OLE-Objekte konnen selbst einen Resize-Schutz wuenschen (StarMath)
+
+ const SdrMarkList &rMrkList = GetMarkedObjectList();
+ sal_Bool bProtect = sal_False,
+ bSzProtect = sal_False;
+ for ( sal_uInt16 i = 0; !bProtect && i < rMrkList.GetMarkCount(); ++i )
+ {
+ const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ const SwFrm *pFrm = NULL;
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ if ( pFly )
+ {
+ pFrm = pFly->GetAnchorFrm();
+ if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ SwOLENode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode();
+ if ( pNd )
+ {
+ uno::Reference < embed::XEmbeddedObject > xObj = pNd->GetOLEObj().GetOleRef();
+ if ( xObj.is() )
+ {
+ // --> improvement for the future, when more
+ // than one Writer fly frame can be selected.
+
+ // TODO/LATER: retrieve Aspect - from where?!
+ bSzProtect |= ( embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ) ) ? sal_True : sal_False;
+
+ // <--
+
+ // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
+ SwDoc* pDoc = Imp().GetShell()->GetDoc();
+ const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
+ && FLY_AS_CHAR == pFly->GetFmt()->GetAnchor().GetAnchorId()
+ && pDoc->get( IDocumentSettingAccess::MATH_BASELINE_ALIGNMENT );
+ if (bProtectMathPos)
+ bMoveProtect = true;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
+ if ( pC )
+ pFrm = pC->GetAnchorFrm( pObj );
+ }
+ if ( pFrm )
+ bProtect = pFrm->IsProtected(); //Rahmen, Bereiche usw.
+ {
+ SwFrmFmt* pFrmFmt( ::FindFrmFmt( const_cast<SdrObject*>(pObj) ) );
+ if ( !pFrmFmt )
+ {
+ OSL_FAIL( "<SwDrawView::CheckPossibilities()> - missing frame format" );
+ bProtect = sal_True;
+ }
+ else if ((FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId()) &&
+ rMrkList.GetMarkCount() > 1 )
+ {
+ bProtect = sal_True;
+ }
+ }
+ }
+ bMoveProtect |= bProtect;
+ bResizeProtect |= bProtect | bSzProtect;
+}
+
+/** replace marked <SwDrawVirtObj>-objects by its reference object for delete
+ marked objects.
+
+ @author OD
+*/
+void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView )
+{
+ SdrPageView* pDrawPageView = _rMarkView.GetSdrPageView();
+ const SdrMarkList& rMarkList = _rMarkView.GetMarkedObjectList();
+
+ if( rMarkList.GetMarkCount() )
+ {
+ // collect marked objects in a local data structure
+ std::vector<SdrObject*> aMarkedObjs;
+ for( sal_uInt32 i = 0; i < rMarkList.GetMarkCount(); ++i )
+ {
+ SdrObject* pMarkedObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
+ aMarkedObjs.push_back( pMarkedObj );
+ }
+ // unmark all objects
+ _rMarkView.UnmarkAllObj();
+ // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its
+ // reference object.
+ while ( !aMarkedObjs.empty() )
+ {
+ SdrObject* pMarkObj = aMarkedObjs.back();
+ if ( pMarkObj->ISA(SwDrawVirtObj) )
+ {
+ SdrObject* pRefObj = &(static_cast<SwDrawVirtObj*>(pMarkObj)->ReferencedObj());
+ if ( !_rMarkView.IsObjMarked( pRefObj ) )
+ {
+ _rMarkView.MarkObj( pRefObj, pDrawPageView );
+ }
+ }
+ else
+ {
+ _rMarkView.MarkObj( pMarkObj, pDrawPageView );
+ }
+
+ aMarkedObjs.pop_back();
+ }
+ // sort marked list in order to assure consistent state in drawing layer
+ _rMarkView.SortMarkedObjects();
+ }
+}
+
+void SwDrawView::DeleteMarked()
+{
+ SwDoc* pDoc = Imp().GetShell()->GetDoc();
+ SwRootFrm *pTmpRoot = pDoc->GetCurrentLayout();//swmod 080317
+ if ( pTmpRoot )
+ pTmpRoot->StartAllAction();
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ // replace marked <SwDrawVirtObj>-objects by its reference objects.
+ {
+ SdrPageView* pDrawPageView = rImp.GetPageView();
+ if ( pDrawPageView )
+ {
+ SdrMarkView* pMarkView = PTR_CAST( SdrMarkView, &(pDrawPageView->GetView()) );
+ if ( pMarkView )
+ {
+ ReplaceMarkedDrawVirtObjs( *pMarkView );
+ }
+ }
+ }
+ if ( pDoc->DeleteSelection( *this ) )
+ {
+ FmFormView::DeleteMarked();
+ ::FrameNotify( Imp().GetShell(), FLY_DRAG_END );
+ }
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ if( pTmpRoot )
+ pTmpRoot->EndAllAction(); //swmod 080218
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */