merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / slidesorter / view / SlsPageObjectViewObjectContact.cxx
bloba5d861a86a7b6008690cea44da8255f5e3165cb4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SlsPageObjectViewObjectContact.cxx,v $
10 * $Revision: 1.23 $
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"
47 #include "sdpage.hxx"
48 #include "sdresid.hxx"
49 #include "glob.hrc"
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(),
94 mpCache(rpCache),
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();
116 if(pPage)
118 mpCache->ReleasePreviewBitmap(GetPage());
126 void PageObjectViewObjectContact::SetCache (const ::boost::shared_ptr<cache::PageCache>& rpCache)
128 mpCache = 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);
145 switch(eType)
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();
154 break;
156 case PreviewBoundingBox:
158 // The aBoundingBox already has the right value.
159 break;
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();
169 break;
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();
179 break;
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();
189 break;
191 case PageNumberBoundingBox:
193 Size aModelOffset = rDevice.PixelToLogic(Size(mnPageNumberOffset,mnPageNumberOffset));
194 Size aNumberSize (GetPageDescriptor()->GetPageNumberAreaModelSize());
195 aBoundingBox = Rectangle (
196 Point (
197 aBoundingBox.Left() - aModelOffset.Width() - aNumberSize.Width(),
198 aBoundingBox.Top()),
199 aNumberSize);
200 break;
203 case NameBoundingBox:
204 break;
206 case FadeEffectIndicatorBoundingBox:
207 Size aModelOffset = rDevice.PixelToLogic(Size (0, mnFadeEffectIndicatorOffset));
208 // Flush left just outside the selection rectangle.
209 aBoundingBox = Rectangle (
210 Point (
211 aBoundingBox.Left(),
212 aBoundingBox.Bottom() + aModelOffset.Height()
214 rDevice.PixelToLogic (
215 IconCache::Instance().GetIcon(BMP_FADE_EFFECT_INDICATOR).GetSizePixel())
217 break;
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()));
227 else
228 aBoundingBox = Rectangle(
229 rDevice.LogicToPixel(aBoundingBox.TopLeft()),
230 rDevice.LogicToPixel(aBoundingBox.GetSize()));
232 return aBoundingBox;
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
257 // is pure virtual
259 class SdPageObjectBasePrimitive : public drawinglayer::primitive2d::BasePrimitive2D
261 private:
262 // the inner range of the SdPageObject visualisation
263 basegfx::B2DRange maRange;
265 public:
266 // constructor and destructor
267 SdPageObjectBasePrimitive(const basegfx::B2DRange& rRange);
268 virtual ~SdPageObjectBasePrimitive();
270 // data access
271 const basegfx::B2DRange& getPageObjectRange() const { return maRange; }
273 // compare operator
274 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
277 SdPageObjectBasePrimitive::SdPageObjectBasePrimitive(const basegfx::B2DRange& rRange)
278 : drawinglayer::primitive2d::BasePrimitive2D(),
279 maRange(rRange)
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());
295 return false;
298 ///////////////////////////////////////////////////////////////////////////////////////////////
299 // SdPageObjectPrimitive for selected visualisation
301 class SdPageObjectPageBitmapPrimitive : public SdPageObjectBasePrimitive
303 private:
304 // the bitmap containing the PagePreview
305 BitmapEx maBitmapEx;
307 protected:
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;
311 public:
312 // constructor and destructor
313 SdPageObjectPageBitmapPrimitive(
314 const basegfx::B2DRange& rRange,
315 const BitmapEx& rBitmapEx);
316 ~SdPageObjectPageBitmapPrimitive();
318 // data access
319 const BitmapEx& getBitmapEx() const { return maBitmapEx; }
321 // compare operator
322 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
324 // provide unique ID
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());
369 return false;
372 ImplPrimitrive2DIDBlock(SdPageObjectPageBitmapPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTPAGEBITMAPPRIMITIVE)
374 ///////////////////////////////////////////////////////////////////////////////////////////////
375 // SdPageObjectPrimitive for selected visualisation
377 class SdPageObjectSelectPrimitive : public SdPageObjectBasePrimitive
379 private:
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;
386 protected:
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;
390 public:
391 // constructor and destructor
392 SdPageObjectSelectPrimitive(const basegfx::B2DRange& rRange);
393 ~SdPageObjectSelectPrimitive();
395 // provide unique ID
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
448 // painted correctly
449 xRetval[1] = Primitive2DReference(
450 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aRoundedOuterPolygon, aFrameColor));
452 return xRetval;
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
471 protected:
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;
475 public:
476 // constructor and destructor
477 SdPageObjectBorderPrimitive(const basegfx::B2DRange& rRange);
478 ~SdPageObjectBorderPrimitive();
480 // provide unique ID
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
520 private:
521 /// Gap between border of page object and inside of focus rectangle.
522 static const sal_Int32 mnFocusIndicatorOffset;
523 const bool mbContrastToSelected;
525 protected:
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;
529 public:
530 // constructor and destructor
531 SdPageObjectFocusPrimitive(const basegfx::B2DRange& rRange, const bool bContrast);
532 ~SdPageObjectFocusPrimitive();
534 // provide unique ID
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());
557 // create polygon
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));
584 return xRetval;
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
604 private:
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
620 String maPageName;
621 sal_uInt32 mnPageNumber;
622 Font maPageNameFont;
623 Size maPageNumberAreaModelSize;
625 // bitfield
626 bool mbShowFadeEffectIcon : 1;
627 bool mbShowCommentsIcon : 1;
628 bool mbExcluded : 1;
630 // private helpers
631 const BitmapEx& getFadeEffectIconBitmap() const;
632 const BitmapEx& getCommentsIconBitmap() const;
634 protected:
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;
638 public:
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,
648 bool bExcluded);
649 ~SdPageObjectFadeNameNumberPrimitive();
651 // data access
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; }
660 // compare operator
661 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
663 // provide unique ID
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(
732 aTextSizeAttribute,
733 getPageNameFont(),
734 false,
735 false));
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() *
747 basegfx::B2DVector(
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));
765 if(nTextLength)
767 // prepare fFadeEffect Sizes since it consumes from text size
768 const basegfx::B2DVector aFadeEffectBitmapSizeLogic(rViewInformation.getInverseObjectToViewTransformation() *
769 basegfx::B2DVector(
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
781 double fStartX(
782 aAdaptedInnerRange.getMaxX()
783 - fTextWidth
784 + (aDiscretePixel.getX() * 3.0));
785 const double fStartY(
786 aAdaptedInnerRange.getMaxY()
787 + fTextHeight
788 + fFadeEffectTextGap);
789 const bool bNeedClipping(fStartX < aAdaptedInnerRange.getMinX() + fFadeEffectWidth);
791 // if text is too big, clip it
792 if(bNeedClipping)
794 // new left start
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()));
801 xub_StrLen a(1);
803 for(; a < (xub_StrLen)nTextLength; a++)
805 const double fSnippetLength(aTextLayouter.getTextWidth(aPageName, 0, a));
807 if(fSnippetLength + fWidthThreePoints > fAvailableLength)
809 break;
813 // build new string
814 aPageName = String(aPageName, 0, a - 1);
815 aPageName += aThreePoints;
818 // fill text matrix
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(
832 aTextMatrix,
833 aPageName,
835 aPageName.Len(),
836 aDXArray,
837 aFontAttributes,
838 aLocale,
839 aFontColor));
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());
851 // Get text size
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());
859 // fill text matrix
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(
873 aTextMatrix,
874 aPageNumber,
876 nNumberLen,
877 aDXArray,
878 aFontAttributes,
879 aLocale,
880 aFontColor));
882 if(getExcluded())
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));
899 return xRetval;
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,
910 bool bExcluded)
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());
940 return false;
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
990 #ifdef DBG_UTIL
991 if(mbInDestructor)
993 OSL_ENSURE(false, "Higher call inside PageObjectViewObjectContact in destructor (!)");
995 #endif
997 // Check if buffering can and shall be done.
998 if (pDevice != NULL
999 && !GetObjectContact().isOutputToPrinter()
1000 && !GetObjectContact().isOutputToRecordingMetaFile()
1001 && !mbInDestructor)
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
1020 String aPageName;
1021 Font aPageNameFont;
1022 sal_uInt32 nPageNumber(0);
1023 Size aPageNumberAreaModelSize;
1024 bool bShowFadeEffectIcon(false);
1025 bool bShowCommentsIcon(false);
1026 bool bExcluded(false);
1028 if(GetPage())
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);
1071 if(bCreateBitmap)
1073 // add selection indicator if used
1074 xRetval[nInsert++] = Primitive2DReference(new SdPageObjectPageBitmapPrimitive(aInnerRange, aBitmapEx));
1077 if(true)
1079 // add border (always)
1080 xRetval[nInsert++] = Primitive2DReference(new SdPageObjectBorderPrimitive(aInnerRange));
1083 if(true)
1085 // add fade effext, page name and number if used
1086 xRetval[nInsert++] = Primitive2DReference(new SdPageObjectFadeNameNumberPrimitive(
1087 aInnerRange,
1088 aPageName,
1089 nPageNumber,
1090 aPageNameFont,
1091 aPageNumberAreaModelSize,
1092 bShowFadeEffectIcon,
1093 bShowCommentsIcon,
1094 bExcluded));
1097 if(bCreateSelected)
1099 // add selection indicator if used
1100 xRetval[nInsert++] = Primitive2DReference(new SdPageObjectSelectPrimitive(aInnerRange));
1103 if(bCreateFocused)
1105 // add focus indicator if used
1106 xRetval[nInsert++] = Primitive2DReference(new SdPageObjectFocusPrimitive(aInnerRange, bCreateSelected));
1109 return xRetval;
1111 else
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();
1123 if(pDevice)
1125 Rectangle aPreviewPixelBox (GetBoundingBox(*pDevice,PreviewBoundingBox,PixelCoordinateSystem));
1127 PreviewRenderer aRenderer (pDevice);
1128 Image aPreview (aRenderer.RenderPage(
1129 pPage,
1130 aPreviewPixelBox.GetSize(),
1131 String()));
1133 return aPreview.GetBitmapEx();
1135 else
1137 return BitmapEx();
1144 BitmapEx PageObjectViewObjectContact::GetPreview (
1145 const DisplayInfo& rDisplayInfo,
1146 const Rectangle& rNewSizePixel)
1148 BitmapEx aBitmap;
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(
1161 GetPage(),
1162 rNewSizePixel.GetSize());
1163 mpCache->SetPreciousFlag(GetPage(), true);
1165 else
1166 aBitmap = CreatePreview(rDisplayInfo);
1169 catch (const ::com::sun::star::uno::Exception&)
1171 OSL_TRACE("PageObjectViewObjectContact::GetPreview: caught exception");
1174 return aBitmap;
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(),
1198 GetPage());
1201 // call parent
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
1216 private:
1217 basegfx::B2DRange maLogicRange;
1218 sal_uInt32 mnDiscreteOffset;
1219 sal_uInt32 mnDiscreteWidth;
1220 basegfx::BColor maRGBColor;
1222 protected:
1223 virtual drawinglayer::primitive2d::Primitive2DSequence createLocalDecomposition(
1224 const drawinglayer::geometry::ViewInformation2D& rViewInformation) const;
1226 public:
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)
1239 // data access
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));
1263 // grow range
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(
1272 aPolygon,
1273 aLineAttribute));
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());
1290 return false;
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.
1306 else
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(
1314 aLogicRange,
1315 mnMouseOverEffectOffset,
1316 mnMouseOverEffectThickness,
1317 aSelectionColor));
1319 aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1);
1322 return aRetval;
1328 SvBorder PageObjectViewObjectContact::CalculatePageModelBorder (
1329 OutputDevice* pDevice,
1330 int nPageCount)
1332 SvBorder aModelBorder;
1334 if (pDevice != NULL)
1336 // 1. Initialize the border with the values that do not depend on
1337 // the device.
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,
1372 int nPageCount)
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");
1388 else
1389 sPageNumberTemplate = String::CreateFromAscii("9999");
1390 // More then 9999 pages are not handled.
1392 Size aSize (
1393 pDevice->GetTextWidth (sPageNumberTemplate),
1394 pDevice->GetTextHeight ());
1396 pDevice->SetFont (aOriginalFont);
1398 return aSize;
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