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