blob: f30042ea0558823623e9140c33141ca611091df9 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <com/sun/star/embed/EmbedMisc.hpp>
#include "hintids.hxx"
#include <svx/sdrobjectfilter.hxx>
#include <svx/svditer.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdouno.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdogrp.hxx>
#include <svx/svdocirc.hxx>
#include <svx/svdopath.hxx>
#include <svx/xfillit.hxx>
#include <svx/svdocapt.hxx>
#include <sfx2/app.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/opaqitem.hxx>
#include <editeng/protitem.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdpagv.hxx>
#include <IDocumentSettingAccess.hxx>
#include <cmdid.h>
#include <poolfmt.hrc> // fuer InitFldTypes
#include <frmfmt.hxx>
#include <frmatr.hxx>
#include <fmtfsize.hxx>
#include <fmtanchr.hxx>
#include <fmtornt.hxx>
#include <fmtsrnd.hxx>
#include <fmtcntnt.hxx>
#include <fmtflcnt.hxx>
#include <fmtcnct.hxx>
#include <docary.hxx>
#include <tblsel.hxx>
#include <swtable.hxx>
#include <flyfrms.hxx>
#include "fesh.hxx"
#include "rootfrm.hxx"
#include "pagefrm.hxx"
#include "sectfrm.hxx"
#include "doc.hxx"
#include <IDocumentUndoRedo.hxx>
#include "dview.hxx"
#include "dflyobj.hxx"
#include "dcontact.hxx"
#include "viewimp.hxx"
#include "flyfrm.hxx"
#include "pam.hxx"
#include "ndole.hxx"
#include "ndgrf.hxx"
#include "ndtxt.hxx"
#include "viewopt.hxx" // fuer GetHTMLMode
#include "swundo.hxx"
#include "notxtfrm.hxx"
#include "txtfrm.hxx"
#include "txatbase.hxx"
#include "mdiexp.hxx" // fuer Update der Statuszeile bei drag
#include <sortedobjs.hxx>
#include <HandleAnchorNodeChg.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <svx/svdlegacy.hxx>
#include <svx/fmmodel.hxx>
#include <svx/svdview.hxx>
#include <switerator.hxx>
#include <drawdoc.hxx>
#include <svx/obj3d.hxx>
#define SCROLLVAL 75
using namespace com::sun::star;
//Tattergrenze fuer Drawing-SS
#define MINMOVE ((sal_uInt16)GetOut()->PixelToLogic(Size(Imp()->GetDrawView()->GetMarkHdlSizePixel()/2,0)).Width())
SwFlyFrm *GetFlyFromMarked( ViewShell *pSh )
{
SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(
pSh->GetDrawView() ? pSh->Imp()->GetDrawView()->getSelectedIfSingle() : 0);
if(pSwVirtFlyDrawObj)
{
return pSwVirtFlyDrawObj->GetFlyFrm();
}
return 0;
}
void lcl_GrabCursor( SwFEShell* pSh, SwFlyFrm* pOldSelFly)
{
const SwFrmFmt *pFlyFmt = pSh->SelFlyGrabCrsr();
if( pFlyFmt && !pSh->ActionPend() &&
(!pOldSelFly || pOldSelFly->GetFmt() != pFlyFmt) )
{
// dann das evt. gesetzte Macro rufen
pSh->GetFlyMacroLnk().Call( (void*)pFlyFmt );
extern sal_Bool bNoInterrupt; // in swapp.cxx
// wir in dem Makro ein Dialog gestartet, dann kommt das
// MouseButtonUp zu diesem und nicht zu uns. Dadurch ist
// Flag bei uns immer gesetzt und schaltet nie die auf die
// entsp. Shell um !!!!!!!
bNoInterrupt = sal_False;
}
else if( !pFlyFmt || RES_DRAWFRMFMT == pFlyFmt->Which() )
{
// --> OD 2007-07-25 #136039#
// assure consistent cursor
pSh->KillPams();
pSh->ClearMark();
// <--
const basegfx::B2DRange aAllRange(pSh->Imp()->GetDrawView()->getMarkedObjectSnapRange());
pSh->SetCrsr(Point(basegfx::fround(aAllRange.getMinX()), basegfx::fround(aAllRange.getMinY())), true);
}
}
/*************************************************************************
|*
|* SwFEShell::SelectObj()
*************************************************************************/
sal_Bool SwFEShell::SelectObj( const basegfx::B2DPoint& rPt, sal_uInt8 nFlag, SdrObject *pObj )
{
return SelectObj(Point(basegfx::fround(rPt.getX()), basegfx::fround(rPt.getY())), nFlag, pObj);
}
sal_Bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 nFlag, SdrObject *pObj )
{
SwDrawView *pDView = Imp()->GetDrawView();
if(!pDView)
return sal_False;
SET_CURR_SHELL( this );
StartAction(); //Aktion ist Notwendig, damit nicht mehrere
//AttrChgdNotify (etwa durch Unmark->MarkListHasChgd)
//durchkommen
const sal_Bool bHadSelection(pDView ? pDView->areSdrObjectsSelected() : sal_False);
const sal_Bool bAddSelect = 0 != (SW_ADD_SELECT & nFlag);
const sal_Bool bEnterGroup = 0 != (SW_ENTER_GROUP & nFlag);
SwFlyFrm* pOldSelFly = 0;
const basegfx::B2DRange aAllRange(pDView->getMarkedObjectSnapRange());
const Point aOldPos(Point(basegfx::fround(aAllRange.getMinX()), basegfx::fround(aAllRange.getMinY())));
if( bHadSelection )
{
//Unmark rufen wenn !bAddSelect oder wenn ein Fly selektiert ist.
sal_Bool bUnmark = !bAddSelect;
//Wenn ein Fly selektiert ist, so muss er erst deselektiert werden.
pOldSelFly = ::GetFlyFromMarked( this );
if ( pOldSelFly )
{
const sal_uInt16 nType = GetCntType();
if( nType != CNT_TXT || (SW_LEAVE_FRAME & nFlag) ||
( pOldSelFly->GetFmt()->GetProtect().IsCntntProtected()
&& !IsReadOnlyAvailable() ))
{
//Wenn ein Fly deselektiert wird, der Grafik, Ole o.ae.
//enthaelt, so muss der Crsr aus diesem entfernt werden.
//Desgleichen wenn ein Fly mit geschuetztem Inhalt deselektiert
//wird. Der Einfachheit halber wire der Crsr 'grad so neben die
//linke obere Ecke gesetzt.
Point aPt( pOldSelFly->Frm().Pos() );
aPt.X() -= 1;
sal_Bool bUnLockView = !IsViewLocked();
LockView( sal_True );
SetCrsr( aPt, sal_True );
if( bUnLockView )
LockView( sal_False );
}
if ( nType & CNT_GRF &&
((SwNoTxtFrm*)pOldSelFly->Lower())->HasAnimation() )
{
GetWin()->Invalidate( pOldSelFly->Frm().SVRect() );
}
bUnmark = sal_True;
}
if ( bUnmark )
pDView->UnmarkAll();
}
else
{
KillPams();
ClearMark();
}
if ( pObj )
{
ASSERT( !bEnterGroup, "SW_ENTER_GROUP is not supported" );
pDView->MarkObj( *pObj );
}
else
{
pDView->MarkObj( basegfx::B2DPoint(rPt.X(), rPt.Y()), MINMOVE, bAddSelect, bEnterGroup );
}
const sal_Bool bRet(pDView ? pDView->areSdrObjectsSelected() : sal_False);
if ( bRet )
{
//Ganz dumm ist es, wenn Zeichenobjekte Selektiert waren und
//nun ein Fly hinzuselektiert wird.
const SdrObjectVector aSelection(pDView->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(aSelection[i]);
if(pSwVirtFlyDrawObj)
{
pDView->UnmarkAll();
pDView->MarkObj( *pSwVirtFlyDrawObj, bAddSelect );
break;
}
}
}
if ( bRet )
{
::lcl_GrabCursor(this, pOldSelFly);
if ( GetCntType() & CNT_GRF )
{
const SwFlyFrm *pTmp = GetFlyFromMarked( this );
ASSERT( pTmp, "Graphic without Fly" );
if ( ((SwNoTxtFrm*)pTmp->Lower())->HasAnimation() )
((SwNoTxtFrm*)pTmp->Lower())->StopAnimation( GetOut() );
}
}
else if ( !pOldSelFly && bHadSelection )
SetCrsr( aOldPos, sal_True);
if( bRet || !bHadSelection )
CallChgLnk();
// update der Statuszeile
::FrameNotify( this, bRet ? FLY_DRAG_START : FLY_DRAG_END );
EndAction();
return bRet;
}
/*************************************************************************
|*
|* sal_Bool SwFEShell::MoveAnchor( sal_uInt16 nDir )
|*
|* Description: MoveAnchor( nDir ) looked for an another Anchor for
|* the selected drawing object (or fly frame) in the given direction.
|* An object "as character" doesn't moves anyway.
|* A page bounded object could move to the previous/next page with up/down,
|* an object bounded "at paragraph" moves to the previous/next paragraph, too.
|* An object bounded "at character" moves to the previous/next paragraph
|* with up/down and to the previous/next character with left/right.
|* If the anchor for at paragraph/character bounded objects has vertical or
|* right_to_left text direction, the directions for up/down/left/right will
|* interpreted accordingly.
|* An object bounded "at fly" takes the center of the actual anchor and looks
|* for the nearest fly frame in the given direction.
|*
*************************************************************************/
#define LESS_X( aPt1, aPt2, bOld ) ( aPt1.X() < aPt2.X() || \
( aPt1.X() == aPt2.X() && ( aPt1.Y() < aPt2.Y() || \
( aPt1.Y() == aPt2.Y() && bOld ) ) ) )
#define LESS_Y( aPt1, aPt2, bOld ) ( aPt1.Y() < aPt2.Y() || \
( aPt1.Y() == aPt2.Y() && ( aPt1.X() < aPt2.X() || \
( aPt1.X() == aPt2.X() && bOld ) ) ) )
sal_Bool SwFEShell::MoveAnchor( sal_uInt16 nDir )
{
SdrObject* pObj = Imp()->GetDrawView() ? Imp()->GetDrawView()->getSelectedIfSingle() : 0;
if(!pObj)
{
return sal_False;
}
SwFrm* pOld;
SwFlyFrm* pFly = NULL;
if( dynamic_cast< SwVirtFlyDrawObj* >(pObj) )
{
pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
pOld = pFly->AnchorFrm();
}
else
pOld = ((SwDrawContact*)findConnectionToSdrObject(pObj))->GetAnchorFrm( pObj );
sal_Bool bRet = sal_False;
if( pOld )
{
SwFrm* pNew = pOld;
// --> OD 2004-07-16 #i28701#
SwAnchoredObject* pAnchoredObj = ::findConnectionToSdrObject( pObj )->GetAnchoredObj( pObj );
SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
SwFmtAnchor aAnch( rFmt.GetAnchor() );
RndStdIds nAnchorId = aAnch.GetAnchorId();
if ( FLY_AS_CHAR == nAnchorId )
return sal_False;
if( pOld->IsVertical() )
{
if( pOld->IsTxtFrm() )
{
switch( nDir ) {
case SW_MOVE_UP: nDir = SW_MOVE_LEFT; break;
case SW_MOVE_DOWN: nDir = SW_MOVE_RIGHT; break;
case SW_MOVE_LEFT: nDir = SW_MOVE_DOWN; break;
case SW_MOVE_RIGHT: nDir = SW_MOVE_UP; break;
}
if( pOld->IsRightToLeft() )
{
if( nDir == SW_MOVE_LEFT )
nDir = SW_MOVE_RIGHT;
else if( nDir == SW_MOVE_RIGHT )
nDir = SW_MOVE_LEFT;
}
}
}
switch ( nAnchorId ) {
case FLY_AT_PAGE:
{
ASSERT( pOld->IsPageFrm(), "Wrong anchor, page exspected." );
if( SW_MOVE_UP == nDir )
pNew = pOld->GetPrev();
else if( SW_MOVE_DOWN == nDir )
pNew = pOld->GetNext();
if( pNew && pNew != pOld )
{
aAnch.SetPageNum( ((SwPageFrm*)pNew)->GetPhyPageNum() );
bRet = sal_True;
}
break;
}
case FLY_AT_CHAR:
{
ASSERT( pOld->IsCntntFrm(), "Wrong anchor, page exspected." );
if( SW_MOVE_LEFT == nDir || SW_MOVE_RIGHT == nDir )
{
SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
SwTxtNode* pTxtNd = ((SwTxtFrm*)pOld)->GetTxtNode();
xub_StrLen nAct = pPos->nContent.GetIndex();
if( SW_MOVE_LEFT == nDir )
{
bRet = sal_True;
if( nAct )
{
--nAct;
pPos->nContent.Assign( pTxtNd, nAct );
}
else
nDir = SW_MOVE_UP;
}
else
{
xub_StrLen nMax =
((SwTxtFrm*)pOld)->GetTxtNode()->GetTxt().Len();
if( nAct < nMax )
{
++nAct;
bRet = sal_True;
pPos->nContent.Assign( pTxtNd, nAct );
}
else
nDir = SW_MOVE_DOWN;
}
}
} // no break!
case FLY_AT_PARA:
{
ASSERT( pOld->IsCntntFrm(), "Wrong anchor, page exspected." );
if( SW_MOVE_UP == nDir )
pNew = pOld->FindPrev();
else if( SW_MOVE_DOWN == nDir )
pNew = pOld->FindNext();
if( pNew && pNew != pOld && pNew->IsCntntFrm() )
{
SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
SwTxtNode* pTxtNd = ((SwTxtFrm*)pNew)->GetTxtNode();
pPos->nNode = *pTxtNd;
xub_StrLen nTmp = 0;
if( bRet )
{
nTmp = ((SwTxtFrm*)pNew)->GetTxtNode()->GetTxt().Len();
if( nTmp )
--nTmp;
}
pPos->nContent.Assign( pTxtNd, nTmp );
bRet = sal_True;
}
else if( SW_MOVE_UP == nDir || SW_MOVE_DOWN == nDir )
bRet = sal_False;
break;
}
case FLY_AT_FLY:
{
ASSERT( pOld->IsFlyFrm(), "Wrong anchor, fly frame exspected.");
SwPageFrm* pPage = pOld->FindPageFrm();
ASSERT( pPage, "Where's my page?" );
SwFlyFrm* pNewFly = NULL;
if( pPage->GetSortedObjs() )
{
int i;
sal_Bool bOld = sal_False;
Point aCenter( pOld->Frm().Left() + pOld->Frm().Width()/2,
pOld->Frm().Top() + pOld->Frm().Height()/2 );
Point aBest;
for( i = 0; (sal_uInt16)i<pPage->GetSortedObjs()->Count(); ++i )
{
SwAnchoredObject* pAnchObj = (*pPage->GetSortedObjs())[i];
SwFlyFrm* pTmp = dynamic_cast< SwFlyFrm* >(pAnchObj);
if( pTmp )
{
if( pTmp == pOld )
bOld = sal_True;
else
{
const SwFlyFrm* pCheck = pFly ? pTmp : 0;
while( pCheck )
{
if( pCheck == pFly )
break;
const SwFrm *pNxt = pCheck->GetAnchorFrm();
pCheck = pNxt ? pNxt->FindFlyFrm() : NULL;
}
if( pCheck || pTmp->IsProtected() )
continue;
Point aNew( pTmp->Frm().Left() +
pTmp->Frm().Width()/2,
pTmp->Frm().Top() +
pTmp->Frm().Height()/2 );
sal_Bool bAccept = sal_False;
switch( nDir ) {
case SW_MOVE_RIGHT:
{
bAccept = LESS_X( aCenter, aNew, bOld )
&& ( !pNewFly ||
LESS_X( aNew, aBest, sal_False ) );
break;
}
case SW_MOVE_LEFT:
{
bAccept = LESS_X( aNew, aCenter, !bOld )
&& ( !pNewFly ||
LESS_X( aBest, aNew, sal_True ) );
break;
}
case SW_MOVE_UP:
{
bAccept = LESS_Y( aNew, aCenter, !bOld )
&& ( !pNewFly ||
LESS_Y( aBest, aNew, sal_True ) );
break;
}
case SW_MOVE_DOWN:
{
bAccept = LESS_Y( aCenter, aNew, bOld )
&& ( !pNewFly ||
LESS_Y( aNew, aBest, sal_False ) );
break;
}
}
if( bAccept )
{
pNewFly = pTmp;
aBest = aNew;
}
}
}
}
}
if( pNewFly )
{
SwPosition aPos( *pNewFly->GetFmt()->
GetCntnt().GetCntntIdx());
aAnch.SetAnchor( &aPos );
bRet = sal_True;
}
break;
}
default: break;
}
if( bRet )
{
StartAllAction();
// --> OD 2006-02-28 #125892#
// handle change of anchor node:
// if count of the anchor frame also change, the fly frames have to be
// re-created. Thus, delete all fly frames except the <this> before the
// anchor attribute is change and re-create them afterwards.
{
SwHandleAnchorNodeChg* pHandleAnchorNodeChg( 0L );
SwFlyFrmFmt* pFlyFrmFmt( dynamic_cast<SwFlyFrmFmt*>(&rFmt) );
if ( pFlyFrmFmt )
{
pHandleAnchorNodeChg =
new SwHandleAnchorNodeChg( *pFlyFrmFmt, aAnch );
}
rFmt.GetDoc()->SetAttr( aAnch, rFmt );
delete pHandleAnchorNodeChg;
}
// <--
// --> OD 2004-06-24 #i28701# - no call of method
// <CheckCharRectAndTopOfLine()> for to-character anchored
// Writer fly frame needed. This method call can cause a
// format of the anchor frame, which is no longer intended.
// Instead clear the anchor character rectangle and
// the top of line values for all to-character anchored objects.
pAnchoredObj->ClearCharRectAndTopOfLine();
EndAllAction();
}
}
return bRet;
}
/*************************************************************************
|*
|* SwFEShell::GetSelFrmType()
|*
*************************************************************************/
sal_uInt16 SwFEShell::GetSelFrmType() const
{
sal_uInt16 eType(FRMTYPE_NONE);
// get marked frame list, and check if anything is selected
if(Imp()->GetDrawView() && Imp()->GetDrawView()->areSdrObjectsSelected())
{
// obtain marked item as fly frame; if no fly frame, it must
// be a draw object
const SwFlyFrm* pFly = ::GetFlyFromMarked((ViewShell*)this);
if ( pFly != NULL )
{
if( pFly->IsFlyLayFrm() )
eType = FRMTYPE_FLY_FREE;
else if( pFly->IsFlyAtCntFrm() )
eType = FRMTYPE_FLY_ATCNT;
else
{
ASSERT( pFly->IsFlyInCntFrm(), "Neuer Rahmentyp?" );
eType = FRMTYPE_FLY_INCNT;
}
}
else
{
eType = FRMTYPE_DRAWOBJ;
}
}
return eType;
}
// #108784# does the draw selection contain a control?
bool SwFEShell::IsSelContainsControl() const
{
bool bRet = false;
// basically, copy the mechanism from GetSelFrmType(), but call
// CheckControl... if you get a drawing object
const SdrObject* pSingleSelected = Imp()->GetDrawView() ? Imp()->GetDrawView()->getSelectedIfSingle() : 0;
if(pSingleSelected)
{
// if we have one marked object, get the SdrObject and check
// whether it contains a control
bRet = ::CheckControlLayer( pSingleSelected );
}
return bRet;
}
/*************************************************************************
|*
|* SwFEShell::Scroll()
|*
*************************************************************************/
void SwFEShell::ScrollTo( const basegfx::B2DPoint &rPt )
{
ScrollTo(Point(basegfx::fround(rPt.getX()), basegfx::fround(rPt.getY())));
}
void SwFEShell::ScrollTo( const Point &rPt )
{
const SwRect aRect( rPt, rPt );
if ( IsScrollMDI( this, aRect ) &&
(!Imp()->GetDrawView()->areSdrObjectsSelected() ||
Imp()->IsDragPossible( rPt )) )
{
//SwSaveHdl aSave( Imp() );
ScrollMDI( this, aRect, SCROLLVAL, SCROLLVAL );
}
}
/*************************************************************************
|*
|* SwFEShell::SetDragMode()
|*
*************************************************************************/
void SwFEShell::SetDragMode( sal_uInt16 eDragMode )
{
if ( Imp()->HasDrawView() )
Imp()->GetDrawView()->SetDragMode( (SdrDragMode)eDragMode );
}
/*************************************************************************
|*
|* SwFEShell::BeginDrag()
|*
*************************************************************************/
long SwFEShell::BeginDrag( const Point* pPt, sal_Bool )
{
SdrView *pView = Imp()->GetDrawView();
if ( pView && pView->areSdrObjectsSelected() )
{
delete pChainFrom; delete pChainTo; pChainFrom = pChainTo = 0;
const basegfx::B2DPoint aB2DPt(pPt->X(), pPt->Y());
SdrHdl* pHdl = pView->PickHandle(aB2DPt);
pView->BegDragObj( aB2DPt, pHdl );
::FrameNotify( this, FLY_DRAG );
return 1;
}
return 0;
}
/*************************************************************************
|*
|* SwFEShell::Drag()
|*
*************************************************************************/
long SwFEShell::Drag( const Point *pPt, sal_Bool )
{
ASSERT( Imp()->HasDrawView(), "Drag without DrawView?" );
if ( Imp()->GetDrawView()->IsDragObj() )
{
ScrollTo( *pPt );
const basegfx::B2DPoint aB2DPt(pPt->X(), pPt->Y());
Imp()->GetDrawView()->MovDragObj(aB2DPt);
Imp()->GetDrawView()->ShowDragAnchor();
::FrameNotify( this, FLY_DRAG );
return 1;
}
return 0;
}
/*************************************************************************
|*
|* SwFEShell::EndDrag()
|*
*************************************************************************/
long SwFEShell::EndDrag( const Point *, sal_Bool )
{
ASSERT( Imp()->HasDrawView(), "EndDrag without DrawView?" );
SdrView *pView = Imp()->GetDrawView();
if ( pView->IsDragObj() )
{
//Start-/EndActions nur an der ViewShell aufsetzen
ViewShell *pSh = this;
do {
pSh->StartAction();
} while ( this != (pSh = (ViewShell*)pSh->GetNext()) );
StartUndo( UNDO_START );
//#50778# Bug im Draging: Im StartAction wird ein HideShowXor gerufen.
//Im EndDragObj() wird dies unsinniger und faelschlicherweise wieder
//Rueckgaengig gemacht. Um Konsistenz herzustellen muessen wir das
//Xor also wieder zur Anzeige bringen.
// Reanimation from the hack #50778 to fix bug #97057
// May be not the best solution, but the one with lowest risc at the moment.
//pView->ShowShownXor( GetOut() );
pView->EndDragObj();
// DrawUndo-Action auf FlyFrames werden nicht gespeichert
// Die Fly aendern das Flag
GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
ChgAnchor( 0, sal_True );
EndUndo( UNDO_END );
do {
pSh->EndAction();
SwCrsrShell* pSwCrsrShell = dynamic_cast< SwCrsrShell* >(pSh);
if( pSwCrsrShell )
pSwCrsrShell->CallChgLnk();
} while ( this != (pSh = (ViewShell*)pSh->GetNext()) );
GetDoc()->SetModified();
::FrameNotify( this, FLY_DRAG );
return 1;
}
return 0;
}
/*************************************************************************
|*
|* SwFEShell::BreakDrag()
|*
*************************************************************************/
void SwFEShell::BreakDrag()
{
ASSERT( Imp()->HasDrawView(), "BreakDrag without DrawView?" );
if ( Imp()->GetDrawView()->IsDragObj() )
Imp()->GetDrawView()->BrkDragObj();
SetChainMarker();
}
/*************************************************************************
|*
|* SwFEShell::SelFlyGrabCrsr()
|*
|* Beschreibung Wenn ein Fly selektiert ist, zieht er den Crsr in
|* den ersten CntntFrm
*************************************************************************/
const SwFrmFmt* SwFEShell::SelFlyGrabCrsr()
{
SwFlyFrm *pFly = ::GetFlyFromMarked( this );
if( pFly )
{
// --> OD 2004-06-11 #i28701# - no format here
// pFly->GetAnchorFrm()->Calc();
SwCntntFrm *pCFrm = pFly->ContainsCntnt();
if ( pCFrm )
{
SwCntntFrm *pCFrm = pFly->ContainsCntnt();
if ( pCFrm )
{
SwCntntNode *pCNode = pCFrm->GetNode();
// --> OD 2007-07-25 #126039#
// assure, that the cursor is consistent.
KillPams();
ClearMark();
// <--
SwPaM *pCrsr = GetCrsr();
pCrsr->GetPoint()->nNode = *pCNode;
pCrsr->GetPoint()->nContent.Assign( pCNode, 0 );
SwRect& rChrRect = (SwRect&)GetCharRect();
rChrRect = pFly->Prt();
rChrRect.Pos() += pFly->Frm().Pos();
GetCrsrDocPos() = rChrRect.Pos();
}
return pFly->GetFmt();
}
return pFly->GetFmt();
}
return 0;
}
/*************************************************************************
|*
|* SwFEShell::SelectionToTop(), SelectionToBottom()
|*
|* Beschreibung Selektion nach oben/unten (Z-Order)
|*
*************************************************************************/
void lcl_NotifyNeighbours( ViewShell *pSh )
{
if(pSh->HasDrawView())
{
const SdrObjectVector aSelection(pSh->Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
//Die Regeln fuer die Ausweichmanoever haben sich veraendert.
//1. Die Umgebung des Fly und aller innenliegenden muss benachrichtigt
// werden.
//2. Der Inhalt des Rahmen selbst muss benachrichtigt werden.
//3. Rahmen die dem Rahmen ausweichen bzw. wichen muessen benachrichtigt werden.
//4. Auch Zeichenobjekte koennen Rahmen verdraengen
for( sal_uInt32 j(0); j < aSelection.size(); ++j )
{
SwPageFrm *pPage;
sal_Bool bCheckNeighbours = sal_False;
sal_Int16 aHori = text::HoriOrientation::NONE;
SwRect aRect;
SdrObject *pO = aSelection[j]; // TTTT: Changed from always getting the 0th element, couldn't have been correct ?!?
if ( dynamic_cast< SwVirtFlyDrawObj* >(pO) )
{
SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
const SwFmtHoriOrient &rHori = pFly->GetFmt()->GetHoriOrient();
aHori = rHori.GetHoriOrient();
if( text::HoriOrientation::NONE != aHori && text::HoriOrientation::CENTER != aHori &&
pFly->IsFlyAtCntFrm() )
{
bCheckNeighbours = sal_True;
pFly->InvalidatePos();
pFly->Frm().Pos().Y() += 1;
}
pPage = pFly->FindPageFrm();
aRect = pFly->Frm();
}
else
{
SwFrm* pAnch = ( (SwDrawContact*)findConnectionToSdrObject(pO) )->GetAnchorFrm( pO );
if( !pAnch )
continue;
pPage = pAnch->FindPageFrm();
// --> OD 2006-08-15 #i68520# - naming changed
aRect = GetBoundRectOfAnchoredObj( pO );
// <--
}
sal_uInt32 nCount = pPage->GetSortedObjs() ? pPage->GetSortedObjs()->Count() : 0;
for ( sal_uInt32 i = 0; i < nCount; ++i )
{
SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
if ( !dynamic_cast< SwFlyFrm* >(pAnchoredObj) )
continue;
SwFlyFrm* pAct = static_cast<SwFlyFrm*>(pAnchoredObj);
SwRect aTmpCalcPnt( pAct->Prt() );
aTmpCalcPnt += pAct->Frm().Pos();
if ( aRect.IsOver( aTmpCalcPnt ) )
{
SwCntntFrm *pCnt = pAct->ContainsCntnt();
while ( pCnt )
{
aTmpCalcPnt = pCnt->Prt();
aTmpCalcPnt += pCnt->Frm().Pos();
if ( aRect.IsOver( aTmpCalcPnt ) )
((SwFrm*)pCnt)->Prepare( PREP_FLY_ATTR_CHG );
pCnt = pCnt->GetNextCntntFrm();
}
}
if ( bCheckNeighbours && pAct->IsFlyAtCntFrm() )
{
const SwFmtHoriOrient &rH = pAct->GetFmt()->GetHoriOrient();
if ( rH.GetHoriOrient() == aHori &&
pAct->Frm().Top() <= aRect.Bottom() &&
pAct->Frm().Bottom() >= aRect.Top() )
{
pAct->InvalidatePos();
pAct->Frm().Pos().Y() += 1;
}
}
}
}
}
}
void SwFEShell::SelectionToTop( sal_Bool bTop )
{
SwFlyFrm *pFly = ::GetFlyFromMarked( this );
if ( pFly && pFly->IsFlyInCntFrm() )
return;
StartAllAction();
if ( bTop )
Imp()->GetDrawView()->PutMarkedToTop();
else
Imp()->GetDrawView()->MovMarkedToTop();
::lcl_NotifyNeighbours( this );
GetDoc()->SetModified();
EndAllAction();
}
void SwFEShell::SelectionToBottom( sal_Bool bBottom )
{
SwFlyFrm *pFly = ::GetFlyFromMarked( this );
if ( pFly && pFly->IsFlyInCntFrm() )
return;
StartAllAction();
if ( bBottom )
Imp()->GetDrawView()->PutMarkedToBtm();
else
Imp()->GetDrawView()->MovMarkedToBtm();
::lcl_NotifyNeighbours( this );
GetDoc()->SetModified();
EndAllAction();
}
/*************************************************************************
|*
|* SwFEShell::GetLayerId()
|*
|* Beschreibung Objekt ueber/unter dem Dokument?
|* 2 Controls, 1 Heaven, 0 Hell, -1 Uneindeutig
*************************************************************************/
short SwFEShell::GetLayerId() const
{
short nRet = SHRT_MAX;
if ( Imp()->HasDrawView() && Imp()->GetDrawView()->areSdrObjectsSelected() )
{
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
const SdrObject *pObj = aSelection[i];
if ( nRet == SHRT_MAX )
nRet = pObj->GetLayer();
else if ( nRet != pObj->GetLayer() )
{
nRet = -1;
break;
}
}
}
if ( nRet == SHRT_MAX )
nRet = -1;
return nRet;
}
/*************************************************************************
|*
|* SwFEShell::SelectionToHeaven(), SelectionToHell()
|*
|* Beschreibung Objekt ueber/unter dem Dokument
|*
*************************************************************************/
// OD 25.06.2003 #108784#
// Note: only visible objects can be marked. Thus, objects with invisible
// layer IDs have not to be considered.
// If <SwFEShell> exists, layout exists!!
void SwFEShell::ChangeOpaque( SdrLayerID nLayerId )
{
if ( Imp()->HasDrawView() && Imp()->GetDrawView()->areSdrObjectsSelected() )
{
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
const IDocumentDrawModelAccess* pIDDMA = getIDocumentDrawModelAccess();
// OD 25.06.2003 #108784# - correct type of <nControls>
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
SdrObject* pObj = aSelection[i];
// OD 21.08.2003 #i18447# - no change of layer for controls
// or group objects containing controls.
// --> OD 2010-09-14 #i113730#
// consider that a member of a drawing group has been selected.
const SwContact* pContact = dynamic_cast< SwDrawContact* >(findConnectionToSdrObject(pObj));
ASSERT( pContact && pContact->GetMaster(), "<SwFEShell::ChangeOpaque(..)> - missing contact or missing master object at contact!" );
const bool bControlObj = ( pContact && pContact->GetMaster() )
? ::CheckControlLayer( pContact->GetMaster() )
: ::CheckControlLayer( pObj );
// <--
if ( !bControlObj && pObj->GetLayer() != nLayerId )
{
pObj->SetLayer( nLayerId );
InvalidateWindows( SwRect( sdr::legacy::GetBoundRect(*pObj) ) );
if ( dynamic_cast< SwVirtFlyDrawObj* >(pObj) )
{
SwFmt *pFmt = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetFmt();
SvxOpaqueItem aOpa( pFmt->GetOpaque() );
aOpa.SetValue( nLayerId == pIDDMA->GetHellId() );
pFmt->SetFmtAttr( aOpa );
}
}
}
GetDoc()->SetModified();
}
}
void SwFEShell::SelectionToHeaven()
{
ChangeOpaque( getIDocumentDrawModelAccess()->GetHeavenId() );
}
void SwFEShell::SelectionToHell()
{
ChangeOpaque( getIDocumentDrawModelAccess()->GetHellId() );
}
/*************************************************************************
|*
|* SwFEShell::IsObjSelected(), IsFrmSelected()
|*
*************************************************************************/
sal_uInt32 SwFEShell::GetNumberOfSelectedObjects() const
{
if ( IsFrmSelected() || !Imp()->HasDrawView() )
return 0;
else
return Imp()->GetDrawView()->getSelectedSdrObjectCount();
}
sal_Bool SwFEShell::IsObjSelected() const
{
if ( IsFrmSelected() || !Imp()->HasDrawView() )
return sal_False;
else
return Imp()->GetDrawView()->areSdrObjectsSelected();
}
sal_Bool SwFEShell::IsFrmSelected() const
{
return 0 != ::GetFlyFromMarked( (ViewShell*)this );
}
sal_Bool SwFEShell::IsObjSelected( const SdrObject& rObj ) const
{
if ( IsFrmSelected() || !Imp()->HasDrawView() )
return sal_False;
else
return Imp()->GetDrawView()->isSdrObjectSelected(rObj);
}
bool SwFEShell::IsObjSameLevelWithMarked(const SdrObject& rObj) const
{
if(!Imp()->GetDrawView()->areSdrObjectsSelected())
{
return true;
}
const SdrObjectVector aSdrObjectVector(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
if(aSdrObjectVector.empty())
{
OSL_ENSURE(false, "OOps, areSdrObjectsSelected is true, but SdrObjectVector is empty (!)");
}
else
{
const SdrObject& rFirstMarked = *aSdrObjectVector[0];
return rFirstMarked.GetParentSdrObject() == rObj.GetParentSdrObject();
}
return false;
}
SdrObject* SwFEShell::getSingleSelected() const
{
if(Imp()->GetDrawView())
{
return Imp()->GetDrawView()->getSelectedIfSingle();
}
return 0;
}
//-----IAccessibility2 Implementation 2009
/*************************************************************************
|*
|* SwFEShell::EndTextEdit()
|*
*************************************************************************/
void SwFEShell::EndTextEdit()
{
//Beenden des TextEditModus. Wenn gewuenscht (default wenn das Objekt
//keinen Text mehr enthaelt und keine Attribute traegt) wird das
//Objekt gel�scht. Alle anderen markierten Objekte bleiben erhalten.
ASSERT( Imp()->HasDrawView() && Imp()->GetDrawView()->IsTextEdit(),
"EndTextEdit an no Object" );
StartAllAction();
SdrView *pView = Imp()->GetDrawView();
SdrObject *pObj = pView->GetTextEditObject();
SwDrawContact* pSwDrawContact;
if( 0 != ( pSwDrawContact = dynamic_cast< SwDrawContact* >(findConnectionToSdrObject(pObj)) ) )
{
SdrObject *pTmp = pSwDrawContact->GetMaster();
if( !pTmp )
pTmp = pObj;
pSwDrawContact->HandleChanged(*pTmp, HINT_OBJCHG_RESIZE);
}
if ( !pObj->GetParentSdrObject() )
{
if ( SDRENDTEXTEDIT_SHOULDBEDELETED == pView->SdrEndTextEdit(sal_True) )
{
if ( pView->getSelectedSdrObjectCount() > 1 )
{
SdrObjectVector aSave(pView->getSelectedSdrObjectVectorFromSdrMarkView());
for(sal_uInt32 a(0); a < aSave.size(); a++)
{
if(aSave[a] == pObj)
{
aSave.erase(aSave.begin() + a);
break;
}
}
if ( aSave.size() )
{
pView->UnmarkAll();
pView->MarkObj( *pObj );
}
DelSelectedObj();
for ( sal_uInt32 i = 0; i < aSave.size(); ++i )
{
pView->MarkObj( *aSave[i] );
}
}
else
{
DelSelectedObj();
}
}
}
else
pView->SdrEndTextEdit();
EndAllAction();
}
/*************************************************************************
|*
|* SwFEShell::IsInsideSelectedObj()
|*
*************************************************************************/
int SwFEShell::IsInsideSelectedObj( const basegfx::B2DPoint &rPt )
{
if( Imp()->HasDrawView() )
{
SwDrawView *pDView = Imp()->GetDrawView();
if( pDView->areSdrObjectsSelected() && pDView->IsMarkedObjHit( rPt ) )
{
return SDRHIT_OBJECT;
}
}
return SDRHIT_NONE;
}
/*************************************************************************
|*
|* SwFEShell::IsObjSelectable()
|*
*************************************************************************/
bool SwFEShell::IsObjSelectable( const basegfx::B2DPoint& rPt )
{
return IsObjSelectable(Point(basegfx::fround(rPt.getX()), basegfx::fround(rPt.getY())));
}
bool SwFEShell::IsObjSelectable( const Point& rPt )
{
SET_CURR_SHELL(this);
#ifdef OLD
if( Imp()->HasDrawView() )
{
return Imp()->GetDrawView()->PickSomething( basegfx::B2DPoint(rPt.X(), rPt.Y()), MINMOVE );
}
return 0;
#else
SwDrawView *pDView = Imp()->GetDrawView();
bool bRet = false;
if( pDView )
{
SdrObject* pObj;
const double fOld(pDView->GetHitTolerancePixel());
pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
bRet = 0 != pDView->PickObj( basegfx::B2DPoint(rPt.X(), rPt.Y()), pDView->getHitTolLog(), pObj, SDRSEARCH_PICKMARKABLE );
pDView->SetHitTolerancePixel(fOld);
}
return bRet;
#endif
}
// #107513#
// Test if there is a object at that position and if it should be selected.
sal_Bool SwFEShell::ShouldObjectBeSelected(const Point& rPt)
{
SET_CURR_SHELL(this);
SwDrawView *pDrawView = Imp()->GetDrawView();
sal_Bool bRet(sal_False);
if(pDrawView)
{
SdrObject* pObj;
const double fOld(pDrawView->GetHitTolerancePixel());
pDrawView->SetHitTolerancePixel(pDrawView->GetMarkHdlSizePixel()/2);
bRet = pDrawView->PickObj(basegfx::B2DPoint(rPt.X(), rPt.Y()), pDrawView->getHitTolLog(), pObj, SDRSEARCH_PICKMARKABLE);
pDrawView->SetHitTolerancePixel(fOld);
if ( bRet && pObj )
{
const IDocumentDrawModelAccess* pIDDMA = getIDocumentDrawModelAccess();
// --> OD 2009-12-30 #i89920#
// Do not select object in background which is overlapping this text
// at the given position.
bool bObjInBackground( false );
{
if ( pObj->GetLayer() == pIDDMA->GetHellId() )
{
const SwAnchoredObject* pAnchoredObj = ::findConnectionToSdrObject( pObj )->GetAnchoredObj( pObj );
const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
const SwFmtSurround& rSurround = rFmt.GetSurround();
if ( rSurround.GetSurround() == SURROUND_THROUGHT )
{
bObjInBackground = true;
}
}
}
if ( bObjInBackground )
{
const SwPageFrm* pPageFrm = GetLayout()->GetPageAtPos( rPt );
if( pPageFrm )
{
const SwCntntFrm* pCntntFrm( pPageFrm->ContainsCntnt() );
while ( pCntntFrm )
{
if ( pCntntFrm->UnionFrm().IsInside( rPt ) )
{
const SwTxtFrm* pTxtFrm =
dynamic_cast<const SwTxtFrm*>(pCntntFrm);
if ( pTxtFrm )
{
SwPosition* pPos =
new SwPosition( *(pTxtFrm->GetTxtNode()) );
Point aTmpPt( rPt );
if ( pTxtFrm->GetKeyCrsrOfst( pPos, aTmpPt ) )
{
SwRect aCursorCharRect;
if ( pTxtFrm->GetCharRect( aCursorCharRect, *pPos ) )
{
if ( aCursorCharRect.IsOver( SwRect( sdr::legacy::GetBoundRect(*pObj) ) ) )
{
bRet = sal_False;
}
}
}
}
else
{
bRet = sal_False;
}
break;
}
pCntntFrm = pCntntFrm->GetNextCntntFrm();
}
}
}
// <--
if ( bRet )
{
const SdrPage* pPage = pIDDMA->GetDrawModel()->GetPage(0);
for(sal_uInt32 a(pObj->GetNavigationPosition() + 1); bRet && a < pPage->GetObjCount(); a++)
{
SdrObject *pCandidate = pPage->GetObj(a);
if (dynamic_cast< SwVirtFlyDrawObj* >(pCandidate) &&
sdr::legacy::GetBoundRect(*( (SwVirtFlyDrawObj*)pCandidate)).IsInside(rPt) )
{
bRet = sal_False;
}
}
}
}
}
return bRet;
}
/*************************************************************************
|*
|* SwFEShell::GotoObj()
|*
|* Beschreibung Wenn ein Obj selektiert ist, gehen wir von dessen
|* TopLeft aus, andernfalls von der Mitte des aktuellen CharRects.
|*
*************************************************************************/
/* ------------------------------------
* Beinhaltet das Objekt ein Control oder Gruppen,
* die nur aus Controls bestehen
* --------------------------------------------------*/
sal_Bool lcl_IsControlGroup( const SdrObject *pObj )
{
sal_Bool bRet = sal_False;
if(dynamic_cast< const SdrUnoObj* >(pObj))
bRet = sal_True;
else if( dynamic_cast< const SdrObjGroup* >(pObj) )
{
bRet = sal_True;
const SdrObjList *pLst = pObj->getChildrenOfSdrObject();
for ( sal_uInt32 i = 0; i < pLst->GetObjCount(); ++i )
if( !::lcl_IsControlGroup( pLst->GetObj( i ) ) )
return sal_False;
}
return bRet;
}
namespace
{
class MarkableObjectsOnly : public ::svx::ISdrObjectFilter
{
public:
MarkableObjectsOnly( SdrPageView* i_pPV )
:m_pPV( i_pPV )
{
}
virtual bool includeObject( const SdrObject& i_rObject ) const
{
return m_pPV && m_pPV->GetView().IsObjMarkable( i_rObject );
}
private:
SdrPageView* m_pPV;
};
}
const SdrObject* SwFEShell::GetBestObject( sal_Bool bNext, sal_uInt16 /*GOTOOBJ_...*/ eType, sal_Bool bFlat, const ::svx::ISdrObjectFilter* pFilter )
{
if( !Imp()->HasDrawView() )
return NULL;
const SdrObject *pBest = 0,
*pTop = 0;
const long nTmp = bNext ? LONG_MAX : 0;
Point aBestPos( nTmp, nTmp );
Point aTopPos( nTmp, nTmp );
Point aCurPos;
Point aPos;
sal_Bool bNoDraw = 0 == (GOTOOBJ_DRAW_ANY & eType);
sal_Bool bNoFly = 0 == (GOTOOBJ_FLY_ANY & eType);
if( !bNoFly && bNoDraw )
{
SwFlyFrm *pFly = GetCurrFrm( sal_False )->FindFlyFrm();
if( pFly )
pBest = pFly->GetVirtDrawObj();
}
SdrPageView* pPV = Imp()->GetDrawView()->GetSdrPageView();
MarkableObjectsOnly aDefaultFilter( pPV );
if ( !pFilter )
pFilter = &aDefaultFilter;
const SdrObject* pStartObj = Imp()->GetDrawView()->getSelectedIfSingle();
if( !pBest || pStartObj)
{
// Ausgangspunkt bestimmen.
SdrObjList* pList = NULL;
if ( pStartObj )
{
if( dynamic_cast< const SwVirtFlyDrawObj* >(pStartObj) )
aPos = ((SwVirtFlyDrawObj*)pStartObj)->GetFlyFrm()->Frm().Pos();
else
aPos = sdr::legacy::GetSnapRect(*pStartObj).TopLeft();
// If an object inside a group is selected, we want to
// iterate over the group members.
if ( ! findConnectionToSdrObjectDirect(pStartObj) )
pList = pStartObj->getParentOfSdrObject();
}
else
{
// If no object is selected, we check if we just entered a group.
// In this case we want to iterate over the group members.
aPos = GetCharRect().Center();
const SdrObject* pStartObj = pPV ? pPV->GetCurrentGroup() : 0;
if ( pStartObj && dynamic_cast< const SdrObjGroup* >(pStartObj) )
pList = pStartObj->getChildrenOfSdrObject();
}
if ( ! pList )
{
// Here we are if
// A No object has been selected and no group has been entered or
// B An object has been selected and it is not inside a group
pList = getIDocumentDrawModelAccess()->GetDrawModel()->GetPage( 0 );
}
ASSERT( pList, "No object list to iterate" )
SdrObjListIter aObjIter( *pList, bFlat ? IM_FLAT : IM_DEEPNOGROUPS );
while ( aObjIter.IsMore() )
{
SdrObject* pObj = aObjIter.Next();
bool bFlyFrm(dynamic_cast< SwVirtFlyDrawObj* >(pObj));
if( ( bNoFly && bFlyFrm ) ||
( bNoDraw && !bFlyFrm ) ||
( eType == GOTOOBJ_DRAW_SIMPLE && lcl_IsControlGroup( pObj ) ) ||
( eType == GOTOOBJ_DRAW_CONTROL && !lcl_IsControlGroup( pObj ) ) ||
( pFilter && !pFilter->includeObject( *pObj ) ) )
continue;
if( bFlyFrm )
{
SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pObj;
SwFlyFrm *pFly = pO->GetFlyFrm();
if( GOTOOBJ_FLY_ANY != ( GOTOOBJ_FLY_ANY & eType ) )
{
switch ( eType )
{
case GOTOOBJ_FLY_FRM:
if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
continue;
break;
case GOTOOBJ_FLY_GRF:
if ( pFly->Lower() &&
(pFly->Lower()->IsLayoutFrm() ||
!((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode()))
continue;
break;
case GOTOOBJ_FLY_OLE:
if ( pFly->Lower() &&
(pFly->Lower()->IsLayoutFrm() ||
!((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode()))
continue;
break;
}
}
aCurPos = pFly->Frm().Pos();
}
else
aCurPos = sdr::legacy::GetBoundRect(*pObj).TopLeft();
// Sonderfall wenn ein anderes Obj auf selber Y steht.
if( aCurPos != aPos && // nur wenn ich es nicht selber bin
aCurPos.Y() == aPos.Y() && // ist die Y Position gleich
(bNext? (aCurPos.X() > aPos.X()) : // liegt neben mir
(aCurPos.X() < aPos.X())) ) // " reverse
{
aBestPos = Point( nTmp, nTmp );
SdrObjListIter aTmpIter( *pList, bFlat ? IM_FLAT : IM_DEEPNOGROUPS );
while ( aTmpIter.IsMore() )
{
SdrObject* pTmpObj = aTmpIter.Next();
bFlyFrm = dynamic_cast< SwVirtFlyDrawObj* >(pTmpObj);
if( ( bNoFly && bFlyFrm ) || ( bNoDraw && !bFlyFrm ) )
continue;
if( bFlyFrm )
{
SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pTmpObj;
aCurPos = pO->GetFlyFrm()->Frm().Pos();
}
else
aCurPos = sdr::legacy::GetBoundRect(*pTmpObj).TopLeft();
if( aCurPos != aPos && aCurPos.Y() == aPos.Y() &&
(bNext? (aCurPos.X() > aPos.X()) : // liegt neben mir
(aCurPos.X() < aPos.X())) && // " reverse
(bNext? (aCurPos.X() < aBestPos.X()) : // besser als Beste
(aCurPos.X() > aBestPos.X())) ) // " reverse
{
aBestPos = aCurPos;
pBest = pTmpObj;
}
}
break;
}
if( (
(bNext? (aPos.Y() < aCurPos.Y()) : // nur unter mir
(aPos.Y() > aCurPos.Y())) && // " reverse
(bNext? (aBestPos.Y() > aCurPos.Y()) : // naeher drunter
(aBestPos.Y() < aCurPos.Y()))
) || // " reverse
(aBestPos.Y() == aCurPos.Y() &&
(bNext? (aBestPos.X() > aCurPos.X()) : // weiter links
(aBestPos.X() < aCurPos.X())))) // " reverse
{
aBestPos = aCurPos;
pBest = pObj;
}
if( (bNext? (aTopPos.Y() > aCurPos.Y()) : // hoeher als Beste
(aTopPos.Y() < aCurPos.Y())) || // " reverse
(aTopPos.Y() == aCurPos.Y() &&
(bNext? (aTopPos.X() > aCurPos.X()) : // weiter links
(aTopPos.X() < aCurPos.X())))) // " reverse
{
aTopPos = aCurPos;
pTop = pObj;
}
}
// leider nichts gefunden
if( (bNext? (aBestPos.X() == LONG_MAX) : (aBestPos.X() == 0)) )
pBest = pTop;
}
return pBest;
}
sal_Bool SwFEShell::GotoObj( sal_Bool bNext, sal_uInt16 /*GOTOOBJ_...*/ eType )
{
const SdrObject* pBest = GetBestObject( bNext, eType );
if ( !pBest )
return sal_False;
const bool bFlyFrm(dynamic_cast< const SwVirtFlyDrawObj* >(pBest));
if( bFlyFrm )
{
SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pBest;
const SwRect& rFrm = pO->GetFlyFrm()->Frm();
SelectObj( rFrm.Pos(), 0, (SdrObject*)pBest );
if( !ActionPend() )
MakeVisible( rFrm );
}
else
{
SelectObj( basegfx::B2DPoint(0.0, 0.0), 0, (SdrObject*)pBest );
if( !ActionPend() )
MakeVisible(pBest->getObjectRange(Imp()->GetDrawView()));
}
CallChgLnk();
return sal_True;
}
/*************************************************************************
|*
|* SwFEShell::BeginCreate()
|*
*************************************************************************/
bool SwFEShell::BeginCreate(const SdrObjectCreationInfo& rSdrObjectCreationInfo, const basegfx::B2DPoint& rPos )
{
bool bRet(false);
if ( !Imp()->HasDrawView() )
Imp()->MakeDrawView();
if ( GetPageNumber( rPos ) )
{
Imp()->GetDrawView()->setSdrObjectCreationInfo(rSdrObjectCreationInfo);
if(OBJ_CAPTION == rSdrObjectCreationInfo.getIdent())
{
bRet = Imp()->GetDrawView()->BegCreateCaptionObj(
rPos,
basegfx::B2DVector(lMinBorder - MINFLY, lMinBorder - MINFLY));
}
else
{
bRet = Imp()->GetDrawView()->BegCreateObj( rPos );
}
}
if ( bRet )
{
::FrameNotify( this, FLY_DRAG_START );
}
return bRet;
}
/*************************************************************************
|*
|* SwFEShell::MoveCreate()
|*
*************************************************************************/
void SwFEShell::MoveCreate( const basegfx::B2DPoint &rPos )
{
ASSERT( Imp()->HasDrawView(), "MoveCreate without DrawView?" );
if ( GetPageNumber( rPos ) )
{
const Point aOldPos(basegfx::fround(rPos.getX()), basegfx::fround(rPos.getY()));
ScrollTo( aOldPos );
Imp()->GetDrawView()->MovCreateObj( rPos );
::FrameNotify( this, FLY_DRAG );
}
}
/*************************************************************************
|*
|* SwFEShell::EndCreate(), ImpEndCreate()
|*
*************************************************************************/
bool SwFEShell::EndCreate( sal_uInt16 eSdrCreateCmd )
{
// Damit das Undo-Object aus der DrawEngine nicht bei uns
// gespeichert wird, (wir erzeugen ein eigenes Undo-Object!) hier kurz
// das Undo abschalten
ASSERT( Imp()->HasDrawView(), "EndCreate without DrawView?" );
if( !Imp()->GetDrawView()->IsGroupEntered() )
{
GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
}
sal_Bool bCreate = Imp()->GetDrawView()->EndCreateObj(
SdrCreateCmd( eSdrCreateCmd ) );
GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
if ( !bCreate )
{
::FrameNotify( this, FLY_DRAG_END );
return sal_False;
}
if ( (SdrCreateCmd)eSdrCreateCmd == SDRCREATE_NEXTPOINT )
{
::FrameNotify( this, FLY_DRAG );
return sal_True;
}
return ImpEndCreate();
}
sal_Bool SwFEShell::ImpEndCreate()
{
SdrObject* pSdrObj = Imp()->GetDrawView()->getSelectedIfSingle();
OSL_ENSURE( pSdrObj, "Neues Object nicht selektiert." );
if( sdr::legacy::GetSnapRect(*pSdrObj).IsEmpty() )
{
// das Object vergessen wir lieber, fuerht nur
// zu Problemen
Imp()->GetDrawView()->DeleteMarked();
Imp()->GetDrawView()->UnmarkAll();
::FrameNotify( this, FLY_DRAG_END );
return sal_False;
}
if( pSdrObj->GetParentSdrObject() )
{
Point aTmpPos( sdr::legacy::GetSnapRect(*pSdrObj).TopLeft() );
const basegfx::B2DPoint& rNewAnchor( pSdrObj->GetParentSdrObject()->GetAnchorPos() );
// OD 2004-04-05 #i26791# - direct object positioning for group members
// #i108739#
pSdrObj->SetAnchorPos(rNewAnchor);
::FrameNotify( this, FLY_DRAG );
return sal_True;
}
LockPaint();
StartAllAction();
Imp()->GetDrawView()->UnmarkAll();
const Rectangle rBound(sdr::legacy::GetSnapRect(*pSdrObj));
Point aPt( rBound.TopRight() );
//Fremde Identifier sollen in den Default laufen.
//Ueberschneidungen sind moeglich!!
sal_uInt16 nIdent = SdrInventor == pSdrObj->GetObjInventor()
? pSdrObj->GetObjIdentifier()
: 0xFFFF;
//Default fuer Controls ist Zeichengebunden, Absatzgebunden sonst.
SwFmtAnchor aAnch;
const SwFrm *pAnch = 0;
sal_Bool bCharBound = sal_False;
if( dynamic_cast< SdrUnoObj* >(pSdrObj) )
{
SwPosition aPos( GetDoc()->GetNodes() );
SwCrsrMoveState aState( MV_SETONLYTEXT );
Point aPoint( aPt.X(), aPt.Y() + rBound.GetHeight()/2 );
GetLayout()->GetCrsrOfst( &aPos, aPoint, &aState ); //swmod 080317
//Zeichenbindung ist im ReadnOnly-Inhalt nicht erlaubt
if( !aPos.nNode.GetNode().IsProtect() )
{
pAnch = aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(), &aPoint, &aPos );
SwRect aTmp;
pAnch->GetCharRect( aTmp, aPos );
//Der Crsr darf nicht zu weit entfernt sein.
bCharBound = sal_True;
Rectangle aRect( aTmp.SVRect() );
aRect.Left() -= MM50*2;
aRect.Top() -= MM50*2;
aRect.Right() += MM50*2;
aRect.Bottom()+= MM50*2;
if( !aRect.IsOver( rBound ) && !::GetHtmlMode( GetDoc()->GetDocShell() ))
bCharBound = sal_False;
//Bindung in Kopf-/Fusszeilen ist ebenfalls nicht erlaubt.
if( bCharBound )
bCharBound = !GetDoc()->IsInHeaderFooter( aPos.nNode );
if( bCharBound )
{
aAnch.SetType( FLY_AS_CHAR );
aAnch.SetAnchor( &aPos );
}
}
}
if( !bCharBound )
{
// OD 16.05.2003 #108784# - allow native drawing objects in header/footer.
// Thus, set <bBodyOnly> to <false> for these objects using value
// of <nIdent> - value <0xFFFF> indicates control objects, which aren't
// allowed in header/footer.
//bool bBodyOnly = OBJ_NONE != nIdent;
bool bBodyOnly = 0xFFFF == nIdent;
bool bAtPage = false;
const SwFrm* pPage = 0;
SwCrsrMoveState aState( MV_SETONLYTEXT );
Point aPoint( aPt );
SwPosition aPos( GetDoc()->GetNodes() );
GetLayout()->GetCrsrOfst( &aPos, aPoint, &aState );
//nicht in ReadnOnly-Inhalt setzen
if( aPos.nNode.GetNode().IsProtect() )
// dann darf er nur seitengebunden sein. Oder sollte man
// die naechste nicht READONLY Position suchen?
bAtPage = true;
pAnch = aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(), &aPoint, 0, sal_False );
if( !bAtPage )
{
const SwFlyFrm *pTmp = pAnch->FindFlyFrm();
if( pTmp )
{
const SwFrm* pTmpFrm = pAnch;
SwRect aBound( rBound );
while( pTmp )
{
if( pTmp->Frm().IsInside( aBound ) )
{
if( !bBodyOnly || !pTmp->FindFooterOrHeader() )
pPage = pTmpFrm;
break;
}
pTmp = pTmp->GetAnchorFrm()
? pTmp->GetAnchorFrm()->FindFlyFrm()
: 0;
pTmpFrm = pTmp;
}
}
if( !pPage )
pPage = pAnch->FindPageFrm();
// immer ueber FindAnchor gehen, damit der Frame immer an den
// davorgehen gebunden wird. Beim GetCrsOfst kann man auch zum
// nachfolgenden kommen. DAS IST FALSCH
pAnch = ::FindAnchor( pPage, aPt, bBodyOnly );
aPos.nNode = *((SwCntntFrm*)pAnch)->GetNode();
//nicht in ReadnOnly-Inhalt setzen
if( aPos.nNode.GetNode().IsProtect() )
// dann darf er nur seitengebunden sein. Oder sollte man
// die naechste nicht READONLY Position suchen?
bAtPage = true;
else
{
aAnch.SetType( FLY_AT_PARA );
aAnch.SetAnchor( &aPos );
}
}
if( bAtPage )
{
pPage = pAnch->FindPageFrm();
aAnch.SetType( FLY_AT_PAGE );
aAnch.SetPageNum( pPage->GetPhyPageNum() );
pAnch = pPage; // die Page wird jetzt zum Anker
}
}
SfxItemSet aSet( GetDoc()->GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE,
RES_SURROUND, RES_ANCHOR, 0 );
aSet.Put( aAnch );
// OD 2004-03-30 #i26791# - determine relative object position
SwTwips nXOffset;
SwTwips nYOffset = rBound.Top() - pAnch->Frm().Top();
{
if( pAnch->IsVertical() )
{
nXOffset = nYOffset;
nYOffset = pAnch->Frm().Left()+pAnch->Frm().Width()-rBound.Right();
}
else if( pAnch->IsRightToLeft() )
nXOffset = pAnch->Frm().Left()+pAnch->Frm().Width()-rBound.Right();
else
nXOffset = rBound.Left() - pAnch->Frm().Left();
if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() )
{
SwTxtFrm* pTmp = (SwTxtFrm*)pAnch;
do {
pTmp = pTmp->FindMaster();
ASSERT( pTmp, "Where's my Master?" );
// OD 2004-03-30 #i26791# - correction: add frame area height
// of master frames.
nYOffset += pTmp->IsVertical() ?
pTmp->Frm().Width() : pTmp->Frm().Height();
} while ( pTmp->IsFollow() );
}
}
if( OBJ_NONE == nIdent )
{
//Bei OBJ_NONE wird ein Fly eingefuegt.
const long nWidth = rBound.Right() - rBound.Left();
const long nHeight= rBound.Bottom() - rBound.Top();
aSet.Put( SwFmtFrmSize( ATT_MIN_SIZE, Max( nWidth, long(MINFLY) ),
Max( nHeight, long(MINFLY) )));
SwFmtHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
SwFmtVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME );
aSet.Put( SwFmtSurround( SURROUND_PARALLEL ) );
aSet.Put( aHori );
aSet.Put( aVert );
//Schnell noch das Rechteck merken
const SwRect aFlyRect( rBound );
//Erzeugtes Object wegwerfen, so kann der Fly am elegentesten
//ueber vorhandene SS erzeugt werden.
GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false); // see above
// --> OD 2005-08-08 #i52858# - method name changed
SdrPage *pPg = getIDocumentDrawModelAccess()->GetOrCreateDrawModel()->GetPage( 0 );
// <--
if( !pPg )
{
SdrModel* pTmpSdrModel = getIDocumentDrawModelAccess()->GetDrawModel();
pPg = pTmpSdrModel->AllocPage( false );
pTmpSdrModel->InsertPage( pPg );
}
SdrObject* pRemovedObject = pPg->RemoveObjectFromSdrObjList( pSdrObj->GetNavigationPosition() );
deleteSdrObjectSafeAndClearPointer( pRemovedObject );
GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
SwFlyFrm* pFlyFrm;
if( NewFlyFrm( aSet, sal_True ) &&
::GetHtmlMode( GetDoc()->GetDocShell() ) &&
0 != ( pFlyFrm = FindFlyFrm() ))
{
SfxItemSet aHtmlSet( GetDoc()->GetAttrPool(), RES_VERT_ORIENT, RES_HORI_ORIENT );
//Horizontale Ausrichtung:
const sal_Bool bLeftFrm = aFlyRect.Left() <
pAnch->Frm().Left() + pAnch->Prt().Left(),
bLeftPrt = aFlyRect.Left() + aFlyRect.Width() <
pAnch->Frm().Left() + pAnch->Prt().Width()/2;
if( bLeftFrm || bLeftPrt )
{
aHori.SetHoriOrient( text::HoriOrientation::LEFT );
aHori.SetRelationOrient( bLeftFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
}
else
{
const sal_Bool bRightFrm = aFlyRect.Left() >
pAnch->Frm().Left() + pAnch->Prt().Width();
aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
aHori.SetRelationOrient( bRightFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
}
aHtmlSet.Put( aHori );
aVert.SetVertOrient( text::VertOrientation::TOP );
aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA );
aHtmlSet.Put( aVert );
GetDoc()->SetAttr( aHtmlSet, *pFlyFrm->GetFmt() );
}
}
else
{
aSet.Put( aAnch );
aSet.Put( SwFmtSurround( SURROUND_THROUGHT ) );
// OD 2004-03-30 #i26791# - set horizontal position
SwFmtHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
aSet.Put( aHori );
// OD 2004-03-30 #i26791# - set vertical position
if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() )
{
SwTxtFrm* pTmp = (SwTxtFrm*)pAnch;
do {
pTmp = pTmp->FindMaster();
ASSERT( pTmp, "Where's my Master?" );
nYOffset += pTmp->IsVertical() ?
pTmp->Prt().Width() : pTmp->Prt().Height();
} while ( pTmp->IsFollow() );
}
SwFmtVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME );
aSet.Put( aVert );
SwDrawFrmFmt* pFmt = (SwDrawFrmFmt*)getIDocumentLayoutAccess()->MakeLayoutFmt( RND_DRAW_OBJECT, &aSet );
// --> OD 2004-10-25 #i36010# - set layout direction of the position
pFmt->SetPositionLayoutDir(
text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
// <--
// --> OD 2005-03-11 #i44344#, #i44681# - positioning attributes already set
pFmt->PosAttrSet();
// <--
SwDrawContact *pContact = new SwDrawContact( pFmt, pSdrObj );
// --> OD 2004-11-22 #i35635#
pContact->MoveObjToVisibleLayer( pSdrObj );
// <--
if( bCharBound )
{
ASSERT( aAnch.GetAnchorId() == FLY_AS_CHAR, "wrong AnchorType" );
SwTxtNode *pNd = aAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
SwFmtFlyCnt aFmt( pFmt );
pNd->InsertItem(aFmt,
aAnch.GetCntntAnchor()->nContent.GetIndex(), 0 );
SwFmtVertOrient aVertical( pFmt->GetVertOrient() );
aVertical.SetVertOrient( text::VertOrientation::LINE_CENTER );
pFmt->SetFmtAttr( aVertical );
}
if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() )
{
SwTxtFrm* pTmp = (SwTxtFrm*)pAnch;
do {
pTmp = pTmp->FindMaster();
ASSERT( pTmp, "Where's my Master?" );
} while( pTmp->IsFollow() );
pAnch = pTmp;
}
pContact->ConnectToLayout();
// OD 25.06.2003 #108784# - mark object at frame the object is inserted at.
{
SdrObject* pMarkObj = pContact->GetDrawObjectByAnchorFrm( *pAnch );
if ( pMarkObj )
{
Imp()->GetDrawView()->MarkObj( *pMarkObj, false );
}
else
{
Imp()->GetDrawView()->MarkObj( *pSdrObj, false );
}
}
}
GetDoc()->SetModified();
KillPams();
EndAllActionAndCall();
UnlockPaint();
return sal_True;
}
/*************************************************************************
|*
|* SwFEShell::BreakCreate()
|*
*************************************************************************/
void SwFEShell::BreakCreate()
{
ASSERT( Imp()->HasDrawView(), "BreakCreate without DrawView?" );
Imp()->GetDrawView()->BrkCreateObj();
::FrameNotify( this, FLY_DRAG_END );
}
/*************************************************************************
|*
|* SwFEShell::IsDrawCreate()
|*
*************************************************************************/
bool SwFEShell::IsDrawCreate() const
{
return Imp()->HasDrawView() ? 0 != Imp()->GetDrawView()->GetCreateObj() : sal_False;
}
/*************************************************************************
|*
|* SwFEShell::BeginMark()
|*
*************************************************************************/
bool SwFEShell::BeginMark(const basegfx::B2DPoint& rPos)
{
if ( !Imp()->HasDrawView() )
{
Imp()->MakeDrawView();
}
if ( GetPageNumber( rPos ) )
{
SwDrawView* pDView = Imp()->GetDrawView();
if (pDView->HasMarkablePoints())
{
return pDView->BegMarkPoints( rPos );
}
else
{
return pDView->BegMarkObj( rPos );
}
}
else
{
return false;
}
}
/*************************************************************************
|*
|* SwFEShell::MoveMark()
|*
*************************************************************************/
void SwFEShell::MoveMark( const basegfx::B2DPoint& rPos )
{
ASSERT( Imp()->HasDrawView(), "MoveMark without DrawView?" );
if ( GetPageNumber( rPos ) )
{
ScrollTo( rPos );
SwDrawView* pDView = Imp()->GetDrawView();
if (pDView->IsInsObjPoint())
{
pDView->MovInsObjPoint( rPos );
}
else if (pDView->IsMarkPoints())
{
pDView->MovMarkPoints( rPos );
}
else
{
pDView->MovAction( rPos );
}
}
}
/*************************************************************************
|*
|* SwFEShell::EndMark()
|*
*************************************************************************/
bool SwFEShell::EndMark()
{
sal_Bool bRet = sal_False;
ASSERT( Imp()->HasDrawView(), "EndMark without DrawView?" );
if (Imp()->GetDrawView()->IsMarkObj())
{
bRet = Imp()->GetDrawView()->EndMarkObj();
if ( bRet )
{
SwDrawView* pDView = Imp()->GetDrawView();
//Rahmen werden auf diese Art nicht Selektiert, es sein denn es
//ist nur ein Rahmen.
SwFlyFrm* pOldSelFly = ::GetFlyFromMarked( this );
if ( pDView->getSelectedSdrObjectCount() > 1 )
{
const SdrObjectVector aSelection(pDView->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
SdrObject *pObj = aSelection[i];
if( dynamic_cast< SwVirtFlyDrawObj* >(pObj) )
{
// deselect SwVirtFlyDrawObj's
pDView->MarkObj(*pObj, true);
}
}
}
if ( pDView->areSdrObjectsSelected() )
::lcl_GrabCursor(this, pOldSelFly);
else
bRet = sal_False;
}
if ( bRet )
::FrameNotify( this, FLY_DRAG_START );
}
else
{
if (Imp()->GetDrawView()->IsMarkPoints())
bRet = Imp()->GetDrawView()->EndMarkPoints();
}
SetChainMarker();
return bRet;
}
/*************************************************************************
|*
|* SwFEShell::BreakSelect()
|*
*************************************************************************/
void SwFEShell::BreakMark()
{
ASSERT( Imp()->HasDrawView(), "BreakMark without DrawView?" );
Imp()->GetDrawView()->BrkMarkObj();
}
/*************************************************************************
|*
|* SwFEShell::GetAnchorId()
|*
*************************************************************************/
short SwFEShell::GetAnchorId() const
{
short nRet = SHRT_MAX;
if ( Imp()->HasDrawView() && Imp()->GetDrawView()->areSdrObjectsSelected() )
{
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
SdrObject *pObj = aSelection[i];
if ( dynamic_cast< SwVirtFlyDrawObj* >(pObj) )
{
nRet = -1;
break;
}
SwDrawContact *pContact = (SwDrawContact*)findConnectionToSdrObject(pObj);
short nId = static_cast<short>(pContact->GetFmt()->GetAnchor().GetAnchorId());
if ( nRet == SHRT_MAX )
nRet = nId;
else if ( nRet != nId )
{
nRet = -1;
break;
}
}
}
if ( nRet == SHRT_MAX )
nRet = -1;
return nRet;
}
/*************************************************************************
|*
|* SwFEShell::ChgAnchor()
|*
*************************************************************************/
void SwFEShell::ChgAnchor( int eAnchorId, sal_Bool bSameOnly, sal_Bool bPosCorr )
{
ASSERT( Imp()->HasDrawView(), "ChgAnchor without DrawView?" );
const SdrObjectVector aSdrObjectVector = Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView();
if( aSdrObjectVector.size() &&
!aSdrObjectVector[0]->GetParentSdrObject() )
{
StartAllAction();
if( GetDoc()->ChgAnchor( aSdrObjectVector, (RndStdIds)eAnchorId, bSameOnly, bPosCorr ))
Imp()->GetDrawView()->UnmarkAll();
EndAllAction();
::FrameNotify( this, FLY_DRAG );
}
}
/*************************************************************************
|*
|* SwFEShell::DelSelectedObj()
|*
*************************************************************************/
void SwFEShell::DelSelectedObj()
{
ASSERT( Imp()->HasDrawView(), "DelSelectedObj(), no DrawView available" );
if ( Imp()->HasDrawView() )
{
StartAllAction();
Imp()->GetDrawView()->DeleteMarked();
EndAllAction();
::FrameNotify( this, FLY_DRAG_END );
}
}
/*************************************************************************
|*
|* SwFEShell::GetObjSize(), GetAnchorObjDiff()
|*
|* Beschreibung Fuer die Statuszeile zum Erfragen der aktuellen
|* Verhaeltnisse
|*
*************************************************************************/
Size SwFEShell::GetObjSize() const
{
basegfx::B2DRange aObjectRange;
if ( Imp()->HasDrawView() )
{
if ( Imp()->GetDrawView()->IsAction() )
{
aObjectRange = Imp()->GetDrawView()->TakeActionRange();
}
else
{
aObjectRange = Imp()->GetDrawView()->getMarkedObjectSnapRange();
}
}
return Size(basegfx::fround(aObjectRange.getWidth()), basegfx::fround(aObjectRange.getHeight()));
}
Point SwFEShell::GetAnchorObjDiff() const
{
const SdrView *pView = Imp()->GetDrawView();
ASSERT( pView, "GetAnchorObjDiff without DrawView?" );
basegfx::B2DRange aObjectRange;
if ( Imp()->GetDrawView()->IsAction() )
{
aObjectRange = Imp()->GetDrawView()->TakeActionRange();
}
else
{
aObjectRange = Imp()->GetDrawView()->getMarkedObjectSnapRange();
}
Point aRet(basegfx::fround(aObjectRange.getMinX()), basegfx::fround(aObjectRange.getMinY()));
if ( IsFrmSelected() )
{
SwFlyFrm *pFly = FindFlyFrm();
aRet -= pFly->GetAnchorFrm()->Frm().Pos();
}
else
{
const SdrObject *pObj = pView->getSelectedIfSingle();
if ( pObj )
aRet -= sdr::legacy::GetAnchorPos(*pObj);
}
return aRet;
}
Point SwFEShell::GetObjAbsPos() const
{
ASSERT( Imp()->GetDrawView(), "GetObjAbsPos() without DrawView?" );
const basegfx::B2DRange aActionRange(Imp()->GetDrawView()->GetDragStat().GetActionRange());
return Point(basegfx::fround(aActionRange.getMinX()), basegfx::fround(aActionRange.getMinY()));
}
/*************************************************************************
|*
|* SwFEShell::IsGroupSelected()
|*
*************************************************************************/
sal_Bool SwFEShell::IsGroupSelected()
{
if ( Imp()->GetDrawView() && IsObjSelected() && Imp()->GetDrawView()->areSdrObjectsSelected() )
{
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
SdrObject* pObj = aSelection[i];
// OD 30.06.2003 #108784# - consider 'virtual' drawing objects.
// Thus, use corresponding method instead of checking type.
if ( pObj->getChildrenOfSdrObject() &&
// --> FME 2004-12-08 #i38505# No ungroup allowed for 3d objects
!dynamic_cast< E3dObject* >(pObj) &&
// <--
FLY_AS_CHAR != ((SwDrawContact*)findConnectionToSdrObject(pObj))->
GetFmt()->GetAnchor().GetAnchorId() )
{
return sal_True;
}
}
}
return sal_False;
}
// OD 27.06.2003 #108784# - change return type.
// OD 27.06.2003 #108784# - adjustments for drawing objects in header/footer:
// allow group, only if all selected objects are in the same header/footer
// or not in header/footer.
bool SwFEShell::IsGroupAllowed() const
{
bool bIsGroupAllowed = false;
if ( Imp()->GetDrawView() && Imp()->GetDrawView()->getSelectedSdrObjectCount() > 1 )
{
bIsGroupAllowed = true;
const SdrObject* pUpGroup = 0L;
const SwFrm* pHeaderFooterFrm = 0L;
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); bIsGroupAllowed && i < aSelection.size(); ++i )
{
const SdrObject* pObj = aSelection[i];
if ( i )
bIsGroupAllowed = pObj->GetParentSdrObject() == pUpGroup;
else
pUpGroup = pObj->GetParentSdrObject();
if ( bIsGroupAllowed )
{
SwFrmFmt* pFrmFmt( ::FindFrmFmt( const_cast<SdrObject*>(pObj) ) );
if ( !pFrmFmt )
{
ASSERT( false,
"<SwFEShell::IsGroupAllowed()> - missing frame format" );
bIsGroupAllowed = false;
}
else if ( FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
{
bIsGroupAllowed = false;
}
}
// OD 27.06.2003 #108784# - check, if all selected objects are in the
// same header/footer or not in header/footer.
if ( bIsGroupAllowed )
{
const SwFrm* pAnchorFrm = 0L;
if ( dynamic_cast< const SwVirtFlyDrawObj* >(pObj) )
{
const SwFlyFrm* pFlyFrm =
static_cast<const SwVirtFlyDrawObj*>(pObj)->GetFlyFrm();
if ( pFlyFrm )
{
pAnchorFrm = pFlyFrm->GetAnchorFrm();
}
}
else
{
SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(findConnectionToSdrObject( pObj ));
if ( pDrawContact )
{
pAnchorFrm = pDrawContact->GetAnchorFrm( pObj );
}
}
if ( pAnchorFrm )
{
if ( i )
{
bIsGroupAllowed =
( pAnchorFrm->FindFooterOrHeader() == pHeaderFooterFrm );
}
else
{
pHeaderFooterFrm = pAnchorFrm->FindFooterOrHeader();
}
}
}
}
}
return bIsGroupAllowed;
}
/*************************************************************************
|*
|* SwFEShell::GroupSelection()
|*
|* Beschreibung Die Gruppe bekommt den Anker und das Contactobjekt
|* des ersten in der Selektion
|*
*************************************************************************/
void SwFEShell::GroupSelection()
{
if ( IsGroupAllowed() )
{
StartAllAction();
StartUndo( UNDO_START );
GetDoc()->GroupSelection( *Imp()->GetDrawView() );
EndUndo( UNDO_END );
EndAllAction();
}
}
/*************************************************************************
|*
|* SwFEShell::UnGroupSelection()
|*
|* Beschreibung Die Einzelobjekte bekommen eine Kopie vom Anker und
|* Contactobjekt der Gruppe.
|*
*************************************************************************/
void SwFEShell::UnGroupSelection()
{
if ( IsGroupSelected() )
{
StartAllAction();
StartUndo( UNDO_START );
GetDoc()->UnGroupSelection( *Imp()->GetDrawView() );
EndUndo( UNDO_END );
EndAllAction();
}
}
/*************************************************************************
|*
|* SwFEShell::MirrorSelection()
|*
*************************************************************************/
void SwFEShell::MirrorSelection( sal_Bool bHorizontal )
{
SdrView *pView = Imp()->GetDrawView();
if ( IsObjSelected() && pView->IsMirrorAllowed() )
{
if ( bHorizontal )
pView->MirrorMarkedObjHorizontal();
else
pView->MirrorMarkedObjVertical();
}
}
// springe zum benannten Rahmen (Grafik/OLE)
sal_Bool SwFEShell::GotoFly( const String& rName, FlyCntType eType, sal_Bool bSelFrm )
{
sal_Bool bRet = sal_False;
static sal_uInt8 __READONLY_DATA aChkArr[ 4 ] = {
/* FLYCNTTYPE_ALL */ 0,
/* FLYCNTTYPE_FRM */ ND_TEXTNODE,
/* FLYCNTTYPE_GRF */ ND_GRFNODE,
/* FLYCNTTYPE_OLE */ ND_OLENODE
};
const SwFlyFrmFmt* pFlyFmt = pDoc->FindFlyByName( rName, aChkArr[ eType]);
if( pFlyFmt )
{
SET_CURR_SHELL( this );
SwFlyFrm* pFrm = SwIterator<SwFlyFrm,SwFmt>::FirstElement( *pFlyFmt );
if( pFrm )
{
if( bSelFrm )
{
SelectObj( pFrm->Frm().Pos(), 0, pFrm->GetVirtDrawObj() );
if( !ActionPend() )
MakeVisible( pFrm->Frm() );
}
else
{
// --> OD 2004-06-11 #i28701# - no format here
// pFrm->GetAnchorFrm()->Calc();
SwCntntFrm *pCFrm = pFrm->ContainsCntnt();
if ( pCFrm )
{
SwCntntNode *pCNode = pCFrm->GetNode();
ClearMark();
SwPaM* pCrsr = GetCrsr();
pCrsr->GetPoint()->nNode = *pCNode;
pCrsr->GetPoint()->nContent.Assign( pCNode, 0 );
SwRect& rChrRect = (SwRect&)GetCharRect();
rChrRect = pFrm->Prt();
rChrRect.Pos() += pFrm->Frm().Pos();
GetCrsrDocPos() = rChrRect.Pos();
}
}
bRet = sal_True;
}
}
return bRet;
}
sal_uInt16 SwFEShell::GetFlyCount( FlyCntType eType ) const
{
return GetDoc()->GetFlyCount(eType);
}
const SwFrmFmt* SwFEShell::GetFlyNum(sal_uInt16 nIdx, FlyCntType eType ) const
{
return GetDoc()->GetFlyNum(nIdx, eType );
}
// zeige das akt. selektierte "Object" an
void SwFEShell::MakeSelVisible()
{
if( Imp()->HasDrawView() &&
Imp()->GetDrawView()->areSdrObjectsSelected())
{
MakeVisible( Imp()->GetDrawView()->getMarkedObjectSnapRange() );
}
else
SwCrsrShell::MakeSelVisible();
}
//Welcher Schutz ist am selektierten Objekt gesetzt?
sal_uInt8 SwFEShell::IsSelObjProtected( sal_uInt16 eType ) const
{
int nChk = 0;
const bool bParent = (eType & FLYPROTECT_PARENT);
if( Imp()->HasDrawView() && Imp()->GetDrawView()->areSdrObjectsSelected() )
{
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
for( sal_uInt32 i = aSelection.size(); i; )
{
SdrObject *pObj = aSelection[--i];
if( !bParent )
{
nChk |= ( pObj->IsMoveProtect() ? FLYPROTECT_POS : 0 ) |
( pObj->IsResizeProtect()? FLYPROTECT_SIZE : 0 );
if( dynamic_cast< SwVirtFlyDrawObj* >(pObj) )
{
SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
if ( (FLYPROTECT_CONTENT & eType) && pFly->GetFmt()->GetProtect().IsCntntProtected() )
nChk |= FLYPROTECT_CONTENT;
if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
{
SwOLENode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode();
uno::Reference < embed::XEmbeddedObject > xObj( pNd ? pNd->GetOLEObj().GetOleRef() : 0 );
if ( xObj.is() )
{
// TODO/LATER: use correct aspect
const bool bNeverResize = (embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ));
if ( ( (FLYPROTECT_CONTENT & eType) || (FLYPROTECT_SIZE & eType) ) && bNeverResize )
{
nChk |= FLYPROTECT_SIZE;
nChk |= FLYPROTECT_FIXED;
}
// set FLYPROTECT_POS if it is a Math object anchored 'as char' and baseline alignment is activated
const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
&& FLY_AS_CHAR == pFly->GetFmt()->GetAnchor().GetAnchorId()
&& pDoc->get( IDocumentSettingAccess::MATH_BASELINE_ALIGNMENT );
if ((FLYPROTECT_POS & eType) && bProtectMathPos)
nChk |= FLYPROTECT_POS;
}
}
}
nChk &= eType;
if( nChk == eType )
return static_cast<sal_uInt8>(eType);
}
const SwFrm* pAnch;
if( dynamic_cast< SwVirtFlyDrawObj* >(pObj) )
pAnch = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm()->GetAnchorFrm();
else
{
SwDrawContact* pTmp = (SwDrawContact*)findConnectionToSdrObject(pObj);
pAnch = pTmp ? pTmp->GetAnchorFrm( pObj ) : NULL;
}
if( pAnch && pAnch->IsProtected() )
return static_cast<sal_uInt8>(eType);
}
}
return static_cast<sal_uInt8>(nChk);
}
sal_Bool SwFEShell::GetObjAttr( SfxItemSet &rSet ) const
{
if ( !IsObjSelected() || !Imp()->GetDrawView() )
return sal_False;
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
SdrObject *pObj = aSelection[i];
SwDrawContact *pContact = (SwDrawContact*)findConnectionToSdrObject(pObj);
// --> OD 2007-07-24 #143008# - make code robust
ASSERT( pContact, "<SwFEShell::GetObjAttr(..)> - missing <pContact> - please inform OD." );
if ( pContact )
{
if ( i )
rSet.MergeValues( pContact->GetFmt()->GetAttrSet() );
else
rSet.Put( pContact->GetFmt()->GetAttrSet() );
}
// <--
}
return sal_True;
}
sal_Bool SwFEShell::SetObjAttr( const SfxItemSet& rSet )
{
SET_CURR_SHELL( this );
if ( !rSet.Count() || !Imp()->GetDrawView() || !Imp()->GetDrawView()->areSdrObjectsSelected())
{
ASSERT( !this, "SetObjAttr, empty set." );
return sal_False;
}
StartAllAction();
StartUndo( UNDO_INSATTR );
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
SdrObject *pObj = aSelection[i];
SwDrawContact *pContact = (SwDrawContact*)findConnectionToSdrObject(pObj);
GetDoc()->SetAttr( rSet, *pContact->GetFmt() );
}
EndUndo( UNDO_INSATTR );
EndAllActionAndCall();
GetDoc()->SetModified();
return sal_True;
}
sal_Bool SwFEShell::IsAlignPossible() const
{
if(Imp()->GetDrawView() && Imp()->GetDrawView()->areSdrObjectsSelected())
{
sal_Bool bRet = sal_True;
SdrObject *pO = Imp()->GetDrawView()->getSelectedIfSingle();
if ( pO )
{
SwDrawContact *pC = (SwDrawContact*)findConnectionToSdrObject(pO);
//only as character bound drawings can be aligned
bRet = (pC->GetFmt()->GetAnchor().GetAnchorId() == FLY_AS_CHAR);
}
if ( bRet )
return Imp()->GetDrawView()->IsAlignPossible();
}
return sal_False;
}
//Temporaerer Fix bis SS von JOE da ist
void SwFEShell::CheckUnboundObjects()
{
SET_CURR_SHELL( this );
if(Imp()->GetDrawView() && Imp()->GetDrawView()->areSdrObjectsSelected())
{
const SdrObjectVector aSelection(Imp()->GetDrawView()->getSelectedSdrObjectVectorFromSdrMarkView());
for ( sal_uInt32 i(0); i < aSelection.size(); ++i )
{
SdrObject *pObj = aSelection[i];
if ( !findConnectionToSdrObject(pObj) )
{
const Rectangle rBound(sdr::legacy::GetSnapRect(*pObj));
const Point aPt( rBound.TopLeft() );
const SwFrm *pPage = GetLayout()->Lower();
const SwFrm *pLast = pPage;
while ( pPage && !pPage->Frm().IsInside( aPt ) )
{
if ( aPt.Y() > pPage->Frm().Bottom() )
pLast = pPage;
pPage = pPage->GetNext();
}
if ( !pPage )
pPage = pLast;
ASSERT( pPage, "Page not found." );
//Fremde Identifier sollen in den Default laufen.
//Ueberschneidungen sind moeglich!!
//sal_uInt16 nIdent =
// Imp()->GetDrawView()->GetCurrentObjInventor() == SdrInventor ?
// Imp()->GetDrawView()->GetCurrentObjIdentifier() : 0xFFFF;
SwFmtAnchor aAnch;
const SwFrm *pAnch = 0;
{
pAnch = ::FindAnchor( pPage, aPt, sal_True );
SwPosition aPos( *((SwCntntFrm*)pAnch)->GetNode() );
aAnch.SetType( FLY_AT_PARA );
aAnch.SetAnchor( &aPos );
((SwRect&)GetCharRect()).Pos() = aPt;
}
//Erst hier die Action, damit das GetCharRect aktuelle Werte liefert.
StartAllAction();
SfxItemSet aSet( GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE,
RES_SURROUND, RES_ANCHOR, 0 );
aSet.Put( aAnch );
aSet.Put( SwFmtSurround( SURROUND_THROUGHT ) );
SwFrmFmt* pFmt = getIDocumentLayoutAccess()->MakeLayoutFmt( RND_DRAW_OBJECT, &aSet );
SwDrawContact *pContact = new SwDrawContact(
(SwDrawFrmFmt*)pFmt, pObj );
// --> OD 2004-11-22 #i35635#
pContact->MoveObjToVisibleLayer( pObj );
// <--
pContact->ConnectToLayout();
EndAllAction();
}
}
}
}
void SwFEShell::SetCalcFieldValueHdl(Outliner* pOutliner)
{
GetDoc()->SetCalcFieldValueHdl(pOutliner);
}
int SwFEShell::Chainable( SwRect &rRect, const SwFrmFmt &rSource,
const Point &rPt ) const
{
rRect.Clear();
//Die Source darf noch keinen Follow haben.
const SwFmtChain &rChain = rSource.GetChain();
if ( rChain.GetNext() )
return SW_CHAIN_SOURCE_CHAINED;
if( Imp()->HasDrawView() )
{
SdrObject* pObj;
SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();
const double fOld(pDView->GetHitTolerancePixel());
pDView->SetHitTolerancePixel( 0 );
if( pDView->PickObj( basegfx::B2DPoint(rPt.X(), rPt.Y()), pDView->getHitTolLog(), pObj, SDRSEARCH_PICKMARKABLE ) &&
dynamic_cast< SwVirtFlyDrawObj* >(pObj) )
{
SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
rRect = pFly->Frm();
//Ziel darf natuerlich nicht gleich Source sein und es
//darf keine geschlossene Kette entstehen.
SwFrmFmt *pFmt = pFly->GetFmt();
return GetDoc()->Chainable(rSource, *pFmt);
}
pDView->SetHitTolerancePixel(fOld);
}
return SW_CHAIN_NOT_FOUND;
}
int SwFEShell::Chain( SwFrmFmt &rSource, const SwFrmFmt &rDest )
{
return GetDoc()->Chain(rSource, rDest);
}
int SwFEShell::Chain( SwFrmFmt &rSource, const Point &rPt )
{
SwRect aDummy;
int nErr = Chainable( aDummy, rSource, rPt );
if ( !nErr )
{
StartAllAction();
SdrObject* pObj;
SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();
const double fOld(pDView->GetHitTolerancePixel());
pDView->SetHitTolerancePixel( 0 );
pDView->PickObj( basegfx::B2DPoint(rPt.X(), rPt.Y()), pDView->getHitTolLog(), pObj, SDRSEARCH_PICKMARKABLE );
pDView->SetHitTolerancePixel(fOld);
SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)pFly->GetFmt();
GetDoc()->Chain(rSource, *pFmt);
EndAllAction();
SetChainMarker();
}
return nErr;
}
void SwFEShell::Unchain( SwFrmFmt &rFmt )
{
StartAllAction();
GetDoc()->Unchain(rFmt);
EndAllAction();
}
void SwFEShell::HideChainMarker()
{
if ( pChainFrom )
{
delete pChainFrom;
pChainFrom = 0L;
}
if ( pChainTo )
{
delete pChainTo;
pChainTo = 0L;
}
}
void SwFEShell::SetChainMarker()
{
sal_Bool bDelFrom = sal_True,
bDelTo = sal_True;
if ( IsFrmSelected() )
{
SwFlyFrm *pFly = FindFlyFrm();
if ( pFly->GetPrevLink() )
{
bDelFrom = sal_False;
const SwFrm *pPre = pFly->GetPrevLink();
Point aStart( pPre->Frm().Right(), pPre->Frm().Bottom());
Point aEnd(pFly->Frm().Pos());
if ( !pChainFrom )
{
pChainFrom = new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd );
}
}
if ( pFly->GetNextLink() )
{
bDelTo = sal_False;
const SwFlyFrm *pNxt = pFly->GetNextLink();
Point aStart( pFly->Frm().Right(), pFly->Frm().Bottom());
Point aEnd(pNxt->Frm().Pos());
if ( !pChainTo )
{
pChainTo = new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd );
}
}
}
if ( bDelFrom )
{
delete pChainFrom, pChainFrom = 0;
}
if ( bDelTo )
{
delete pChainTo, pChainTo = 0;
}
}
long SwFEShell::GetSectionWidth( SwFmt& rFmt ) const
{
SwFrm *pFrm = GetCurrFrm();
// Steht der Cursor z.Z. in einem SectionFrm?
if( pFrm && pFrm->IsInSct() )
{
SwSectionFrm* pSect = pFrm->FindSctFrm();
do
{
// Ist es der Gewuenschte?
if( pSect->KnowsFormat( rFmt ) )
return pSect->Frm().Width();
// fuer geschachtelte Bereiche
pSect = pSect->GetUpper()->FindSctFrm();
}
while( pSect );
}
SwIterator<SwSectionFrm,SwFmt> aIter( rFmt );
for ( SwSectionFrm* pSct = aIter.First(); pSct; pSct = aIter.Next() )
{
if( !pSct->IsFollow() )
{
return pSct->Frm().Width();
}
}
return 0;
}
void SwFEShell::CreateDefaultShape(const SdrObjectCreationInfo& rSdrObjectCreationInfo, const Rectangle& rRect, sal_uInt16 nSlotId)
{
SdrView* pDrawView = GetDrawView();
SdrObject* pObj = 0;
if(pDrawView)
{
pObj = SdrObjFactory::MakeNewObject(pDrawView->getSdrModelFromSdrView(), rSdrObjectCreationInfo);
}
if(pObj)
{
Rectangle aRect(rRect);
if(OBJ_CIRC == rSdrObjectCreationInfo.getIdent()
&& (CircleType_Arc == rSdrObjectCreationInfo.getSdrCircleObjType()
|| CircleType_Segment == rSdrObjectCreationInfo.getSdrCircleObjType()))
{
// force quadratic
if(aRect.GetWidth() > aRect.GetHeight())
{
aRect = Rectangle(
Point(aRect.Left() + ((aRect.GetWidth() - aRect.GetHeight()) / 2), aRect.Top()),
Size(aRect.GetHeight(), aRect.GetHeight()));
}
else
{
aRect = Rectangle(
Point(aRect.Left(), aRect.Top() + ((aRect.GetHeight() - aRect.GetWidth()) / 2)),
Size(aRect.GetWidth(), aRect.GetWidth()));
}
}
sdr::legacy::SetLogicRect(*pObj, aRect);
SdrCircObj* pSdrCircObj = dynamic_cast< SdrCircObj* >(pObj);
SdrPathObj* pSdrPathObj = dynamic_cast< SdrPathObj* >(pObj);
SdrCaptionObj* pSdrCaptionObj = dynamic_cast< SdrCaptionObj* >(pObj);
SdrTextObj* pSdrTextObj = dynamic_cast< SdrTextObj* >(pObj);
if(pSdrCircObj)
{
pSdrCircObj->SetStartAngle(F_PI2); // TTTT formally 9000, needs check (mirror?)
pSdrCircObj->SetEndAngle(0.0);
}
else if(pSdrPathObj)
{
basegfx::B2DPolyPolygon aPoly;
switch(pSdrPathObj->getSdrPathObjType())
{
case PathType_OpenBezier:
case PathType_ClosedBezier:
{
if(rSdrObjectCreationInfo.getFreehandMode())
{
basegfx::B2DPolygon aInnerPoly;
aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
aInnerPoly.appendBezierSegment(
basegfx::B2DPoint(aRect.Left(), aRect.Top()),
basegfx::B2DPoint(aRect.Center().X(), aRect.Top()),
basegfx::B2DPoint(aRect.Center().X(), aRect.Center().Y()));
aInnerPoly.appendBezierSegment(
basegfx::B2DPoint(aRect.Center().X(), aRect.Bottom()),
basegfx::B2DPoint(aRect.Right(), aRect.Bottom()),
basegfx::B2DPoint(aRect.Right(), aRect.Top()));
aInnerPoly.append(basegfx::B2DPoint(aRect.Right(), aRect.Bottom()));
aInnerPoly.setClosed(true);
aPoly.append(aInnerPoly);
}
else
{
basegfx::B2DPolygon aInnerPoly;
aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
const basegfx::B2DPoint aCenterBottom(aRect.Center().X(), aRect.Bottom());
aInnerPoly.appendBezierSegment(
aCenterBottom,
aCenterBottom,
basegfx::B2DPoint(aRect.Center().X(), aRect.Center().Y()));
const basegfx::B2DPoint aCenterTop(aRect.Center().X(), aRect.Top());
aInnerPoly.appendBezierSegment(
aCenterTop,
aCenterTop,
basegfx::B2DPoint(aRect.Right(), aRect.Top()));
aInnerPoly.setClosed(true);
aPoly.append(aInnerPoly);
}
}
break;
case PathType_ClosedPolygon:
case PathType_OpenPolygon:
{
basegfx::B2DPolygon aInnerPoly;
sal_Int32 nWdt(aRect.GetWidth());
sal_Int32 nHgt(aRect.GetHeight());
aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 30) / 100, aRect.Top() + (nHgt * 70) / 100));
aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Top() + (nHgt * 15) / 100));
aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 65) / 100, aRect.Top()));
aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + nWdt, aRect.Top() + (nHgt * 30) / 100));
aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 50) / 100));
aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 75) / 100));
aInnerPoly.append(basegfx::B2DPoint(aRect.Bottom(), aRect.Right()));
if(PathType_OpenPolygon == pSdrPathObj->getSdrPathObjType())
{
aInnerPoly.append(basegfx::B2DPoint(aRect.Center().X(), aRect.Bottom()));
}
else
{
aInnerPoly.setClosed(true);
}
aPoly.append(aInnerPoly);
}
break;
case PathType_Line:
{
sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2);
basegfx::B2DPolygon aTempPoly;
aTempPoly.append(basegfx::B2DPoint(aRect.TopLeft().X(), nYMiddle));
aTempPoly.append(basegfx::B2DPoint(aRect.BottomRight().X(), nYMiddle));
aPoly.append(aTempPoly);
}
break;
}
pSdrPathObj->setB2DPolyPolygonInObjectCoordinates(aPoly);
}
else if(pSdrCaptionObj)
{
sal_Bool bVerticalText = ( SID_DRAW_TEXT_VERTICAL == nSlotId || SID_DRAW_CAPTION_VERTICAL == nSlotId );
pSdrCaptionObj->SetVerticalWriting(bVerticalText);
if(bVerticalText)
{
SfxItemSet aSet(pSdrCaptionObj->GetMergedItemSet());
aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
pSdrCaptionObj->SetMergedItemSet(aSet);
}
sdr::legacy::SetLogicRect(*pSdrCaptionObj, aRect);
const Point aTailPos(aRect.TopLeft() - Point(aRect.GetWidth() / 2, aRect.GetHeight() / 2));
pSdrCaptionObj->SetTailPos(basegfx::B2DPoint(aTailPos.X(), aTailPos.Y()));
}
else if(pSdrTextObj)
{
sdr::legacy::SetLogicRect(*pSdrTextObj, aRect);
sal_Bool bVertical = (SID_DRAW_TEXT_VERTICAL == nSlotId);
sal_Bool bMarquee = (SID_DRAW_TEXT_MARQUEE == nSlotId);
pSdrTextObj->SetVerticalWriting(bVertical);
if(bVertical)
{
SfxItemSet aSet(pSdrTextObj->GetObjectItemPool());
aSet.Put(SdrOnOffItem(SDRATTR_TEXT_AUTOGROWWIDTH, true));
aSet.Put(SdrOnOffItem(SDRATTR_TEXT_AUTOGROWHEIGHT, false));
aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
pSdrTextObj->SetMergedItemSet(aSet);
}
if(bMarquee)
{
SfxItemSet aSet(pObj->GetObjectItemPool(), SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST);
aSet.Put( SdrOnOffItem(SDRATTR_TEXT_AUTOGROWWIDTH, false) );
aSet.Put( SdrOnOffItem(SDRATTR_TEXT_AUTOGROWHEIGHT, false) );
aSet.Put( SdrTextAniKindItem( SDRTEXTANI_SLIDE ) );
aSet.Put( SdrTextAniDirectionItem( SDRTEXTANI_LEFT ) );
aSet.Put( SfxUInt16Item(SDRATTR_TEXT_ANICOUNT, 1 ) );
aSet.Put( SdrTextAniAmountItem( (sal_Int16)GetWin()->PixelToLogic(Size(2,1)).Width()) );
pObj->SetMergedItemSetAndBroadcast(aSet);
}
}
pDrawView->InsertObjectAtView(*pObj);
}
ImpEndCreate();
}
/** SwFEShell::GetShapeBackgrd
OD 02.09.2002 for #102450#:
method determines background color of the page the selected drawing
object is on and returns this color.
If no color is found, because no drawing object is selected or ...,
color COL_BLACK (default color on constructing object of class Color)
is returned.
@author OD
@returns an object of class Color
*/
const Color SwFEShell::GetShapeBackgrd() const
{
Color aRetColor;
// check, if a draw view exists
ASSERT( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!");
const SdrObject *pSdrObj = Imp()->GetDrawView() ? Imp()->GetDrawView()->getSelectedIfSingle() : 0;
if( pSdrObj )
{
// check, if selected object is a shape (drawing object)
ASSERT( !dynamic_cast< const SwVirtFlyDrawObj* >(pSdrObj), "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!");
if ( !dynamic_cast< const SwVirtFlyDrawObj* >(pSdrObj) )
{
// determine page frame of the frame the shape is anchored.
const SwFrm* pAnchorFrm =
static_cast<SwDrawContact*>(findConnectionToSdrObject(pSdrObj))->GetAnchorFrm( pSdrObj );
ASSERT( pAnchorFrm, "inconsistent modell - no anchor at shape!");
if ( pAnchorFrm )
{
const SwPageFrm* pPageFrm = pAnchorFrm->FindPageFrm();
ASSERT( pPageFrm, "inconsistent modell - no page!");
if ( pPageFrm )
{
aRetColor = pPageFrm->GetDrawBackgrdColor();
}
}
}
}
return aRetColor;
}
/** Is default horizontal text direction for selected drawing object right-to-left
OD 09.12.2002 #103045#
Because drawing objects only painted for each page only, the default
horizontal text direction of a drawing object is given by the corresponding
page property.
@author OD
@returns boolean, indicating, if the horizontal text direction of the
page, the selected drawing object is on, is right-to-left.
*/
bool SwFEShell::IsShapeDefaultHoriTextDirR2L() const
{
bool bRet = false;
// check, if a draw view exists
ASSERT( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!");
const SdrObject* pSdrObj = Imp()->GetDrawView() ? Imp()->GetDrawView()->getSelectedIfSingle() : 0;
if(pSdrObj)
{
// check, if selected object is a shape (drawing object)
ASSERT( !dynamic_cast< const SwVirtFlyDrawObj* >(pSdrObj), "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!");
if ( !dynamic_cast< const SwVirtFlyDrawObj* >(pSdrObj) )
{
// determine page frame of the frame the shape is anchored.
const SwFrm* pAnchorFrm =
static_cast<SwDrawContact*>(findConnectionToSdrObject(pSdrObj))->GetAnchorFrm( pSdrObj );
ASSERT( pAnchorFrm, "inconsistent modell - no anchor at shape!");
if ( pAnchorFrm )
{
const SwPageFrm* pPageFrm = pAnchorFrm->FindPageFrm();
ASSERT( pPageFrm, "inconsistent modell - no page!");
if ( pPageFrm )
{
bRet = pPageFrm->IsRightToLeft() ? true : false;
}
}
}
}
return bRet;
}
Point SwFEShell::GetRelativePagePosition(const Point& rDocPos)
{
Point aRet(-1, -1);
const SwFrm *pPage = GetLayout()->Lower();
while ( pPage && !pPage->Frm().IsInside( rDocPos ) )
{
pPage = pPage->GetNext();
}
if(pPage)
{
aRet = rDocPos - pPage->Frm().TopLeft();
}
return aRet;
}