Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "hintids.hxx"
21 : #include <editeng/protitem.hxx>
22 : #include <svx/svdpagv.hxx>
23 : #include <svx/fmmodel.hxx>
24 : #include <sot/exchange.hxx>
25 : #include <svx/sdrundomanager.hxx>
26 : #include <editeng/outliner.hxx>
27 : #include <com/sun/star/embed/EmbedMisc.hpp>
28 :
29 : #include "swtypes.hxx"
30 : #include "pagefrm.hxx"
31 : #include "rootfrm.hxx"
32 : #include "cntfrm.hxx"
33 : #include "flyfrm.hxx"
34 : #include "frmfmt.hxx"
35 : #include "dflyobj.hxx"
36 : #include "dcontact.hxx"
37 : #include "textboxhelper.hxx"
38 : #include "frmatr.hxx"
39 : #include "viewsh.hxx"
40 : #include "viewimp.hxx"
41 : #include "dview.hxx"
42 : #include "dpage.hxx"
43 : #include "doc.hxx"
44 : #include "mdiexp.hxx"
45 : #include <ndole.hxx>
46 : #include <fmtanchr.hxx>
47 : #include "shellres.hxx"
48 : #include <IDocumentUndoRedo.hxx>
49 : #include <DocumentSettingManager.hxx>
50 : #include <IDocumentLayoutAccess.hxx>
51 :
52 : #include <com/sun/star/embed/Aspects.hpp>
53 :
54 : #include <vector>
55 :
56 : #include <sortedobjs.hxx>
57 : #include <flyfrms.hxx>
58 : #include <UndoManager.hxx>
59 :
60 : using namespace com::sun::star;
61 :
62 24 : class SwSdrHdl : public SdrHdl
63 : {
64 : public:
65 12 : SwSdrHdl(const Point& rPnt, bool bTopRight ) :
66 12 : SdrHdl( rPnt, bTopRight ? HDL_ANCHOR_TR : HDL_ANCHOR ) {}
67 : virtual bool IsFocusHdl() const SAL_OVERRIDE;
68 : };
69 :
70 16 : bool SwSdrHdl::IsFocusHdl() const
71 : {
72 16 : if( HDL_ANCHOR == eKind || HDL_ANCHOR_TR == eKind )
73 16 : return true;
74 0 : return SdrHdl::IsFocusHdl();
75 : }
76 :
77 4 : static const SwFrm *lcl_FindAnchor( const SdrObject *pObj, bool bAll )
78 : {
79 4 : const SwVirtFlyDrawObj *pVirt = pObj->ISA(SwVirtFlyDrawObj) ?
80 4 : static_cast<const SwVirtFlyDrawObj*>(pObj) : 0;
81 4 : if ( pVirt )
82 : {
83 0 : if ( bAll || !pVirt->GetFlyFrm()->IsFlyInCntFrm() )
84 0 : return pVirt->GetFlyFrm()->GetAnchorFrm();
85 : }
86 : else
87 : {
88 4 : const SwDrawContact *pCont = static_cast<const SwDrawContact*>(GetUserCall(pObj));
89 4 : if ( pCont )
90 4 : return pCont->GetAnchorFrm( pObj );
91 : }
92 0 : return 0;
93 : }
94 :
95 3109 : SwDrawView::SwDrawView( SwViewShellImp &rI, SdrModel *pMd, OutputDevice *pOutDev) :
96 : FmFormView( static_cast<FmFormModel*>(pMd), pOutDev ),
97 3109 : rImp( rI )
98 : {
99 3109 : SetPageVisible( false );
100 3109 : SetBordVisible( false );
101 3109 : SetGridVisible( false );
102 3109 : SetHlplVisible( false );
103 3109 : SetGlueVisible( false );
104 3109 : SetFrameDragSingles( true );
105 3109 : SetVirtualObjectBundling( true );
106 3109 : SetSwapAsynchron( true );
107 :
108 3109 : EnableExtendedKeyInputDispatcher( false );
109 3109 : EnableExtendedMouseEventDispatcher( false );
110 3109 : EnableExtendedCommandEventDispatcher( false );
111 :
112 3109 : SetHitTolerancePixel( GetMarkHdlSizePixel()/2 );
113 :
114 3109 : SetPrintPreview( rI.GetShell()->IsPreview() );
115 :
116 : // #i73602# Use default from the configuration
117 3109 : SetBufferedOverlayAllowed(getOptionsDrawinglayer().IsOverlayBuffer_Writer());
118 :
119 : // #i74769#, #i75172# Use default from the configuration
120 3109 : SetBufferedOutputAllowed(getOptionsDrawinglayer().IsPaintBuffer_Writer());
121 3109 : }
122 :
123 : // #i99665#
124 292 : bool SwDrawView::IsAntiAliasing() const
125 : {
126 292 : return getOptionsDrawinglayer().IsAntiAliasing();
127 : }
128 :
129 21 : SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol, const SdrMarkList &rMrkList)
130 : {
131 21 : if(!nTol)
132 : {
133 : // the old method forced back to outer bounds test when nTol == 0, so
134 : // do not try to correct when nTol is not set (used from HelpContent)
135 : }
136 : else
137 : {
138 : // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since
139 : // the SdrObject-specific CheckHit implementations are now replaced with primitives and
140 : // 'tricks' like in the old implementation (e.g. using a view from a model-data class to
141 : // detect if object is selected) are no longer valid.
142 : // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old
143 : // implementation reduced this excluding the inner bound when the object was not selected.
144 21 : SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(pRetval);
145 :
146 21 : if(pSwVirtFlyDrawObj)
147 : {
148 17 : if(pSwVirtFlyDrawObj->GetFlyFrm()->Lower() && pSwVirtFlyDrawObj->GetFlyFrm()->Lower()->IsNoTextFrm())
149 : {
150 : // the old method used IsNoTextFrm (should be for SW's own OLE and
151 : // graphic's) to accept hit only based on outer bounds; nothing to do
152 : }
153 : else
154 : {
155 : // check if the object is selected in this view
156 1 : const size_t nMarkCount(rMrkList.GetMarkCount());
157 1 : bool bSelected(false);
158 :
159 1 : for(size_t a = 0; !bSelected && a < nMarkCount; ++a)
160 : {
161 0 : if(pSwVirtFlyDrawObj == rMrkList.GetMark(a)->GetMarkedSdrObj())
162 : {
163 0 : bSelected = true;
164 : }
165 : }
166 :
167 1 : if(!bSelected)
168 : {
169 : // when not selected, the object is not hit when hit position is inside
170 : // inner range. Get and shrink inner range
171 1 : basegfx::B2DRange aInnerBound(pSwVirtFlyDrawObj->getInnerBound());
172 :
173 1 : aInnerBound.grow(-1.0 * nTol);
174 :
175 1 : if(aInnerBound.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y())))
176 : {
177 : // exclude this hit
178 0 : pRetval = 0;
179 : }
180 : }
181 : }
182 : }
183 : }
184 :
185 21 : return pRetval;
186 : }
187 :
188 3098 : SdrObject* SwDrawView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const SetOfByte* pMVisLay) const
189 : {
190 : // call parent
191 3098 : SdrObject* pRetval = FmFormView::CheckSingleSdrObjectHit(rPnt, nTol, pObj, pPV, nOptions, pMVisLay);
192 :
193 3098 : if(pRetval)
194 : {
195 : // override to allow extra handling when picking SwVirtFlyDrawObj's
196 21 : pRetval = impLocalHitCorrection(pRetval, rPnt, nTol, GetMarkedObjectList());
197 : }
198 :
199 3098 : return pRetval;
200 : }
201 :
202 : /// Gets called every time the handles need to be build
203 28687 : void SwDrawView::AddCustomHdl()
204 : {
205 28687 : const SdrMarkList &rMrkList = GetMarkedObjectList();
206 :
207 28687 : if(rMrkList.GetMarkCount() != 1 || !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()))
208 57350 : return;
209 :
210 12 : SdrObject *pObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
211 : // make code robust
212 12 : SwFrameFormat* pFrameFormat( ::FindFrameFormat( pObj ) );
213 12 : if ( !pFrameFormat )
214 : {
215 : OSL_FAIL( "<SwDrawView::AddCustomHdl()> - missing frame format!" );
216 0 : return;
217 : }
218 12 : const SwFormatAnchor &rAnchor = pFrameFormat->GetAnchor();
219 :
220 12 : if (FLY_AS_CHAR == rAnchor.GetAnchorId())
221 0 : return;
222 :
223 : const SwFrm* pAnch;
224 12 : if(0 == (pAnch = CalcAnchor()))
225 0 : return;
226 :
227 12 : Point aPos(aAnchorPoint);
228 :
229 12 : if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
230 : {
231 : // #i28701# - use last character rectangle saved at object
232 : // in order to avoid a format of the anchor frame
233 0 : SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
234 0 : SwRect aAutoPos = pAnchoredObj->GetLastCharRect();
235 0 : if ( aAutoPos.Height() )
236 : {
237 0 : aPos = aAutoPos.Pos();
238 : }
239 : }
240 :
241 : // add anchor handle:
242 24 : maHdlList.AddHdl( new SwSdrHdl( aPos, ( pAnch->IsVertical() && !pAnch->IsVertLR() ) ||
243 24 : pAnch->IsRightToLeft() ) );
244 : }
245 :
246 2 : SdrObject* SwDrawView::GetMaxToTopObj( SdrObject* pObj ) const
247 : {
248 2 : if ( GetUserCall(pObj) )
249 : {
250 2 : const SwFrm *pAnch = ::lcl_FindAnchor( pObj, false );
251 2 : if ( pAnch )
252 : {
253 : //The topmost Obj within the anchor must not be overtaken.
254 2 : const SwFlyFrm *pFly = pAnch->FindFlyFrm();
255 2 : if ( pFly )
256 : {
257 0 : const SwPageFrm *pPage = pFly->FindPageFrm();
258 0 : if ( pPage->GetSortedObjs() )
259 : {
260 0 : size_t nOrdNum = 0;
261 0 : for ( size_t i = 0; i < pPage->GetSortedObjs()->size(); ++i )
262 : {
263 0 : const SdrObject *pO = (*pPage->GetSortedObjs())[i]->GetDrawObj();
264 :
265 0 : if ( pO->GetOrdNumDirect() > nOrdNum )
266 : {
267 0 : const SwFrm *pTmpAnch = ::lcl_FindAnchor( pO, false );
268 0 : if ( pFly->IsAnLower( pTmpAnch ) )
269 : {
270 0 : nOrdNum = pO->GetOrdNumDirect();
271 : }
272 : }
273 : }
274 0 : if ( nOrdNum )
275 : {
276 0 : SdrPage *pTmpPage = GetModel()->GetPage( 0 );
277 0 : ++nOrdNum;
278 0 : if ( nOrdNum < pTmpPage->GetObjCount() )
279 : {
280 0 : return pTmpPage->GetObj( nOrdNum );
281 : }
282 : }
283 : }
284 : }
285 : }
286 : }
287 2 : return 0;
288 : }
289 :
290 2 : SdrObject* SwDrawView::GetMaxToBtmObj(SdrObject* pObj) const
291 : {
292 2 : if ( GetUserCall(pObj) )
293 : {
294 2 : const SwFrm *pAnch = ::lcl_FindAnchor( pObj, false );
295 2 : if ( pAnch )
296 : {
297 : //The Fly of the anchor must not be "flying under".
298 2 : const SwFlyFrm *pFly = pAnch->FindFlyFrm();
299 2 : if ( pFly )
300 : {
301 0 : SdrObject *pRet = const_cast<SdrObject*>(static_cast<SdrObject const *>(pFly->GetVirtDrawObj()));
302 0 : return pRet != pObj ? pRet : 0;
303 : }
304 : }
305 : }
306 2 : return 0;
307 : }
308 :
309 : /// determine maximal order number for a 'child' object of given 'parent' object
310 0 : sal_uInt32 SwDrawView::_GetMaxChildOrdNum( const SwFlyFrm& _rParentObj,
311 : const SdrObject* _pExclChildObj )
312 : {
313 0 : sal_uInt32 nMaxChildOrdNum = _rParentObj.GetDrawObj()->GetOrdNum();
314 :
315 0 : const SdrPage* pDrawPage = _rParentObj.GetDrawObj()->GetPage();
316 : OSL_ENSURE( pDrawPage,
317 : "<SwDrawView::_GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!" );
318 :
319 0 : const size_t nObjCount = pDrawPage->GetObjCount();
320 0 : for ( size_t i = nObjCount-1; i > _rParentObj.GetDrawObj()->GetOrdNum() ; --i )
321 : {
322 0 : const SdrObject* pObj = pDrawPage->GetObj( i );
323 :
324 : // Don't consider 'child' object <_pExclChildObj>
325 0 : if ( pObj == _pExclChildObj )
326 : {
327 0 : continue;
328 : }
329 :
330 0 : if ( pObj->GetOrdNum() > nMaxChildOrdNum &&
331 0 : _rParentObj.IsAnLower( lcl_FindAnchor( pObj, true ) ) )
332 : {
333 0 : nMaxChildOrdNum = pObj->GetOrdNum();
334 0 : break;
335 : }
336 : }
337 :
338 0 : return nMaxChildOrdNum;
339 : }
340 :
341 : /// method to move 'repeated' objects of the given moved object to the according level
342 0 : void SwDrawView::_MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj,
343 : const std::vector<SdrObject*>& _rMovedChildObjs ) const
344 : {
345 : // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
346 0 : std::list<SwAnchoredObject*> aAnchoredObjs;
347 : {
348 0 : const SwContact* pContact = ::GetUserCall( _rMovedAnchoredObj.GetDrawObj() );
349 : assert(pContact && "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash.");
350 0 : pContact->GetAnchoredObjs( aAnchoredObjs );
351 : }
352 :
353 : // check, if 'repeated' objects exists.
354 0 : if ( aAnchoredObjs.size() > 1 )
355 : {
356 0 : SdrPage* pDrawPage = GetModel()->GetPage( 0 );
357 :
358 : // move 'repeated' ones to the same order number as the already moved one.
359 0 : const size_t nNewPos = _rMovedAnchoredObj.GetDrawObj()->GetOrdNum();
360 0 : while ( !aAnchoredObjs.empty() )
361 : {
362 0 : SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
363 0 : if ( pAnchoredObj != &_rMovedAnchoredObj )
364 : {
365 0 : pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
366 0 : nNewPos );
367 0 : pDrawPage->RecalcObjOrdNums();
368 : // adjustments for accessibility API
369 0 : if ( pAnchoredObj->ISA(SwFlyFrm) )
370 : {
371 0 : const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj);
372 0 : rImp.DisposeAccessibleFrm( pTmpFlyFrm );
373 0 : rImp.AddAccessibleFrm( pTmpFlyFrm );
374 : }
375 : else
376 : {
377 0 : rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() );
378 0 : rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
379 : }
380 : }
381 0 : aAnchoredObjs.pop_back();
382 : }
383 :
384 : // move 'repeated' ones of 'child' objects
385 0 : for ( std::vector<SdrObject*>::const_iterator aObjIter = _rMovedChildObjs.begin();
386 0 : aObjIter != _rMovedChildObjs.end(); ++aObjIter )
387 : {
388 0 : SdrObject* pChildObj = (*aObjIter);
389 : {
390 0 : const SwContact* pContact = ::GetUserCall( pChildObj );
391 : assert(pContact && "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash.");
392 0 : pContact->GetAnchoredObjs( aAnchoredObjs );
393 : }
394 : // move 'repeated' ones to the same order number as the already moved one.
395 0 : const size_t nTmpNewPos = pChildObj->GetOrdNum();
396 0 : while ( !aAnchoredObjs.empty() )
397 : {
398 0 : SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
399 0 : if ( pAnchoredObj->GetDrawObj() != pChildObj )
400 : {
401 0 : pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
402 0 : nTmpNewPos );
403 0 : pDrawPage->RecalcObjOrdNums();
404 : // adjustments for accessibility API
405 0 : if ( pAnchoredObj->ISA(SwFlyFrm) )
406 : {
407 0 : const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj);
408 0 : rImp.DisposeAccessibleFrm( pTmpFlyFrm );
409 0 : rImp.AddAccessibleFrm( pTmpFlyFrm );
410 : }
411 : else
412 : {
413 0 : rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() );
414 0 : rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
415 : }
416 : }
417 0 : aAnchoredObjs.pop_back();
418 : }
419 : }
420 0 : }
421 0 : }
422 :
423 : // --> adjustment and re-factoring of method
424 0 : void SwDrawView::ObjOrderChanged( SdrObject* pObj, sal_uLong nOldPos,
425 : sal_uLong nNewPos )
426 : {
427 : // nothing to do for group members
428 0 : if ( pObj->GetUpGroup() )
429 : {
430 0 : return;
431 : }
432 :
433 : // determine drawing page and assure that the order numbers are correct.
434 0 : SdrPage* pDrawPage = GetModel()->GetPage( 0 );
435 0 : if ( pDrawPage->IsObjOrdNumsDirty() )
436 0 : pDrawPage->RecalcObjOrdNums();
437 0 : const size_t nObjCount = pDrawPage->GetObjCount();
438 :
439 : SwAnchoredObject* pMovedAnchoredObj =
440 0 : ::GetUserCall( pObj )->GetAnchoredObj( pObj );
441 : const SwFlyFrm* pParentAnchoredObj =
442 0 : pMovedAnchoredObj->GetAnchorFrm()->FindFlyFrm();
443 :
444 0 : const bool bMovedForward = nOldPos < nNewPos;
445 :
446 : // assure for a 'child' object, that it doesn't exceed the limits of its 'parent'
447 0 : if ( pParentAnchoredObj )
448 : {
449 0 : if ( bMovedForward )
450 : {
451 : const size_t nMaxChildOrdNumWithoutMoved =
452 0 : _GetMaxChildOrdNum( *pParentAnchoredObj, pMovedAnchoredObj->GetDrawObj() );
453 0 : if ( nNewPos > nMaxChildOrdNumWithoutMoved+1 )
454 : {
455 : // set position to the top of the 'child' object group
456 0 : pDrawPage->SetObjectOrdNum( nNewPos, nMaxChildOrdNumWithoutMoved+1 );
457 0 : nNewPos = nMaxChildOrdNumWithoutMoved+1;
458 : }
459 : }
460 : else
461 : {
462 0 : const size_t nParentOrdNum = pParentAnchoredObj->GetDrawObj()->GetOrdNum();
463 0 : if ( nNewPos < nParentOrdNum )
464 : {
465 : // set position to the bottom of the 'child' object group
466 0 : pDrawPage->SetObjectOrdNum( nNewPos, nParentOrdNum );
467 0 : nNewPos = nParentOrdNum;
468 : }
469 : }
470 0 : if ( pDrawPage->IsObjOrdNumsDirty() )
471 0 : pDrawPage->RecalcObjOrdNums();
472 : }
473 :
474 : // Assure, that object isn't positioned between 'repeated' ones
475 0 : if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
476 0 : ( !bMovedForward && nNewPos > 0 ) )
477 : {
478 : const SdrObject* pTmpObj =
479 0 : pDrawPage->GetObj( bMovedForward ? nNewPos - 1 : nNewPos + 1 );
480 0 : if ( pTmpObj )
481 : {
482 0 : size_t nTmpNewPos( nNewPos );
483 0 : if ( bMovedForward )
484 : {
485 : // move before the top 'repeated' object
486 : const sal_uInt32 nTmpMaxOrdNum =
487 0 : ::GetUserCall( pTmpObj )->GetMaxOrdNum();
488 0 : if ( nTmpMaxOrdNum > nNewPos )
489 0 : nTmpNewPos = nTmpMaxOrdNum;
490 : }
491 : else
492 : {
493 : // move behind the bottom 'repeated' object
494 : const sal_uInt32 nTmpMinOrdNum =
495 0 : ::GetUserCall( pTmpObj )->GetMinOrdNum();
496 0 : if ( nTmpMinOrdNum < nNewPos )
497 0 : nTmpNewPos = nTmpMinOrdNum;
498 : }
499 0 : if ( nTmpNewPos != nNewPos )
500 : {
501 0 : pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
502 0 : nNewPos = nTmpNewPos;
503 0 : pDrawPage->RecalcObjOrdNums();
504 : }
505 : }
506 : }
507 :
508 : // On move forward, assure that object is moved before its own children.
509 : // Only Writer fly frames can have children.
510 0 : if ( pMovedAnchoredObj->ISA(SwFlyFrm) &&
511 0 : bMovedForward && nNewPos < nObjCount - 1 )
512 : {
513 : sal_uInt32 nMaxChildOrdNum =
514 0 : _GetMaxChildOrdNum( *(static_cast<const SwFlyFrm*>(pMovedAnchoredObj)) );
515 0 : if ( nNewPos < nMaxChildOrdNum )
516 : {
517 : // determine position before the object before its top 'child' object
518 0 : const SdrObject* pTmpObj = pDrawPage->GetObj( nMaxChildOrdNum );
519 0 : size_t nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum() + 1;
520 0 : if ( nTmpNewPos >= nObjCount )
521 : {
522 0 : --nTmpNewPos;
523 : }
524 : // assure, that determined position isn't between 'repeated' objects
525 0 : pTmpObj = pDrawPage->GetObj( nTmpNewPos );
526 0 : nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
527 : // apply new position
528 0 : pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
529 0 : nNewPos = nTmpNewPos;
530 0 : pDrawPage->RecalcObjOrdNums();
531 : }
532 : }
533 :
534 : // Assure, that object isn't positioned between nested objects
535 0 : if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
536 0 : ( !bMovedForward && nNewPos > 0 ) )
537 : {
538 0 : size_t nTmpNewPos( nNewPos );
539 : const SwFrameFormat* pParentFrameFormat =
540 0 : pParentAnchoredObj ? &(pParentAnchoredObj->GetFrameFormat()) : 0L;
541 0 : const SdrObject* pTmpObj = pDrawPage->GetObj( nNewPos + 1 );
542 0 : while ( pTmpObj )
543 : {
544 : // #i38563# - assure, that anchor frame exists.
545 : // If object is anchored inside a invisible part of the document
546 : // (e.g. page header, whose page style isn't applied, or hidden
547 : // section), no anchor frame exists.
548 0 : const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, true );
549 : const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm
550 0 : ? pTmpAnchorFrm->FindFlyFrm() : 0L;
551 0 : if ( pTmpParentObj &&
552 0 : &(pTmpParentObj->GetFrameFormat()) != pParentFrameFormat )
553 : {
554 0 : if ( bMovedForward )
555 : {
556 0 : nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
557 0 : pTmpObj = pDrawPage->GetObj( nTmpNewPos + 1 );
558 : }
559 : else
560 : {
561 : nTmpNewPos = ::GetUserCall( pTmpParentObj->GetDrawObj() )
562 0 : ->GetMinOrdNum();
563 0 : pTmpObj = pTmpParentObj->GetDrawObj();
564 : }
565 : }
566 : else
567 0 : break;
568 : }
569 0 : if ( nTmpNewPos != nNewPos )
570 : {
571 0 : pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
572 0 : nNewPos = nTmpNewPos;
573 0 : pDrawPage->RecalcObjOrdNums();
574 : }
575 : }
576 :
577 : // setup collection of moved 'child' objects to move its 'repeated' objects.
578 0 : std::vector< SdrObject* > aMovedChildObjs;
579 :
580 : // move 'children' accordingly
581 0 : if ( pMovedAnchoredObj->ISA(SwFlyFrm) )
582 : {
583 0 : const SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pMovedAnchoredObj);
584 :
585 : // adjustments for accessibility API
586 0 : rImp.DisposeAccessibleFrm( pFlyFrm );
587 0 : rImp.AddAccessibleFrm( pFlyFrm );
588 :
589 0 : const sal_uInt32 nChildNewPos = bMovedForward ? nNewPos : nNewPos+1;
590 0 : size_t i = bMovedForward ? nOldPos : nObjCount-1;
591 0 : do
592 : {
593 0 : SdrObject* pTmpObj = pDrawPage->GetObj( i );
594 0 : if ( pTmpObj == pObj )
595 0 : break;
596 :
597 : // #i38563# - assure, that anchor frame exists.
598 : // If object is anchored inside a invisible part of the document
599 : // (e.g. page header, whose page style isn't applied, or hidden
600 : // section), no anchor frame exists.
601 0 : const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, true );
602 : const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm
603 0 : ? pTmpAnchorFrm->FindFlyFrm() : 0L;
604 0 : if ( pTmpParentObj &&
605 0 : ( ( pTmpParentObj == pFlyFrm ) ||
606 0 : ( pFlyFrm->IsUpperOf( *pTmpParentObj ) ) ) )
607 : {
608 : // move child object.,
609 0 : pDrawPage->SetObjectOrdNum( i, nChildNewPos );
610 0 : pDrawPage->RecalcObjOrdNums();
611 : // collect 'child' object
612 0 : aMovedChildObjs.push_back( pTmpObj );
613 : // adjustments for accessibility API
614 0 : if ( pTmpObj->ISA(SwVirtFlyDrawObj) )
615 : {
616 : const SwFlyFrm *pTmpFlyFrm =
617 0 : static_cast<SwVirtFlyDrawObj*>(pTmpObj)->GetFlyFrm();
618 0 : rImp.DisposeAccessibleFrm( pTmpFlyFrm );
619 0 : rImp.AddAccessibleFrm( pTmpFlyFrm );
620 : }
621 : else
622 : {
623 0 : rImp.DisposeAccessibleObj( pTmpObj );
624 0 : rImp.AddAccessibleObj( pTmpObj );
625 : }
626 : }
627 : else
628 : {
629 : // adjust loop counter
630 0 : if ( bMovedForward )
631 0 : ++i;
632 0 : else if ( !bMovedForward && i > 0 )
633 0 : --i;
634 : }
635 :
636 0 : } while ( ( bMovedForward && i < ( nObjCount - aMovedChildObjs.size() ) ) ||
637 0 : ( !bMovedForward && i > ( nNewPos + aMovedChildObjs.size() ) ) );
638 : }
639 : else
640 : {
641 : // adjustments for accessibility API
642 0 : rImp.DisposeAccessibleObj( pObj );
643 0 : rImp.AddAccessibleObj( pObj );
644 : }
645 :
646 0 : _MoveRepeatedObjs( *pMovedAnchoredObj, aMovedChildObjs );
647 : }
648 :
649 1 : bool SwDrawView::TakeDragLimit( SdrDragMode eMode,
650 : Rectangle& rRect ) const
651 : {
652 1 : const SdrMarkList &rMrkList = GetMarkedObjectList();
653 1 : bool bRet = false;
654 1 : if( 1 == rMrkList.GetMarkCount() )
655 : {
656 1 : const SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
657 1 : SwRect aRect;
658 1 : if( ::CalcClipRect( pObj, aRect, eMode == SDRDRAG_MOVE ) )
659 : {
660 0 : rRect = aRect.SVRect();
661 0 : bRet = true;
662 : }
663 : }
664 1 : return bRet;
665 : }
666 :
667 13 : const SwFrm* SwDrawView::CalcAnchor()
668 : {
669 13 : const SdrMarkList &rMrkList = GetMarkedObjectList();
670 13 : if ( rMrkList.GetMarkCount() != 1 )
671 0 : return NULL;
672 :
673 13 : SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
674 :
675 : //Search for paragraph bound objects, otherwise only the
676 : //current anchor. Search only if we currently drag.
677 : const SwFrm* pAnch;
678 13 : Rectangle aMyRect;
679 13 : const bool bFly = pObj->ISA(SwVirtFlyDrawObj);
680 13 : if ( bFly )
681 : {
682 1 : pAnch = static_cast<SwVirtFlyDrawObj*>(pObj)->GetFlyFrm()->GetAnchorFrm();
683 1 : aMyRect = static_cast<SwVirtFlyDrawObj*>(pObj)->GetFlyFrm()->Frm().SVRect();
684 : }
685 : else
686 : {
687 12 : SwDrawContact *pC = static_cast<SwDrawContact*>(GetUserCall(pObj));
688 : // determine correct anchor position for 'virtual' drawing objects.
689 : // #i26791#
690 12 : pAnch = pC->GetAnchorFrm( pObj );
691 12 : if( !pAnch )
692 : {
693 0 : pC->ConnectToLayout();
694 : // determine correct anchor position for 'virtual' drawing objects.
695 : // #i26791#
696 0 : pAnch = pC->GetAnchorFrm( pObj );
697 : }
698 12 : aMyRect = pObj->GetSnapRect();
699 : }
700 :
701 13 : const bool bTopRight = pAnch && ( ( pAnch->IsVertical() &&
702 13 : !pAnch->IsVertLR() ) ||
703 26 : pAnch->IsRightToLeft() );
704 13 : const Point aMyPt = bTopRight ? aMyRect.TopRight() : aMyRect.TopLeft();
705 :
706 13 : Point aPt;
707 13 : if ( IsAction() )
708 : {
709 1 : if ( !TakeDragObjAnchorPos( aPt, bTopRight ) )
710 0 : return NULL;
711 : }
712 : else
713 : {
714 12 : Rectangle aRect = pObj->GetSnapRect();
715 12 : aPt = bTopRight ? aRect.TopRight() : aRect.TopLeft();
716 : }
717 :
718 13 : if ( aPt != aMyPt )
719 : {
720 0 : if ( pAnch && pAnch->IsContentFrm() )
721 : {
722 : // allow drawing objects in header/footer,
723 : // but exclude control objects.
724 0 : bool bBodyOnly = CheckControlLayer( pObj );
725 0 : pAnch = ::FindAnchor( static_cast<const SwContentFrm*>(pAnch), aPt, bBodyOnly );
726 : }
727 0 : else if ( !bFly )
728 : {
729 0 : const SwRect aRect( aPt.getX(), aPt.getY(), 1, 1 );
730 :
731 0 : SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
732 0 : if ( pContact->GetAnchorFrm( pObj ) &&
733 0 : pContact->GetAnchorFrm( pObj )->IsPageFrm() )
734 0 : pAnch = pContact->GetPageFrm();
735 : else
736 0 : pAnch = pContact->FindPage( aRect );
737 : }
738 : }
739 13 : if( pAnch && !pAnch->IsProtected() )
740 13 : aAnchorPoint = pAnch->GetFrmAnchorPos( ::HasWrap( pObj ) );
741 : else
742 0 : pAnch = 0;
743 13 : return pAnch;
744 : }
745 :
746 1 : void SwDrawView::ShowDragAnchor()
747 : {
748 1 : SdrHdl* pHdl = maHdlList.GetHdl(HDL_ANCHOR);
749 1 : if ( ! pHdl )
750 0 : pHdl = maHdlList.GetHdl(HDL_ANCHOR_TR);
751 :
752 1 : if(pHdl)
753 : {
754 1 : CalcAnchor();
755 1 : pHdl->SetPos(aAnchorPoint);
756 : }
757 1 : }
758 :
759 3139 : void SwDrawView::MarkListHasChanged()
760 : {
761 3139 : Imp().GetShell()->DrawSelChanged();
762 3139 : FmFormView::MarkListHasChanged();
763 3139 : }
764 :
765 : // #i7672#
766 1237 : void SwDrawView::ModelHasChanged()
767 : {
768 : // The ModelHasChanged() call in DrawingLayer also updates
769 : // a eventually active text edit view (OutlinerView). This also leads
770 : // to newly setting the background color for that edit view. Thus,
771 : // this method rescues the current background color if a OutlinerView
772 : // exists and re-establishes it then. To be more safe, the OutlinerView
773 : // will be fetched again (maybe textedit has ended).
774 1237 : OutlinerView* pView = GetTextEditOutlinerView();
775 1237 : Color aBackColor;
776 1237 : bool bColorWasSaved(false);
777 :
778 1237 : if(pView)
779 : {
780 0 : aBackColor = pView->GetBackgroundColor();
781 0 : bColorWasSaved = true;
782 : }
783 :
784 : // call parent
785 1237 : FmFormView::ModelHasChanged();
786 :
787 1237 : if(bColorWasSaved)
788 : {
789 0 : pView = GetTextEditOutlinerView();
790 :
791 0 : if(pView)
792 : {
793 0 : pView->SetBackgroundColor(aBackColor);
794 : }
795 : }
796 1237 : }
797 :
798 2 : void SwDrawView::MakeVisible( const Rectangle &rRect, vcl::Window & )
799 : {
800 : OSL_ENSURE( rImp.GetShell()->GetWin(), "MakeVisible, unknown Window");
801 2 : rImp.GetShell()->MakeVisible( SwRect( rRect ) );
802 2 : }
803 :
804 2 : void SwDrawView::CheckPossibilities()
805 : {
806 2 : FmFormView::CheckPossibilities();
807 :
808 : //In addition to the existing flags of the objects themselves,
809 : //which are evaluated by the DrawingEngine, other circumstances
810 : //lead to a protection.
811 : //Objects that are anchored in frames need to be protected
812 : //if the content of the frame is protected.
813 : //OLE-Objects may themselves wish a resize protection (StarMath)
814 :
815 2 : const SdrMarkList &rMrkList = GetMarkedObjectList();
816 2 : bool bProtect = false;
817 2 : bool bSzProtect = false;
818 4 : for ( size_t i = 0; !bProtect && i < rMrkList.GetMarkCount(); ++i )
819 : {
820 2 : const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
821 2 : const SwFrm *pFrm = NULL;
822 2 : if ( pObj->ISA(SwVirtFlyDrawObj) )
823 : {
824 0 : const SwFlyFrm *pFly = static_cast<const SwVirtFlyDrawObj*>(pObj)->GetFlyFrm();
825 0 : if ( pFly )
826 : {
827 0 : pFrm = pFly->GetAnchorFrm();
828 0 : if ( pFly->Lower() && pFly->Lower()->IsNoTextFrm() )
829 : {
830 0 : SwOLENode *pNd = const_cast<SwContentFrm*>(static_cast<const SwContentFrm*>(pFly->Lower()))->GetNode()->GetOLENode();
831 0 : if ( pNd )
832 : {
833 0 : uno::Reference < embed::XEmbeddedObject > xObj = pNd->GetOLEObj().GetOleRef();
834 0 : if ( xObj.is() )
835 : {
836 : // --> improvement for the future, when more
837 : // than one Writer fly frame can be selected.
838 :
839 : // TODO/LATER: retrieve Aspect - from where?!
840 0 : bSzProtect |= ( embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ) ) != 0;
841 :
842 : // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
843 0 : SwDoc* pDoc = Imp().GetShell()->GetDoc();
844 0 : const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
845 0 : && FLY_AS_CHAR == pFly->GetFormat()->GetAnchor().GetAnchorId()
846 0 : && pDoc->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT );
847 0 : if (bProtectMathPos)
848 0 : bMoveProtect = true;
849 0 : }
850 : }
851 : }
852 : }
853 : }
854 : else
855 : {
856 2 : SwDrawContact *pC = static_cast<SwDrawContact*>(GetUserCall(pObj));
857 2 : if ( pC )
858 2 : pFrm = pC->GetAnchorFrm( pObj );
859 : }
860 2 : if ( pFrm )
861 2 : bProtect = pFrm->IsProtected(); //Frames, areas etc.
862 : {
863 2 : SwFrameFormat* pFrameFormat( ::FindFrameFormat( const_cast<SdrObject*>(pObj) ) );
864 2 : if ( !pFrameFormat )
865 : {
866 : OSL_FAIL( "<SwDrawView::CheckPossibilities()> - missing frame format" );
867 0 : bProtect = true;
868 : }
869 2 : else if ((FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId()) &&
870 0 : rMrkList.GetMarkCount() > 1 )
871 : {
872 0 : bProtect = true;
873 : }
874 : }
875 : }
876 2 : bMoveProtect |= bProtect;
877 2 : bResizeProtect |= bProtect || bSzProtect;
878 2 : }
879 :
880 : /// replace marked <SwDrawVirtObj>-objects by its reference object for delete marked objects.
881 1 : void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView )
882 : {
883 1 : SdrPageView* pDrawPageView = _rMarkView.GetSdrPageView();
884 1 : const SdrMarkList& rMarkList = _rMarkView.GetMarkedObjectList();
885 :
886 1 : if( rMarkList.GetMarkCount() )
887 : {
888 : // collect marked objects in a local data structure
889 1 : std::vector<SdrObject*> aMarkedObjs;
890 2 : for( size_t i = 0; i < rMarkList.GetMarkCount(); ++i )
891 : {
892 1 : SdrObject* pMarkedObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
893 1 : aMarkedObjs.push_back( pMarkedObj );
894 : }
895 : // unmark all objects
896 1 : _rMarkView.UnmarkAllObj();
897 : // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its
898 : // reference object.
899 3 : while ( !aMarkedObjs.empty() )
900 : {
901 1 : SdrObject* pMarkObj = aMarkedObjs.back();
902 1 : if ( pMarkObj->ISA(SwDrawVirtObj) )
903 : {
904 0 : SdrObject* pRefObj = &(static_cast<SwDrawVirtObj*>(pMarkObj)->ReferencedObj());
905 0 : if ( !_rMarkView.IsObjMarked( pRefObj ) )
906 : {
907 0 : _rMarkView.MarkObj( pRefObj, pDrawPageView );
908 : }
909 : }
910 : else
911 : {
912 1 : _rMarkView.MarkObj( pMarkObj, pDrawPageView );
913 : }
914 :
915 1 : aMarkedObjs.pop_back();
916 : }
917 : // sort marked list in order to assure consistent state in drawing layer
918 1 : _rMarkView.SortMarkedObjects();
919 : }
920 1 : }
921 :
922 1 : void SwDrawView::DeleteMarked()
923 : {
924 1 : SwDoc* pDoc = Imp().GetShell()->GetDoc();
925 1 : SwRootFrm *pTmpRoot = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
926 1 : if ( pTmpRoot )
927 1 : pTmpRoot->StartAllAction();
928 1 : pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
929 : // replace marked <SwDrawVirtObj>-objects by its reference objects.
930 : {
931 1 : SdrPageView* pDrawPageView = rImp.GetPageView();
932 1 : if ( pDrawPageView )
933 : {
934 1 : SdrMarkView* pMarkView = &(pDrawPageView->GetView());
935 1 : if ( pMarkView )
936 : {
937 1 : ReplaceMarkedDrawVirtObjs( *pMarkView );
938 : }
939 : }
940 : }
941 :
942 : // Check what textboxes have to be deleted afterwards.
943 1 : const SdrMarkList& rMarkList = GetMarkedObjectList();
944 1 : std::vector<SwFrameFormat*> aTextBoxesToDelete;
945 2 : for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i)
946 : {
947 1 : SdrObject *pObject = rMarkList.GetMark(i)->GetMarkedSdrObj();
948 1 : SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(GetUserCall(pObject));
949 1 : SwFrameFormat* pFormat = pDrawContact->GetFormat();
950 1 : if (SwFrameFormat* pTextBox = SwTextBoxHelper::findTextBox(pFormat))
951 1 : aTextBoxesToDelete.push_back(pTextBox);
952 : }
953 :
954 1 : if ( pDoc->DeleteSelection( *this ) )
955 : {
956 1 : FmFormView::DeleteMarked();
957 1 : ::FrameNotify( Imp().GetShell(), FLY_DRAG_END );
958 :
959 : // Only delete these now: earlier deletion would clear the mark list as well.
960 2 : for (std::vector<SwFrameFormat*>::iterator i = aTextBoxesToDelete.begin(); i != aTextBoxesToDelete.end(); ++i)
961 1 : pDoc->getIDocumentLayoutAccess().DelLayoutFormat(*i);
962 : }
963 1 : pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
964 1 : if( pTmpRoot )
965 1 : pTmpRoot->EndAllAction();
966 1 : }
967 :
968 : // support enhanced text edit for draw objects
969 4 : SdrUndoManager* SwDrawView::getSdrUndoManagerForEnhancedTextEdit() const
970 : {
971 4 : SwDoc* pDoc = Imp().GetShell()->GetDoc();
972 :
973 4 : return pDoc ? dynamic_cast< SdrUndoManager* >(&(pDoc->GetUndoManager())) : 0;
974 177 : }
975 :
976 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|