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