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