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