merge the formfield patch from ooo-build
[ooovba.git] / drawinglayer / source / primitive2d / controlprimitive2d.cxx
blob5fc261a79e4b64909b1b137a75050c4a17c8d1a1
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: controlprimitive2d.cxx,v $
7 * $Revision: 1.6 $
9 * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * MA 02111-1307 USA
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
39 #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <comphelper/processfactory.hxx>
42 #include <com/sun/star/awt/XWindow2.hpp>
43 #include <drawinglayer/geometry/viewinformation2d.hxx>
44 #include <vcl/virdev.hxx>
45 #include <vcl/svapp.hxx>
46 #include <com/sun/star/awt/PosSize.hpp>
47 #include <vcl/bitmapex.hxx>
48 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
49 #include <tools/diagnose_ex.h>
50 #include <basegfx/polygon/b2dpolygontools.hxx>
51 #include <basegfx/polygon/b2dpolygon.hxx>
52 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
53 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
54 #include <svtools/optionsdrawinglayer.hxx>
55 #include <toolkit/awt/vclxwindow.hxx>
56 #include <vcl/window.hxx>
58 //////////////////////////////////////////////////////////////////////////////
60 using namespace com::sun::star;
62 //////////////////////////////////////////////////////////////////////////////
64 namespace drawinglayer
66 namespace primitive2d
68 void ControlPrimitive2D::createXControl()
70 if(!mxXControl.is() && getControlModel().is())
72 uno::Reference< beans::XPropertySet > xSet(getControlModel(), uno::UNO_QUERY);
74 if(xSet.is())
76 uno::Any aValue(xSet->getPropertyValue(rtl::OUString::createFromAscii("DefaultControl")));
77 rtl::OUString aUnoControlTypeName;
79 if(aValue >>= aUnoControlTypeName)
81 if(aUnoControlTypeName.getLength())
83 uno::Reference< lang::XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
85 if(xFactory.is())
87 uno::Reference< awt::XControl > xXControl(xFactory->createInstance(aUnoControlTypeName), uno::UNO_QUERY);
89 if(xXControl.is())
91 xXControl->setModel(getControlModel());
93 // remember XControl
94 mxXControl = xXControl;
103 Primitive2DReference ControlPrimitive2D::createBitmapDecomposition(const geometry::ViewInformation2D& rViewInformation) const
105 Primitive2DReference xRetval;
106 const uno::Reference< awt::XControl >& rXControl(getXControl());
108 if(rXControl.is())
110 uno::Reference< awt::XWindow > xControlWindow(rXControl, uno::UNO_QUERY);
112 if(xControlWindow.is())
114 // get decomposition to get size
115 basegfx::B2DVector aScale, aTranslate;
116 double fRotate, fShearX;
117 getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
119 // get absolute discrete size (no mirror or rotate here)
120 aScale = basegfx::absolute(aScale);
121 basegfx::B2DVector aDiscreteSize(rViewInformation.getObjectToViewTransformation() * aScale);
123 // limit to a maximum square size, e.g. 300x150 pixels (45000)
124 const SvtOptionsDrawinglayer aDrawinglayerOpt;
125 const double fDiscreteMax(aDrawinglayerOpt.GetQuadraticFormControlRenderLimit());
126 const double fDiscreteQuadratic(aDiscreteSize.getX() * aDiscreteSize.getY());
127 const bool bScaleUsed(fDiscreteQuadratic > fDiscreteMax);
128 double fFactor(1.0);
130 if(bScaleUsed)
132 // get factor and adapt to scaled size
133 fFactor = sqrt(fDiscreteMax / fDiscreteQuadratic);
134 aDiscreteSize *= fFactor;
137 // go to integer
138 const sal_Int32 nSizeX(basegfx::fround(aDiscreteSize.getX()));
139 const sal_Int32 nSizeY(basegfx::fround(aDiscreteSize.getY()));
141 if(nSizeX > 0 && nSizeY > 0)
143 // prepare VirtualDevice
144 VirtualDevice aVirtualDevice(*Application::GetDefaultDevice());
145 const Size aSizePixel(nSizeX, nSizeY);
146 aVirtualDevice.SetOutputSizePixel(aSizePixel);
148 // set size at control
149 xControlWindow->setPosSize(0, 0, nSizeX, nSizeY, awt::PosSize::POSSIZE);
151 // get graphics and view
152 uno::Reference< awt::XGraphics > xGraphics(aVirtualDevice.CreateUnoGraphics());
153 uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY);
155 if(xGraphics.is() && xControlView.is())
157 // link graphics and view
158 xControlView->setGraphics(xGraphics);
160 { // #i93162# For painting the control setting a Zoom (using setZoom() at the xControlView)
161 // is needed to define the font size. Normally this is done in
162 // ViewObjectContactOfUnoControl::createPrimitive2DSequence by using positionControlForPaint().
163 // For some reason the difference between MAP_TWIPS and MAP_100TH_MM still plays
164 // a role there so that for Draw/Impress/Calc (the MAP_100TH_MM users) i need to set a zoom
165 // here, too. The factor includes the needed scale, but is calculated by pure comparisons. It
166 // is somehow related to the twips/100thmm relationship.
167 bool bUserIs100thmm(false);
168 const uno::Reference< awt::XControl > xControl(xControlView, uno::UNO_QUERY);
170 if(xControl.is())
172 uno::Reference< awt::XWindowPeer > xWindowPeer(xControl->getPeer());
174 if(xWindowPeer.is())
176 VCLXWindow* pVCLXWindow = VCLXWindow::GetImplementation(xWindowPeer);
178 if(pVCLXWindow)
180 Window* pWindow = pVCLXWindow->GetWindow();
182 if(pWindow)
184 pWindow = pWindow->GetParent();
186 if(pWindow)
188 if(MAP_100TH_MM == pWindow->GetMapMode().GetMapUnit())
190 bUserIs100thmm = true;
198 if(bUserIs100thmm)
200 // calc screen zoom for text display. fFactor is already added indirectly in aDiscreteSize
201 basegfx::B2DVector aScreenZoom(
202 basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : aDiscreteSize.getX() / aScale.getX(),
203 basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : aDiscreteSize.getY() / aScale.getY());
204 static double fZoomScale(28.0); // do not ask for this constant factor, but it gets the zoom right
205 aScreenZoom *= fZoomScale;
207 // set zoom at control view for text scaling
208 xControlView->setZoom((float)aScreenZoom.getX(), (float)aScreenZoom.getY());
214 // try to paint it to VirtualDevice
215 xControlView->draw(0, 0);
217 // get bitmap
218 const Bitmap aContent(aVirtualDevice.GetBitmap(Point(), aSizePixel));
220 // to avoid scaling, use the Bitmap pixel size as primitive size
221 const Size aBitmapSize(aContent.GetSizePixel());
222 basegfx::B2DVector aBitmapSizeLogic(
223 rViewInformation.getInverseObjectToViewTransformation() *
224 basegfx::B2DVector(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1));
226 if(bScaleUsed)
228 // if scaled adapt to scaled size
229 aBitmapSizeLogic /= fFactor;
232 // short form for scale and translate transformation
233 basegfx::B2DHomMatrix aBitmapTransform;
235 aBitmapTransform.set(0L, 0L, aBitmapSizeLogic.getX());
236 aBitmapTransform.set(1L, 1L, aBitmapSizeLogic.getY());
237 aBitmapTransform.set(0L, 2L, aTranslate.getX());
238 aBitmapTransform.set(1L, 2L, aTranslate.getY());
240 // create primitive
241 xRetval = new BitmapPrimitive2D(BitmapEx(aContent), aBitmapTransform);
243 catch( const uno::Exception& )
245 DBG_UNHANDLED_EXCEPTION();
252 return xRetval;
255 Primitive2DReference ControlPrimitive2D::createPlaceholderDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
257 // create a gray placeholder hairline polygon in object size
258 basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0);
259 aObjectRange.transform(getTransform());
260 const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aObjectRange));
261 const basegfx::BColor aGrayTone(0xc0 / 255.0, 0xc0 / 255.0, 0xc0 / 255.0);
263 // The replacement object may also get a text like 'empty group' here later
264 Primitive2DReference xRetval(new PolygonHairlinePrimitive2D(aOutline, aGrayTone));
266 return xRetval;
269 Primitive2DSequence ControlPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const
271 // try to create a bitmap decomposition. If that fails for some reason,
272 // at least create a replacement decomposition.
273 Primitive2DReference xReference(createBitmapDecomposition(rViewInformation));
275 if(!xReference.is())
277 xReference = createPlaceholderDecomposition(rViewInformation);
280 return Primitive2DSequence(&xReference, 1L);
283 ControlPrimitive2D::ControlPrimitive2D(
284 const basegfx::B2DHomMatrix& rTransform,
285 const uno::Reference< awt::XControlModel >& rxControlModel)
286 : BasePrimitive2D(),
287 maTransform(rTransform),
288 mxControlModel(rxControlModel),
289 mxXControl(),
290 maLastViewScaling()
294 ControlPrimitive2D::ControlPrimitive2D(
295 const basegfx::B2DHomMatrix& rTransform,
296 const uno::Reference< awt::XControlModel >& rxControlModel,
297 const uno::Reference< awt::XControl >& rxXControl)
298 : BasePrimitive2D(),
299 maTransform(rTransform),
300 mxControlModel(rxControlModel),
301 mxXControl(rxXControl),
302 maLastViewScaling()
306 const uno::Reference< awt::XControl >& ControlPrimitive2D::getXControl() const
308 if(!mxXControl.is())
310 const_cast< ControlPrimitive2D* >(this)->createXControl();
313 return mxXControl;
316 bool ControlPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
318 // use base class compare operator
319 if(BasePrimitive2D::operator==(rPrimitive))
321 const ControlPrimitive2D& rCompare = (ControlPrimitive2D&)rPrimitive;
323 if(getTransform() == rCompare.getTransform())
325 // check if ControlModel references both are/are not
326 bool bRetval(getControlModel().is() == rCompare.getControlModel().is());
328 if(bRetval && getControlModel().is())
330 // both exist, check for equality
331 bRetval = (getControlModel() == rCompare.getControlModel());
334 if(bRetval)
336 // check if XControl references both are/are not
337 bRetval = (getXControl().is() == rCompare.getXControl().is());
340 if(bRetval && getXControl().is())
342 // both exist, check for equality
343 bRetval = (getXControl() == rCompare.getXControl());
346 return bRetval;
350 return false;
353 basegfx::B2DRange ControlPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
355 // simply derivate from unit range
356 basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
357 aRetval.transform(getTransform());
358 return aRetval;
361 Primitive2DSequence ControlPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
363 // this primitive is view-dependent related to the scaling. If scaling has changed,
364 // destroy existing decomposition. To detect change, use size of unit size in view coordinates
365 ::osl::MutexGuard aGuard( m_aMutex );
366 const basegfx::B2DVector aNewScaling(rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
368 if(getLocalDecomposition().hasElements())
370 if(!maLastViewScaling.equal(aNewScaling))
372 // conditions of last local decomposition have changed, delete
373 const_cast< ControlPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence());
377 if(!getLocalDecomposition().hasElements())
379 // remember ViewTransformation
380 const_cast< ControlPrimitive2D* >(this)->maLastViewScaling = aNewScaling;
383 // use parent implementation
384 return BasePrimitive2D::get2DDecomposition(rViewInformation);
387 // provide unique ID
388 ImplPrimitrive2DIDBlock(ControlPrimitive2D, PRIMITIVE2D_ID_CONTROLPRIMITIVE2D)
390 } // end of namespace primitive2d
391 } // end of namespace drawinglayer
393 //////////////////////////////////////////////////////////////////////////////
394 // eof