xref: /trunk/main/sw/source/core/draw/dview.cxx (revision 8218eba2)
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