1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SlsPageObjectViewObjectContact.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "precompiled_sd.hxx"
33 #include "view/SlsPageObjectViewObjectContact.hxx"
35 #include "controller/SlsProperties.hxx"
36 #include "view/SlideSorterView.hxx"
37 #include "view/SlsPageObjectViewContact.hxx"
38 #include "view/SlsPageObject.hxx"
39 #include "view/SlsFontProvider.hxx"
40 #include "model/SlsPageDescriptor.hxx"
41 #include "cache/SlsPageCache.hxx"
42 #include "cache/SlsPageCacheManager.hxx"
43 #include "res_bmp.hrc"
44 #include "tools/IconCache.hxx"
45 #include "PreviewRenderer.hxx"
48 #include "sdresid.hxx"
50 #include "drawdoc.hxx"
51 #include <svx/sdr/contact/displayinfo.hxx>
52 #include <svx/sdr/contact/viewcontact.hxx>
53 #include <svx/svdopage.hxx>
54 #include <svx/svdpagv.hxx>
55 #include <svx/xlndsit.hxx>
56 #include <svx/xlnclit.hxx>
57 #include <svx/svdoutl.hxx>
58 #include <svx/sdrpagewindow.hxx>
59 #include <vcl/bitmap.hxx>
60 #include <vcl/outdev.hxx>
61 #include <vcl/virdev.hxx>
62 #include <vcl/lineinfo.hxx>
63 #include <tools/color.hxx>
64 #include <boost/shared_ptr.hpp>
65 #include <com/sun/star/uno/Exception.hpp>
66 #include <vcl/svapp.hxx>
68 using namespace ::sdr::contact
;
69 using namespace ::sd::slidesorter::model
;
71 using drawinglayer::primitive2d::Primitive2DReference
;
72 using drawinglayer::primitive2d::Primitive2DSequence
;
74 namespace sd
{ namespace slidesorter
{ namespace view
{
77 const sal_Int32
PageObjectViewObjectContact::mnSelectionIndicatorOffset
= 2;
78 const sal_Int32
PageObjectViewObjectContact::mnSelectionIndicatorThickness
= 3;
79 const sal_Int32
PageObjectViewObjectContact::mnFocusIndicatorOffset
= 3;
80 const sal_Int32
PageObjectViewObjectContact::mnFadeEffectIndicatorOffset
= 9;
81 const sal_Int32
PageObjectViewObjectContact::mnFadeEffectIndicatorSize
= 14;
82 const sal_Int32
PageObjectViewObjectContact::mnPageNumberOffset
= 9;
83 const sal_Int32
PageObjectViewObjectContact::mnMouseOverEffectOffset
= 3;
84 const sal_Int32
PageObjectViewObjectContact::mnMouseOverEffectThickness
= 1;
86 PageObjectViewObjectContact::PageObjectViewObjectContact (
87 ObjectContact
& rObjectContact
,
88 ViewContact
& rViewContact
,
89 const ::boost::shared_ptr
<cache::PageCache
>& rpCache
,
90 const ::boost::shared_ptr
<controller::Properties
>& rpProperties
)
91 : ViewObjectContactOfPageObj(rObjectContact
, rViewContact
),
92 mbInDestructor(false),
93 mxCurrentPageContents(),
95 mpProperties(rpProperties
)
97 SharedPageDescriptor
pDescriptor (GetPageDescriptor());
98 OSL_ASSERT(pDescriptor
.get()!=NULL
);
99 if (pDescriptor
.get() != NULL
)
100 pDescriptor
->SetViewObjectContact(this);
106 PageObjectViewObjectContact::~PageObjectViewObjectContact (void)
108 mbInDestructor
= true;
110 GetPageDescriptor()->SetViewObjectContact(NULL
);
112 if (mpCache
.get() != NULL
)
114 const SdrPage
* pPage
= GetPage();
118 mpCache
->ReleasePreviewBitmap(GetPage());
126 void PageObjectViewObjectContact::SetCache (const ::boost::shared_ptr
<cache::PageCache
>& rpCache
)
134 Rectangle
PageObjectViewObjectContact::GetBoundingBox (
135 OutputDevice
& rDevice
,
136 BoundingBoxType eType
,
137 CoordinateSystem eCoordinateSystem
) const
139 // Most of the bounding boxes are based on the bounding box of the preview.
140 // SdrPageObj is a SdrObject, so use SdrObject::aOutRect as model data
141 const PageObjectViewContact
& rPaObVOC(static_cast<PageObjectViewContact
&>(GetViewContact()));
142 Rectangle
aBoundingBox(rPaObVOC
.GetPageObject().GetLastBoundRect());
144 CoordinateSystem
eCurrentCoordinateSystem (ModelCoordinateSystem
);
147 case PageObjectBoundingBox
:
149 const SvBorder
aPageDescriptorBorder(GetPageDescriptor()->GetModelBorder());
150 aBoundingBox
.Left() -= aPageDescriptorBorder
.Left();
151 aBoundingBox
.Top() -= aPageDescriptorBorder
.Top();
152 aBoundingBox
.Right() += aPageDescriptorBorder
.Right();
153 aBoundingBox
.Bottom() += aPageDescriptorBorder
.Bottom();
156 case PreviewBoundingBox
:
158 // The aBoundingBox already has the right value.
161 case MouseOverIndicatorBoundingBox
:
163 const sal_Int32
nBorderWidth (mnMouseOverEffectOffset
+mnMouseOverEffectThickness
);
164 const Size
aBorderSize (rDevice
.PixelToLogic(Size(nBorderWidth
,nBorderWidth
)));
165 aBoundingBox
.Left() -= aBorderSize
.Width();
166 aBoundingBox
.Top() -= aBorderSize
.Height();
167 aBoundingBox
.Right() += aBorderSize
.Width();
168 aBoundingBox
.Bottom() += aBorderSize
.Height();
171 case FocusIndicatorBoundingBox
:
173 const sal_Int32
nBorderWidth (mnFocusIndicatorOffset
+1);
174 const Size
aBorderSize (rDevice
.PixelToLogic(Size(nBorderWidth
,nBorderWidth
)));
175 aBoundingBox
.Left() -= aBorderSize
.Width();
176 aBoundingBox
.Top() -= aBorderSize
.Height();
177 aBoundingBox
.Right() += aBorderSize
.Width();
178 aBoundingBox
.Bottom() += aBorderSize
.Height();
181 case SelectionIndicatorBoundingBox
:
183 const sal_Int32
nBorderWidth(mnSelectionIndicatorOffset
+mnSelectionIndicatorThickness
);
184 const Size
aBorderSize (rDevice
.PixelToLogic(Size(nBorderWidth
,nBorderWidth
)));
185 aBoundingBox
.Left() -= aBorderSize
.Width();
186 aBoundingBox
.Top() -= aBorderSize
.Height();
187 aBoundingBox
.Right() += aBorderSize
.Width();
188 aBoundingBox
.Bottom() += aBorderSize
.Height();
191 case PageNumberBoundingBox
:
193 Size aModelOffset
= rDevice
.PixelToLogic(Size(mnPageNumberOffset
,mnPageNumberOffset
));
194 Size
aNumberSize (GetPageDescriptor()->GetPageNumberAreaModelSize());
195 aBoundingBox
= Rectangle (
197 aBoundingBox
.Left() - aModelOffset
.Width() - aNumberSize
.Width(),
203 case NameBoundingBox
:
206 case FadeEffectIndicatorBoundingBox
:
207 Size aModelOffset
= rDevice
.PixelToLogic(Size (0, mnFadeEffectIndicatorOffset
));
208 // Flush left just outside the selection rectangle.
209 aBoundingBox
= Rectangle (
212 aBoundingBox
.Bottom() + aModelOffset
.Height()
214 rDevice
.PixelToLogic (
215 IconCache::Instance().GetIcon(BMP_FADE_EFFECT_INDICATOR
).GetSizePixel())
220 // Make sure the bounding box uses the requested coordinate system.
221 if (eCurrentCoordinateSystem
!= eCoordinateSystem
)
223 if (eCoordinateSystem
== ModelCoordinateSystem
)
224 aBoundingBox
= Rectangle(
225 rDevice
.PixelToLogic(aBoundingBox
.TopLeft()),
226 rDevice
.PixelToLogic(aBoundingBox
.GetSize()));
228 aBoundingBox
= Rectangle(
229 rDevice
.LogicToPixel(aBoundingBox
.TopLeft()),
230 rDevice
.LogicToPixel(aBoundingBox
.GetSize()));
235 ///////////////////////////////////////////////////////////////////////////////////////////////
236 // example implementation for primitive usage for PageObjectViewObjectContact
238 } } } // end of namespace ::sd::slidesorter::view
240 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
241 #include <basegfx/polygon/b2dpolygontools.hxx>
242 #include <basegfx/matrix/b2dhommatrix.hxx>
243 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
244 #include <sd_primitivetypes2d.hxx>
245 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
246 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
247 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
248 #include <drawinglayer/geometry/viewinformation2d.hxx>
249 #include <svx/sdr/contact/objectcontact.hxx>
251 namespace sd
{ namespace slidesorter
{ namespace view
{
253 ///////////////////////////////////////////////////////////////////////////////////////////////
254 // All primitives for SdrPageObject visualisation are based on one range which describes
255 // the size of the inner rectangle for PagePreview visualisation. Use a common implementation
256 // class for all derived SdPageObjectPrimitives. The SdPageObjectBasePrimitive itself
259 class SdPageObjectBasePrimitive
: public drawinglayer::primitive2d::BasePrimitive2D
262 // the inner range of the SdPageObject visualisation
263 basegfx::B2DRange maRange
;
266 // constructor and destructor
267 SdPageObjectBasePrimitive(const basegfx::B2DRange
& rRange
);
268 virtual ~SdPageObjectBasePrimitive();
271 const basegfx::B2DRange
& getPageObjectRange() const { return maRange
; }
274 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D
& rPrimitive
) const;
277 SdPageObjectBasePrimitive::SdPageObjectBasePrimitive(const basegfx::B2DRange
& rRange
)
278 : drawinglayer::primitive2d::BasePrimitive2D(),
283 SdPageObjectBasePrimitive::~SdPageObjectBasePrimitive()
287 bool SdPageObjectBasePrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D
& rPrimitive
) const
289 if(drawinglayer::primitive2d::BasePrimitive2D::operator==(rPrimitive
))
291 const SdPageObjectBasePrimitive
& rCompare
= static_cast< const SdPageObjectBasePrimitive
& >(rPrimitive
);
292 return (getPageObjectRange() == rCompare
.getPageObjectRange());
298 ///////////////////////////////////////////////////////////////////////////////////////////////
299 // SdPageObjectPrimitive for selected visualisation
301 class SdPageObjectPageBitmapPrimitive
: public SdPageObjectBasePrimitive
304 // the bitmap containing the PagePreview
308 // method which is to be used to implement the local decomposition of a 2D primitive.
309 virtual Primitive2DSequence
createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const;
312 // constructor and destructor
313 SdPageObjectPageBitmapPrimitive(
314 const basegfx::B2DRange
& rRange
,
315 const BitmapEx
& rBitmapEx
);
316 ~SdPageObjectPageBitmapPrimitive();
319 const BitmapEx
& getBitmapEx() const { return maBitmapEx
; }
322 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D
& rPrimitive
) const;
325 DeclPrimitrive2DIDBlock()
328 Primitive2DSequence
SdPageObjectPageBitmapPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const
330 // add bitmap primitive
331 // to avoid scaling, use the Bitmap pixel size as primitive size
332 basegfx::B2DHomMatrix aBitmapTransform
;
333 const Size
aBitmapSize(getBitmapEx().GetSizePixel());
334 const basegfx::B2DVector
aBitmapSizeLogic(rViewInformation
.getInverseObjectToViewTransformation() *
335 basegfx::B2DVector(aBitmapSize
.getWidth() - 1, aBitmapSize
.getHeight() - 1));
337 // short form for scale and translate transformation
338 aBitmapTransform
.set(0L, 0L, aBitmapSizeLogic
.getX());
339 aBitmapTransform
.set(1L, 1L, aBitmapSizeLogic
.getY());
340 aBitmapTransform
.set(0L, 2L, getPageObjectRange().getMinX());
341 aBitmapTransform
.set(1L, 2L, getPageObjectRange().getMinY());
343 // add a BitmapPrimitive2D to the result
344 const Primitive2DReference
xReference(
345 new drawinglayer::primitive2d::BitmapPrimitive2D(getBitmapEx(), aBitmapTransform
));
346 return Primitive2DSequence(&xReference
, 1);
349 SdPageObjectPageBitmapPrimitive::SdPageObjectPageBitmapPrimitive(
350 const basegfx::B2DRange
& rRange
,
351 const BitmapEx
& rBitmapEx
)
352 : SdPageObjectBasePrimitive(rRange
),
353 maBitmapEx(rBitmapEx
)
357 SdPageObjectPageBitmapPrimitive::~SdPageObjectPageBitmapPrimitive()
361 bool SdPageObjectPageBitmapPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D
& rPrimitive
) const
363 if(SdPageObjectBasePrimitive::operator==(rPrimitive
))
365 const SdPageObjectPageBitmapPrimitive
& rCompare
= static_cast< const SdPageObjectPageBitmapPrimitive
& >(rPrimitive
);
366 return (getBitmapEx() == rCompare
.getBitmapEx());
372 ImplPrimitrive2DIDBlock(SdPageObjectPageBitmapPrimitive
, PRIMITIVE2D_ID_SDPAGEOBJECTPAGEBITMAPPRIMITIVE
)
374 ///////////////////////////////////////////////////////////////////////////////////////////////
375 // SdPageObjectPrimitive for selected visualisation
377 class SdPageObjectSelectPrimitive
: public SdPageObjectBasePrimitive
380 /// Gap between border of page object and inside of selection rectangle.
381 static const sal_Int32 mnSelectionIndicatorOffset
;
383 /// Thickness of the selection rectangle.
384 static const sal_Int32 mnSelectionIndicatorThickness
;
387 // method which is to be used to implement the local decomposition of a 2D primitive.
388 virtual Primitive2DSequence
createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const;
391 // constructor and destructor
392 SdPageObjectSelectPrimitive(const basegfx::B2DRange
& rRange
);
393 ~SdPageObjectSelectPrimitive();
396 DeclPrimitrive2DIDBlock()
399 const sal_Int32
SdPageObjectSelectPrimitive::mnSelectionIndicatorOffset(1);
400 const sal_Int32
SdPageObjectSelectPrimitive::mnSelectionIndicatorThickness(3);
402 Primitive2DSequence
SdPageObjectSelectPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const
404 Primitive2DSequence
xRetval(2);
406 // since old Width/Height calculations always added a single pixel value,
407 // it is necessary to create a inner range which is one display unit less
408 // at the bottom right.
409 const basegfx::B2DVector
aDiscretePixel(rViewInformation
.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
410 const basegfx::B2DRange
aAdaptedInnerRange(
411 getPageObjectRange().getMinX(), getPageObjectRange().getMinY(),
412 getPageObjectRange().getMaxX() - aDiscretePixel
.getX(), getPageObjectRange().getMaxY() - aDiscretePixel
.getY());
414 // PaintSelectionIndicator replacement. Grow by offset first
415 basegfx::B2DRange
aDiscreteOuterRange(aAdaptedInnerRange
);
416 aDiscreteOuterRange
.grow(mnSelectionIndicatorOffset
* aDiscretePixel
.getX());
418 // Remember inner border. Make it one bigger in top left since polygons
419 // do not paint their lower-right corners. Since this is the inner polygon,
420 // the top-left corders are the ones to grow here
421 const basegfx::B2DRange
aDiscreteInnerRange(
422 aDiscreteOuterRange
.getMinimum() + aDiscretePixel
,
423 aDiscreteOuterRange
.getMaximum() - aDiscretePixel
);
425 // grow by line width
426 aDiscreteOuterRange
.grow((mnSelectionIndicatorThickness
- 1) * aDiscretePixel
.getX());
428 // create a PolyPolygon from those ranges. For the outer polygon, round edges by
429 // giving a relative radius to the polygon creator (use mnSelectionIndicatorThickness here, too)
430 const double fPixelFactor(aDiscretePixel
.getX() * (mnSelectionIndicatorThickness
+ 2.5));
431 const double fRelativeRadiusX(fPixelFactor
/ ::std::max(aDiscreteOuterRange
.getWidth(), 1.0));
432 const double fRelativeRadiusY(fPixelFactor
/ ::std::max(aDiscreteOuterRange
.getHeight(), 1.0));
433 basegfx::B2DPolyPolygon aFramePolyPolygon
;
434 const basegfx::B2DPolygon
aRoundedOuterPolygon(basegfx::tools::createPolygonFromRect(aDiscreteOuterRange
, fRelativeRadiusX
, fRelativeRadiusY
));
436 aFramePolyPolygon
.append(aRoundedOuterPolygon
);
437 aFramePolyPolygon
.append(basegfx::tools::createPolygonFromRect(aDiscreteInnerRange
));
439 // add colored PolyPolygon
440 const svtools::ColorConfig aColorConfig
;
441 static bool bTestWithBrightColors(false);
442 const basegfx::BColor
aFrameColor(bTestWithBrightColors
? basegfx::BColor(0,1,0) : Application::GetSettings().GetStyleSettings().GetMenuHighlightColor().getBColor());
444 xRetval
[0] = Primitive2DReference(
445 new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(aFramePolyPolygon
, aFrameColor
));
447 // add aRoundedOuterPolygon again as non-filled line polygon to get the roundungs
449 xRetval
[1] = Primitive2DReference(
450 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aRoundedOuterPolygon
, aFrameColor
));
455 SdPageObjectSelectPrimitive::SdPageObjectSelectPrimitive(const basegfx::B2DRange
& rRange
)
456 : SdPageObjectBasePrimitive(rRange
)
460 SdPageObjectSelectPrimitive::~SdPageObjectSelectPrimitive()
464 ImplPrimitrive2DIDBlock(SdPageObjectSelectPrimitive
, PRIMITIVE2D_ID_SDPAGEOBJECTSELECTPRIMITIVE
)
466 ///////////////////////////////////////////////////////////////////////////////////////////////
467 // SdPageObjectPrimitive for border around bitmap visualisation
469 class SdPageObjectBorderPrimitive
: public SdPageObjectBasePrimitive
472 // method which is to be used to implement the local decomposition of a 2D primitive.
473 virtual Primitive2DSequence
createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const;
476 // constructor and destructor
477 SdPageObjectBorderPrimitive(const basegfx::B2DRange
& rRange
);
478 ~SdPageObjectBorderPrimitive();
481 DeclPrimitrive2DIDBlock()
484 Primitive2DSequence
SdPageObjectBorderPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const
486 // since old Width/Height calculations always added a single pixel value,
487 // it is necessary to create a inner range which is one display unit less
488 // at the bottom right.
489 const basegfx::B2DVector
aDiscretePixel(rViewInformation
.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
490 const basegfx::B2DRange
aAdaptedInnerRange(
491 getPageObjectRange().getMinX(), getPageObjectRange().getMinY(),
492 getPageObjectRange().getMaxX() - aDiscretePixel
.getX(), getPageObjectRange().getMaxY() - aDiscretePixel
.getY());
494 // Paint_Border replacement. (use aBorderColor)
495 static bool bTestWithBrightColors(false);
496 const svtools::ColorConfig aColorConfig
;
497 const basegfx::BColor
aBorderColor(bTestWithBrightColors
? basegfx::BColor(1,0,0) : Color(aColorConfig
.GetColorValue(svtools::FONTCOLOR
).nColor
).getBColor());
499 const Primitive2DReference
xReference(
500 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(basegfx::tools::createPolygonFromRect(aAdaptedInnerRange
), aBorderColor
));
501 return Primitive2DSequence(&xReference
, 1);
504 SdPageObjectBorderPrimitive::SdPageObjectBorderPrimitive(const basegfx::B2DRange
& rRange
)
505 : SdPageObjectBasePrimitive(rRange
)
509 SdPageObjectBorderPrimitive::~SdPageObjectBorderPrimitive()
513 ImplPrimitrive2DIDBlock(SdPageObjectBorderPrimitive
, PRIMITIVE2D_ID_SDPAGEOBJECTBORDERPRIMITIVE
)
515 ///////////////////////////////////////////////////////////////////////////////////////////////
516 // SdPageObjectPrimitive for focus visualisation
518 class SdPageObjectFocusPrimitive
: public SdPageObjectBasePrimitive
521 /// Gap between border of page object and inside of focus rectangle.
522 static const sal_Int32 mnFocusIndicatorOffset
;
523 const bool mbContrastToSelected
;
526 // method which is to be used to implement the local decomposition of a 2D primitive.
527 virtual Primitive2DSequence
createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const;
530 // constructor and destructor
531 SdPageObjectFocusPrimitive(const basegfx::B2DRange
& rRange
, const bool bContrast
);
532 ~SdPageObjectFocusPrimitive();
535 DeclPrimitrive2DIDBlock()
538 const sal_Int32
SdPageObjectFocusPrimitive::mnFocusIndicatorOffset(2);
540 Primitive2DSequence
SdPageObjectFocusPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const
542 Primitive2DSequence
xRetval(2);
544 // since old Width/Height calculations always added a single pixel value,
545 // it is necessary to create a inner range which is one display unit less
546 // at the bottom right.
547 const basegfx::B2DVector
aDiscretePixel(rViewInformation
.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
548 const basegfx::B2DRange
aAdaptedInnerRange(
549 getPageObjectRange().getMinX(), getPageObjectRange().getMinY(),
550 getPageObjectRange().getMaxX() - aDiscretePixel
.getX(), getPageObjectRange().getMaxY() - aDiscretePixel
.getY());
552 // Paint_FocusIndicator replacement. (black and white).
553 // imitate Paint_DottedRectangle: First paint a white rectangle and above it a black dotted one
554 basegfx::B2DRange
aFocusIndicatorRange(aAdaptedInnerRange
);
555 aFocusIndicatorRange
.grow(mnFocusIndicatorOffset
* aDiscretePixel
.getX());
558 const basegfx::B2DPolygon
aIndicatorPolygon(basegfx::tools::createPolygonFromRect(aFocusIndicatorRange
));
560 const StyleSettings
& rStyleSettings(Application::GetSettings().GetStyleSettings());
562 // "background" rectangle
563 const Color
aBackgroundColor(mbContrastToSelected
? rStyleSettings
.GetMenuHighlightColor() : rStyleSettings
.GetWindowColor());
564 xRetval
[0] = Primitive2DReference(
565 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aIndicatorPolygon
, Color(COL_WHITE
).getBColor()));
567 // dotted black rectangle with same geometry
568 ::std::vector
< double > aDotDashArray
;
570 const sal_Int32
nFocusIndicatorWidth (3);
571 aDotDashArray
.push_back(nFocusIndicatorWidth
*aDiscretePixel
.getX());
572 aDotDashArray
.push_back(nFocusIndicatorWidth
* aDiscretePixel
.getX());
574 // prepare line and stroke attributes
575 const Color
aLineColor(mbContrastToSelected
? rStyleSettings
.GetMenuHighlightTextColor() : rStyleSettings
.GetWindowTextColor());
576 const drawinglayer::attribute::LineAttribute
aLineAttribute(aLineColor
.getBColor());
577 const drawinglayer::attribute::StrokeAttribute
aStrokeAttribute(
578 aDotDashArray
, 2.0 * nFocusIndicatorWidth
* aDiscretePixel
.getX());
581 xRetval
[1] = Primitive2DReference(
582 new drawinglayer::primitive2d::PolygonStrokePrimitive2D(aIndicatorPolygon
, aLineAttribute
, aStrokeAttribute
));
587 SdPageObjectFocusPrimitive::SdPageObjectFocusPrimitive(const basegfx::B2DRange
& rRange
, const bool bContrast
)
588 : SdPageObjectBasePrimitive(rRange
),
589 mbContrastToSelected(bContrast
)
593 SdPageObjectFocusPrimitive::~SdPageObjectFocusPrimitive()
597 ImplPrimitrive2DIDBlock(SdPageObjectFocusPrimitive
, PRIMITIVE2D_ID_SDPAGEOBJECTFOCUSPRIMITIVE
)
599 ///////////////////////////////////////////////////////////////////////////////////////////////
600 // SdPageObjectPrimitive for fade effect visualisation
602 class SdPageObjectFadeNameNumberPrimitive
: public SdPageObjectBasePrimitive
605 /// Size of width and height of the fade effect indicator in pixels.
606 static const sal_Int32 mnFadeEffectIndicatorOffset
;
608 /// Size of width and height of the comments indicator in pixels.
609 static const sal_Int32 mnCommentsIndicatorOffset
;
611 /// Gap between border of page object and number rectangle.
612 static const sal_Int32 mnPageNumberOffset
;
614 /// the indicator bitmaps. Static since it is usable outside this primitive
615 /// for size comparisons
616 static BitmapEx
* mpFadeEffectIconBitmap
;
617 static BitmapEx
* mpCommentsIconBitmap
;
619 /// page name, number and needed infos
621 sal_uInt32 mnPageNumber
;
623 Size maPageNumberAreaModelSize
;
626 bool mbShowFadeEffectIcon
: 1;
627 bool mbShowCommentsIcon
: 1;
631 const BitmapEx
& getFadeEffectIconBitmap() const;
632 const BitmapEx
& getCommentsIconBitmap() const;
635 // method which is to be used to implement the local decomposition of a 2D primitive.
636 virtual Primitive2DSequence
createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const;
639 // constructor and destructor
640 SdPageObjectFadeNameNumberPrimitive(
641 const basegfx::B2DRange
& rRange
,
642 const String
& rPageName
,
643 sal_uInt32 nPageNumber
,
644 const Font
& rPageNameFont
,
645 const Size
& rPageNumberAreaModelSize
,
646 bool bShowFadeEffectIcon
,
647 bool bShowCommentsIcon
,
649 ~SdPageObjectFadeNameNumberPrimitive();
652 const String
& getPageName() const { return maPageName
; }
653 sal_uInt32
getPageNumber() const { return mnPageNumber
; }
654 const Font
& getPageNameFont() const { return maPageNameFont
; }
655 const Size
& getPageNumberAreaModelSize() const { return maPageNumberAreaModelSize
; }
656 bool getShowFadeEffectIcon() const { return mbShowFadeEffectIcon
; }
657 bool getShowCommentsIcon() const { return mbShowCommentsIcon
; }
658 bool getExcluded() const { return mbExcluded
; }
661 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D
& rPrimitive
) const;
664 DeclPrimitrive2DIDBlock()
667 const sal_Int32
SdPageObjectFadeNameNumberPrimitive::mnFadeEffectIndicatorOffset(9);
668 const sal_Int32
SdPageObjectFadeNameNumberPrimitive::mnPageNumberOffset(9);
669 BitmapEx
* SdPageObjectFadeNameNumberPrimitive::mpFadeEffectIconBitmap
= 0;
671 const BitmapEx
& SdPageObjectFadeNameNumberPrimitive::getFadeEffectIconBitmap() const
673 if(mpFadeEffectIconBitmap
== NULL
)
675 // prepare FadeEffectIconBitmap on demand
676 const sal_uInt16
nIconId(Application::GetSettings().GetStyleSettings().GetHighContrastMode()
677 ? BMP_FADE_EFFECT_INDICATOR_H
678 : BMP_FADE_EFFECT_INDICATOR
);
679 const BitmapEx
aFadeEffectIconBitmap(IconCache::Instance().GetIcon(nIconId
).GetBitmapEx());
680 const_cast< SdPageObjectFadeNameNumberPrimitive
* >(this)->mpFadeEffectIconBitmap
= new BitmapEx(aFadeEffectIconBitmap
);
683 return *mpFadeEffectIconBitmap
;
686 const sal_Int32
SdPageObjectFadeNameNumberPrimitive::mnCommentsIndicatorOffset(9);
687 BitmapEx
* SdPageObjectFadeNameNumberPrimitive::mpCommentsIconBitmap
= 0;
689 const BitmapEx
& SdPageObjectFadeNameNumberPrimitive::getCommentsIconBitmap() const
691 if(mpCommentsIconBitmap
== NULL
)
693 // prepare CommentsIconBitmap on demand
694 const sal_uInt16
nIconId(Application::GetSettings().GetStyleSettings().GetHighContrastMode()
695 ? BMP_COMMENTS_INDICATOR_H
696 : BMP_COMMENTS_INDICATOR
);
697 const BitmapEx
aCommentsIconBitmap(IconCache::Instance().GetIcon(nIconId
).GetBitmapEx());
698 const_cast< SdPageObjectFadeNameNumberPrimitive
* >(this)->mpCommentsIconBitmap
= new BitmapEx(aCommentsIconBitmap
);
701 return *mpCommentsIconBitmap
;
704 Primitive2DSequence
SdPageObjectFadeNameNumberPrimitive::createLocalDecomposition(const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const
706 const xub_StrLen
nTextLength(getPageName().Len());
707 const sal_uInt32
nCount(
708 (getShowFadeEffectIcon() ? 1 : 0) + // FadeEffect icon
709 (nTextLength
? 1 : 0) + // PageName
710 1 + // PageNumber (always)
711 (getExcluded() ? 2 : 0) // PageNumber crossed out
713 sal_uInt32
nInsert(0);
714 Primitive2DSequence
xRetval(nCount
);
716 // since old Width/Height calculations always added a single pixel value,
717 // it is necessary to create a inner range which is one display unit less
718 // at the bottom right.
719 const basegfx::B2DVector
aDiscretePixel(rViewInformation
.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
720 const basegfx::B2DRange
aAdaptedInnerRange(
721 getPageObjectRange().getMinX(), getPageObjectRange().getMinY(),
722 getPageObjectRange().getMaxX() - aDiscretePixel
.getX(), getPageObjectRange().getMaxY() - aDiscretePixel
.getY());
724 // preapre TextLayouter
725 drawinglayer::primitive2d::TextLayouterDevice aTextLayouter
;
726 aTextLayouter
.setFont(getPageNameFont());
728 // get font attributes
729 basegfx::B2DVector aTextSizeAttribute
;
730 const drawinglayer::primitive2d::FontAttributes
aFontAttributes(
731 drawinglayer::primitive2d::getFontAttributesFromVclFont(
737 // prepare locale; this may need some more information in the future
738 const ::com::sun::star::lang::Locale aLocale
;
740 // prepare font color from System
741 const basegfx::BColor
aFontColor(Application::GetSettings().GetStyleSettings().GetFontColor().getBColor());
743 if(getShowFadeEffectIcon())
745 // prepare fFadeEffect Sizes
746 const basegfx::B2DVector
aFadeEffectBitmapSizeLogic(rViewInformation
.getInverseObjectToViewTransformation() *
748 getFadeEffectIconBitmap().GetSizePixel().getWidth() - 1,
749 getFadeEffectIconBitmap().GetSizePixel().getHeight() - 1));
751 // Paint_FadeEffectIndicator replacement.
752 // create transformation. To avoid bitmap scaling, use bitmap size as size
753 basegfx::B2DHomMatrix aBitmapTransform
;
755 // short form for scale and translate transformation
756 aBitmapTransform
.set(0L, 0L, aFadeEffectBitmapSizeLogic
.getX());
757 aBitmapTransform
.set(1L, 1L, aFadeEffectBitmapSizeLogic
.getY());
758 aBitmapTransform
.set(0L, 2L, aAdaptedInnerRange
.getMinX());
759 aBitmapTransform
.set(1L, 2L, aAdaptedInnerRange
.getMaxY() + ((mnFadeEffectIndicatorOffset
+ 1) * aDiscretePixel
.getX()));
761 xRetval
[nInsert
++] = Primitive2DReference(
762 new drawinglayer::primitive2d::BitmapPrimitive2D(getFadeEffectIconBitmap(), aBitmapTransform
));
767 // prepare fFadeEffect Sizes since it consumes from text size
768 const basegfx::B2DVector
aFadeEffectBitmapSizeLogic(rViewInformation
.getInverseObjectToViewTransformation() *
770 getFadeEffectIconBitmap().GetSizePixel().getWidth() - 1,
771 getFadeEffectIconBitmap().GetSizePixel().getHeight() - 1));
773 // Paint_PageName replacement. Get text size
774 const double fTextWidth(aTextLayouter
.getTextWidth(getPageName(), 0, nTextLength
));
775 const double fTextHeight(getPageNameFont().GetHeight());
776 const double fFadeEffectWidth(aFadeEffectBitmapSizeLogic
.getX() * 2.0);
777 const double fFadeEffectTextGap(((mnFadeEffectIndicatorOffset
+ 2) * aDiscretePixel
.getX()));
778 String
aPageName(getPageName());
780 // calculate text start position
782 aAdaptedInnerRange
.getMaxX()
784 + (aDiscretePixel
.getX() * 3.0));
785 const double fStartY(
786 aAdaptedInnerRange
.getMaxY()
788 + fFadeEffectTextGap
);
789 const bool bNeedClipping(fStartX
< aAdaptedInnerRange
.getMinX() + fFadeEffectWidth
);
791 // if text is too big, clip it
795 fStartX
= aAdaptedInnerRange
.getMinX() + fFadeEffectWidth
;
797 // find out how many characters to use
798 const double fAvailableLength(aAdaptedInnerRange
.getWidth() - fFadeEffectWidth
);
799 static const String
aThreePoints(String::CreateFromAscii("..."));
800 const double fWidthThreePoints(aTextLayouter
.getTextWidth(aThreePoints
, 0, aThreePoints
.Len()));
803 for(; a
< (xub_StrLen
)nTextLength
; a
++)
805 const double fSnippetLength(aTextLayouter
.getTextWidth(aPageName
, 0, a
));
807 if(fSnippetLength
+ fWidthThreePoints
> fAvailableLength
)
814 aPageName
= String(aPageName
, 0, a
- 1);
815 aPageName
+= aThreePoints
;
819 basegfx::B2DHomMatrix aTextMatrix
;
821 aTextMatrix
.set(0, 0, aTextSizeAttribute
.getX());
822 aTextMatrix
.set(1, 1, aTextSizeAttribute
.getY());
823 aTextMatrix
.set(0, 2, fStartX
);
824 aTextMatrix
.set(1, 2, fStartY
);
826 // prepare DXTextArray (can be empty one)
827 const ::std::vector
< double > aDXArray
;
829 // create Text primitive and add to target
830 xRetval
[nInsert
++] = Primitive2DReference(
831 new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
843 // Paint_PageNumber replacement. Get the range where it shall be centered and prepare the string
844 const double fLeft(aAdaptedInnerRange
.getMinX() - (mnPageNumberOffset
* aDiscretePixel
.getX()) - getPageNumberAreaModelSize().Width());
845 const double fTop(aAdaptedInnerRange
.getMinY());
846 const basegfx::B2DRange
aNumberRange(fLeft
, fTop
,
847 fLeft
+ getPageNumberAreaModelSize().Width(), fTop
+ getPageNumberAreaModelSize().Height());
848 const String
aPageNumber(String::CreateFromInt32(getPageNumber()));
849 const xub_StrLen
nNumberLen(aPageNumber
.Len());
852 const double fTextWidth(aTextLayouter
.getTextWidth(aPageNumber
, 0, nNumberLen
));
853 const double fTextHeight(getPageNameFont().GetHeight());
855 // get text start postion
856 const double fStartX(aNumberRange
.getCenterX() - (fTextWidth
/ 2.0));
857 const double fStartY(aNumberRange
.getMinY() + fTextHeight
+ aDiscretePixel
.getX());
860 basegfx::B2DHomMatrix aTextMatrix
;
862 aTextMatrix
.set(0, 0, aTextSizeAttribute
.getX());
863 aTextMatrix
.set(1, 1, aTextSizeAttribute
.getY());
864 aTextMatrix
.set(0, 2, fStartX
);
865 aTextMatrix
.set(1, 2, fStartY
);
867 // prepare DXTextArray (can be empty one)
868 const ::std::vector
< double > aDXArray
;
870 // create Text primitive
871 xRetval
[nInsert
++] = Primitive2DReference(
872 new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
884 // create a box with strikethrough from top left to bottom right
885 const basegfx::BColor
aActiveColor(Application::GetSettings().GetStyleSettings().GetActiveColor().getBColor());
886 basegfx::B2DPolygon aStrikethrough
;
888 aStrikethrough
.append(aNumberRange
.getMinimum());
889 aStrikethrough
.append(aNumberRange
.getMaximum());
891 xRetval
[nInsert
++] = Primitive2DReference(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
892 basegfx::tools::createPolygonFromRect(aNumberRange
), aActiveColor
));
894 xRetval
[nInsert
++] = Primitive2DReference(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
895 aStrikethrough
, aActiveColor
));
902 SdPageObjectFadeNameNumberPrimitive::SdPageObjectFadeNameNumberPrimitive(
903 const basegfx::B2DRange
& rRange
,
904 const String
& rPageName
,
905 sal_uInt32 nPageNumber
,
906 const Font
& rPageNameFont
,
907 const Size
& rPageNumberAreaModelSize
,
908 bool bShowFadeEffectIcon
,
909 bool bShowCommentsIcon
,
911 : SdPageObjectBasePrimitive(rRange
),
912 maPageName(rPageName
),
913 mnPageNumber(nPageNumber
),
914 maPageNameFont(rPageNameFont
),
915 maPageNumberAreaModelSize(rPageNumberAreaModelSize
),
916 mbShowFadeEffectIcon(bShowFadeEffectIcon
),
917 mbShowCommentsIcon(bShowCommentsIcon
),
918 mbExcluded(bExcluded
)
922 SdPageObjectFadeNameNumberPrimitive::~SdPageObjectFadeNameNumberPrimitive()
926 bool SdPageObjectFadeNameNumberPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D
& rPrimitive
) const
928 if(SdPageObjectBasePrimitive::operator==(rPrimitive
))
930 const SdPageObjectFadeNameNumberPrimitive
& rCompare
= static_cast< const SdPageObjectFadeNameNumberPrimitive
& >(rPrimitive
);
932 return (getPageName() == rCompare
.getPageName()
933 && getPageNumber() == rCompare
.getPageNumber()
934 && getPageNameFont() == rCompare
.getPageNameFont()
935 && getPageNumberAreaModelSize() == rCompare
.getPageNumberAreaModelSize()
936 && getShowFadeEffectIcon() == rCompare
.getShowFadeEffectIcon()
937 && getExcluded() == rCompare
.getExcluded());
943 ImplPrimitrive2DIDBlock(SdPageObjectFadeNameNumberPrimitive
, PRIMITIVE2D_ID_SDPAGEOBJECTFADENAMENUMBERPRIMITIVE
)
945 ///////////////////////////////////////////////////////////////////////////////////////////////
946 // createPrimitive2DSequence
948 // This method will replace the whole painting mechanism. Task is no longer to paint stuff to an OutDev,
949 // but to provide the necessary geometrical information using primitives.
951 Primitive2DSequence
PageObjectViewObjectContact::createPrimitive2DSequence(const sdr::contact::DisplayInfo
& rDisplayInfo
) const
953 // OutputDevice* pDevice = rDisplayInfo.GetDIOutputDevice();
954 OutputDevice
* pDevice
= GetObjectContact().TryToGetOutputDevice();
956 // get primitive vector from parent class. Do remember the contents for later use; this
957 // is done to create the page content renderer (see PagePrimitiveExtractor in svx) at the
958 // original object and to setup the draw hierarchy there so that changes to VCs of displayed
959 // objects will lead to InvalidatePartOfView-calls which will be forwarded from the helper-OC
960 // to this VOC in calling a ActionChanged().
962 // This already produces the displayable page content as a primitive sequence, complete with
963 // embedding in the page visualizer, clipping if needed and object and aspect ratio
964 // preparations. It would thus be the base for creating the cached visualisation, too,
965 // by just painting extactly this primitive sequence.
967 // Currently, this slows down PagePane display heavily. Reason is that the current mechanism
968 // to react on a SdrObject change in an edit view is to react on the ModelChange and to completely
969 // reset the PagePane (delete SdrPageObjs, re-create and layout them). This works, but kicks
970 // the complete sequence of primitive creation at VOCs and VCs and their buffering out of
971 // memory each time. So there are two choices:
973 // 1, disable getting the sequence of primtives
974 // -> invalidate uses ModelChange
975 // -> cache repaint uses complete view creation and repainting
977 // 2, create and use the sequence of primitives
978 // -> invalidate would not need ModelChange, no destroy/recreate of SdrObjects, no rearrange,
979 // the invalidate and the following repaint would exactly update the SdrPages involved and
980 // use the DrawingLayer provided ActionChanged() invalidations over the VOCs and VCs
981 // -> cache repaint could use the here offered sequence of primitives to re-create the bitmap
982 // (just hand over the local member to the cache)
984 // For the moment i will use (1) and disable primitive creation for SdrPageObj contents here
986 // const_cast< PageObjectViewObjectContact* >(this)->mxCurrentPageContents = ViewObjectContactOfPageObj::createPrimitive2DSequence(rDisplayInfo);
988 // assert when this call is issued indirectly from the destructor of
989 // this instance. This is not allowed and needs to be looked at
993 OSL_ENSURE(false, "Higher call inside PageObjectViewObjectContact in destructor (!)");
997 // Check if buffering can and shall be done.
999 && !GetObjectContact().isOutputToPrinter()
1000 && !GetObjectContact().isOutputToRecordingMetaFile()
1003 // get inner and outer logic rectangles. Use model data directly for creation. Do NOT use getBoundRect()/
1004 // getSnapRect() functionality; these will use the sequence of primitives in the long run itself. SdrPageObj
1005 // is a SdrObject, so use SdrObject::aOutRect as model data. Access using GetLastBoundRect() to not execute anything
1006 PageObjectViewContact
& rPaObVOC(static_cast< PageObjectViewContact
& >(GetViewContact()));
1007 const Rectangle
aInnerLogic(rPaObVOC
.GetPageObject().GetLastBoundRect());
1009 // get BitmapEx from cache. Do exactly the same as Paint_Preview() to avoid a repaint loop
1010 // caused by slightly different pixel sizes of what the cache sees as pixel size and what is
1011 // calculated here in discrete coordinates. This includes to not use LogicToPiyel on the Rectangle,
1012 // but to do the same as the GetBoundingBox() implementation
1013 const Rectangle
aInnerPixel(Rectangle(pDevice
->LogicToPixel(aInnerLogic
.TopLeft()), pDevice
->LogicToPixel(aInnerLogic
.GetSize())));
1014 BitmapEx
aBitmapEx(const_cast< PageObjectViewObjectContact
* >(this)->GetPreview(rDisplayInfo
, aInnerPixel
));
1016 // prepare inner range
1017 const basegfx::B2DRange
aInnerRange(aInnerLogic
.Left(), aInnerLogic
.Top(), aInnerLogic
.Right(), aInnerLogic
.Bottom());
1019 // provide default parameters
1022 sal_uInt32
nPageNumber(0);
1023 Size aPageNumberAreaModelSize
;
1024 bool bShowFadeEffectIcon(false);
1025 bool bShowCommentsIcon(false);
1026 bool bExcluded(false);
1030 const SdPage
* pPage
= static_cast<const SdPage
*>(GetPage());
1032 // decide if fade effect indicator will be painted
1033 if(pPage
->getTransitionType() > 0)
1035 bShowFadeEffectIcon
= true;
1038 bShowCommentsIcon
= !pPage
->getAnnotations().empty();
1040 // prepare PageName, PageNumber, font and AreaModelSize
1041 aPageName
= pPage
->GetName();
1042 aPageNameFont
= *FontProvider::Instance().GetFont(*pDevice
);
1043 nPageNumber
= ((pPage
->GetPageNum() - 1) / 2) + 1;
1044 aPageNumberAreaModelSize
= GetPageDescriptor()->GetPageNumberAreaModelSize();
1046 if(!aPageName
.Len())
1048 aPageName
= String(SdResId(STR_PAGE
));
1049 aPageName
+= String::CreateFromInt32(nPageNumber
);
1052 // decide if page is excluded
1053 bExcluded
= pPage
->IsExcluded();
1056 // create specialized primitives for focus, select and PagePreview itself
1057 const bool bCreateBitmap(!aBitmapEx
.IsEmpty());
1058 const bool bCreateFocused(GetPageDescriptor()->IsFocused());
1059 const bool bCreateSelected(GetPageDescriptor()->IsSelected());
1061 const sal_uInt32
nCount(
1062 (bCreateBitmap
? 1 : 0) + // bitmap itself
1063 1 + // border around bitmap (always)
1064 1 + // FadeEffect, PageName and PageNumber visualisation (always)
1065 (bCreateFocused
? 1 : 0) + // create focused
1066 (bCreateSelected
? 1 : 0) // create selected
1068 sal_uInt32
nInsert(0);
1069 Primitive2DSequence
xRetval(nCount
);
1073 // add selection indicator if used
1074 xRetval
[nInsert
++] = Primitive2DReference(new SdPageObjectPageBitmapPrimitive(aInnerRange
, aBitmapEx
));
1079 // add border (always)
1080 xRetval
[nInsert
++] = Primitive2DReference(new SdPageObjectBorderPrimitive(aInnerRange
));
1085 // add fade effext, page name and number if used
1086 xRetval
[nInsert
++] = Primitive2DReference(new SdPageObjectFadeNameNumberPrimitive(
1091 aPageNumberAreaModelSize
,
1092 bShowFadeEffectIcon
,
1099 // add selection indicator if used
1100 xRetval
[nInsert
++] = Primitive2DReference(new SdPageObjectSelectPrimitive(aInnerRange
));
1105 // add focus indicator if used
1106 xRetval
[nInsert
++] = Primitive2DReference(new SdPageObjectFocusPrimitive(aInnerRange
, bCreateSelected
));
1113 // Call parent. Output to printer or metafile will use vector data, not cached bitmaps
1114 return ViewObjectContactOfPageObj::createPrimitive2DSequence(rDisplayInfo
);
1118 BitmapEx
PageObjectViewObjectContact::CreatePreview (const DisplayInfo
& /*rDisplayInfo*/)
1120 const SdPage
* pPage
= static_cast<const SdPage
*>(GetPage());
1121 OutputDevice
* pDevice
= GetObjectContact().TryToGetOutputDevice();
1125 Rectangle
aPreviewPixelBox (GetBoundingBox(*pDevice
,PreviewBoundingBox
,PixelCoordinateSystem
));
1127 PreviewRenderer
aRenderer (pDevice
);
1128 Image
aPreview (aRenderer
.RenderPage(
1130 aPreviewPixelBox
.GetSize(),
1133 return aPreview
.GetBitmapEx();
1144 BitmapEx
PageObjectViewObjectContact::GetPreview (
1145 const DisplayInfo
& rDisplayInfo
,
1146 const Rectangle
& rNewSizePixel
)
1152 // assert when this call is issued indirectly from the destructor of
1153 // this instance. This is not allowed and needs to be looked at
1154 OSL_ENSURE(!mbInDestructor
, "Higher call inside PageObjectViewObjectContact in destructor (!)");
1156 if (!mbInDestructor
)
1158 if (mpCache
!= NULL
)
1160 aBitmap
= mpCache
->GetPreviewBitmap(
1162 rNewSizePixel
.GetSize());
1163 mpCache
->SetPreciousFlag(GetPage(), true);
1166 aBitmap
= CreatePreview(rDisplayInfo
);
1169 catch (const ::com::sun::star::uno::Exception
&)
1171 OSL_TRACE("PageObjectViewObjectContact::GetPreview: caught exception");
1180 const SdrPage
* PageObjectViewObjectContact::GetPage (void) const
1182 return static_cast<PageObjectViewContact
&>(GetViewContact()).GetPage();
1188 void PageObjectViewObjectContact::ActionChanged (void)
1190 // Even when we are called from destructor we still have to invalide
1191 // the preview bitmap in the cache.
1192 const SdrPage
* pPage
= GetPage();
1193 SdDrawDocument
* pDocument
= dynamic_cast<SdDrawDocument
*>(pPage
->GetModel());
1194 if (mpCache
!=NULL
&& pPage
!=NULL
&& pDocument
!=NULL
)
1196 cache::PageCacheManager::Instance()->InvalidatePreviewBitmap(
1197 pDocument
->getUnoModel(),
1202 ViewObjectContactOfPageObj::ActionChanged();
1205 //////////////////////////////////////////////////////////////////////////////
1206 // helper MouseOverEffectPrimitive
1208 // Used to allow view-dependent primitive definition. For that purpose, the
1209 // initially created primitive (here: in createMouseOverEffectPrimitive2DSequence())
1210 // always has to be view-independent, but the decomposition is made view-dependent.
1211 // Very simple primitive which just remembers the discrete data and applies
1212 // it at decomposition time.
1214 class MouseOverEffectPrimitive
: public drawinglayer::primitive2d::BasePrimitive2D
1217 basegfx::B2DRange maLogicRange
;
1218 sal_uInt32 mnDiscreteOffset
;
1219 sal_uInt32 mnDiscreteWidth
;
1220 basegfx::BColor maRGBColor
;
1223 virtual drawinglayer::primitive2d::Primitive2DSequence
createLocalDecomposition(
1224 const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const;
1227 MouseOverEffectPrimitive(
1228 const basegfx::B2DRange
& rLogicRange
,
1229 sal_uInt32 nDiscreteOffset
,
1230 sal_uInt32 nDiscreteWidth
,
1231 const basegfx::BColor
& rRGBColor
)
1232 : drawinglayer::primitive2d::BasePrimitive2D(),
1233 maLogicRange(rLogicRange
),
1234 mnDiscreteOffset(nDiscreteOffset
),
1235 mnDiscreteWidth(nDiscreteWidth
),
1236 maRGBColor(rRGBColor
)
1240 const basegfx::B2DRange
& getLogicRange() const { return maLogicRange
; }
1241 sal_uInt32
getDiscreteOffset() const { return mnDiscreteOffset
; }
1242 sal_uInt32
getDiscreteWidth() const { return mnDiscreteWidth
; }
1243 const basegfx::BColor
& getRGBColor() const { return maRGBColor
; }
1245 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D
& rPrimitive
) const;
1247 DeclPrimitrive2DIDBlock()
1250 drawinglayer::primitive2d::Primitive2DSequence
MouseOverEffectPrimitive::createLocalDecomposition(
1251 const drawinglayer::geometry::ViewInformation2D
& rViewInformation
) const
1253 // get logic sizes in object coordinate system
1254 const double fDiscreteWidth((rViewInformation
.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
1255 const double fOffset(fDiscreteWidth
* getDiscreteOffset());
1256 const double fWidth(fDiscreteWidth
* getDiscreteWidth());
1258 // create range (one pixel less to get a good fitting)
1259 basegfx::B2DRange
aRange(
1260 getLogicRange().getMinimum(),
1261 getLogicRange().getMaximum() - basegfx::B2DTuple(fDiscreteWidth
, fDiscreteWidth
));
1264 aRange
.grow(fOffset
- (fWidth
* 0.5));
1266 // create fat line with parameters. The formerly hand-painted edge
1267 // roundings will now be done using rounded edges of this fat line
1268 const basegfx::B2DPolygon
aPolygon(basegfx::tools::createPolygonFromRect(aRange
));
1269 const drawinglayer::attribute::LineAttribute
aLineAttribute(getRGBColor(), fWidth
);
1270 const drawinglayer::primitive2d::Primitive2DReference
xReference(
1271 new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
1275 return drawinglayer::primitive2d::Primitive2DSequence(&xReference
, 1);
1278 bool MouseOverEffectPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D
& rPrimitive
) const
1280 if(drawinglayer::primitive2d::BasePrimitive2D::operator==(rPrimitive
))
1282 const MouseOverEffectPrimitive
& rCompare
= static_cast< const MouseOverEffectPrimitive
& >(rPrimitive
);
1284 return (getLogicRange() == rCompare
.getLogicRange()
1285 && getDiscreteOffset() == rCompare
.getDiscreteOffset()
1286 && getDiscreteWidth() == rCompare
.getDiscreteWidth()
1287 && getRGBColor() == rCompare
.getRGBColor());
1293 ImplPrimitrive2DIDBlock(MouseOverEffectPrimitive
, PRIMITIVE2D_ID_SDMOUSEOVEREFFECTPRIMITIVE
)
1295 //////////////////////////////////////////////////////////////////////////////
1297 drawinglayer::primitive2d::Primitive2DSequence
PageObjectViewObjectContact::createMouseOverEffectPrimitive2DSequence()
1299 drawinglayer::primitive2d::Primitive2DSequence aRetval
;
1301 if(GetPageDescriptor()->IsSelected() && mpProperties
.get() && mpProperties
->IsShowSelection())
1303 // When the selection frame is visualized the mouse over frame is not
1304 // visible and does not have to be created.
1308 const PageObjectViewContact
& rPaObVOC(static_cast<PageObjectViewContact
&>(GetViewContact()));
1309 const Rectangle
aBoundingBox(rPaObVOC
.GetPageObject().GetLastBoundRect());
1310 const basegfx::B2DRange
aLogicRange(aBoundingBox
.Left(), aBoundingBox
.Top(), aBoundingBox
.Right(), aBoundingBox
.Bottom());
1311 const basegfx::BColor
aSelectionColor(mpProperties
->GetSelectionColor().getBColor());
1312 const drawinglayer::primitive2d::Primitive2DReference
aReference(
1313 new MouseOverEffectPrimitive(
1315 mnMouseOverEffectOffset
,
1316 mnMouseOverEffectThickness
,
1319 aRetval
= drawinglayer::primitive2d::Primitive2DSequence(&aReference
, 1);
1328 SvBorder
PageObjectViewObjectContact::CalculatePageModelBorder (
1329 OutputDevice
* pDevice
,
1332 SvBorder aModelBorder
;
1334 if (pDevice
!= NULL
)
1336 // 1. Initialize the border with the values that do not depend on
1338 Size
aTopLeftBorders (pDevice
->PixelToLogic (Size (
1339 mnPageNumberOffset
+1,
1340 mnSelectionIndicatorOffset
+ mnSelectionIndicatorThickness
)));
1341 Size
aBottomRightBorders (pDevice
->PixelToLogic (Size (
1342 mnSelectionIndicatorOffset
+ mnSelectionIndicatorThickness
,
1343 mnFadeEffectIndicatorOffset
)));
1344 aModelBorder
= SvBorder (
1345 aTopLeftBorders
.Width(),
1346 aTopLeftBorders
.Height(),
1347 aBottomRightBorders
.Width(),
1348 aBottomRightBorders
.Height());
1351 // 2. Add the device dependent values.
1353 // Calculate the area of the page number.
1354 Size
aPageNumberModelSize (
1355 CalculatePageNumberAreaModelSize (pDevice
, nPageCount
));
1357 // Update the border.
1358 aModelBorder
.Left() += aPageNumberModelSize
.Width();
1359 // The height of the page number area is the same as the height of
1360 // the page name area.
1361 aModelBorder
.Bottom() += aPageNumberModelSize
.Height();
1364 return aModelBorder
;
1370 Size
PageObjectViewObjectContact::CalculatePageNumberAreaModelSize (
1371 OutputDevice
* pDevice
,
1374 // Set the correct font.
1375 Font
aOriginalFont (pDevice
->GetFont());
1376 pDevice
->SetFont(*FontProvider::Instance().GetFont(*pDevice
));
1378 String sPageNumberTemplate
;
1379 if (nPageCount
< 10)
1380 sPageNumberTemplate
= String::CreateFromAscii("9");
1381 else if (nPageCount
< 100)
1382 sPageNumberTemplate
= String::CreateFromAscii("99");
1383 else if (nPageCount
< 200)
1384 // Just for the case that 1 is narrower than 9.
1385 sPageNumberTemplate
= String::CreateFromAscii("199");
1386 else if (nPageCount
< 1000)
1387 sPageNumberTemplate
= String::CreateFromAscii("999");
1389 sPageNumberTemplate
= String::CreateFromAscii("9999");
1390 // More then 9999 pages are not handled.
1393 pDevice
->GetTextWidth (sPageNumberTemplate
),
1394 pDevice
->GetTextHeight ());
1396 pDevice
->SetFont (aOriginalFont
);
1404 model::SharedPageDescriptor
1405 PageObjectViewObjectContact::GetPageDescriptor (void) const
1407 PageObjectViewContact
& rViewContact (
1408 static_cast<PageObjectViewContact
&>(GetViewContact()));
1409 PageObject
& rPageObject (
1410 static_cast<PageObject
&>(rViewContact
.GetPageObject()));
1411 return rPageObject
.GetDescriptor();
1416 } } } // end of namespace ::sd::slidesorter::view