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