Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "hintids.hxx"
21 : #include <svx/svdtrans.hxx>
22 : #include <editeng/protitem.hxx>
23 : #include <editeng/opaqitem.hxx>
24 : #include <svx/svdpage.hxx>
25 :
26 : #include <fmtclds.hxx>
27 : #include <fmtornt.hxx>
28 : #include <fmtfsize.hxx>
29 : #include <fmturl.hxx>
30 : #include "viewsh.hxx"
31 : #include "viewimp.hxx"
32 : #include "cntfrm.hxx"
33 : #include "frmatr.hxx"
34 : #include "doc.hxx"
35 : #include <IDocumentUndoRedo.hxx>
36 : #include "dview.hxx"
37 : #include "dflyobj.hxx"
38 : #include "flyfrm.hxx"
39 : #include "frmfmt.hxx"
40 : #include "viewopt.hxx"
41 : #include "frmtool.hxx"
42 : #include "flyfrms.hxx"
43 : #include "ndnotxt.hxx"
44 : #include "grfatr.hxx"
45 : #include "pagefrm.hxx"
46 : #include "rootfrm.hxx"
47 :
48 : #include <svx/sdr/properties/defaultproperties.hxx>
49 : #include <basegfx/range/b2drange.hxx>
50 : #include <basegfx/polygon/b2dpolygontools.hxx>
51 : #include <basegfx/polygon/b2dpolygon.hxx>
52 :
53 : // AW: For VCOfDrawVirtObj and stuff
54 : #include <svx/sdr/contact/viewcontactofvirtobj.hxx>
55 : #include <drawinglayer/primitive2d/baseprimitive2d.hxx>
56 : #include <sw_primitivetypes2d.hxx>
57 : #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
58 :
59 : using namespace ::com::sun::star;
60 :
61 : static bool bInResize = false;
62 :
63 80271 : TYPEINIT1( SwFlyDrawObj, SdrObject )
64 4444123 : TYPEINIT1( SwVirtFlyDrawObj, SdrVirtObj )
65 :
66 : namespace sdr
67 : {
68 : namespace contact
69 : {
70 : /**
71 : * @see #i95264#
72 : *
73 : * currently needed since createViewIndependentPrimitive2DSequence() is called when
74 : * RecalcBoundRect() is used. There should currently no VOCs being constructed since it
75 : * gets not visualized (instead the corresponding SwVirtFlyDrawObj's referencing this one
76 : * are visualized).
77 : */
78 : class VCOfSwFlyDrawObj : public ViewContactOfSdrObj
79 : {
80 : protected:
81 : /** This method is responsible for creating the graphical visualisation data
82 : *
83 : * @note ONLY based on model data
84 : */
85 : virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const SAL_OVERRIDE;
86 :
87 : public:
88 : /// basic constructor, used from SdrObject.
89 2842 : VCOfSwFlyDrawObj(SwFlyDrawObj& rObj)
90 2842 : : ViewContactOfSdrObj(rObj)
91 : {
92 2842 : }
93 : virtual ~VCOfSwFlyDrawObj();
94 : };
95 :
96 498 : drawinglayer::primitive2d::Primitive2DSequence VCOfSwFlyDrawObj::createViewIndependentPrimitive2DSequence() const
97 : {
98 : // currently gets not visualized, return empty sequence
99 498 : return drawinglayer::primitive2d::Primitive2DSequence();
100 : }
101 :
102 5684 : VCOfSwFlyDrawObj::~VCOfSwFlyDrawObj()
103 : {
104 5684 : }
105 : } // end of namespace contact
106 : } // end of namespace sdr
107 :
108 0 : sdr::properties::BaseProperties* SwFlyDrawObj::CreateObjectSpecificProperties()
109 : {
110 : // create default properties
111 0 : return new sdr::properties::DefaultProperties(*this);
112 : }
113 :
114 2842 : sdr::contact::ViewContact* SwFlyDrawObj::CreateObjectSpecificViewContact()
115 : {
116 : // needs an own VC since createViewIndependentPrimitive2DSequence()
117 : // is called when RecalcBoundRect() is used
118 2842 : return new sdr::contact::VCOfSwFlyDrawObj(*this);
119 : }
120 :
121 3916 : SwFlyDrawObj::SwFlyDrawObj()
122 : {
123 3916 : }
124 :
125 7832 : SwFlyDrawObj::~SwFlyDrawObj()
126 : {
127 7832 : }
128 :
129 : // SwFlyDrawObj - Factory-Methods
130 :
131 15740 : sal_uInt32 SwFlyDrawObj::GetObjInventor() const
132 : {
133 15740 : return SWGInventor;
134 : }
135 :
136 0 : sal_uInt16 SwFlyDrawObj::GetObjIdentifier() const
137 : {
138 0 : return SwFlyDrawObjIdentifier;
139 : }
140 :
141 : // TODO: Need own primitive to get the FlyFrame paint working
142 :
143 : namespace drawinglayer
144 : {
145 : namespace primitive2d
146 : {
147 11964 : class SwVirtFlyDrawObjPrimitive : public BufferedDecompositionPrimitive2D
148 : {
149 : private:
150 : const SwVirtFlyDrawObj& mrSwVirtFlyDrawObj;
151 : const basegfx::B2DRange maOuterRange;
152 :
153 : protected:
154 : /// method which is to be used to implement the local decomposition of a 2D primitive
155 : virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const SAL_OVERRIDE;
156 :
157 : public:
158 5982 : SwVirtFlyDrawObjPrimitive(
159 : const SwVirtFlyDrawObj& rSwVirtFlyDrawObj,
160 : const basegfx::B2DRange &rOuterRange)
161 : : BufferedDecompositionPrimitive2D(),
162 : mrSwVirtFlyDrawObj(rSwVirtFlyDrawObj),
163 5982 : maOuterRange(rOuterRange)
164 : {
165 5982 : }
166 :
167 : virtual bool operator==(const BasePrimitive2D& rPrimitive) const SAL_OVERRIDE;
168 :
169 : virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const SAL_OVERRIDE;
170 :
171 : // override to allow callbacks to wrap_DoPaintObject
172 : virtual Primitive2DSequence get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const SAL_OVERRIDE;
173 :
174 : // data read access
175 14157 : const SwVirtFlyDrawObj& getSwVirtFlyDrawObj() const { return mrSwVirtFlyDrawObj; }
176 26390 : const basegfx::B2DRange& getOuterRange() const { return maOuterRange; }
177 :
178 : /// provide unique ID
179 : DeclPrimitive2DIDBlock()
180 : };
181 : } // end of namespace primitive2d
182 : } // end of namespace drawinglayer
183 :
184 : namespace drawinglayer
185 : {
186 : namespace primitive2d
187 : {
188 620 : Primitive2DSequence SwVirtFlyDrawObjPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
189 : {
190 620 : Primitive2DSequence aRetval;
191 :
192 620 : if(!getOuterRange().isEmpty())
193 : {
194 : // currently this SW object has no primitive representation. As long as this is the case,
195 : // create invisible geometry to allow corfect HitTest and BoundRect calculations for the
196 : // object. Use a filled primitive to get 'inside' as default object hit. The special cases from
197 : // the old SwVirtFlyDrawObj::CheckHit implementation are handled now in SwDrawView::PickObj;
198 : // this removed the 'hack' to get a view from inside model data or to react on null-tolerance
199 : // as it was done in the old implementation
200 : const Primitive2DReference aHitTestReference(
201 : createHiddenGeometryPrimitives2D(
202 : true,
203 620 : getOuterRange()));
204 :
205 620 : aRetval = Primitive2DSequence(&aHitTestReference, 1);
206 : }
207 :
208 620 : return aRetval;
209 : }
210 :
211 6636 : bool SwVirtFlyDrawObjPrimitive::operator==(const BasePrimitive2D& rPrimitive) const
212 : {
213 6636 : if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
214 : {
215 6636 : const SwVirtFlyDrawObjPrimitive& rCompare = (SwVirtFlyDrawObjPrimitive&)rPrimitive;
216 :
217 6636 : return (&getSwVirtFlyDrawObj() == &rCompare.getSwVirtFlyDrawObj()
218 6636 : && getOuterRange() == rCompare.getOuterRange());
219 : }
220 :
221 0 : return false;
222 : }
223 :
224 11878 : basegfx::B2DRange SwVirtFlyDrawObjPrimitive::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
225 : {
226 11878 : return getOuterRange();
227 : }
228 :
229 885 : Primitive2DSequence SwVirtFlyDrawObjPrimitive::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
230 : {
231 : // This is the callback to keep the FlyFrame painting in SW alive as long as it
232 : // is not changed to primitives. This is the method which will be called by the processors
233 : // when they do not know this primitive (and they do not). Inside wrap_DoPaintObject
234 : // there needs to be a test that paint is only done during SW repaints (see there).
235 : // Using this mechanism guarantees the correct Z-Order of the VirtualObject-based FlyFrames.
236 885 : getSwVirtFlyDrawObj().wrap_DoPaintObject(rViewInformation);
237 :
238 : // call parent
239 885 : return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
240 : }
241 :
242 : // provide unique ID
243 18313 : ImplPrimitive2DIDBlock(SwVirtFlyDrawObjPrimitive, PRIMITIVE2D_ID_SWVIRTFLYDRAWOBJPRIMITIVE2D)
244 :
245 : } // end of namespace primitive2d
246 : } // end of namespace drawinglayer
247 :
248 : // AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
249 : // since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
250 : // For paint, that offset is used by setting at the OutputDevice; for primitives this is
251 : // not possible since we have no OutputDevice, but define the geometry itself.
252 :
253 : namespace sdr
254 : {
255 : namespace contact
256 : {
257 : class VCOfSwVirtFlyDrawObj : public ViewContactOfVirtObj
258 : {
259 : protected:
260 : /** This method is responsible for creating the graphical visualisation data
261 : *
262 : * @note ONLY based on model data
263 : */
264 : virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const SAL_OVERRIDE;
265 :
266 : public:
267 : /// basic constructor, used from SdrObject.
268 3800 : VCOfSwVirtFlyDrawObj(SwVirtFlyDrawObj& rObj)
269 3800 : : ViewContactOfVirtObj(rObj)
270 : {
271 3800 : }
272 : virtual ~VCOfSwVirtFlyDrawObj();
273 :
274 : /// access to SwVirtFlyDrawObj
275 17946 : SwVirtFlyDrawObj& GetSwVirtFlyDrawObj() const
276 : {
277 17946 : return (SwVirtFlyDrawObj&)mrObject;
278 : }
279 : };
280 : } // end of namespace contact
281 : } // end of namespace sdr
282 :
283 : namespace sdr
284 : {
285 : namespace contact
286 : {
287 5982 : drawinglayer::primitive2d::Primitive2DSequence VCOfSwVirtFlyDrawObj::createViewIndependentPrimitive2DSequence() const
288 : {
289 5982 : drawinglayer::primitive2d::Primitive2DSequence xRetval;
290 5982 : const SdrObject& rReferencedObject = GetSwVirtFlyDrawObj().GetReferencedObj();
291 :
292 5982 : if(rReferencedObject.ISA(SwFlyDrawObj))
293 : {
294 : // create an own specialized primitive which is used as repaint callpoint and HitTest
295 : // for HitTest processor (see primitive implementation above)
296 5982 : const basegfx::B2DRange aOuterRange(GetSwVirtFlyDrawObj().getOuterBound());
297 :
298 5982 : if(!aOuterRange.isEmpty())
299 : {
300 : const drawinglayer::primitive2d::Primitive2DReference xPrimitive(
301 : new drawinglayer::primitive2d::SwVirtFlyDrawObjPrimitive(
302 : GetSwVirtFlyDrawObj(),
303 5982 : aOuterRange));
304 :
305 5982 : xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xPrimitive, 1);
306 : }
307 : }
308 :
309 5982 : return xRetval;
310 : }
311 :
312 7600 : VCOfSwVirtFlyDrawObj::~VCOfSwVirtFlyDrawObj()
313 : {
314 7600 : }
315 : } // end of namespace contact
316 : } // end of namespace sdr
317 :
318 5982 : basegfx::B2DRange SwVirtFlyDrawObj::getOuterBound() const
319 : {
320 5982 : basegfx::B2DRange aOuterRange;
321 5982 : const SdrObject& rReferencedObject = GetReferencedObj();
322 :
323 5982 : if(rReferencedObject.ISA(SwFlyDrawObj))
324 : {
325 5982 : const SwFlyFrm* pFlyFrame = GetFlyFrm();
326 :
327 5982 : if(pFlyFrame)
328 : {
329 5982 : const Rectangle aOuterRectangle(pFlyFrame->Frm().Pos(), pFlyFrame->Frm().SSize());
330 :
331 11964 : if(!aOuterRectangle.IsEmpty()
332 5982 : && RECT_EMPTY != aOuterRectangle.Right()
333 11964 : && RECT_EMPTY != aOuterRectangle.Bottom())
334 : {
335 5982 : aOuterRange.expand(basegfx::B2DTuple(aOuterRectangle.Left(), aOuterRectangle.Top()));
336 5982 : aOuterRange.expand(basegfx::B2DTuple(aOuterRectangle.Right(), aOuterRectangle.Bottom()));
337 : }
338 : }
339 : }
340 :
341 5982 : return aOuterRange;
342 : }
343 :
344 0 : basegfx::B2DRange SwVirtFlyDrawObj::getInnerBound() const
345 : {
346 0 : basegfx::B2DRange aInnerRange;
347 0 : const SdrObject& rReferencedObject = GetReferencedObj();
348 :
349 0 : if(rReferencedObject.ISA(SwFlyDrawObj))
350 : {
351 0 : const SwFlyFrm* pFlyFrame = GetFlyFrm();
352 :
353 0 : if(pFlyFrame)
354 : {
355 0 : const Rectangle aInnerRectangle(pFlyFrame->Frm().Pos() + pFlyFrame->Prt().Pos(), pFlyFrame->Prt().SSize());
356 :
357 0 : if(!aInnerRectangle.IsEmpty()
358 0 : && RECT_EMPTY != aInnerRectangle.Right()
359 0 : && RECT_EMPTY != aInnerRectangle.Bottom())
360 : {
361 0 : aInnerRange.expand(basegfx::B2DTuple(aInnerRectangle.Left(), aInnerRectangle.Top()));
362 0 : aInnerRange.expand(basegfx::B2DTuple(aInnerRectangle.Right(), aInnerRectangle.Bottom()));
363 : }
364 : }
365 : }
366 :
367 0 : return aInnerRange;
368 : }
369 :
370 3800 : sdr::contact::ViewContact* SwVirtFlyDrawObj::CreateObjectSpecificViewContact()
371 : {
372 : // need an own ViewContact (VC) to allow creation of a specialized primitive
373 : // for being able to visualize the FlyFrames in primitive renderers
374 3800 : return new sdr::contact::VCOfSwVirtFlyDrawObj(*this);
375 : }
376 :
377 3800 : SwVirtFlyDrawObj::SwVirtFlyDrawObj(SdrObject& rNew, SwFlyFrm* pFly) :
378 : SdrVirtObj( rNew ),
379 3800 : pFlyFrm( pFly )
380 : {
381 : //#110094#-1
382 : // bNotPersistent = bNeedColorRestore = bWriterFlyFrame = sal_True;
383 3800 : const SvxProtectItem &rP = pFlyFrm->GetFmt()->GetProtect();
384 3800 : bMovProt = rP.IsPosProtected();
385 3800 : bSizProt = rP.IsSizeProtected();
386 3800 : }
387 :
388 11400 : SwVirtFlyDrawObj::~SwVirtFlyDrawObj()
389 : {
390 3800 : if ( GetPage() ) //Withdraw SdrPage the responsibility.
391 3546 : GetPage()->RemoveObject( GetOrdNum() );
392 7600 : }
393 :
394 0 : const SwFrmFmt *SwVirtFlyDrawObj::GetFmt() const
395 : {
396 0 : return GetFlyFrm()->GetFmt();
397 : }
398 9359 : SwFrmFmt *SwVirtFlyDrawObj::GetFmt()
399 : {
400 9359 : return GetFlyFrm()->GetFmt();
401 : }
402 :
403 : // --> OD #i102707#
404 : namespace
405 : {
406 : class RestoreMapMode
407 : {
408 : public:
409 637 : explicit RestoreMapMode( SwViewShell* pViewShell )
410 : : mbMapModeRestored( false )
411 637 : , mpOutDev( pViewShell->GetOut() )
412 : {
413 637 : if ( pViewShell->getPrePostMapMode() != mpOutDev->GetMapMode() )
414 : {
415 595 : mpOutDev->Push(PushFlags::MAPMODE);
416 :
417 595 : GDIMetaFile* pMetaFile = mpOutDev->GetConnectMetaFile();
418 595 : if ( pMetaFile &&
419 595 : pMetaFile->IsRecord() && !pMetaFile->IsPause() )
420 : {
421 : OSL_FAIL( "MapMode restoration during meta file creation is somehow suspect - using <SetRelativeMapMode(..)>, but not sure, if correct." );
422 0 : mpOutDev->SetRelativeMapMode( pViewShell->getPrePostMapMode() );
423 : }
424 : else
425 : {
426 595 : mpOutDev->SetMapMode( pViewShell->getPrePostMapMode() );
427 : }
428 :
429 595 : mbMapModeRestored = true;
430 : }
431 637 : };
432 :
433 637 : ~RestoreMapMode()
434 : {
435 637 : if ( mbMapModeRestored )
436 : {
437 595 : mpOutDev->Pop();
438 : }
439 637 : };
440 :
441 : private:
442 : bool mbMapModeRestored;
443 : OutputDevice* mpOutDev;
444 : };
445 : }
446 : // <--
447 :
448 885 : void SwVirtFlyDrawObj::wrap_DoPaintObject(
449 : drawinglayer::geometry::ViewInformation2D const& rViewInformation) const
450 : {
451 885 : SwViewShell* pShell = pFlyFrm->getRootFrm()->GetCurrShell();
452 :
453 : // Only paint when we have a current shell and a DrawingLayer paint is in progress.
454 : // This avcoids evtl. problems with renderers which do processing stuff,
455 : // but no paints. IsPaintInProgress() depends on SW repaint, so, as long
456 : // as SW paints self and calls DrawLayer() for Heaven and Hell, this will
457 : // be correct
458 885 : if ( pShell && pShell->IsDrawingLayerPaintInProgress() )
459 : {
460 875 : bool bDrawObject(true);
461 :
462 875 : if ( !SwFlyFrm::IsPaint( (SdrObject*)this, pShell ) )
463 : {
464 0 : bDrawObject = false;
465 : }
466 :
467 875 : if ( bDrawObject )
468 : {
469 : // if there's no viewport set, all fly-frames will be painted,
470 : // which is slow, wastes memory, and can cause other trouble.
471 : (void) rViewInformation; // suppress "unused parameter" warning
472 : assert(!rViewInformation.getViewport().isEmpty());
473 875 : if ( !pFlyFrm->IsFlyInCntFrm() )
474 : {
475 : // it is also necessary to restore the VCL MapMode from ViewInformation since e.g.
476 : // the VCL PixelRenderer resets it at the used OutputDevice. Unfortunately, this
477 : // excludes shears and rotates which are not expressable in MapMode.
478 : // OD #i102707#
479 : // new helper class to restore MapMode - restoration, only if
480 : // needed and consideration of paint for meta file creation .
481 637 : RestoreMapMode aRestoreMapModeIfNeeded( pShell );
482 :
483 : // paint the FlyFrame (use standard VCL-Paint)
484 637 : pFlyFrm->Paint( GetFlyFrm()->Frm() );
485 : }
486 : }
487 : }
488 885 : }
489 :
490 0 : void SwVirtFlyDrawObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
491 : {
492 : rInfo.bSelectAllowed = rInfo.bMoveAllowed =
493 0 : rInfo.bResizeFreeAllowed = rInfo.bResizePropAllowed = true;
494 :
495 : rInfo.bRotateFreeAllowed = rInfo.bRotate90Allowed =
496 : rInfo.bMirrorFreeAllowed = rInfo.bMirror45Allowed =
497 : rInfo.bMirror90Allowed = rInfo.bShearAllowed =
498 : rInfo.bCanConvToPath = rInfo.bCanConvToPoly =
499 0 : rInfo.bCanConvToPathLineToArea = rInfo.bCanConvToPolyLineToArea = false;
500 0 : }
501 :
502 : // SwVirtFlyDrawObj - Size Determination
503 :
504 75512 : void SwVirtFlyDrawObj::SetRect() const
505 : {
506 75512 : if ( GetFlyFrm()->Frm().HasArea() )
507 75512 : ((SwVirtFlyDrawObj*)this)->aOutRect = GetFlyFrm()->Frm().SVRect();
508 : else
509 0 : ((SwVirtFlyDrawObj*)this)->aOutRect = Rectangle();
510 75512 : }
511 :
512 60046 : const Rectangle& SwVirtFlyDrawObj::GetCurrentBoundRect() const
513 : {
514 60046 : SetRect();
515 60046 : return aOutRect;
516 : }
517 :
518 48378 : const Rectangle& SwVirtFlyDrawObj::GetLastBoundRect() const
519 : {
520 48378 : return GetCurrentBoundRect();
521 : }
522 :
523 0 : void SwVirtFlyDrawObj::RecalcBoundRect()
524 : {
525 0 : SetRect();
526 0 : }
527 :
528 0 : void SwVirtFlyDrawObj::RecalcSnapRect()
529 : {
530 0 : SetRect();
531 0 : }
532 :
533 6360 : const Rectangle& SwVirtFlyDrawObj::GetSnapRect() const
534 : {
535 6360 : SetRect();
536 6360 : return aOutRect;
537 : }
538 :
539 0 : void SwVirtFlyDrawObj::SetSnapRect(const Rectangle& )
540 : {
541 0 : Rectangle aTmp( GetLastBoundRect() );
542 0 : SetRect();
543 0 : SetChanged();
544 0 : BroadcastObjectChange();
545 0 : if (pUserCall!=NULL)
546 0 : pUserCall->Changed(*this, SDRUSERCALL_RESIZE, aTmp);
547 0 : }
548 :
549 0 : void SwVirtFlyDrawObj::NbcSetSnapRect(const Rectangle& )
550 : {
551 0 : SetRect();
552 0 : }
553 :
554 0 : const Rectangle& SwVirtFlyDrawObj::GetLogicRect() const
555 : {
556 0 : SetRect();
557 0 : return aOutRect;
558 : }
559 :
560 0 : void SwVirtFlyDrawObj::SetLogicRect(const Rectangle& )
561 : {
562 0 : Rectangle aTmp( GetLastBoundRect() );
563 0 : SetRect();
564 0 : SetChanged();
565 0 : BroadcastObjectChange();
566 0 : if (pUserCall!=NULL)
567 0 : pUserCall->Changed(*this, SDRUSERCALL_RESIZE, aTmp);
568 0 : }
569 :
570 0 : void SwVirtFlyDrawObj::NbcSetLogicRect(const Rectangle& )
571 : {
572 0 : SetRect();
573 0 : }
574 :
575 0 : ::basegfx::B2DPolyPolygon SwVirtFlyDrawObj::TakeXorPoly() const
576 : {
577 0 : const Rectangle aSourceRectangle(GetFlyFrm()->Frm().SVRect());
578 0 : const ::basegfx::B2DRange aSourceRange(aSourceRectangle.Left(), aSourceRectangle.Top(), aSourceRectangle.Right(), aSourceRectangle.Bottom());
579 0 : ::basegfx::B2DPolyPolygon aRetval;
580 :
581 0 : aRetval.append(::basegfx::tools::createPolygonFromRect(aSourceRange));
582 :
583 0 : return aRetval;
584 : }
585 :
586 : // SwVirtFlyDrawObj::Move() und Resize()
587 :
588 0 : void SwVirtFlyDrawObj::NbcMove(const Size& rSiz)
589 : {
590 0 : MoveRect( aOutRect, rSiz );
591 0 : const Point aOldPos( GetFlyFrm()->Frm().Pos() );
592 0 : const Point aNewPos( aOutRect.TopLeft() );
593 0 : const SwRect aFlyRect( aOutRect );
594 :
595 : //If the Fly has a automatic align (right or top),
596 : //so preserve the automatic.
597 0 : SwFrmFmt *pFmt = GetFlyFrm()->GetFmt();
598 0 : const sal_Int16 eHori = pFmt->GetHoriOrient().GetHoriOrient();
599 0 : const sal_Int16 eVert = pFmt->GetVertOrient().GetVertOrient();
600 0 : const sal_Int16 eRelHori = pFmt->GetHoriOrient().GetRelationOrient();
601 0 : const sal_Int16 eRelVert = pFmt->GetVertOrient().GetRelationOrient();
602 : //On paragraph bound Flys starting from the new position a new
603 : //anchor must be set. Anchor and the new RelPos is calculated and
604 : //placed by the Fly itself.
605 0 : if( GetFlyFrm()->IsFlyAtCntFrm() )
606 0 : ((SwFlyAtCntFrm*)GetFlyFrm())->SetAbsPos( aNewPos );
607 : else
608 : {
609 0 : const SwFrmFmt *pTmpFmt = GetFmt();
610 0 : const SwFmtVertOrient &rVert = pTmpFmt->GetVertOrient();
611 0 : const SwFmtHoriOrient &rHori = pTmpFmt->GetHoriOrient();
612 0 : long lXDiff = aNewPos.X() - aOldPos.X();
613 0 : if( rHori.IsPosToggle() && text::HoriOrientation::NONE == eHori &&
614 0 : !GetFlyFrm()->FindPageFrm()->OnRightPage() )
615 0 : lXDiff = -lXDiff;
616 :
617 0 : if( GetFlyFrm()->GetAnchorFrm()->IsRightToLeft() &&
618 : text::HoriOrientation::NONE == eHori )
619 0 : lXDiff = -lXDiff;
620 :
621 0 : long lYDiff = aNewPos.Y() - aOldPos.Y();
622 0 : if( GetFlyFrm()->GetAnchorFrm()->IsVertical() )
623 : {
624 : //lXDiff -= rVert.GetPos();
625 : //lYDiff += rHori.GetPos();
626 :
627 0 : if ( GetFlyFrm()->GetAnchorFrm()->IsVertLR() )
628 : {
629 0 : lXDiff += rVert.GetPos();
630 0 : lXDiff = -lXDiff;
631 : }
632 : else
633 : {
634 0 : lXDiff -= rVert.GetPos();
635 0 : lYDiff += rHori.GetPos();
636 : }
637 : }
638 : else
639 : {
640 0 : lXDiff += rHori.GetPos();
641 0 : lYDiff += rVert.GetPos();
642 : }
643 :
644 0 : if( GetFlyFrm()->GetAnchorFrm()->IsRightToLeft() &&
645 : text::HoriOrientation::NONE != eHori )
646 0 : lXDiff = GetFlyFrm()->GetAnchorFrm()->Frm().Width() -
647 0 : aFlyRect.Width() - lXDiff;
648 :
649 0 : const Point aTmp( lXDiff, lYDiff );
650 0 : GetFlyFrm()->ChgRelPos( aTmp );
651 : }
652 :
653 0 : SwAttrSet aSet( pFmt->GetDoc()->GetAttrPool(),
654 0 : RES_VERT_ORIENT, RES_HORI_ORIENT );
655 0 : SwFmtHoriOrient aHori( pFmt->GetHoriOrient() );
656 0 : SwFmtVertOrient aVert( pFmt->GetVertOrient() );
657 0 : bool bPut = false;
658 :
659 0 : if( !GetFlyFrm()->IsFlyLayFrm() &&
660 0 : ::GetHtmlMode(pFmt->GetDoc()->GetDocShell()) )
661 : {
662 : //In HTML-Mode only automatic aligns are allowed.
663 : //Only we can try a snap to left/right respectively left-/right border
664 0 : const SwFrm* pAnch = GetFlyFrm()->GetAnchorFrm();
665 0 : bool bNextLine = false;
666 :
667 0 : if( !GetFlyFrm()->IsAutoPos() || text::RelOrientation::PAGE_FRAME != aHori.GetRelationOrient() )
668 : {
669 0 : if( text::RelOrientation::CHAR == eRelHori )
670 : {
671 0 : aHori.SetHoriOrient( text::HoriOrientation::LEFT );
672 0 : aHori.SetRelationOrient( text::RelOrientation::CHAR );
673 : }
674 : else
675 : {
676 0 : bNextLine = true;
677 : //Horizontal Align:
678 : const bool bLeftFrm =
679 0 : aFlyRect.Left() < pAnch->Frm().Left() + pAnch->Prt().Left(),
680 0 : bLeftPrt = aFlyRect.Left() + aFlyRect.Width() <
681 0 : pAnch->Frm().Left() + pAnch->Prt().Width()/2;
682 0 : if ( bLeftFrm || bLeftPrt )
683 : {
684 0 : aHori.SetHoriOrient( text::HoriOrientation::LEFT );
685 0 : aHori.SetRelationOrient( bLeftFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
686 : }
687 : else
688 : {
689 0 : const bool bRightFrm = aFlyRect.Left() >
690 0 : pAnch->Frm().Left() + pAnch->Prt().Width();
691 0 : aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
692 0 : aHori.SetRelationOrient( bRightFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
693 : }
694 : }
695 0 : aSet.Put( aHori );
696 : }
697 : //Vertical alignment simply is retained principally,
698 : //only on manual align will be switched over.
699 0 : bool bRelChar = text::RelOrientation::CHAR == eRelVert;
700 : aVert.SetVertOrient( eVert != text::VertOrientation::NONE ? eVert :
701 0 : GetFlyFrm()->IsFlyInCntFrm() ? text::VertOrientation::CHAR_CENTER :
702 0 : bRelChar && bNextLine ? text::VertOrientation::CHAR_TOP : text::VertOrientation::TOP );
703 0 : if( bRelChar )
704 0 : aVert.SetRelationOrient( text::RelOrientation::CHAR );
705 : else
706 0 : aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA );
707 0 : aSet.Put( aVert );
708 0 : bPut = true;
709 : }
710 :
711 : //We want preferably not to lose the automatic alignments.
712 0 : if ( !bPut && bInResize )
713 : {
714 0 : if ( text::HoriOrientation::NONE != eHori )
715 : {
716 0 : aHori.SetHoriOrient( eHori );
717 0 : aHori.SetRelationOrient( eRelHori );
718 0 : aSet.Put( aHori );
719 0 : bPut = true;
720 : }
721 0 : if ( text::VertOrientation::NONE != eVert )
722 : {
723 0 : aVert.SetVertOrient( eVert );
724 0 : aVert.SetRelationOrient( eRelVert );
725 0 : aSet.Put( aVert );
726 0 : bPut = true;
727 : }
728 : }
729 0 : if ( bPut )
730 0 : pFmt->SetFmtAttr( aSet );
731 0 : }
732 :
733 0 : void SwVirtFlyDrawObj::NbcResize(const Point& rRef,
734 : const Fraction& xFact, const Fraction& yFact)
735 : {
736 0 : ResizeRect( aOutRect, rRef, xFact, yFact );
737 :
738 0 : const SwFrm* pTmpFrm = GetFlyFrm()->GetAnchorFrm();
739 0 : if( !pTmpFrm )
740 0 : pTmpFrm = GetFlyFrm();
741 0 : const bool bVertX = pTmpFrm->IsVertical();
742 :
743 0 : const bool bRTL = pTmpFrm->IsRightToLeft();
744 :
745 0 : const bool bVertL2RX = pTmpFrm->IsVertLR();
746 0 : const Point aNewPos( ( bVertX && !bVertL2RX ) || bRTL ?
747 0 : aOutRect.Right() + 1 :
748 0 : aOutRect.Left(),
749 0 : aOutRect.Top() );
750 :
751 0 : Size aSz( aOutRect.Right() - aOutRect.Left() + 1,
752 0 : aOutRect.Bottom()- aOutRect.Top() + 1 );
753 0 : if( aSz != GetFlyFrm()->Frm().SSize() )
754 : {
755 : //The width of the columns should not be too narrow
756 0 : if ( GetFlyFrm()->Lower() && GetFlyFrm()->Lower()->IsColumnFrm() )
757 : {
758 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), GetFlyFrm() );
759 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
760 0 : long nMin = rAttrs.CalcLeftLine()+rAttrs.CalcRightLine();
761 0 : const SwFmtCol& rCol = rAttrs.GetAttrSet().GetCol();
762 0 : if ( rCol.GetColumns().size() > 1 )
763 : {
764 0 : for ( sal_uInt16 i = 0; i < rCol.GetColumns().size(); ++i )
765 : {
766 0 : nMin += rCol.GetColumns()[i].GetLeft() +
767 0 : rCol.GetColumns()[i].GetRight() +
768 0 : MINFLY;
769 : }
770 0 : nMin -= MINFLY;
771 : }
772 0 : aSz.Width() = std::max( aSz.Width(), nMin );
773 : }
774 :
775 0 : SwFrmFmt *pFmt = GetFmt();
776 0 : const SwFmtFrmSize aOldFrmSz( pFmt->GetFrmSize() );
777 0 : GetFlyFrm()->ChgSize( aSz );
778 0 : SwFmtFrmSize aFrmSz( pFmt->GetFrmSize() );
779 0 : if ( aFrmSz.GetWidthPercent() || aFrmSz.GetHeightPercent() )
780 : {
781 : long nRelWidth, nRelHeight;
782 0 : const SwFrm *pRel = GetFlyFrm()->IsFlyLayFrm() ?
783 0 : GetFlyFrm()->GetAnchorFrm() :
784 0 : GetFlyFrm()->GetAnchorFrm()->GetUpper();
785 0 : const SwViewShell *pSh = GetFlyFrm()->getRootFrm()->GetCurrShell();
786 0 : if ( pSh && pRel->IsBodyFrm() &&
787 0 : pSh->GetViewOptions()->getBrowseMode() &&
788 0 : pSh->VisArea().HasArea() )
789 : {
790 0 : nRelWidth = pSh->GetBrowseWidth();
791 0 : nRelHeight = pSh->VisArea().Height();
792 0 : const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
793 0 : nRelHeight -= 2*aBorder.Height();
794 : }
795 : else
796 : {
797 0 : nRelWidth = pRel->Prt().Width();
798 0 : nRelHeight = pRel->Prt().Height();
799 : }
800 0 : if ( aFrmSz.GetWidthPercent() && aFrmSz.GetWidthPercent() != 0xFF &&
801 0 : aOldFrmSz.GetWidth() != aFrmSz.GetWidth() )
802 0 : aFrmSz.SetWidthPercent( sal_uInt8(aSz.Width() * 100.0 / nRelWidth + 0.5) );
803 0 : if ( aFrmSz.GetHeightPercent() && aFrmSz.GetHeightPercent() != 0xFF &&
804 0 : aOldFrmSz.GetHeight() != aFrmSz.GetHeight() )
805 0 : aFrmSz.SetHeightPercent( sal_uInt8(aSz.Height() * 100.0 / nRelHeight + 0.5) );
806 0 : pFmt->GetDoc()->SetAttr( aFrmSz, *pFmt );
807 0 : }
808 : }
809 :
810 : //Position can also be changed!
811 0 : const Point aOldPos( ( bVertX && !bVertL2RX ) || bRTL ?
812 0 : GetFlyFrm()->Frm().TopRight() :
813 0 : GetFlyFrm()->Frm().Pos() );
814 0 : if ( aNewPos != aOldPos )
815 : {
816 : //May have been altered by the ChgSize!
817 0 : if( bVertX || bRTL )
818 : {
819 0 : if( aOutRect.TopRight() != aNewPos )
820 : {
821 : SwTwips nDeltaX;
822 0 : if ( bVertL2RX )
823 0 : nDeltaX = aNewPos.X() - aOutRect.Left();
824 : else
825 0 : nDeltaX = aNewPos.X() - aOutRect.Right();
826 0 : SwTwips nDeltaY = aNewPos.Y() - aOutRect.Top();
827 0 : MoveRect( aOutRect, Size( nDeltaX, nDeltaY ) );
828 0 : }
829 : }
830 0 : else if ( aOutRect.TopLeft() != aNewPos )
831 0 : aOutRect.SetPos( aNewPos );
832 0 : bInResize = true;
833 0 : NbcMove( Size( 0, 0 ) );
834 0 : bInResize = false;
835 : }
836 0 : }
837 :
838 0 : void SwVirtFlyDrawObj::Move(const Size& rSiz)
839 : {
840 0 : NbcMove( rSiz );
841 0 : SetChanged();
842 0 : GetFmt()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
843 0 : }
844 :
845 0 : void SwVirtFlyDrawObj::Resize(const Point& rRef,
846 : const Fraction& xFact, const Fraction& yFact, bool /*bUnsetRelative*/)
847 : {
848 0 : NbcResize( rRef, xFact, yFact );
849 0 : SetChanged();
850 0 : GetFmt()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
851 0 : }
852 :
853 : // Macro
854 :
855 0 : Pointer SwVirtFlyDrawObj::GetMacroPointer(
856 : const SdrObjMacroHitRec& ) const
857 : {
858 0 : return Pointer( POINTER_REFHAND );
859 : }
860 :
861 0 : bool SwVirtFlyDrawObj::HasMacro() const
862 : {
863 0 : const SwFmtURL &rURL = pFlyFrm->GetFmt()->GetURL();
864 0 : return rURL.GetMap() || !rURL.GetURL().isEmpty();
865 : }
866 :
867 0 : SdrObject* SwVirtFlyDrawObj::CheckMacroHit( const SdrObjMacroHitRec& rRec ) const
868 : {
869 0 : const SwFmtURL &rURL = pFlyFrm->GetFmt()->GetURL();
870 0 : if( rURL.GetMap() || !rURL.GetURL().isEmpty() )
871 : {
872 0 : SwRect aRect;
873 0 : if ( pFlyFrm->Lower() && pFlyFrm->Lower()->IsNoTxtFrm() )
874 : {
875 0 : aRect = pFlyFrm->Prt();
876 0 : aRect += pFlyFrm->Frm().Pos();
877 : }
878 : else
879 0 : aRect = pFlyFrm->Frm();
880 :
881 0 : if( aRect.IsInside( rRec.aPos ) )
882 : {
883 0 : aRect.Pos().setX(aRect.Pos().getX() + rRec.nTol);
884 0 : aRect.Pos().setY(aRect.Pos().getY() + rRec.nTol);
885 0 : aRect.SSize().Height()-= 2 * rRec.nTol;
886 0 : aRect.SSize().Width() -= 2 * rRec.nTol;
887 :
888 0 : if( aRect.IsInside( rRec.aPos ) )
889 : {
890 0 : if( !rURL.GetMap() ||
891 0 : pFlyFrm->GetFmt()->GetIMapObject( rRec.aPos, pFlyFrm ))
892 0 : return (SdrObject*)this;
893 :
894 0 : return 0;
895 : }
896 : }
897 : }
898 0 : return SdrObject::CheckMacroHit( rRec );
899 : }
900 :
901 : // Dragging
902 :
903 0 : bool SwVirtFlyDrawObj::supportsFullDrag() const
904 : {
905 : // call parent
906 0 : return SdrVirtObj::supportsFullDrag();
907 : }
908 :
909 0 : SdrObject* SwVirtFlyDrawObj::getFullDragClone() const
910 : {
911 : // call parent
912 0 : return SdrVirtObj::getFullDragClone();
913 270 : }
914 :
915 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|