nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / frmedt / feshview.cxx
blob439d99e9e2d776d40b93c36728b91c80be6180d8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
21 #include <svx/strings.hrc>
22 #include <svx/sdrobjectfilter.hxx>
23 #include <svx/svddrgmt.hxx>
24 #include <svx/svditer.hxx>
25 #include <svx/svdobj.hxx>
26 #include <svx/svdouno.hxx>
27 #include <svx/svdogrp.hxx>
28 #include <svx/svdocirc.hxx>
29 #include <svx/svdopath.hxx>
30 #include <svx/sxciaitm.hxx>
31 #include <svx/svdocapt.hxx>
32 #include <svx/xlnwtit.hxx>
33 #include <svx/xlnstwit.hxx>
34 #include <svx/xlnedwit.hxx>
35 #include <svx/xlnedit.hxx>
36 #include <svx/xlnstit.hxx>
37 #include <svx/svdomeas.hxx>
38 #include <svx/sdtagitm.hxx>
39 #include <svx/sdtacitm.hxx>
40 #include <svx/sdtaaitm.hxx>
41 #include <editeng/opaqitem.hxx>
42 #include <editeng/protitem.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdpagv.hxx>
45 #include <svx/dialmgr.hxx>
46 #include <tools/globname.hxx>
47 #include <sot/exchange.hxx>
48 #include <IDocumentDrawModelAccess.hxx>
49 #include <IDocumentSettingAccess.hxx>
50 #include <DocumentSettingManager.hxx>
51 #include <IDocumentState.hxx>
52 #include <IDocumentLayoutAccess.hxx>
53 #include <drawdoc.hxx>
54 #include <textboxhelper.hxx>
55 #include <frmfmt.hxx>
56 #include <frmatr.hxx>
57 #include <frmtool.hxx>
58 #include <fmtfsize.hxx>
59 #include <fmtanchr.hxx>
60 #include <fmtornt.hxx>
61 #include <fmtsrnd.hxx>
62 #include <fmtcntnt.hxx>
63 #include <fmtflcnt.hxx>
64 #include <fmtcnct.hxx>
65 #include <swmodule.hxx>
66 #include <fesh.hxx>
67 #include <rootfrm.hxx>
68 #include <pagefrm.hxx>
69 #include <sectfrm.hxx>
70 #include <doc.hxx>
71 #include <IDocumentUndoRedo.hxx>
72 #include <dview.hxx>
73 #include <dflyobj.hxx>
74 #include <dcontact.hxx>
75 #include <viewimp.hxx>
76 #include <flyfrm.hxx>
77 #include <pam.hxx>
78 #include <ndole.hxx>
79 #include <ndgrf.hxx>
80 #include <ndtxt.hxx>
81 #include <viewopt.hxx>
82 #include <swundo.hxx>
83 #include <notxtfrm.hxx>
84 #include <txtfrm.hxx>
85 #include <mdiexp.hxx>
86 #include <sortedobjs.hxx>
87 #include <HandleAnchorNodeChg.hxx>
88 #include <basegfx/polygon/b2dpolygon.hxx>
89 #include <comphelper/lok.hxx>
90 #include <sfx2/lokhelper.hxx>
91 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
92 #include <calbck.hxx>
93 #include <basegfx/polygon/b2dpolygontools.hxx>
94 #include <svx/svxids.hrc>
96 #include <com/sun/star/embed/EmbedMisc.hpp>
97 #include <com/sun/star/embed/Aspects.hpp>
98 #include <com/sun/star/embed/XEmbeddedObject.hpp>
100 #include <svx/srchdlg.hxx>
102 #define SCROLLVAL 75
104 using namespace com::sun::star;
107 * set line starts and ends for the object to be created
110 namespace {
112 ::basegfx::B2DPolyPolygon getPolygon(const char* pResId, const SdrModel& rModel)
114 ::basegfx::B2DPolyPolygon aRetval;
115 XLineEndListRef pLineEndList(rModel.GetLineEndList());
117 if( pLineEndList.is() )
119 OUString aArrowName( SvxResId(pResId) );
120 tools::Long nCount = pLineEndList->Count();
121 tools::Long nIndex;
122 for( nIndex = 0; nIndex < nCount; nIndex++ )
124 const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nIndex);
125 if( pEntry->GetName() == aArrowName )
127 aRetval = pEntry->GetLineEnd();
128 break;
133 return aRetval;
138 SwFlyFrame *GetFlyFromMarked( const SdrMarkList *pLst, SwViewShell *pSh )
140 if ( !pLst )
141 pLst = pSh->HasDrawView() ? &pSh->Imp()->GetDrawView()->GetMarkedObjectList():nullptr;
143 if ( pLst && pLst->GetMarkCount() == 1 )
145 SdrObject *pO = pLst->GetMark( 0 )->GetMarkedSdrObj();
146 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pO))
147 return pVirtO->GetFlyFrame();
149 return nullptr;
152 static void lcl_GrabCursor( SwFEShell* pSh, SwFlyFrame* pOldSelFly)
154 const SwFrameFormat *pFlyFormat = pSh->SelFlyGrabCursor();
155 if( pFlyFormat && !pSh->ActionPend() &&
156 (!pOldSelFly || pOldSelFly->GetFormat() != pFlyFormat) )
158 // now call set macro if applicable
159 pSh->GetFlyMacroLnk().Call( static_cast<const SwFlyFrameFormat*>(pFlyFormat) );
160 // if a dialog was started inside a macro, then
161 // MouseButtonUp arrives at macro and not to us. Therefore
162 // flag is always set here and will never be switched to
163 // respective Shell !!!!!!!
165 g_bNoInterrupt = false;
167 else if( !pFlyFormat || RES_DRAWFRMFMT == pFlyFormat->Which() )
169 // --> assure consistent cursor
170 pSh->KillPams();
171 pSh->ClearMark();
172 pSh->SetCursor( pSh->Imp()->GetDrawView()->GetAllMarkedRect().TopLeft(), true);
176 bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 nFlag, SdrObject *pObj )
178 SwDrawView *pDView = Imp()->GetDrawView();
179 if(!pDView)
180 return false;
181 CurrShell aCurr( this );
182 StartAction(); // action is necessary to assure only one AttrChgdNotify
183 // (e.g. due to Unmark->MarkListHasChgd) arrives
185 const SdrMarkList &rMrkList = pDView->GetMarkedObjectList();
186 const bool bHadSelection = rMrkList.GetMarkCount();
187 const bool bAddSelect = 0 != (SW_ADD_SELECT & nFlag);
188 const bool bEnterGroup = 0 != (SW_ENTER_GROUP & nFlag);
189 SwFlyFrame* pOldSelFly = nullptr;
190 const Point aOldPos( pDView->GetAllMarkedRect().TopLeft() );
192 if( bHadSelection )
194 // call Unmark when !bAddSelect or if fly was selected
195 bool bUnmark = !bAddSelect;
197 if ( rMrkList.GetMarkCount() == 1 )
199 // if fly was selected, deselect it first
200 pOldSelFly = ::GetFlyFromMarked( &rMrkList, this );
201 if ( pOldSelFly )
203 const sal_uInt16 nType = GetCntType();
204 if( nType != CNT_TXT || (SW_LEAVE_FRAME & nFlag) ||
205 ( pOldSelFly->GetFormat()->GetProtect().IsContentProtected()
206 && !IsReadOnlyAvailable() ))
208 // If a fly is deselected, which contains graphic, OLE or
209 // otherwise, the cursor should be removed from it.
210 // Similar if a fly with protected content is deselected.
211 // For simplicity we put the cursor next to the upper-left
212 // corner.
213 Point aPt( pOldSelFly->getFrameArea().Pos() );
214 aPt.setX(aPt.getX() - 1);
215 bool bUnLockView = !IsViewLocked();
216 LockView( true );
217 SetCursor( aPt, true );
218 if( bUnLockView )
219 LockView( false );
221 if ( nType & CNT_GRF &&
222 static_cast<SwNoTextFrame*>(pOldSelFly->Lower())->HasAnimation() )
224 GetWin()->Invalidate( pOldSelFly->getFrameArea().SVRect() );
227 // Cancel crop mode
228 if ( SdrDragMode::Crop == GetDragMode() )
229 SetDragMode( SdrDragMode::Move );
231 bUnmark = true;
234 if ( bUnmark )
236 pDView->UnmarkAll();
237 if (pOldSelFly)
238 pOldSelFly->SelectionHasChanged(this);
241 else
243 KillPams();
244 ClearMark();
247 if ( pObj )
249 OSL_ENSURE( !bEnterGroup, "SW_ENTER_GROUP is not supported" );
250 pDView->MarkObj( pObj, Imp()->GetPageView() );
252 else
254 // tolerance limit of Drawing-SS
255 const auto nHdlSizePixel = Imp()->GetDrawView()->GetMarkHdlSizePixel();
256 const short nMinMove = static_cast<short>(GetOut()->PixelToLogic(Size(nHdlSizePixel/2, 0)).Width());
257 pDView->MarkObj( rPt, nMinMove, bAddSelect, bEnterGroup );
260 const bool bRet = 0 != rMrkList.GetMarkCount();
262 if ( rMrkList.GetMarkCount() > 1 )
264 // It sucks if Drawing objects were selected and now
265 // additionally a fly is selected.
266 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
268 SdrObject *pTmpObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
269 bool bForget = dynamic_cast<const SwVirtFlyDrawObj*>( pTmpObj) != nullptr;
270 if( bForget )
272 pDView->UnmarkAll();
273 pDView->MarkObj( pTmpObj, Imp()->GetPageView(), bAddSelect, bEnterGroup );
274 break;
279 if ( rMrkList.GetMarkCount() == 1 )
281 SwFlyFrame *pSelFly = ::GetFlyFromMarked( &rMrkList, this );
282 if (pSelFly)
283 pSelFly->SelectionHasChanged(this);
286 if (!(nFlag & SW_ALLOW_TEXTBOX))
288 // If the fly frame is a textbox of a shape, then select the shape instead.
289 for (size_t i = 0; i < rMrkList.GetMarkCount(); ++i)
291 SdrObject* pObject = rMrkList.GetMark(i)->GetMarkedSdrObj();
292 SwFrameFormat* pFormat = GetUserCall(pObject)->GetFormat();
293 if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT))
295 SdrObject* pShape = pShapeFormat->FindSdrObject();
296 pDView->UnmarkAll();
297 pDView->MarkObj(pShape, Imp()->GetPageView(), bAddSelect, bEnterGroup);
298 break;
303 if ( bRet )
305 ::lcl_GrabCursor(this, pOldSelFly);
306 if ( GetCntType() & CNT_GRF )
308 const SwFlyFrame *pTmp = GetFlyFromMarked( &rMrkList, this );
309 OSL_ENSURE( pTmp, "Graphic without Fly" );
310 if ( static_cast<const SwNoTextFrame*>(pTmp->Lower())->HasAnimation() )
311 static_cast<const SwNoTextFrame*>(pTmp->Lower())->StopAnimation( GetOut() );
314 else if ( !pOldSelFly && bHadSelection )
315 SetCursor( aOldPos, true);
317 if( bRet || !bHadSelection )
318 CallChgLnk();
320 // update status line
321 ::FrameNotify( this, bRet ? FLY_DRAG_START : FLY_DRAG_END );
323 EndAction();
324 return bRet;
328 * Description: MoveAnchor( nDir ) looked for an another Anchor for
329 * the selected drawing object (or fly frame) in the given direction.
330 * An object "as character" doesn't moves anyway.
331 * A page bounded object could move to the previous/next page with up/down,
332 * an object bounded "at paragraph" moves to the previous/next paragraph, too.
333 * An object bounded "at character" moves to the previous/next paragraph
334 * with up/down and to the previous/next character with left/right.
335 * If the anchor for at paragraph/character bounded objects has vertical or
336 * right_to_left text direction, the directions for up/down/left/right will
337 * interpreted accordingly.
338 * An object bounded "at fly" takes the center of the actual anchor and looks
339 * for the nearest fly frame in the given direction.
342 static bool LessX( Point const & aPt1, Point const & aPt2, bool bOld )
344 return aPt1.getX() < aPt2.getX()
345 || ( aPt1.getX() == aPt2.getX()
346 && ( aPt1.getY() < aPt2.getY()
347 || ( aPt1.getY() == aPt2.getY() && bOld ) ) );
349 static bool LessY( Point const & aPt1, Point const & aPt2, bool bOld )
351 return aPt1.getY() < aPt2.getY()
352 || ( aPt1.getY() == aPt2.getY()
353 && ( aPt1.getX() < aPt2.getX()
354 || ( aPt1.getX() == aPt2.getX() && bOld ) ) );
357 bool SwFEShell::MoveAnchor( SwMove nDir )
359 if (!Imp()->GetDrawView())
360 return false;
361 const SdrMarkList& pMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
362 if (1 != pMrkList.GetMarkCount())
363 return false;
364 SwFrame* pOld;
365 SwFlyFrame* pFly = nullptr;
366 SdrObject *pObj = pMrkList.GetMark( 0 )->GetMarkedSdrObj();
367 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
369 pFly = pVirtO->GetFlyFrame();
370 pOld = pFly->AnchorFrame();
372 else
373 pOld = static_cast<SwDrawContact*>(GetUserCall(pObj))->GetAnchorFrame( pObj );
374 bool bRet = false;
375 if( pOld )
377 SwFrame* pNew = pOld;
378 // #i28701#
379 SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
380 SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
381 SwFormatAnchor aAnch( rFormat.GetAnchor() );
382 RndStdIds nAnchorId = aAnch.GetAnchorId();
383 if ( RndStdIds::FLY_AS_CHAR == nAnchorId )
384 return false;
385 if( pOld->IsVertical() )
387 if( pOld->IsTextFrame() )
389 switch( nDir ) {
390 case SwMove::UP: nDir = SwMove::LEFT; break;
391 case SwMove::DOWN: nDir = SwMove::RIGHT; break;
392 case SwMove::LEFT: nDir = SwMove::DOWN; break;
393 case SwMove::RIGHT: nDir = SwMove::UP; break;
395 if( pOld->IsRightToLeft() )
397 if( nDir == SwMove::LEFT )
398 nDir = SwMove::RIGHT;
399 else if( nDir == SwMove::RIGHT )
400 nDir = SwMove::LEFT;
404 switch ( nAnchorId ) {
405 case RndStdIds::FLY_AT_PAGE:
407 OSL_ENSURE( pOld->IsPageFrame(), "Wrong anchor, page expected." );
408 if( SwMove::UP == nDir )
409 pNew = pOld->GetPrev();
410 else if( SwMove::DOWN == nDir )
411 pNew = pOld->GetNext();
412 if( pNew && pNew != pOld )
414 aAnch.SetPageNum( static_cast<SwPageFrame*>(pNew)->GetPhyPageNum() );
415 bRet = true;
417 break;
419 case RndStdIds::FLY_AT_CHAR:
421 OSL_ENSURE(pOld->IsTextFrame(), "Wrong anchor, text frame expected.");
422 if( SwMove::LEFT == nDir || SwMove::RIGHT == nDir )
424 SwPosition pos = *aAnch.GetContentAnchor();
425 SwTextFrame *const pOldFrame(static_cast<SwTextFrame*>(pOld));
426 TextFrameIndex const nAct(pOldFrame->MapModelToViewPos(pos));
427 if( SwMove::LEFT == nDir )
429 bRet = true;
430 if( nAct )
432 pos = pOldFrame->MapViewToModelPos(nAct - TextFrameIndex(1));
434 else
435 nDir = SwMove::UP;
437 else
439 TextFrameIndex const nMax(pOldFrame->GetText().getLength());
440 if( nAct < nMax )
442 bRet = true;
443 pos = pOldFrame->MapViewToModelPos(nAct + TextFrameIndex(1));
445 else
446 nDir = SwMove::DOWN;
448 if( pos != *aAnch.GetContentAnchor())
449 aAnch.SetAnchor( &pos );
451 [[fallthrough]];
453 case RndStdIds::FLY_AT_PARA:
455 OSL_ENSURE(pOld->IsTextFrame(), "Wrong anchor, text frame expected.");
456 if( SwMove::UP == nDir )
457 pNew = pOld->FindPrev();
458 else if( SwMove::DOWN == nDir )
459 pNew = pOld->FindNext();
460 if( pNew && pNew != pOld && pNew->IsContentFrame() )
462 SwTextFrame *const pNewFrame(static_cast<SwTextFrame*>(pNew));
463 SwPosition const pos = pNewFrame->MapViewToModelPos(
464 TextFrameIndex(
465 (bRet && pNewFrame->GetText().getLength() != 0)
466 ? pNewFrame->GetText().getLength() - 1
467 : 0));
468 aAnch.SetAnchor( &pos );
469 bRet = true;
471 else if( SwMove::UP == nDir || SwMove::DOWN == nDir )
472 bRet = false;
473 break;
475 case RndStdIds::FLY_AT_FLY:
477 OSL_ENSURE( pOld->IsFlyFrame(), "Wrong anchor, fly frame expected.");
478 SwPageFrame* pPage = pOld->FindPageFrame();
479 OSL_ENSURE( pPage, "Where's my page?" );
480 SwFlyFrame* pNewFly = nullptr;
481 if( pPage->GetSortedObjs() )
483 bool bOld = false;
484 Point aCenter( pOld->getFrameArea().Left() + pOld->getFrameArea().Width()/2,
485 pOld->getFrameArea().Top() + pOld->getFrameArea().Height()/2 );
486 Point aBest;
487 for(SwAnchoredObject* pAnchObj : *pPage->GetSortedObjs())
489 if( auto pTmp = dynamic_cast<SwFlyFrame*>( pAnchObj) )
491 if( pTmp == pOld )
492 bOld = true;
493 else
495 const SwFlyFrame* pCheck = pFly ? pTmp : nullptr;
496 while( pCheck )
498 if( pCheck == pFly )
499 break;
500 const SwFrame *pNxt = pCheck->GetAnchorFrame();
501 pCheck = pNxt ? pNxt->FindFlyFrame() : nullptr;
503 if( pCheck || pTmp->IsProtected() )
504 continue;
505 Point aNew( pTmp->getFrameArea().Left() +
506 pTmp->getFrameArea().Width()/2,
507 pTmp->getFrameArea().Top() +
508 pTmp->getFrameArea().Height()/2 );
509 bool bAccept = false;
510 switch( nDir ) {
511 case SwMove::RIGHT:
513 bAccept = LessX( aCenter, aNew, bOld )
514 && ( !pNewFly ||
515 LessX( aNew, aBest, false ) );
516 break;
518 case SwMove::LEFT:
520 bAccept = LessX( aNew, aCenter, !bOld )
521 && ( !pNewFly ||
522 LessX( aBest, aNew, true ) );
523 break;
525 case SwMove::UP:
527 bAccept = LessY( aNew, aCenter, !bOld )
528 && ( !pNewFly ||
529 LessY( aBest, aNew, true ) );
530 break;
532 case SwMove::DOWN:
534 bAccept = LessY( aCenter, aNew, bOld )
535 && ( !pNewFly ||
536 LessY( aNew, aBest, false ) );
537 break;
540 if( bAccept )
542 pNewFly = pTmp;
543 aBest = aNew;
550 if( pNewFly )
552 SwPosition aPos( *pNewFly->GetFormat()->
553 GetContent().GetContentIdx());
554 aAnch.SetAnchor( &aPos );
555 bRet = true;
557 break;
559 default: break;
561 if( bRet )
563 StartAllAction();
564 // --> handle change of anchor node:
565 // if count of the anchor frame also change, the fly frames have to be
566 // re-created. Thus, delete all fly frames except the <this> before the
567 // anchor attribute is change and re-create them afterwards.
569 std::unique_ptr<SwHandleAnchorNodeChg, o3tl::default_delete<SwHandleAnchorNodeChg>> pHandleAnchorNodeChg;
570 SwFlyFrameFormat* pFlyFrameFormat( dynamic_cast<SwFlyFrameFormat*>(&rFormat) );
571 if ( pFlyFrameFormat )
573 pHandleAnchorNodeChg.reset(
574 new SwHandleAnchorNodeChg( *pFlyFrameFormat, aAnch ));
576 rFormat.GetDoc()->SetAttr( aAnch, rFormat );
578 // #i28701# - no call of method
579 // <CheckCharRectAndTopOfLine()> for to-character anchored
580 // Writer fly frame needed. This method call can cause a
581 // format of the anchor frame, which is no longer intended.
582 // Instead clear the anchor character rectangle and
583 // the top of line values for all to-character anchored objects.
584 pAnchoredObj->ClearCharRectAndTopOfLine();
585 EndAllAction();
588 return bRet;
591 const SdrMarkList* SwFEShell::GetMarkList_() const
593 const SdrMarkList* pMarkList = nullptr;
594 if( Imp()->GetDrawView() != nullptr )
595 pMarkList = &Imp()->GetDrawView()->GetMarkedObjectList();
596 return pMarkList;
599 FrameTypeFlags SwFEShell::GetSelFrameType() const
601 FrameTypeFlags eType;
603 // get marked frame list, and check if anything is selected
604 const SdrMarkList* pMarkList = GetMarkList_();
605 if( pMarkList == nullptr || pMarkList->GetMarkCount() == 0 )
606 eType = FrameTypeFlags::NONE;
607 else
609 // obtain marked item as fly frame; if no fly frame, it must
610 // be a draw object
611 const SwFlyFrame* pFly = ::GetFlyFromMarked(pMarkList, const_cast<SwFEShell*>(this));
612 if ( pFly != nullptr )
614 if( pFly->IsFlyLayFrame() )
615 eType = FrameTypeFlags::FLY_FREE;
616 else if( pFly->IsFlyAtContentFrame() )
617 eType = FrameTypeFlags::FLY_ATCNT;
618 else
620 OSL_ENSURE( pFly->IsFlyInContentFrame(), "New frametype?" );
621 eType = FrameTypeFlags::FLY_INCNT;
624 else
625 eType = FrameTypeFlags::DRAWOBJ;
628 return eType;
631 // does the draw selection contain a control?
632 bool SwFEShell::IsSelContainsControl() const
634 bool bRet = false;
636 // basically, copy the mechanism from GetSelFrameType(), but call
637 // CheckControl... if you get a drawing object
638 const SdrMarkList* pMarkList = GetMarkList_();
639 if( pMarkList != nullptr && pMarkList->GetMarkCount() == 1 )
641 // if we have one marked object, get the SdrObject and check
642 // whether it contains a control
643 const SdrObject* pSdrObject = pMarkList->GetMark( 0 )->GetMarkedSdrObj();
644 bRet = pSdrObject && ::CheckControlLayer( pSdrObject );
646 return bRet;
649 void SwFEShell::ScrollTo( const Point &rPt )
651 const SwRect aRect( rPt, rPt );
652 if ( IsScrollMDI( this, aRect ) &&
653 (!Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ||
654 Imp()->IsDragPossible( rPt )) )
656 ScrollMDI( this, aRect, SCROLLVAL, SCROLLVAL );
660 void SwFEShell::SetDragMode( SdrDragMode eDragMode )
662 if ( Imp()->HasDrawView() )
663 Imp()->GetDrawView()->SetDragMode( eDragMode );
666 SdrDragMode SwFEShell::GetDragMode() const
668 SdrDragMode nRet = SdrDragMode(0);
669 if ( Imp()->HasDrawView() )
671 nRet = Imp()->GetDrawView()->GetDragMode();
673 return nRet;
676 void SwFEShell::StartCropImage()
678 if ( !Imp()->HasDrawView() )
680 return;
682 SdrView *pView = Imp()->GetDrawView();
683 if (!pView) return;
685 const SdrMarkList &rMarkList = pView->GetMarkedObjectList();
686 if( 0 == rMarkList.GetMarkCount() ) {
687 // No object selected
688 return;
691 // If more than a single SwVirtFlyDrawObj is selected, select only the first SwVirtFlyDrawObj
692 if ( rMarkList.GetMarkCount() > 1 )
694 for ( size_t i = 0; i < rMarkList.GetMarkCount(); ++i )
696 SdrObject *pTmpObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
697 bool bForget = dynamic_cast<const SwVirtFlyDrawObj*>( pTmpObj) != nullptr;
698 if( bForget )
700 pView->UnmarkAll();
701 pView->MarkObj( pTmpObj, Imp()->GetPageView() );
702 break;
707 // Activate CROP mode
708 pView->SetEditMode( SdrViewEditMode::Edit );
709 SetDragMode( SdrDragMode::Crop );
712 void SwFEShell::BeginDrag( const Point* pPt, bool bIsShift)
714 SdrView *pView = Imp()->GetDrawView();
715 if ( pView && pView->AreObjectsMarked() )
717 m_pChainFrom.reset();
718 m_pChainTo.reset();
719 SdrHdl* pHdl = pView->PickHandle( *pPt );
720 if (pView->BegDragObj( *pPt, nullptr, pHdl ))
721 pView->GetDragMethod()->SetShiftPressed( bIsShift );
722 ::FrameNotify( this );
726 void SwFEShell::Drag( const Point *pPt, bool )
728 OSL_ENSURE( Imp()->HasDrawView(), "Drag without DrawView?" );
729 if ( HasDrawViewDrag() )
731 ScrollTo( *pPt );
732 Imp()->GetDrawView()->MovDragObj( *pPt );
733 Imp()->GetDrawView()->ShowDragAnchor();
734 ::FrameNotify( this );
738 void SwFEShell::EndDrag()
740 OSL_ENSURE( Imp()->HasDrawView(), "EndDrag without DrawView?" );
741 SdrView *pView = Imp()->GetDrawView();
742 if ( !pView->IsDragObj() )
743 return;
745 for(SwViewShell& rSh : GetRingContainer())
746 rSh.StartAction();
748 StartUndo( SwUndoId::START );
750 // #50778# Bug during dragging: In StartAction a HideShowXor is called.
751 // In EndDragObj() this is reversed, for no reason and even wrong.
752 // To restore consistency we should bring up the Xor again.
754 // Reanimation from the hack #50778 to fix bug #97057
755 // May be not the best solution, but the one with lowest risc at the moment.
756 // pView->ShowShownXor( GetOut() );
758 pView->EndDragObj();
760 // DrawUndo on to flyframes are not stored
761 // The flys change the flag.
762 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
763 ChgAnchor( RndStdIds::FLY_AT_PARA, true );
765 EndUndo( SwUndoId::END );
767 for(SwViewShell& rSh : GetRingContainer())
769 rSh.EndAction();
770 if( auto pCursorShell = dynamic_cast<SwCursorShell *>(&rSh) )
771 pCursorShell->CallChgLnk();
774 GetDoc()->getIDocumentState().SetModified();
775 ::FrameNotify( this );
778 void SwFEShell::BreakDrag()
780 OSL_ENSURE( Imp()->HasDrawView(), "BreakDrag without DrawView?" );
781 if( HasDrawViewDrag() )
782 Imp()->GetDrawView()->BrkDragObj();
783 SetChainMarker();
786 // If a fly is selected, pulls the crsr in the first ContentFrame
787 const SwFrameFormat* SwFEShell::SelFlyGrabCursor()
789 if ( Imp()->HasDrawView() )
791 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
792 SwFlyFrame *pFly = ::GetFlyFromMarked( &rMrkList, this );
794 if( pFly )
796 SwContentFrame *pCFrame = pFly->ContainsContent();
797 if ( pCFrame )
799 // --> assure, that the cursor is consistent.
800 KillPams();
801 ClearMark();
802 SwPaM *pCursor = GetCursor();
804 if (pCFrame->IsTextFrame())
806 *pCursor->GetPoint() = static_cast<SwTextFrame *>(pCFrame)
807 ->MapViewToModelPos(TextFrameIndex(0));
809 else
811 assert(pCFrame->IsNoTextFrame());
812 SwContentNode *const pCNode = static_cast<SwNoTextFrame *>(pCFrame)->GetNode();
813 pCursor->GetPoint()->nNode = *pCNode;
814 pCursor->GetPoint()->nContent.Assign( pCNode, 0 );
817 SwRect& rChrRect = const_cast<SwRect&>(GetCharRect());
818 rChrRect = pFly->getFramePrintArea();
819 rChrRect.Pos() += pFly->getFrameArea().Pos();
820 GetCursorDocPos() = rChrRect.Pos();
822 return pFly->GetFormat();
825 return nullptr;
828 // Selection to above/below (Z-Order)
829 static void lcl_NotifyNeighbours( const SdrMarkList *pLst )
831 // Rules for evasion have changed.
832 // 1. The environment of the fly and everything inside should be notified
833 // 2. The content of the frame itself has to be notified
834 // 3. Frames displaced by the frame have to be notified
835 // 4. Also Drawing objects can displace frames
836 for( size_t j = 0; j < pLst->GetMarkCount(); ++j )
838 SwPageFrame *pPage;
839 bool bCheckNeighbours = false;
840 sal_Int16 aHori = text::HoriOrientation::NONE;
841 SwRect aRect;
842 SdrObject *pO = pLst->GetMark( j )->GetMarkedSdrObj();
843 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pO))
845 SwFlyFrame *pFly = pVirtO->GetFlyFrame();
847 const SwFormatHoriOrient &rHori = pFly->GetFormat()->GetHoriOrient();
848 aHori = rHori.GetHoriOrient();
849 if( text::HoriOrientation::NONE != aHori && text::HoriOrientation::CENTER != aHori &&
850 pFly->IsFlyAtContentFrame() )
852 bCheckNeighbours = true;
853 pFly->InvalidatePos();
854 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pFly);
855 aFrm.Pos().AdjustY(1 );
858 pPage = pFly->FindPageFrame();
859 aRect = pFly->getFrameArea();
861 else
863 SwFrame* pAnch = static_cast<SwDrawContact*>( GetUserCall(pO) )->GetAnchorFrame( pO );
864 if( !pAnch )
865 continue;
866 pPage = pAnch->FindPageFrame();
867 // #i68520# - naming changed
868 aRect = GetBoundRectOfAnchoredObj( pO );
871 const size_t nCount = pPage->GetSortedObjs() ? pPage->GetSortedObjs()->size() : 0;
872 for ( size_t i = 0; i < nCount; ++i )
874 SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
875 SwFlyFrame* pAct = dynamic_cast<SwFlyFrame*>(pAnchoredObj);
876 if ( !pAct )
877 continue;
879 SwRect aTmpCalcPnt( pAct->getFramePrintArea() );
880 aTmpCalcPnt += pAct->getFrameArea().Pos();
881 if ( aRect.IsOver( aTmpCalcPnt ) )
883 SwContentFrame *pCnt = pAct->ContainsContent();
884 while ( pCnt )
886 aTmpCalcPnt = pCnt->getFramePrintArea();
887 aTmpCalcPnt += pCnt->getFrameArea().Pos();
888 if ( aRect.IsOver( aTmpCalcPnt ) )
889 static_cast<SwFrame*>(pCnt)->Prepare( PrepareHint::FlyFrameAttributesChanged );
890 pCnt = pCnt->GetNextContentFrame();
893 if ( bCheckNeighbours && pAct->IsFlyAtContentFrame() )
895 const SwFormatHoriOrient &rH = pAct->GetFormat()->GetHoriOrient();
896 if ( rH.GetHoriOrient() == aHori &&
897 pAct->getFrameArea().Top() <= aRect.Bottom() &&
898 pAct->getFrameArea().Bottom() >= aRect.Top() )
900 pAct->InvalidatePos();
901 SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pAct);
902 aFrm.Pos().AdjustY(1 );
909 void SwFEShell::SetLineEnds(SfxItemSet& rAttr, SdrObject const & rObj, sal_uInt16 nSlotId)
911 SdrModel& rModel(rObj.getSdrModelFromSdrObject());
913 if ( !(nSlotId == SID_LINE_ARROW_START ||
914 nSlotId == SID_LINE_ARROW_END ||
915 nSlotId == SID_LINE_ARROWS ||
916 nSlotId == SID_LINE_ARROW_CIRCLE ||
917 nSlotId == SID_LINE_CIRCLE_ARROW ||
918 nSlotId == SID_LINE_ARROW_SQUARE ||
919 nSlotId == SID_LINE_SQUARE_ARROW ||
920 nSlotId == SID_DRAW_MEASURELINE) )
921 return;
923 // set attributes of line start and ends
925 // arrowhead
926 ::basegfx::B2DPolyPolygon aArrow( getPolygon( RID_SVXSTR_ARROW, rModel ) );
927 if( !aArrow.count() )
929 ::basegfx::B2DPolygon aNewArrow;
930 aNewArrow.append(::basegfx::B2DPoint(10.0, 0.0));
931 aNewArrow.append(::basegfx::B2DPoint(0.0, 30.0));
932 aNewArrow.append(::basegfx::B2DPoint(20.0, 30.0));
933 aNewArrow.setClosed(true);
934 aArrow.append(aNewArrow);
937 // Circles
938 ::basegfx::B2DPolyPolygon aCircle( getPolygon( RID_SVXSTR_CIRCLE, rModel ) );
939 if( !aCircle.count() )
941 ::basegfx::B2DPolygon aNewCircle = ::basegfx::utils::createPolygonFromEllipse(::basegfx::B2DPoint(0.0, 0.0), 250.0, 250.0);
942 aNewCircle.setClosed(true);
943 aCircle.append(aNewCircle);
946 // Square
947 ::basegfx::B2DPolyPolygon aSquare( getPolygon( RID_SVXSTR_SQUARE, rModel ) );
948 if( !aSquare.count() )
950 ::basegfx::B2DPolygon aNewSquare;
951 aNewSquare.append(::basegfx::B2DPoint(0.0, 0.0));
952 aNewSquare.append(::basegfx::B2DPoint(10.0, 0.0));
953 aNewSquare.append(::basegfx::B2DPoint(10.0, 10.0));
954 aNewSquare.append(::basegfx::B2DPoint(0.0, 10.0));
955 aNewSquare.setClosed(true);
956 aSquare.append(aNewSquare);
959 SfxItemSet aSet( rModel.GetItemPool() );
960 tools::Long nWidth = 100; // (1/100th mm)
962 // determine line width and calculate with it the line end width
963 if( aSet.GetItemState( XATTR_LINEWIDTH ) != SfxItemState::DONTCARE )
965 tools::Long nValue = aSet.Get( XATTR_LINEWIDTH ).GetValue();
966 if( nValue > 0 )
967 nWidth = nValue * 3;
970 switch (nSlotId)
972 case SID_LINE_ARROWS:
973 case SID_DRAW_MEASURELINE:
975 // connector with arrow ends
976 rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROW), aArrow));
977 rAttr.Put(XLineStartWidthItem(nWidth));
978 rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROW), aArrow));
979 rAttr.Put(XLineEndWidthItem(nWidth));
981 break;
983 case SID_LINE_ARROW_START:
984 case SID_LINE_ARROW_CIRCLE:
985 case SID_LINE_ARROW_SQUARE:
987 // connector with arrow start
988 rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROW), aArrow));
989 rAttr.Put(XLineStartWidthItem(nWidth));
991 break;
993 case SID_LINE_ARROW_END:
994 case SID_LINE_CIRCLE_ARROW:
995 case SID_LINE_SQUARE_ARROW:
997 // connector with arrow end
998 rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROW), aArrow));
999 rAttr.Put(XLineEndWidthItem(nWidth));
1001 break;
1004 // and again, for the still missing ends
1005 switch (nSlotId)
1007 case SID_LINE_ARROW_CIRCLE:
1009 // circle end
1010 rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle));
1011 rAttr.Put(XLineEndWidthItem(nWidth));
1013 break;
1015 case SID_LINE_CIRCLE_ARROW:
1017 // circle start
1018 rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle));
1019 rAttr.Put(XLineStartWidthItem(nWidth));
1021 break;
1023 case SID_LINE_ARROW_SQUARE:
1025 // square end
1026 rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_SQUARE), aSquare));
1027 rAttr.Put(XLineEndWidthItem(nWidth));
1029 break;
1031 case SID_LINE_SQUARE_ARROW:
1033 // square start
1034 rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_SQUARE), aSquare));
1035 rAttr.Put(XLineStartWidthItem(nWidth));
1037 break;
1042 void SwFEShell::SelectionToTop( bool bTop )
1044 OSL_ENSURE( Imp()->HasDrawView(), "SelectionToTop without DrawView?" );
1045 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1046 OSL_ENSURE( rMrkList.GetMarkCount(), "No object selected." );
1048 SwFlyFrame *pFly = ::GetFlyFromMarked( &rMrkList, this );
1049 if ( pFly && pFly->IsFlyInContentFrame() )
1050 return;
1052 StartAllAction();
1053 if ( bTop )
1054 Imp()->GetDrawView()->PutMarkedToTop();
1055 else
1056 Imp()->GetDrawView()->MovMarkedToTop();
1057 ::lcl_NotifyNeighbours( &rMrkList );
1058 GetDoc()->getIDocumentState().SetModified();
1059 EndAllAction();
1062 void SwFEShell::SelectionToBottom( bool bBottom )
1064 OSL_ENSURE( Imp()->HasDrawView(), "SelectionToBottom without DrawView?" );
1065 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1066 OSL_ENSURE( rMrkList.GetMarkCount(), "No object selected." );
1068 SwFlyFrame *pFly = ::GetFlyFromMarked( &rMrkList, this );
1069 if ( pFly && pFly->IsFlyInContentFrame() )
1070 return;
1072 StartAllAction();
1073 if ( bBottom )
1074 Imp()->GetDrawView()->PutMarkedToBtm();
1075 else
1076 Imp()->GetDrawView()->MovMarkedToBtm();
1077 ::lcl_NotifyNeighbours( &rMrkList );
1078 GetDoc()->getIDocumentState().SetModified();
1079 EndAllAction();
1082 // Object above/below the document? 2 Controls, 1 Heaven, 0 Hell,
1083 // SDRLAYER_NOTFOUND Ambiguous
1084 SdrLayerID SwFEShell::GetLayerId() const
1086 if ( !Imp()->HasDrawView() )
1087 return SDRLAYER_NOTFOUND;
1089 SdrLayerID nRet = SDRLAYER_NOTFOUND;
1090 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1091 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
1093 const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
1094 if( !pObj )
1095 continue;
1096 if ( nRet == SDRLAYER_NOTFOUND )
1097 nRet = pObj->GetLayer();
1098 else if ( nRet != pObj->GetLayer() )
1100 return SDRLAYER_NOTFOUND;
1103 return nRet;
1106 // Object above/below the document
1107 // Note: only visible objects can be marked. Thus, objects with invisible
1108 // layer IDs have not to be considered.
1109 // If <SwFEShell> exists, layout exists!!
1110 void SwFEShell::ChangeOpaque( SdrLayerID nLayerId )
1112 if ( !Imp()->HasDrawView() )
1113 return;
1115 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1116 const IDocumentDrawModelAccess& rIDDMA = getIDocumentDrawModelAccess();
1117 // correct type of <nControls>
1118 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
1120 SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
1121 if( !pObj )
1122 continue;
1123 // or group objects containing controls.
1124 // --> #i113730#
1125 // consider that a member of a drawing group has been selected.
1126 const SwContact* pContact = ::GetUserCall( pObj );
1127 OSL_ENSURE( pContact && pContact->GetMaster(), "<SwFEShell::ChangeOpaque(..)> - missing contact or missing master object at contact!" );
1128 const bool bControlObj = ( pContact && pContact->GetMaster() )
1129 ? ::CheckControlLayer( pContact->GetMaster() )
1130 : ::CheckControlLayer( pObj );
1131 if ( !bControlObj && pObj->GetLayer() != nLayerId )
1133 pObj->SetLayer( nLayerId );
1134 InvalidateWindows( SwRect( pObj->GetCurrentBoundRect() ) );
1135 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
1137 SwFormat *pFormat = pVirtO->GetFlyFrame()->GetFormat();
1138 SvxOpaqueItem aOpa( pFormat->GetOpaque() );
1139 aOpa.SetValue( nLayerId == rIDDMA.GetHellId() );
1140 pFormat->SetFormatAttr( aOpa );
1144 GetDoc()->getIDocumentState().SetModified();
1147 void SwFEShell::SelectionToHeaven()
1149 ChangeOpaque( getIDocumentDrawModelAccess().GetHeavenId() );
1152 void SwFEShell::SelectionToHell()
1154 ChangeOpaque( getIDocumentDrawModelAccess().GetHellId() );
1157 size_t SwFEShell::IsObjSelected() const
1159 if ( IsFrameSelected() || !Imp()->HasDrawView() )
1160 return 0;
1162 return Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount();
1165 bool SwFEShell::IsFrameSelected() const
1167 if ( !Imp()->HasDrawView() )
1168 return false;
1169 else
1170 return nullptr != ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(),
1171 const_cast<SwFEShell*>(this) );
1174 bool SwFEShell::IsObjSelected( const SdrObject& rObj ) const
1176 if ( IsFrameSelected() || !Imp()->HasDrawView() )
1177 return false;
1178 else
1179 return Imp()->GetDrawView()->IsObjMarked( &rObj );
1182 bool SwFEShell::IsRotationOfSwGrfNodePossible() const
1184 // RotGrfFlyFrame: check if RotationMode is possible
1185 const SdrView *pSdrView = Imp()->GetDrawView();
1187 if(pSdrView)
1189 const SdrMarkList& rList(pSdrView->GetMarkedObjectList());
1191 if(1 == rList.GetMarkCount())
1193 const SwVirtFlyDrawObj* pVirtFlyDraw(dynamic_cast< const SwVirtFlyDrawObj* >(rList.GetMark(0)->GetMarkedSdrObj()));
1195 if(nullptr != pVirtFlyDraw)
1197 return pVirtFlyDraw->ContainsSwGrfNode();
1202 return false;
1205 bool SwFEShell::IsObjSameLevelWithMarked(const SdrObject* pObj) const
1207 if (pObj)
1209 const SdrMarkList& aMarkList = Imp()->GetDrawView()->GetMarkedObjectList();
1210 if (aMarkList.GetMarkCount() == 0)
1212 return true;
1214 SdrMark* pM=aMarkList.GetMark(0);
1215 if (pM)
1217 SdrObject* pMarkObj = pM->GetMarkedSdrObj();
1218 if (pMarkObj && pMarkObj->getParentSdrObjectFromSdrObject() == pObj->getParentSdrObjectFromSdrObject())
1219 return true;
1222 return false;
1225 void SwFEShell::EndTextEdit()
1227 // Terminate the TextEditMode. If required (default if the object
1228 // does not contain any more text and does not carry attributes) the object
1229 // is deleted. All other objects marked are preserved.
1231 OSL_ENSURE( Imp()->HasDrawView() && Imp()->GetDrawView()->IsTextEdit(),
1232 "EndTextEdit a no Object" );
1234 StartAllAction();
1235 SdrView *pView = Imp()->GetDrawView();
1236 SdrObject *pObj = pView->GetTextEditObject();
1237 SdrObjUserCall* pUserCall = GetUserCall(pObj);
1238 if( nullptr != pUserCall )
1240 SdrObject *pTmp = static_cast<SwContact*>(pUserCall)->GetMaster();
1241 if( !pTmp )
1242 pTmp = pObj;
1243 pUserCall->Changed( *pTmp, SdrUserCallType::Resize, pTmp->GetLastBoundRect() );
1245 if ( !pObj->getParentSdrObjectFromSdrObject() )
1247 if ( SdrEndTextEditKind::ShouldBeDeleted == pView->SdrEndTextEdit(true) )
1249 if ( pView->GetMarkedObjectList().GetMarkCount() > 1 )
1251 SdrMarkList aSave( pView->GetMarkedObjectList() );
1252 aSave.DeleteMark( aSave.FindObject( pObj ) );
1253 if ( aSave.GetMarkCount() )
1255 pView->UnmarkAll();
1256 pView->MarkObj( pObj, Imp()->GetPageView() );
1258 DelSelectedObj();
1259 for ( size_t i = 0; i < aSave.GetMarkCount(); ++i )
1260 pView->MarkObj( aSave.GetMark( i )->GetMarkedSdrObj(), Imp()->GetPageView() );
1262 else
1263 DelSelectedObj();
1266 else
1267 pView->SdrEndTextEdit();
1269 if (comphelper::LibreOfficeKit::isActive())
1270 SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_LOCK, "rectangle", "EMPTY");
1272 EndAllAction();
1275 bool SwFEShell::IsInsideSelectedObj( const Point &rPt )
1277 if( Imp()->HasDrawView() )
1279 SwDrawView *pDView = Imp()->GetDrawView();
1281 if( pDView->GetMarkedObjectList().GetMarkCount() &&
1282 pDView->IsMarkedObjHit( rPt ) )
1284 return true;
1287 return false;
1290 bool SwFEShell::IsObjSelectable( const Point& rPt )
1292 CurrShell aCurr(this);
1293 SwDrawView *pDView = Imp()->GetDrawView();
1294 bool bRet = false;
1295 if( pDView )
1297 SdrPageView* pPV;
1298 const auto nOld = pDView->GetHitTolerancePixel();
1299 pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
1301 bRet = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV, SdrSearchOptions::PICKMARKABLE) != nullptr;
1302 pDView->SetHitTolerancePixel( nOld );
1304 return bRet;
1307 SdrObject* SwFEShell::GetObjAt( const Point& rPt )
1309 SdrObject* pRet = nullptr;
1310 CurrShell aCurr(this);
1311 SwDrawView *pDView = Imp()->GetDrawView();
1312 if( pDView )
1314 SdrPageView* pPV;
1315 const auto nOld = pDView->GetHitTolerancePixel();
1316 pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
1318 pRet = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV, SdrSearchOptions::PICKMARKABLE);
1319 pDView->SetHitTolerancePixel( nOld );
1321 return pRet;
1324 // Test if there is an object at that position and if it should be selected.
1325 bool SwFEShell::ShouldObjectBeSelected(const Point& rPt)
1327 CurrShell aCurr(this);
1328 SwDrawView *pDrawView = Imp()->GetDrawView();
1329 bool bRet(false);
1331 if(pDrawView)
1333 SdrPageView* pPV;
1334 const auto nOld(pDrawView->GetHitTolerancePixel());
1336 pDrawView->SetHitTolerancePixel(pDrawView->GetMarkHdlSizePixel()/2);
1337 SdrObject* pObj = pDrawView->PickObj(rPt, pDrawView->getHitTolLog(), pPV, SdrSearchOptions::PICKMARKABLE);
1338 pDrawView->SetHitTolerancePixel(nOld);
1340 if (pObj)
1342 bRet = true;
1343 const IDocumentDrawModelAccess& rIDDMA = getIDocumentDrawModelAccess();
1344 // #i89920#
1345 // Do not select object in background which is overlapping this text
1346 // at the given position.
1347 bool bObjInBackground( false );
1349 if ( pObj->GetLayer() == rIDDMA.GetHellId() )
1351 const SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
1352 const SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
1353 const SwFormatSurround& rSurround = rFormat.GetSurround();
1354 if ( rSurround.GetSurround() == css::text::WrapTextMode_THROUGH )
1356 bObjInBackground = true;
1360 if ( bObjInBackground )
1362 const SwPageFrame* pPageFrame = GetLayout()->GetPageAtPos( rPt );
1363 if( pPageFrame )
1365 const SwContentFrame* pContentFrame( pPageFrame->ContainsContent() );
1366 while ( pContentFrame )
1368 if ( pContentFrame->UnionFrame().IsInside( rPt ) )
1370 const SwTextFrame* pTextFrame =
1371 dynamic_cast<const SwTextFrame*>(pContentFrame);
1372 if ( pTextFrame )
1374 SwPosition aPos(GetDoc()->GetNodes());
1375 Point aTmpPt( rPt );
1376 if (pTextFrame->GetKeyCursorOfst(&aPos, aTmpPt))
1378 SwRect aCursorCharRect;
1379 if (pTextFrame->GetCharRect(aCursorCharRect,
1380 aPos))
1382 if ( aCursorCharRect.IsOver( SwRect( pObj->GetLastBoundRect() ) ) )
1384 bRet = false;
1389 else
1391 bRet = false;
1393 break;
1396 pContentFrame = pContentFrame->GetNextContentFrame();
1401 // Don't select header / footer objects in body edition and vice-versa
1402 SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
1403 if (pContact && !pContact->ObjAnchoredAtPage() )
1405 const SwPosition& rPos = pContact->GetContentAnchor();
1406 bool bInHdrFtr = GetDoc()->IsInHeaderFooter( rPos.nNode );
1407 if (IsHeaderFooterEdit() != bInHdrFtr)
1409 bRet = false;
1413 if ( bRet )
1415 const SdrPage* pPage = rIDDMA.GetDrawModel()->GetPage(0);
1416 for(size_t a = pObj->GetOrdNum()+1; bRet && a < pPage->GetObjCount(); ++a)
1418 SdrObject *pCandidate = pPage->GetObj(a);
1420 SwVirtFlyDrawObj* pDrawObj = dynamic_cast<SwVirtFlyDrawObj*>(pCandidate);
1421 if (pDrawObj && pDrawObj->GetCurrentBoundRect().IsInside(rPt))
1423 bRet = false;
1430 return bRet;
1434 * If an object was selected, we assume its upper-left corner
1435 * otherwise the middle of the current CharRects.
1436 * Does the object include a control or groups,
1437 * which comprise only controls
1439 static bool lcl_IsControlGroup( const SdrObject *pObj )
1441 bool bRet = false;
1442 if(dynamic_cast<const SdrUnoObj*>( pObj) != nullptr)
1443 bRet = true;
1444 else if( auto pObjGroup = dynamic_cast<const SdrObjGroup*>( pObj) )
1446 bRet = true;
1447 const SdrObjList *pLst = pObjGroup->GetSubList();
1448 for ( size_t i = 0; i < pLst->GetObjCount(); ++i )
1449 if( !::lcl_IsControlGroup( pLst->GetObj( i ) ) )
1450 return false;
1452 return bRet;
1455 namespace
1457 class MarkableObjectsOnly : public svx::ISdrObjectFilter
1459 public:
1460 explicit MarkableObjectsOnly( SdrPageView* i_pPV )
1461 :m_pPV( i_pPV )
1465 virtual bool includeObject( const SdrObject& i_rObject ) const override
1467 return m_pPV && m_pPV->GetView().IsObjMarkable( &i_rObject, m_pPV );
1470 private:
1471 SdrPageView* m_pPV;
1475 const SdrObject* SwFEShell::GetBestObject( bool bNext, GotoObjFlags eType, bool bFlat, const svx::ISdrObjectFilter* pFilter )
1477 if( !Imp()->HasDrawView() )
1478 return nullptr;
1480 const SdrObject *pBest = nullptr,
1481 *pTop = nullptr;
1483 const tools::Long nTmp = bNext ? LONG_MAX : 0;
1484 Point aBestPos( nTmp, nTmp );
1485 Point aTopPos( nTmp, nTmp );
1486 Point aCurPos;
1487 Point aPos;
1488 bool bNoDraw((GotoObjFlags::DrawAny & eType) == GotoObjFlags::NONE);
1489 bool bNoFly((GotoObjFlags::FlyAny & eType) == GotoObjFlags::NONE);
1491 if( !bNoFly && bNoDraw )
1493 SwFlyFrame *pFly = GetCurrFrame( false )->FindFlyFrame();
1494 if( pFly )
1495 pBest = pFly->GetVirtDrawObj();
1497 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1498 SdrPageView* pPV = Imp()->GetDrawView()->GetSdrPageView();
1500 MarkableObjectsOnly aDefaultFilter( pPV );
1501 if ( !pFilter )
1502 pFilter = &aDefaultFilter;
1504 if( !pBest || rMrkList.GetMarkCount() == 1 )
1506 // Determine starting point
1507 SdrObjList* pList = nullptr;
1508 if ( rMrkList.GetMarkCount() )
1510 const SdrObject* pStartObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
1511 if( auto pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>( pStartObj) )
1512 aPos = pVirtFlyDrawObj->GetFlyFrame()->getFrameArea().Pos();
1513 else
1514 aPos = pStartObj->GetSnapRect().TopLeft();
1516 // If an object inside a group is selected, we want to
1517 // iterate over the group members.
1518 if ( ! pStartObj->GetUserCall() )
1519 pList = pStartObj->getParentSdrObjListFromSdrObject();
1521 else
1523 // If no object is selected, we check if we just entered a group.
1524 // In this case we want to iterate over the group members.
1525 aPos = GetCharRect().Center();
1526 const SdrObject* pStartObj = pPV ? pPV->GetCurrentGroup() : nullptr;
1527 if ( dynamic_cast<const SdrObjGroup*>( pStartObj) )
1528 pList = pStartObj->GetSubList();
1531 if ( ! pList )
1533 // Here we are if
1534 // A No object has been selected and no group has been entered or
1535 // B An object has been selected and it is not inside a group
1536 pList = getIDocumentDrawModelAccess().GetDrawModel()->GetPage( 0 );
1539 OSL_ENSURE( pList, "No object list to iterate" );
1541 SdrObjListIter aObjIter( pList, bFlat ? SdrIterMode::Flat : SdrIterMode::DeepNoGroups );
1542 while ( aObjIter.IsMore() )
1544 SdrObject* pObj = aObjIter.Next();
1545 SwVirtFlyDrawObj *pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj);
1546 if( ( bNoFly && pVirtO ) ||
1547 ( bNoDraw && !pVirtO ) ||
1548 // Ignore TextBoxes of draw shapes here, so that
1549 // SwFEShell::SelectObj() won't jump back on this list, meaning
1550 // we never jump to the next draw shape.
1551 (pVirtO && pVirtO->IsTextBox()) ||
1552 ( eType == GotoObjFlags::DrawSimple && lcl_IsControlGroup( pObj ) ) ||
1553 ( eType == GotoObjFlags::DrawControl && !lcl_IsControlGroup( pObj ) ) ||
1554 !pFilter->includeObject( *pObj ) )
1555 continue;
1556 if (pVirtO)
1558 SwFlyFrame *pFly = pVirtO->GetFlyFrame();
1559 if( GotoObjFlags::FlyAny != ( GotoObjFlags::FlyAny & eType ) )
1561 switch ( eType )
1563 case GotoObjFlags::FlyFrame:
1564 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
1565 continue;
1566 break;
1567 case GotoObjFlags::FlyGrf:
1568 if ( pFly->Lower() &&
1569 (!pFly->Lower()->IsNoTextFrame() ||
1570 !static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetGrfNode()))
1571 continue;
1572 break;
1573 case GotoObjFlags::FlyOLE:
1574 if ( pFly->Lower() &&
1575 (!pFly->Lower()->IsNoTextFrame() ||
1576 !static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetOLENode()))
1577 continue;
1578 break;
1579 default: break;
1582 aCurPos = pFly->getFrameArea().Pos();
1584 else
1585 aCurPos = pObj->GetSnapRect().TopLeft();
1587 // Special case if another object is on same Y.
1588 if( aCurPos != aPos && // only when it is not me
1589 aCurPos.getY() == aPos.getY() && // Y positions equal
1590 (bNext? (aCurPos.getX() > aPos.getX()) : // lies next to me
1591 (aCurPos.getX() < aPos.getX())) ) // " reverse
1593 aBestPos = Point( nTmp, nTmp );
1594 SdrObjListIter aTmpIter( pList, bFlat ? SdrIterMode::Flat : SdrIterMode::DeepNoGroups );
1595 while ( aTmpIter.IsMore() )
1597 SdrObject* pTmpObj = aTmpIter.Next();
1598 pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pTmpObj);
1599 if( ( bNoFly && pVirtO ) || ( bNoDraw && !pVirtO ) )
1600 continue;
1601 if (pVirtO)
1603 aCurPos = pVirtO->GetFlyFrame()->getFrameArea().Pos();
1605 else
1606 aCurPos = pTmpObj->GetCurrentBoundRect().TopLeft();
1608 if( aCurPos != aPos && aCurPos.Y() == aPos.Y() &&
1609 (bNext? (aCurPos.getX() > aPos.getX()) : // lies next to me
1610 (aCurPos.getX() < aPos.getX())) && // " reverse
1611 (bNext? (aCurPos.getX() < aBestPos.getX()) : // better as best
1612 (aCurPos.getX() > aBestPos.getX())) ) // " reverse
1614 aBestPos = aCurPos;
1615 pBest = pTmpObj;
1618 break;
1621 if( (
1622 (bNext? (aPos.getY() < aCurPos.getY()) : // only below me
1623 (aPos.getY() > aCurPos.getY())) && // " reverse
1624 (bNext? (aBestPos.getY() > aCurPos.getY()) : // closer below
1625 (aBestPos.getY() < aCurPos.getY()))
1626 ) || // " reverse
1627 (aBestPos.getY() == aCurPos.getY() &&
1628 (bNext? (aBestPos.getX() > aCurPos.getX()) : // further left
1629 (aBestPos.getX() < aCurPos.getX())))) // " reverse
1632 aBestPos = aCurPos;
1633 pBest = pObj;
1636 if( (bNext? (aTopPos.getY() > aCurPos.getY()) : // higher as best
1637 (aTopPos.getY() < aCurPos.getY())) || // " reverse
1638 (aTopPos.getY() == aCurPos.getY() &&
1639 (bNext? (aTopPos.getX() > aCurPos.getX()) : // further left
1640 (aTopPos.getX() < aCurPos.getX())))) // " reverse
1642 aTopPos = aCurPos;
1643 pTop = pObj;
1646 // unfortunately nothing found
1647 if( bNext ? (aBestPos.getX() == LONG_MAX) : (aBestPos.getX() == 0) )
1649 pBest = pTop;
1650 SvxSearchDialogWrapper::SetSearchLabel( bNext ? SearchLabel::EndWrapped : SearchLabel::StartWrapped );
1654 return pBest;
1657 bool SwFEShell::GotoObj( bool bNext, GotoObjFlags eType )
1659 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
1661 const SdrObject* pBest = GetBestObject( bNext, eType );
1663 if ( !pBest )
1665 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
1666 return false;
1669 const SwVirtFlyDrawObj *pVirtO = dynamic_cast<const SwVirtFlyDrawObj*>(pBest);
1670 if (pVirtO)
1672 const SwRect& rFrame = pVirtO->GetFlyFrame()->getFrameArea();
1673 SelectObj( rFrame.Pos(), 0, const_cast<SdrObject*>(pBest) );
1674 if( !ActionPend() )
1675 MakeVisible( rFrame );
1677 else
1679 SelectObj( Point(), 0, const_cast<SdrObject*>(pBest) );
1680 if( !ActionPend() )
1681 MakeVisible( pBest->GetCurrentBoundRect() );
1683 CallChgLnk();
1684 return true;
1687 bool SwFEShell::BeginCreate( SdrObjKind eSdrObjectKind, const Point &rPos )
1689 bool bRet = false;
1691 if ( !Imp()->HasDrawView() )
1692 Imp()->MakeDrawView();
1694 if ( GetPageNumber( rPos ) )
1696 Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind );
1697 if ( eSdrObjectKind == OBJ_CAPTION )
1698 bRet = Imp()->GetDrawView()->BegCreateCaptionObj(
1699 rPos, Size( lMinBorder - MINFLY, lMinBorder - MINFLY ),
1700 GetOut() );
1701 else
1702 bRet = Imp()->GetDrawView()->BegCreateObj( rPos, GetOut() );
1704 if ( bRet )
1706 ::FrameNotify( this, FLY_DRAG_START );
1708 return bRet;
1711 bool SwFEShell::BeginCreate( SdrObjKind eSdrObjectKind, SdrInventor eObjInventor,
1712 const Point &rPos )
1714 bool bRet = false;
1716 if ( !Imp()->HasDrawView() )
1717 Imp()->MakeDrawView();
1719 if ( GetPageNumber( rPos ) )
1721 Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind, eObjInventor );
1722 bRet = Imp()->GetDrawView()->BegCreateObj( rPos, GetOut() );
1724 if ( bRet )
1725 ::FrameNotify( this, FLY_DRAG_START );
1726 return bRet;
1729 void SwFEShell::MoveCreate( const Point &rPos )
1731 OSL_ENSURE( Imp()->HasDrawView(), "MoveCreate without DrawView?" );
1732 if ( GetPageNumber( rPos ) )
1734 ScrollTo( rPos );
1735 Imp()->GetDrawView()->MovCreateObj( rPos );
1736 ::FrameNotify( this );
1740 bool SwFEShell::EndCreate( SdrCreateCmd eSdrCreateCmd )
1742 // To assure undo-object from the DrawEngine is not stored,
1743 // (we create our own undo-object!), temporarily switch-off Undo
1744 OSL_ENSURE( Imp()->HasDrawView(), "EndCreate without DrawView?" );
1745 if( !Imp()->GetDrawView()->IsGroupEntered() )
1747 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
1749 bool bCreate = Imp()->GetDrawView()->EndCreateObj( eSdrCreateCmd );
1750 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
1752 if ( !bCreate )
1754 ::FrameNotify( this, FLY_DRAG_END );
1755 return false;
1758 if ( eSdrCreateCmd == SdrCreateCmd::NextPoint )
1760 ::FrameNotify( this );
1761 return true;
1763 return ImpEndCreate();
1766 bool SwFEShell::ImpEndCreate()
1768 OSL_ENSURE( Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1,
1769 "New object not selected." );
1771 SdrObject& rSdrObj = *Imp()->GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
1773 if( rSdrObj.GetSnapRect().IsEmpty() )
1775 // preferably we forget the object, only gives problems
1776 Imp()->GetDrawView()->DeleteMarked();
1777 Imp()->GetDrawView()->UnmarkAll();
1778 ::FrameNotify( this, FLY_DRAG_END );
1779 return false;
1782 if( rSdrObj.getParentSdrObjectFromSdrObject() )
1784 Point aTmpPos( rSdrObj.GetSnapRect().TopLeft() );
1785 Point aNewAnchor( rSdrObj.getParentSdrObjectFromSdrObject()->GetAnchorPos() );
1786 // OD 2004-04-05 #i26791# - direct object positioning for group members
1787 rSdrObj.NbcSetRelativePos( aTmpPos - aNewAnchor );
1788 rSdrObj.NbcSetAnchorPos( aNewAnchor );
1789 ::FrameNotify( this );
1790 return true;
1793 LockPaint();
1794 StartAllAction();
1796 Imp()->GetDrawView()->UnmarkAll();
1798 const tools::Rectangle &rBound = rSdrObj.GetSnapRect();
1799 Point aPt( rBound.TopRight() );
1801 // alien identifier should end up on defaults
1802 // duplications possible!!
1803 sal_uInt16 nIdent = SdrInventor::Default == rSdrObj.GetObjInventor()
1804 ? rSdrObj.GetObjIdentifier()
1805 : 0xFFFF;
1807 // default for controls character bound, otherwise paragraph bound.
1808 SwFormatAnchor aAnch;
1809 const SwFrame *pAnch = nullptr;
1810 bool bCharBound = false;
1811 if( dynamic_cast<const SdrUnoObj*>( &rSdrObj) != nullptr )
1813 SwPosition aPos( GetDoc()->GetNodes() );
1814 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
1815 Point aPoint( aPt.getX(), aPt.getY() + rBound.GetHeight()/2 );
1816 GetLayout()->GetModelPositionForViewPoint( &aPos, aPoint, &aState );
1818 // characterbinding not allowed in readonly-content
1819 if( !aPos.nNode.GetNode().IsProtect() )
1821 std::pair<Point, bool> const tmp(aPoint, true);
1822 pAnch = aPos.nNode.GetNode().GetContentNode()->getLayoutFrame(GetLayout(), &aPos, &tmp);
1823 SwRect aTmp;
1824 pAnch->GetCharRect( aTmp, aPos );
1826 // The crsr should not be too far away
1827 bCharBound = true;
1828 tools::Rectangle aRect( aTmp.SVRect() );
1829 aRect.AdjustLeft( -(MM50*2) );
1830 aRect.AdjustTop( -(MM50*2) );
1831 aRect.AdjustRight(MM50*2 );
1832 aRect.AdjustBottom(MM50*2 );
1834 if( !aRect.IsOver( rBound ) && !::GetHtmlMode( GetDoc()->GetDocShell() ))
1835 bCharBound = false;
1837 // anchor in header/footer also not allowed.
1838 if( bCharBound )
1839 bCharBound = !GetDoc()->IsInHeaderFooter( aPos.nNode );
1841 if( bCharBound )
1843 aAnch.SetType( RndStdIds::FLY_AS_CHAR );
1844 aAnch.SetAnchor( &aPos );
1849 if( !bCharBound )
1851 // allow native drawing objects in header/footer.
1852 // Thus, set <bBodyOnly> to <false> for these objects using value
1853 // of <nIdent> - value <0xFFFF> indicates control objects, which aren't
1854 // allowed in header/footer.
1855 //bool bBodyOnly = OBJ_NONE != nIdent;
1856 bool bBodyOnly = 0xFFFF == nIdent;
1857 bool bAtPage = false;
1858 const SwFrame* pPage = nullptr;
1859 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
1860 Point aPoint( aPt );
1861 SwPosition aPos( GetDoc()->GetNodes() );
1862 GetLayout()->GetModelPositionForViewPoint( &aPos, aPoint, &aState );
1864 // do not set in ReadnOnly-content
1865 if (aPos.nNode.GetNode().IsProtect())
1867 // then only page bound. Or should we
1868 // search the next not-readonly position?
1869 bAtPage = true;
1872 SwContentNode* pCNode = aPos.nNode.GetNode().GetContentNode();
1873 std::pair<Point, bool> const tmp(aPoint, false);
1874 pAnch = pCNode ? pCNode->getLayoutFrame(GetLayout(), nullptr, &tmp) : nullptr;
1875 if (!pAnch)
1877 // Hidden content. Anchor to the page instead
1878 bAtPage = true;
1881 if( !bAtPage )
1883 const SwFlyFrame *pTmp = pAnch->FindFlyFrame();
1884 if( pTmp )
1886 const SwFrame* pTmpFrame = pAnch;
1887 SwRect aBound( rBound );
1888 while( pTmp )
1890 if( pTmp->getFrameArea().IsInside( aBound ) )
1892 if( !bBodyOnly || !pTmp->FindFooterOrHeader() )
1893 pPage = pTmpFrame;
1894 break;
1896 pTmp = pTmp->GetAnchorFrame()
1897 ? pTmp->GetAnchorFrame()->FindFlyFrame()
1898 : nullptr;
1899 pTmpFrame = pTmp;
1903 if( !pPage )
1904 pPage = pAnch->FindPageFrame();
1906 // Always via FindAnchor, to assure the frame will be bound
1907 // to the previous. With GetCrsOfst we can also reach the next. THIS IS WRONG.
1908 pAnch = ::FindAnchor( pPage, aPt, bBodyOnly );
1909 if (pAnch->IsTextFrame())
1911 std::pair<SwTextNode const*, sal_Int32> const pos(
1912 static_cast<SwTextFrame const*>(pAnch)->MapViewToModel(TextFrameIndex(0)));
1913 aPos.nNode = *pos.first;
1915 else
1917 aPos.nNode = *static_cast<const SwNoTextFrame*>(pAnch)->GetNode();
1920 // do not set in ReadnOnly-content
1921 if( aPos.nNode.GetNode().IsProtect() )
1922 // then only page bound. Or should we
1923 // search the next not-readonly position?
1924 bAtPage = true;
1925 else
1927 aAnch.SetType( RndStdIds::FLY_AT_PARA );
1928 aAnch.SetAnchor( &aPos );
1932 if( bAtPage )
1934 pPage = pAnch ? pAnch->FindPageFrame() : GetLayout()->GetPageAtPos(aPoint);
1936 aAnch.SetType( RndStdIds::FLY_AT_PAGE );
1937 aAnch.SetPageNum( pPage->GetPhyPageNum() );
1938 pAnch = pPage; // page becomes an anchor
1942 SfxItemSet aSet( GetDoc()->GetAttrPool(), svl::Items<RES_FRM_SIZE, RES_FRM_SIZE,
1943 RES_SURROUND, RES_ANCHOR>{} );
1944 aSet.Put( aAnch );
1946 // OD 2004-03-30 #i26791# - determine relative object position
1947 SwTwips nXOffset;
1948 SwTwips nYOffset = rBound.Top() - pAnch->getFrameArea().Top();
1950 if( pAnch->IsVertical() )
1952 nXOffset = nYOffset;
1953 nYOffset = pAnch->getFrameArea().Left()+pAnch->getFrameArea().Width()-rBound.Right();
1955 else if( pAnch->IsRightToLeft() )
1956 nXOffset = pAnch->getFrameArea().Left()+pAnch->getFrameArea().Width()-rBound.Right();
1957 else
1958 nXOffset = rBound.Left() - pAnch->getFrameArea().Left();
1959 if (pAnch->IsTextFrame())
1961 const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnch);
1962 if (pTmp->IsFollow())
1964 do {
1965 pTmp = pTmp->FindMaster();
1966 OSL_ENSURE(pTmp, "Where's my Master?");
1967 // OD 2004-03-30 #i26791# - correction: add frame area height
1968 // of master frames.
1969 nYOffset += pTmp->IsVertical() ?
1970 pTmp->getFrameArea().Width() : pTmp->getFrameArea().Height();
1971 } while (pTmp->IsFollow());
1974 nYOffset -= pTmp->GetBaseVertOffsetForFly(false);
1978 if( OBJ_NONE == nIdent )
1980 // For OBJ_NONE a fly is inserted.
1981 const tools::Long nWidth = rBound.Right() - rBound.Left();
1982 const tools::Long nHeight= rBound.Bottom() - rBound.Top();
1983 aSet.Put( SwFormatFrameSize( SwFrameSize::Minimum, std::max( nWidth, tools::Long(MINFLY) ),
1984 std::max( nHeight, tools::Long(MINFLY) )));
1986 SwFormatHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
1987 SwFormatVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME );
1988 aSet.Put( SwFormatSurround( css::text::WrapTextMode_PARALLEL ) );
1989 aSet.Put( aHori );
1990 aSet.Put( aVert );
1992 // Quickly store the square
1993 const SwRect aFlyRect( rBound );
1995 // Throw away generated object, now the fly can nicely
1996 // via the available SS be generated.
1997 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false); // see above
1998 // #i52858# - method name changed
1999 SdrPage *pPg = getIDocumentDrawModelAccess().GetOrCreateDrawModel()->GetPage( 0 );
2000 if( !pPg )
2002 SdrModel* pTmpSdrModel = getIDocumentDrawModelAccess().GetDrawModel();
2003 pPg = pTmpSdrModel->AllocPage( false );
2004 pTmpSdrModel->InsertPage( pPg );
2006 pPg->RecalcObjOrdNums();
2007 SdrObject* pRemovedObject = pPg->RemoveObject( rSdrObj.GetOrdNumDirect() );
2008 SdrObject::Free( pRemovedObject );
2009 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
2011 SwFlyFrame* pFlyFrame;
2012 if( NewFlyFrame( aSet, true ) &&
2013 ::GetHtmlMode( GetDoc()->GetDocShell() ) &&
2014 nullptr != ( pFlyFrame = GetSelectedFlyFrame() ))
2016 SfxItemSet aHtmlSet( GetDoc()->GetAttrPool(), svl::Items<RES_VERT_ORIENT, RES_HORI_ORIENT>{} );
2017 // horizontal orientation:
2018 const bool bLeftFrame = aFlyRect.Left() <
2019 pAnch->getFrameArea().Left() + pAnch->getFramePrintArea().Left(),
2020 bLeftPrt = aFlyRect.Left() + aFlyRect.Width() <
2021 pAnch->getFrameArea().Left() + pAnch->getFramePrintArea().Width()/2;
2022 if( bLeftFrame || bLeftPrt )
2024 aHori.SetHoriOrient( text::HoriOrientation::LEFT );
2025 aHori.SetRelationOrient( bLeftFrame ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
2027 else
2029 const bool bRightFrame = aFlyRect.Left() >
2030 pAnch->getFrameArea().Left() + pAnch->getFramePrintArea().Width();
2031 aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
2032 aHori.SetRelationOrient( bRightFrame ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
2034 aHtmlSet.Put( aHori );
2035 aVert.SetVertOrient( text::VertOrientation::TOP );
2036 aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA );
2037 aHtmlSet.Put( aVert );
2039 GetDoc()->SetAttr( aHtmlSet, *pFlyFrame->GetFormat() );
2042 else
2044 if (rSdrObj.GetName().isEmpty())
2046 bool bRestore = GetDoc()->GetIDocumentUndoRedo().DoesDrawUndo();
2047 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
2048 rSdrObj.SetName(GetUniqueShapeName());
2049 GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(bRestore);
2052 Point aRelNullPt;
2053 if( OBJ_CAPTION == nIdent )
2054 aRelNullPt = static_cast<SdrCaptionObj&>(rSdrObj).GetTailPos();
2055 else
2056 aRelNullPt = rBound.TopLeft();
2058 aSet.Put( aAnch );
2059 aSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
2060 // OD 2004-03-30 #i26791# - set horizontal position
2061 SwFormatHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
2062 aSet.Put( aHori );
2063 // OD 2004-03-30 #i26791# - set vertical position
2064 if( pAnch->IsTextFrame() && static_cast<const SwTextFrame*>(pAnch)->IsFollow() )
2066 const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnch);
2067 do {
2068 pTmp = pTmp->FindMaster();
2069 assert(pTmp && "Where's my Master?");
2070 nYOffset += pTmp->IsVertical() ?
2071 pTmp->getFramePrintArea().Width() : pTmp->getFramePrintArea().Height();
2072 } while ( pTmp->IsFollow() );
2074 SwFormatVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME );
2075 aSet.Put( aVert );
2076 SwDrawFrameFormat* pFormat = static_cast<SwDrawFrameFormat*>(getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::DRAW_OBJECT, &aSet ));
2077 // #i36010# - set layout direction of the position
2078 pFormat->SetPositionLayoutDir(
2079 text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
2080 // #i44344#, #i44681# - positioning attributes already set
2081 pFormat->PosAttrSet();
2082 pFormat->SetName(rSdrObj.GetName());
2084 SwDrawContact *pContact = new SwDrawContact( pFormat, &rSdrObj );
2085 // #i35635#
2086 pContact->MoveObjToVisibleLayer( &rSdrObj );
2087 if( bCharBound )
2089 OSL_ENSURE( aAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR, "wrong AnchorType" );
2090 SwTextNode *pNd = aAnch.GetContentAnchor()->nNode.GetNode().GetTextNode();
2091 SwFormatFlyCnt aFormat( pFormat );
2092 pNd->InsertItem(aFormat,
2093 aAnch.GetContentAnchor()->nContent.GetIndex(), 0 );
2094 SwFormatVertOrient aVertical( pFormat->GetVertOrient() );
2095 aVertical.SetVertOrient( text::VertOrientation::LINE_CENTER );
2096 pFormat->SetFormatAttr( aVertical );
2098 if( pAnch->IsTextFrame() && static_cast<const SwTextFrame*>(pAnch)->IsFollow() )
2100 const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnch);
2101 do {
2102 pTmp = pTmp->FindMaster();
2103 OSL_ENSURE( pTmp, "Where's my Master?" );
2104 } while( pTmp->IsFollow() );
2105 pAnch = pTmp;
2108 pContact->ConnectToLayout();
2110 // mark object at frame the object is inserted at.
2112 SdrObject* pMarkObj = pContact->GetDrawObjectByAnchorFrame( *pAnch );
2113 if ( pMarkObj )
2115 Imp()->GetDrawView()->MarkObj( pMarkObj, Imp()->GetPageView() );
2117 else
2119 Imp()->GetDrawView()->MarkObj( &rSdrObj, Imp()->GetPageView() );
2124 GetDoc()->getIDocumentState().SetModified();
2126 KillPams();
2127 EndAllActionAndCall();
2128 UnlockPaint();
2129 return true;
2132 void SwFEShell::BreakCreate()
2134 OSL_ENSURE( Imp()->HasDrawView(), "BreakCreate without DrawView?" );
2135 Imp()->GetDrawView()->BrkCreateObj();
2136 ::FrameNotify( this, FLY_DRAG_END );
2139 bool SwFEShell::IsDrawCreate() const
2141 return Imp()->HasDrawView() && Imp()->GetDrawView()->IsCreateObj();
2144 bool SwFEShell::BeginMark( const Point &rPos )
2146 if ( !Imp()->HasDrawView() )
2147 Imp()->MakeDrawView();
2149 if ( GetPageNumber( rPos ) )
2151 SwDrawView* pDView = Imp()->GetDrawView();
2153 if (pDView->HasMarkablePoints())
2154 return pDView->BegMarkPoints( rPos );
2155 else
2157 pDView->BegMarkObj( rPos );
2158 return true;
2161 else
2162 return false;
2165 void SwFEShell::MoveMark( const Point &rPos )
2167 OSL_ENSURE( Imp()->HasDrawView(), "MoveMark without DrawView?" );
2169 if ( GetPageNumber( rPos ) )
2171 ScrollTo( rPos );
2172 SwDrawView* pDView = Imp()->GetDrawView();
2174 if (pDView->IsInsObjPoint())
2175 pDView->MovInsObjPoint( rPos );
2176 else if (pDView->IsMarkPoints())
2177 pDView->MovMarkPoints( rPos );
2178 else
2179 pDView->MovAction( rPos );
2183 bool SwFEShell::EndMark()
2185 bool bRet = false;
2186 OSL_ENSURE( Imp()->HasDrawView(), "EndMark without DrawView?" );
2188 if (Imp()->GetDrawView()->IsMarkObj())
2190 bRet = Imp()->GetDrawView()->EndMarkObj();
2192 if ( bRet )
2194 bool bShowHdl = false;
2195 SwDrawView* pDView = Imp()->GetDrawView();
2196 // frames are not selected this way, except when
2197 // it is only one frame
2198 SdrMarkList &rMrkList = const_cast<SdrMarkList&>(pDView->GetMarkedObjectList());
2199 SwFlyFrame* pOldSelFly = ::GetFlyFromMarked( &rMrkList, this );
2201 if ( rMrkList.GetMarkCount() > 1 )
2202 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2204 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2205 if( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) != nullptr )
2207 if ( !bShowHdl )
2209 bShowHdl = true;
2211 rMrkList.DeleteMark( i );
2212 --i; // no exceptions
2216 if( bShowHdl )
2218 pDView->MarkListHasChanged();
2219 pDView->AdjustMarkHdl();
2222 if ( rMrkList.GetMarkCount() )
2223 ::lcl_GrabCursor(this, pOldSelFly);
2224 else
2225 bRet = false;
2227 if ( bRet )
2228 ::FrameNotify( this, FLY_DRAG_START );
2230 else
2232 if (Imp()->GetDrawView()->IsMarkPoints())
2233 bRet = Imp()->GetDrawView()->EndMarkPoints();
2236 SetChainMarker();
2237 return bRet;
2240 RndStdIds SwFEShell::GetAnchorId() const
2242 RndStdIds nRet = RndStdIds(SHRT_MAX);
2243 if ( Imp()->HasDrawView() )
2245 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2246 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2248 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2249 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pObj) != nullptr )
2251 nRet = RndStdIds::UNKNOWN;
2252 break;
2254 SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
2255 RndStdIds nId = pContact->GetFormat()->GetAnchor().GetAnchorId();
2256 if ( nRet == RndStdIds(SHRT_MAX) )
2257 nRet = nId;
2258 else if ( nRet != nId )
2260 nRet = RndStdIds::UNKNOWN;
2261 break;
2265 if ( nRet == RndStdIds(SHRT_MAX) )
2266 nRet = RndStdIds::UNKNOWN;
2267 return nRet;
2270 void SwFEShell::ChgAnchor( RndStdIds eAnchorId, bool bSameOnly, bool bPosCorr )
2272 OSL_ENSURE( Imp()->HasDrawView(), "ChgAnchor without DrawView?" );
2273 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2274 if( rMrkList.GetMarkCount() &&
2275 !rMrkList.GetMark( 0 )->GetMarkedSdrObj()->getParentSdrObjectFromSdrObject() )
2277 StartAllAction();
2279 if( GetDoc()->ChgAnchor( rMrkList, eAnchorId, bSameOnly, bPosCorr ))
2280 Imp()->GetDrawView()->UnmarkAll();
2282 EndAllAction();
2284 ::FrameNotify( this );
2288 void SwFEShell::DelSelectedObj()
2290 OSL_ENSURE( Imp()->HasDrawView(), "DelSelectedObj(), no DrawView available" );
2291 if ( Imp()->HasDrawView() )
2293 StartAllAction();
2294 Imp()->GetDrawView()->DeleteMarked();
2295 EndAllAction();
2296 ::FrameNotify( this, FLY_DRAG_END );
2300 // For the statusline to request the current conditions
2301 Size SwFEShell::GetObjSize() const
2303 tools::Rectangle aRect;
2304 if ( Imp()->HasDrawView() )
2306 if ( Imp()->GetDrawView()->IsAction() )
2307 Imp()->GetDrawView()->TakeActionRect( aRect );
2308 else
2309 aRect = Imp()->GetDrawView()->GetAllMarkedRect();
2311 return aRect.GetSize();
2314 Point SwFEShell::GetAnchorObjDiff() const
2316 const SdrView *pView = Imp()->GetDrawView();
2317 OSL_ENSURE( pView, "GetAnchorObjDiff without DrawView?" );
2319 tools::Rectangle aRect;
2320 if ( Imp()->GetDrawView()->IsAction() )
2321 Imp()->GetDrawView()->TakeActionRect( aRect );
2322 else
2323 aRect = Imp()->GetDrawView()->GetAllMarkedRect();
2325 Point aRet( aRect.TopLeft() );
2327 if ( IsFrameSelected() )
2329 SwFlyFrame *pFly = GetSelectedFlyFrame();
2330 aRet -= pFly->GetAnchorFrame()->getFrameArea().Pos();
2332 else
2334 const SdrObject *pObj = pView->GetMarkedObjectList().GetMarkCount() == 1 ?
2335 pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj() : nullptr;
2336 if ( pObj )
2337 aRet -= pObj->GetAnchorPos();
2340 return aRet;
2343 Point SwFEShell::GetObjAbsPos() const
2345 OSL_ENSURE( Imp()->GetDrawView(), "GetObjAbsPos() without DrawView?" );
2346 return Imp()->GetDrawView()->GetDragStat().GetActionRect().TopLeft();
2349 bool SwFEShell::IsGroupSelected()
2351 if ( IsObjSelected() )
2353 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2354 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2356 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2357 // consider 'virtual' drawing objects.
2358 // Thus, use corresponding method instead of checking type.
2359 if ( pObj->IsGroupObject() &&
2360 // --> #i38505# No ungroup allowed for 3d objects
2361 !pObj->Is3DObj() &&
2362 RndStdIds::FLY_AS_CHAR != static_cast<SwDrawContact*>(GetUserCall(pObj))->
2363 GetFormat()->GetAnchor().GetAnchorId() )
2365 return true;
2369 return false;
2372 namespace
2374 bool HasSuitableGroupingAnchor(const SdrObject* pObj)
2376 bool bSuitable = true;
2377 SwFrameFormat* pFrameFormat(::FindFrameFormat(const_cast<SdrObject*>(pObj)));
2378 if (!pFrameFormat)
2380 OSL_FAIL( "<HasSuitableGroupingAnchor> - missing frame format" );
2381 bSuitable = false;
2383 else if (RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId())
2385 bSuitable = false;
2387 return bSuitable;
2391 // Change return type.
2392 // Adjustments for drawing objects in header/footer:
2393 // allow group, only if all selected objects are in the same header/footer
2394 // or not in header/footer.
2395 bool SwFEShell::IsGroupAllowed() const
2397 bool bIsGroupAllowed = false;
2398 if ( IsObjSelected() > 1 )
2400 bIsGroupAllowed = true;
2401 const SdrObject* pUpGroup = nullptr;
2402 const SwFrame* pHeaderFooterFrame = nullptr;
2403 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2404 for ( size_t i = 0; bIsGroupAllowed && i < rMrkList.GetMarkCount(); ++i )
2406 const SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2407 if ( i )
2408 bIsGroupAllowed = pObj->getParentSdrObjectFromSdrObject() == pUpGroup;
2409 else
2410 pUpGroup = pObj->getParentSdrObjectFromSdrObject();
2412 if ( bIsGroupAllowed )
2413 bIsGroupAllowed = HasSuitableGroupingAnchor(pObj);
2415 // check, if all selected objects are in the
2416 // same header/footer or not in header/footer.
2417 if ( bIsGroupAllowed )
2419 const SwFrame* pAnchorFrame = nullptr;
2420 if ( auto pVirtFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>( pObj) )
2422 const SwFlyFrame* pFlyFrame = pVirtFlyDrawObj->GetFlyFrame();
2423 if ( pFlyFrame )
2425 pAnchorFrame = pFlyFrame->GetAnchorFrame();
2428 else
2430 SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(GetUserCall( pObj ));
2431 if ( pDrawContact )
2433 pAnchorFrame = pDrawContact->GetAnchorFrame( pObj );
2436 if ( pAnchorFrame )
2438 if ( i )
2440 bIsGroupAllowed =
2441 ( pAnchorFrame->FindFooterOrHeader() == pHeaderFooterFrame );
2443 else
2445 pHeaderFooterFrame = pAnchorFrame->FindFooterOrHeader();
2452 return bIsGroupAllowed;
2455 bool SwFEShell::IsUnGroupAllowed() const
2457 bool bIsUnGroupAllowed = false;
2459 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2460 for (size_t i = 0; i < rMrkList.GetMarkCount(); ++i)
2462 const SdrObject* pObj = rMrkList.GetMark(i)->GetMarkedSdrObj();
2463 bIsUnGroupAllowed = HasSuitableGroupingAnchor(pObj);
2464 if (!bIsUnGroupAllowed)
2465 break;
2468 return bIsUnGroupAllowed;
2471 // The group gets the anchor and the contactobject of the first in the selection
2472 void SwFEShell::GroupSelection()
2474 if ( IsGroupAllowed() )
2476 StartAllAction();
2477 StartUndo( SwUndoId::START );
2479 GetDoc()->GroupSelection( *Imp()->GetDrawView() );
2481 EndUndo( SwUndoId::END );
2482 EndAllAction();
2486 // The individual objects get a copy of the anchor and the contactobject of the group
2487 void SwFEShell::UnGroupSelection()
2489 if ( IsGroupSelected() )
2491 StartAllAction();
2492 StartUndo( SwUndoId::START );
2494 GetDoc()->UnGroupSelection( *Imp()->GetDrawView() );
2496 EndUndo( SwUndoId::END );
2497 EndAllAction();
2501 void SwFEShell::MirrorSelection( bool bHorizontal )
2503 SdrView *pView = Imp()->GetDrawView();
2504 if ( IsObjSelected() && pView->IsMirrorAllowed() )
2506 if ( bHorizontal )
2507 pView->MirrorAllMarkedHorizontal();
2508 else
2509 pView->MirrorAllMarkedVertical();
2513 // jump to named frame (Graphic/OLE)
2515 bool SwFEShell::GotoFly( const OUString& rName, FlyCntType eType, bool bSelFrame )
2517 bool bRet = false;
2518 static SwNodeType const aChkArr[ 4 ] = {
2519 /* FLYCNTTYPE_ALL */ SwNodeType::NONE,
2520 /* FLYCNTTYPE_FRM */ SwNodeType::Text,
2521 /* FLYCNTTYPE_GRF */ SwNodeType::Grf,
2522 /* FLYCNTTYPE_OLE */ SwNodeType::Ole
2525 const SwFlyFrameFormat* pFlyFormat = mxDoc->FindFlyByName( rName, aChkArr[ eType]);
2526 if( pFlyFormat )
2528 CurrShell aCurr( this );
2530 SwFlyFrame* pFrame = SwIterator<SwFlyFrame,SwFormat>( *pFlyFormat ).First();
2531 if( pFrame )
2533 if( bSelFrame )
2535 // first make visible, to get a11y events in proper order
2536 if (!ActionPend())
2537 MakeVisible( pFrame->getFrameArea() );
2538 SelectObj( pFrame->getFrameArea().Pos(), 0, pFrame->GetVirtDrawObj() );
2540 else
2542 SwContentFrame *pCFrame = pFrame->ContainsContent();
2543 if ( pCFrame )
2545 ClearMark();
2546 SwPaM* pCursor = GetCursor();
2548 if (pCFrame->IsTextFrame())
2550 *pCursor->GetPoint() = static_cast<SwTextFrame *>(pCFrame)
2551 ->MapViewToModelPos(TextFrameIndex(0));
2553 else
2555 assert(pCFrame->IsNoTextFrame());
2556 SwContentNode *const pCNode = static_cast<SwNoTextFrame *>(pCFrame)->GetNode();
2558 pCursor->GetPoint()->nNode = *pCNode;
2559 pCursor->GetPoint()->nContent.Assign( pCNode, 0 );
2562 SwRect& rChrRect = const_cast<SwRect&>(GetCharRect());
2563 rChrRect = pFrame->getFramePrintArea();
2564 rChrRect.Pos() += pFrame->getFrameArea().Pos();
2565 GetCursorDocPos() = rChrRect.Pos();
2568 bRet = true;
2571 return bRet;
2574 size_t SwFEShell::GetFlyCount( FlyCntType eType, bool bIgnoreTextBoxes ) const
2576 return GetDoc()->GetFlyCount(eType, bIgnoreTextBoxes);
2579 const SwFrameFormat* SwFEShell::GetFlyNum(size_t nIdx, FlyCntType eType, bool bIgnoreTextBoxes ) const
2581 return GetDoc()->GetFlyNum(nIdx, eType, bIgnoreTextBoxes);
2584 std::vector<SwFrameFormat const*> SwFEShell::GetFlyFrameFormats(
2585 FlyCntType const eType, bool const bIgnoreTextBoxes)
2587 return GetDoc()->GetFlyFrameFormats(eType, bIgnoreTextBoxes);
2590 // show the current selected object
2591 void SwFEShell::MakeSelVisible()
2593 if ( Imp()->HasDrawView() &&
2594 Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2596 GetCurrFrame(); // just to trigger formatting in case the selected object is not formatted.
2597 MakeVisible( Imp()->GetDrawView()->GetAllMarkedRect() );
2599 else
2600 SwCursorShell::MakeSelVisible();
2603 // how is the selected object protected?
2604 FlyProtectFlags SwFEShell::IsSelObjProtected( FlyProtectFlags eType ) const
2606 FlyProtectFlags nChk = FlyProtectFlags::NONE;
2607 const bool bParent(eType & FlyProtectFlags::Parent);
2608 if( Imp()->HasDrawView() )
2610 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2611 for( size_t i = rMrkList.GetMarkCount(); i; )
2613 SdrObject *pObj = rMrkList.GetMark( --i )->GetMarkedSdrObj();
2614 if( !bParent )
2616 nChk |= ( pObj->IsMoveProtect() ? FlyProtectFlags::Pos : FlyProtectFlags::NONE ) |
2617 ( pObj->IsResizeProtect()? FlyProtectFlags::Size : FlyProtectFlags::NONE );
2619 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
2621 SwFlyFrame *pFly = pVirtO->GetFlyFrame();
2622 if ( (FlyProtectFlags::Content & eType) && pFly->GetFormat()->GetProtect().IsContentProtected() )
2623 nChk |= FlyProtectFlags::Content;
2625 if ( pFly->Lower() && pFly->Lower()->IsNoTextFrame() )
2627 SwOLENode *pNd = static_cast<SwNoTextFrame*>(pFly->Lower())->GetNode()->GetOLENode();
2628 uno::Reference < embed::XEmbeddedObject > xObj( pNd ? pNd->GetOLEObj().GetOleRef() : nullptr );
2629 if ( xObj.is() )
2631 // TODO/LATER: use correct aspect
2632 const bool bNeverResize = (embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ));
2633 if ( ( (FlyProtectFlags::Content & eType) || (FlyProtectFlags::Size & eType) ) && bNeverResize )
2635 nChk |= FlyProtectFlags::Size;
2636 nChk |= FlyProtectFlags::Fixed;
2639 // set FlyProtectFlags::Pos if it is a Math object anchored 'as char' and baseline alignment is activated
2640 const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
2641 && RndStdIds::FLY_AS_CHAR == pFly->GetFormat()->GetAnchor().GetAnchorId()
2642 && mxDoc->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT );
2643 if ((FlyProtectFlags::Pos & eType) && bProtectMathPos)
2644 nChk |= FlyProtectFlags::Pos;
2648 nChk &= eType;
2649 if( nChk == eType )
2650 return eType;
2652 const SwFrame* pAnch;
2653 if (SwVirtFlyDrawObj* pVirtO = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
2654 pAnch = pVirtO->GetFlyFrame()->GetAnchorFrame();
2655 else
2657 SwDrawContact* pTmp = static_cast<SwDrawContact*>(GetUserCall(pObj));
2658 pAnch = pTmp ? pTmp->GetAnchorFrame( pObj ) : nullptr;
2660 if( pAnch && pAnch->IsProtected() )
2661 return eType;
2664 return nChk;
2667 bool SwFEShell::GetObjAttr( SfxItemSet &rSet ) const
2669 if ( !IsObjSelected() )
2670 return false;
2672 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2673 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2675 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2676 SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
2677 // --> make code robust
2678 OSL_ENSURE( pContact, "<SwFEShell::GetObjAttr(..)> - missing <pContact>." );
2679 if ( pContact )
2681 if ( i )
2682 rSet.MergeValues( pContact->GetFormat()->GetAttrSet() );
2683 else
2684 rSet.Put( pContact->GetFormat()->GetAttrSet() );
2687 return true;
2690 void SwFEShell::SetObjAttr( const SfxItemSet& rSet )
2692 CurrShell aCurr( this );
2694 if ( !rSet.Count() )
2696 OSL_ENSURE( false, "SetObjAttr, empty set." );
2697 return;
2700 StartAllAction();
2701 StartUndo( SwUndoId::INSATTR );
2703 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2704 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2706 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2707 SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
2708 GetDoc()->SetAttr( rSet, *pContact->GetFormat() );
2711 EndUndo( SwUndoId::INSATTR );
2712 EndAllActionAndCall();
2713 GetDoc()->getIDocumentState().SetModified();
2716 bool SwFEShell::IsAlignPossible() const
2718 return Imp()->GetDrawView()->IsAlignPossible();
2721 void SwFEShell::CheckUnboundObjects()
2723 CurrShell aCurr( this );
2725 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
2726 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
2728 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
2729 if ( !GetUserCall(pObj) )
2731 const tools::Rectangle &rBound = pObj->GetSnapRect();
2732 const Point aPt( rBound.TopLeft() );
2733 const SwFrame *pPage = GetLayout()->Lower();
2734 const SwFrame *pLast = pPage;
2735 while ( pPage && !pPage->getFrameArea().IsInside( aPt ) )
2737 if ( aPt.Y() > pPage->getFrameArea().Bottom() )
2738 pLast = pPage;
2739 pPage = pPage->GetNext();
2741 if ( !pPage )
2742 pPage = pLast;
2743 OSL_ENSURE( pPage, "Page not found." );
2745 // Alien identifier should roll into the default,
2746 // Duplications are possible!!
2747 sal_uInt16 nIdent =
2748 Imp()->GetDrawView()->GetCurrentObjInventor() == SdrInventor::Default ?
2749 Imp()->GetDrawView()->GetCurrentObjIdentifier() : 0xFFFF;
2751 SwFormatAnchor aAnch;
2753 const SwContentFrame *const pAnch = ::FindAnchor(pPage, aPt, true);
2754 SwPosition aPos( pAnch->IsTextFrame()
2755 ? *static_cast<SwTextFrame const*>(pAnch)->GetTextNodeForParaProps()
2756 : *static_cast<SwNoTextFrame const*>(pAnch)->GetNode() );
2757 aAnch.SetType( RndStdIds::FLY_AT_PARA );
2758 aAnch.SetAnchor( &aPos );
2759 const_cast<SwRect&>(GetCharRect()).Pos() = aPt;
2762 // First the action here, to assure GetCharRect delivers current values.
2763 StartAllAction();
2765 SfxItemSet aSet( GetAttrPool(), svl::Items<RES_FRM_SIZE, RES_FRM_SIZE,
2766 RES_SURROUND, RES_ANCHOR>{} );
2767 aSet.Put( aAnch );
2769 Point aRelNullPt;
2771 if( OBJ_CAPTION == nIdent )
2772 aRelNullPt = static_cast<SdrCaptionObj*>(pObj)->GetTailPos();
2773 else
2774 aRelNullPt = rBound.TopLeft();
2776 aSet.Put( aAnch );
2777 aSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
2778 SwFrameFormat* pFormat = getIDocumentLayoutAccess().MakeLayoutFormat( RndStdIds::DRAW_OBJECT, &aSet );
2780 SwDrawContact *pContact = new SwDrawContact(
2781 static_cast<SwDrawFrameFormat*>(pFormat), pObj );
2783 // #i35635#
2784 pContact->MoveObjToVisibleLayer( pObj );
2785 pContact->ConnectToLayout();
2787 EndAllAction();
2792 void SwFEShell::SetCalcFieldValueHdl(Outliner* pOutliner)
2794 GetDoc()->SetCalcFieldValueHdl(pOutliner);
2797 SwChainRet SwFEShell::Chainable( SwRect &rRect, const SwFrameFormat &rSource,
2798 const Point &rPt ) const
2800 rRect.Clear();
2802 // The source is not allowed to have a follow.
2803 const SwFormatChain &rChain = rSource.GetChain();
2804 if ( rChain.GetNext() )
2805 return SwChainRet::SOURCE_CHAINED;
2807 SwChainRet nRet = SwChainRet::NOT_FOUND;
2808 if( Imp()->HasDrawView() )
2810 SdrPageView* pPView;
2811 SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());
2812 const auto nOld = pDView->GetHitTolerancePixel();
2813 pDView->SetHitTolerancePixel( 0 );
2814 SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE);
2815 SwVirtFlyDrawObj* pDrawObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj);
2816 if (pDrawObj)
2818 SwFlyFrame *pFly = pDrawObj->GetFlyFrame();
2819 rRect = pFly->getFrameArea();
2821 // Target and source should not be equal and the list
2822 // should not be cyclic
2823 SwFrameFormat *pFormat = pFly->GetFormat();
2824 nRet = GetDoc()->Chainable(rSource, *pFormat);
2826 pDView->SetHitTolerancePixel( nOld );
2828 return nRet;
2831 void SwFEShell::Chain( SwFrameFormat &rSource, const SwFrameFormat &rDest )
2833 GetDoc()->Chain(rSource, rDest);
2836 SwChainRet SwFEShell::Chain( SwFrameFormat &rSource, const Point &rPt )
2838 SwRect aDummy;
2839 SwChainRet nErr = Chainable( aDummy, rSource, rPt );
2840 if ( nErr == SwChainRet::OK )
2842 StartAllAction();
2843 SdrPageView* pPView;
2844 SwDrawView *pDView = Imp()->GetDrawView();
2845 const auto nOld = pDView->GetHitTolerancePixel();
2846 pDView->SetHitTolerancePixel( 0 );
2847 SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE);
2848 pDView->SetHitTolerancePixel( nOld );
2849 SwFlyFrame *pFly = static_cast<SwVirtFlyDrawObj*>(pObj)->GetFlyFrame();
2851 SwFlyFrameFormat *pFormat = pFly->GetFormat();
2852 GetDoc()->Chain(rSource, *pFormat);
2853 EndAllAction();
2854 SetChainMarker();
2856 return nErr;
2859 void SwFEShell::Unchain( SwFrameFormat &rFormat )
2861 StartAllAction();
2862 GetDoc()->Unchain(rFormat);
2863 EndAllAction();
2866 void SwFEShell::HideChainMarker()
2868 m_pChainFrom.reset();
2869 m_pChainTo.reset();
2872 void SwFEShell::SetChainMarker()
2874 bool bDelFrom = true,
2875 bDelTo = true;
2876 if ( IsFrameSelected() )
2878 SwFlyFrame *pFly = GetSelectedFlyFrame();
2880 if ( pFly->GetPrevLink() )
2882 bDelFrom = false;
2883 const SwFrame *pPre = pFly->GetPrevLink();
2885 Point aStart( pPre->getFrameArea().Right(), pPre->getFrameArea().Bottom());
2886 Point aEnd(pFly->getFrameArea().Pos());
2888 if (!m_pChainFrom)
2890 m_pChainFrom.reset(
2891 new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd ));
2894 if ( pFly->GetNextLink() )
2896 bDelTo = false;
2897 const SwFlyFrame *pNxt = pFly->GetNextLink();
2899 Point aStart( pFly->getFrameArea().Right(), pFly->getFrameArea().Bottom());
2900 Point aEnd(pNxt->getFrameArea().Pos());
2902 if (!m_pChainTo)
2904 m_pChainTo.reset(
2905 new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd ));
2910 if ( bDelFrom )
2912 m_pChainFrom.reset();
2915 if ( bDelTo )
2917 m_pChainTo.reset();
2921 tools::Long SwFEShell::GetSectionWidth( SwFormat const & rFormat ) const
2923 SwFrame *pFrame = GetCurrFrame();
2924 // Is the cursor at this moment in a SectionFrame?
2925 if( pFrame && pFrame->IsInSct() )
2927 SwSectionFrame* pSect = pFrame->FindSctFrame();
2930 // Is it the right one?
2931 if( pSect->KnowsFormat( rFormat ) )
2932 return pSect->getFrameArea().Width();
2933 // for nested areas
2934 pSect = pSect->GetUpper()->FindSctFrame();
2936 while( pSect );
2938 SwIterator<SwSectionFrame,SwFormat> aIter( rFormat );
2939 for ( SwSectionFrame* pSct = aIter.First(); pSct; pSct = aIter.Next() )
2941 if( !pSct->IsFollow() )
2943 return pSct->getFrameArea().Width();
2946 return 0;
2949 void SwFEShell::CreateDefaultShape( SdrObjKind eSdrObjectKind, const tools::Rectangle& rRect,
2950 sal_uInt16 nSlotId)
2952 SdrView* pDrawView = GetDrawView();
2953 SdrModel* pDrawModel = pDrawView->GetModel();
2954 SdrObject* pObj = SdrObjFactory::MakeNewObject(
2955 *pDrawModel,
2956 SdrInventor::Default,
2957 eSdrObjectKind);
2959 if(pObj)
2961 tools::Rectangle aRect(rRect);
2962 if(OBJ_CARC == eSdrObjectKind || OBJ_CCUT == eSdrObjectKind)
2964 // force quadratic
2965 if(aRect.GetWidth() > aRect.GetHeight())
2967 aRect = tools::Rectangle(
2968 Point(aRect.Left() + ((aRect.GetWidth() - aRect.GetHeight()) / 2), aRect.Top()),
2969 Size(aRect.GetHeight(), aRect.GetHeight()));
2971 else
2973 aRect = tools::Rectangle(
2974 Point(aRect.Left(), aRect.Top() + ((aRect.GetHeight() - aRect.GetWidth()) / 2)),
2975 Size(aRect.GetWidth(), aRect.GetWidth()));
2978 pObj->SetLogicRect(aRect);
2980 Point aStart = aRect.TopLeft();
2981 Point aEnd = aRect.BottomRight();
2983 if(dynamic_cast<const SdrCircObj*>( pObj) != nullptr)
2985 SfxItemSet aAttr(pDrawModel->GetItemPool());
2986 aAttr.Put(makeSdrCircStartAngleItem(9000));
2987 aAttr.Put(makeSdrCircEndAngleItem(0));
2988 pObj->SetMergedItemSet(aAttr);
2990 else if(dynamic_cast<const SdrPathObj*>( pObj) != nullptr)
2992 basegfx::B2DPolyPolygon aPoly;
2994 switch(eSdrObjectKind)
2996 case OBJ_PATHLINE:
2997 case OBJ_PATHFILL:
2999 basegfx::B2DPolygon aInnerPoly;
3001 aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
3003 const basegfx::B2DPoint aCenterBottom(aRect.Center().getX(), aRect.Bottom());
3004 aInnerPoly.appendBezierSegment(
3005 aCenterBottom,
3006 aCenterBottom,
3007 basegfx::B2DPoint(aRect.Center().getX(), aRect.Center().getY()));
3009 const basegfx::B2DPoint aCenterTop(aRect.Center().getX(), aRect.Top());
3010 aInnerPoly.appendBezierSegment(
3011 aCenterTop,
3012 aCenterTop,
3013 basegfx::B2DPoint(aRect.Right(), aRect.Top()));
3015 aInnerPoly.setClosed(true);
3016 aPoly.append(aInnerPoly);
3018 break;
3019 case OBJ_FREELINE:
3020 case OBJ_FREEFILL:
3022 basegfx::B2DPolygon aInnerPoly;
3024 aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
3026 aInnerPoly.appendBezierSegment(
3027 basegfx::B2DPoint(aRect.Left(), aRect.Top()),
3028 basegfx::B2DPoint(aRect.Center().getX(), aRect.Top()),
3029 basegfx::B2DPoint(aRect.Center().getX(), aRect.Center().getY()));
3031 aInnerPoly.appendBezierSegment(
3032 basegfx::B2DPoint(aRect.Center().getX(), aRect.Bottom()),
3033 basegfx::B2DPoint(aRect.Right(), aRect.Bottom()),
3034 basegfx::B2DPoint(aRect.Right(), aRect.Top()));
3036 aInnerPoly.append(basegfx::B2DPoint(aRect.Right(), aRect.Bottom()));
3037 aInnerPoly.setClosed(true);
3038 aPoly.append(aInnerPoly);
3040 break;
3041 case OBJ_POLY:
3042 case OBJ_PLIN:
3044 basegfx::B2DPolygon aInnerPoly;
3045 sal_Int32 nWdt(aRect.GetWidth());
3046 sal_Int32 nHgt(aRect.GetHeight());
3048 aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
3049 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 30) / 100, aRect.Top() + (nHgt * 70) / 100));
3050 aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Top() + (nHgt * 15) / 100));
3051 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 65) / 100, aRect.Top()));
3052 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + nWdt, aRect.Top() + (nHgt * 30) / 100));
3053 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 50) / 100));
3054 aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 75) / 100));
3055 aInnerPoly.append(basegfx::B2DPoint(aRect.Bottom(), aRect.Right()));
3057 if(OBJ_PLIN == eSdrObjectKind)
3059 aInnerPoly.append(basegfx::B2DPoint(aRect.Center().getX(), aRect.Bottom()));
3061 else
3063 aInnerPoly.setClosed(true);
3066 aPoly.append(aInnerPoly);
3068 break;
3069 case OBJ_LINE :
3071 sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2);
3072 basegfx::B2DPolygon aTempPoly;
3073 aTempPoly.append(basegfx::B2DPoint(aRect.TopLeft().getX(), nYMiddle));
3074 aTempPoly.append(basegfx::B2DPoint(aRect.BottomRight().getX(), nYMiddle));
3075 aPoly.append(aTempPoly);
3077 SfxItemSet aAttr(pObj->getSdrModelFromSdrObject().GetItemPool());
3078 SetLineEnds(aAttr, *pObj, nSlotId);
3079 pObj->SetMergedItemSet(aAttr);
3081 break;
3082 default:
3083 break;
3086 static_cast<SdrPathObj*>(pObj)->SetPathPoly(aPoly);
3088 else if(auto pMeasureObj = dynamic_cast<SdrMeasureObj*>( pObj))
3090 sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2);
3091 pMeasureObj->SetPoint(Point(aStart.X(), nYMiddle), 0);
3092 pMeasureObj->SetPoint(Point(aEnd.X(), nYMiddle), 1);
3094 SfxItemSet aAttr(pObj->getSdrModelFromSdrObject().GetItemPool());
3095 SetLineEnds(aAttr, *pObj, nSlotId);
3096 pObj->SetMergedItemSet(aAttr);
3098 else if(auto pCationObj = dynamic_cast<SdrCaptionObj*>( pObj))
3100 bool bVerticalText = ( SID_DRAW_TEXT_VERTICAL == nSlotId ||
3101 SID_DRAW_CAPTION_VERTICAL == nSlotId );
3102 static_cast<SdrTextObj*>(pObj)->SetVerticalWriting(bVerticalText);
3103 if(bVerticalText)
3105 SfxItemSet aSet(pObj->GetMergedItemSet());
3106 aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
3107 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
3108 pObj->SetMergedItemSet(aSet);
3111 pCationObj->SetLogicRect(aRect);
3112 pCationObj->SetTailPos(
3113 aRect.TopLeft() - Point(aRect.GetWidth() / 2, aRect.GetHeight() / 2));
3115 else if(auto pText = dynamic_cast<SdrTextObj*>( pObj))
3117 pText->SetLogicRect(aRect);
3119 bool bVertical = (SID_DRAW_TEXT_VERTICAL == nSlotId);
3120 bool bMarquee = (SID_DRAW_TEXT_MARQUEE == nSlotId);
3122 pText->SetVerticalWriting(bVertical);
3124 if(bVertical)
3126 SfxItemSet aSet(pDrawModel->GetItemPool());
3127 aSet.Put(makeSdrTextAutoGrowWidthItem(true));
3128 aSet.Put(makeSdrTextAutoGrowHeightItem(false));
3129 aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
3130 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
3131 pText->SetMergedItemSet(aSet);
3134 if(bMarquee)
3136 SfxItemSet aSet(pDrawModel->GetItemPool(), svl::Items<SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST>{});
3137 aSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
3138 aSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
3139 aSet.Put( SdrTextAniKindItem( SdrTextAniKind::Slide ) );
3140 aSet.Put( SdrTextAniDirectionItem( SdrTextAniDirection::Left ) );
3141 aSet.Put( SdrTextAniCountItem( 1 ) );
3142 aSet.Put( SdrTextAniAmountItem( static_cast<sal_Int16>(GetWin()->PixelToLogic(Size(2,1)).Width())) );
3143 pObj->SetMergedItemSetAndBroadcast(aSet);
3146 SdrPageView* pPageView = pDrawView->GetSdrPageView();
3147 SdrCreateView::SetupObjLayer(pPageView, pDrawView->GetActiveLayer(), pObj);
3148 // switch undo off or this combined with ImpEndCreate will cause two undos
3149 // see comment made in SwFEShell::EndCreate (we create our own undo-object!)
3150 const bool bUndo(GetDoc()->GetIDocumentUndoRedo().DoesUndo());
3151 GetDoc()->GetIDocumentUndoRedo().DoUndo(false);
3152 pDrawView->InsertObjectAtView(pObj, *pPageView);
3153 GetDoc()->GetIDocumentUndoRedo().DoUndo(bUndo);
3155 ImpEndCreate();
3158 /** SwFEShell::GetShapeBackgrd
3159 method determines background color of the page the selected drawing
3160 object is on and returns this color.
3161 If no color is found, because no drawing object is selected or ...,
3162 color COL_BLACK (default color on constructing object of class Color)
3163 is returned.
3165 @returns an object of class Color
3167 Color SwFEShell::GetShapeBackgrd() const
3169 Color aRetColor;
3171 // check, if a draw view exists
3172 OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!");
3173 if( Imp()->GetDrawView() )
3175 // determine list of selected objects
3176 const SdrMarkList* pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
3177 // check, if exactly one object is selected.
3178 OSL_ENSURE( pMrkList->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!");
3179 if ( pMrkList->GetMarkCount() == 1)
3181 // get selected object
3182 const SdrObject *pSdrObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
3183 // check, if selected object is a shape (drawing object)
3184 OSL_ENSURE( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr, "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!");
3185 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr )
3187 // determine page frame of the frame the shape is anchored.
3188 const SwFrame* pAnchorFrame =
3189 static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrame( pSdrObj );
3190 OSL_ENSURE( pAnchorFrame, "inconsistent model - no anchor at shape!");
3191 if ( pAnchorFrame )
3193 const SwPageFrame* pPageFrame = pAnchorFrame->FindPageFrame();
3194 OSL_ENSURE( pPageFrame, "inconsistent model - no page!");
3195 if ( pPageFrame )
3197 aRetColor = pPageFrame->GetDrawBackgrdColor();
3204 return aRetColor;
3207 /** Is default horizontal text direction for selected drawing object right-to-left
3208 Because drawing objects only painted for each page only, the default
3209 horizontal text direction of a drawing object is given by the corresponding
3210 page property.
3212 @returns boolean, indicating, if the horizontal text direction of the
3213 page, the selected drawing object is on, is right-to-left.
3215 bool SwFEShell::IsShapeDefaultHoriTextDirR2L() const
3217 bool bRet = false;
3219 // check, if a draw view exists
3220 OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!");
3221 if( Imp()->GetDrawView() )
3223 // determine list of selected objects
3224 const SdrMarkList* pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
3225 // check, if exactly one object is selected.
3226 OSL_ENSURE( pMrkList->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!");
3227 if ( pMrkList->GetMarkCount() == 1)
3229 // get selected object
3230 const SdrObject *pSdrObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
3231 // check, if selected object is a shape (drawing object)
3232 OSL_ENSURE( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr, "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!");
3233 if ( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) == nullptr )
3235 // determine page frame of the frame the shape is anchored.
3236 const SwFrame* pAnchorFrame =
3237 static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrame( pSdrObj );
3238 OSL_ENSURE( pAnchorFrame, "inconsistent model - no anchor at shape!");
3239 if ( pAnchorFrame )
3241 const SwPageFrame* pPageFrame = pAnchorFrame->FindPageFrame();
3242 OSL_ENSURE( pPageFrame, "inconsistent model - no page!");
3243 if ( pPageFrame )
3245 bRet = pPageFrame->IsRightToLeft();
3252 return bRet;
3255 Point SwFEShell::GetRelativePagePosition(const Point& rDocPos)
3257 Point aRet(-1, -1);
3258 const SwFrame *pPage = GetLayout()->Lower();
3259 while ( pPage && !pPage->getFrameArea().IsInside( rDocPos ) )
3261 pPage = pPage->GetNext();
3263 if(pPage)
3265 aRet = rDocPos - pPage->getFrameArea().TopLeft();
3267 return aRet;
3270 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */