tdf#161412 - UI: fix warning in PDF password dialog didn't disappear
[LibreOffice.git] / svx / source / diagram / IDiagramHelper.cxx
blob5f17433a6181edf017acad8bfe8c51ca9c7e39dd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/diagram/IDiagramHelper.hxx>
21 #include <svx/svdogrp.hxx>
22 #include <svx/svdhdl.hxx>
23 #include <svx/svdmrkv.hxx>
24 #include <svx/svdpagv.hxx>
25 #include <svx/sdrpagewindow.hxx>
26 #include <svx/sdrpaintwindow.hxx>
27 #include <basegfx/polygon/b2dpolygontools.hxx>
28 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
29 #include <drawinglayer/primitive2d/primitivetools2d.hxx>
30 #include <svx/sdr/overlay/overlaymanager.hxx>
31 #include <drawinglayer/attribute/lineattribute.hxx>
32 #include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
33 #include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
34 #include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
35 #include <drawinglayer/primitive2d/groupprimitive2d.hxx>
36 #include <comphelper/dispatchcommand.hxx>
37 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
38 #include <officecfg/Office/Common.hxx>
39 #include <svx/strings.hrc>
40 #include <svx/dialmgr.hxx>
42 namespace {
44 // helper to create the geometry for a rounded polygon, maybe
45 // containing a Lap positioned inside top-left for some text
46 basegfx::B2DPolygon createRoundedPolygon(
47 const basegfx::B2DRange& rRange,
48 double fDistance,
49 bool bCreateLap,
50 double fTextWidth)
52 basegfx::B2DPolygon aRetval;
54 // TopLeft rounded edge
55 aRetval.append(
56 basegfx::utils::createPolygonFromEllipseSegment(
57 basegfx::B2DPoint(rRange.getMinX(), rRange.getMinY()),
58 fDistance,
59 fDistance,
60 M_PI * 1.0,
61 M_PI * 1.5));
63 // create Lap topLeft inside
64 if(bCreateLap)
66 const double fLapLeft(rRange.getMinX() + fDistance);
67 double fLapRight(rRange.getMinX() + (rRange.getWidth() * 0.5) - fDistance);
68 const double fLapTop(rRange.getMinY() - fDistance);
69 const double fLapBottom(fLapTop + (fDistance * 2.0));
70 const double fExtendedTextWidth(fTextWidth + (fDistance * 3.0));
72 if(0.0 != fExtendedTextWidth && fLapLeft + fExtendedTextWidth < fLapRight)
74 fLapRight = fLapLeft + fExtendedTextWidth;
77 aRetval.append(basegfx::B2DPoint(fLapLeft, fLapTop));
78 aRetval.append(basegfx::B2DPoint(fLapLeft + (fDistance * 0.5), fLapBottom));
79 aRetval.append(basegfx::B2DPoint(fLapRight - (fDistance * 0.5), fLapBottom));
80 aRetval.append(basegfx::B2DPoint(fLapRight, fLapTop));
83 // TopRight rounded edge
84 aRetval.append(
85 basegfx::utils::createPolygonFromEllipseSegment(
86 basegfx::B2DPoint(rRange.getMaxX(), rRange.getMinY()),
87 fDistance,
88 fDistance,
89 M_PI * 1.5,
90 M_PI * 0.0));
92 // BottomRight rounded edge
93 aRetval.append(
94 basegfx::utils::createPolygonFromEllipseSegment(
95 basegfx::B2DPoint(rRange.getMaxX(), rRange.getMaxY()),
96 fDistance,
97 fDistance,
98 M_PI * 0.0,
99 M_PI * 0.5));
101 // BottomLeft rounded edge
102 aRetval.append(
103 basegfx::utils::createPolygonFromEllipseSegment(
104 basegfx::B2DPoint(rRange.getMinX(), rRange.getMaxY()),
105 fDistance,
106 fDistance,
107 M_PI * 0.5,
108 M_PI * 1.0));
110 aRetval.setClosed(true);
112 return aRetval;
115 // helper primitive to create/show the overlay geometry for a DynamicDiagram
116 class OverlayDiagramPrimitive final : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D
118 private:
119 basegfx::B2DHomMatrix maTransformation; // object dimensions
120 double mfDiscreteDistance; // distance from object in pixels
121 double mfDiscreteGap; // gap/width of visualization in pixels
122 Color maColor; // base color (made lighter/darker as needed, should be system selection color)
124 virtual drawinglayer::primitive2d::Primitive2DReference create2DDecomposition(
125 const drawinglayer::geometry::ViewInformation2D& rViewInformation) const override;
127 public:
128 OverlayDiagramPrimitive(
129 const basegfx::B2DHomMatrix& rTransformation,
130 double fDiscreteDistance,
131 double fDiscreteGap,
132 Color const & rColor);
134 virtual sal_uInt32 getPrimitive2DID() const override;
137 drawinglayer::primitive2d::Primitive2DReference OverlayDiagramPrimitive::create2DDecomposition(
138 const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const
140 // get the dimensions. Do *not* take rotation/shear into account,
141 // this is intended to be a pure expanded/frame visualization as
142 // needed in UI for simplified visualization
143 basegfx::B2DRange aRange(0.0, 0.0, 1.0, 1.0);
144 aRange.transform(maTransformation);
146 basegfx::B2DPolyPolygon aPolyPolygon;
147 const double fInnerDistance(mfDiscreteDistance * getDiscreteUnit());
148 const double fOuterDistance((mfDiscreteDistance + mfDiscreteGap) * getDiscreteUnit());
149 bool bCreateLap(true);
150 basegfx::B2DPolyPolygon aTextAsPolyPolygon;
151 double fTextWidth(0.0);
153 // initially try to create lap
154 if(bCreateLap)
156 // take a resource text (for now existing one that fits)
157 const OUString aName(SvxResId(RID_STR_DATANAV_EDIT_ELEMENT));
158 drawinglayer::primitive2d::TextLayouterDevice aTextLayouter;
159 basegfx::B2DPolyPolygonVector aTarget;
160 std::vector<double> aDXArray;
162 // to simplify things for now, do not create a TextSimplePortionPrimitive2D
163 // and needed FontAttribute, just get the TextOutlines as geometry
164 aTextLayouter.getTextOutlines(
165 aTarget,
166 aName,
168 aName.getLength(),
169 aDXArray,
170 {});
172 // put into one PolyPolygon (also simplification - overlapping chars
173 // may create XOR gaps, so these exist for a reason, but low probability)
174 for (auto const& elem : aTarget)
176 aTextAsPolyPolygon.append(elem);
179 // get text dimensions & transform to destination
180 const basegfx::B2DRange aTextRange(aTextAsPolyPolygon.getB2DRange());
181 basegfx::B2DHomMatrix aTextTransform;
183 aTextTransform.translate(aTextRange.getMinX(), aTextRange.getMinY());
184 const double fTargetTextHeight((mfDiscreteDistance + mfDiscreteGap - 2.0) * getDiscreteUnit());
185 const double fTextScale(fTargetTextHeight / aTextRange.getHeight());
186 aTextTransform.scale(fTextScale, fTextScale);
187 aTextTransform.translate(
188 aRange.getMinX() + (fInnerDistance * 2.0),
189 aRange.getMinY() + fTargetTextHeight + (fOuterDistance - fInnerDistance) - (2.0 * getDiscreteUnit()));
190 aTextAsPolyPolygon.transform(aTextTransform);
192 // check text size/position
193 fTextWidth = aTextRange.getWidth() * fTextScale;
194 const double fLapLeft(aRange.getMinX() + fInnerDistance);
195 const double fLapRight(aRange.getMinX() + (aRange.getWidth() * 0.5) - fInnerDistance);
197 // if text is too big, do not create a Lap at all
198 // to avoid trouble. It is expected that the user keeps
199 // the object he works with big enough to do useful actions
200 if(fTextWidth + (4.0 * getDiscreteUnit()) > fLapRight - fLapLeft)
201 bCreateLap = false;
204 // create outer polygon
205 aPolyPolygon.append(
206 createRoundedPolygon(
207 aRange,
208 fOuterDistance,
209 false,
210 0.0));
212 // create inner polygon, maybe with Lap
213 aPolyPolygon.append(
214 createRoundedPolygon(
215 aRange,
216 fInnerDistance,
217 bCreateLap,
218 fTextWidth));
220 Color aFillColor(maColor);
221 Color aLineColor(maColor);
223 aFillColor.IncreaseLuminance(10);
224 aLineColor.DecreaseLuminance(30);
226 const drawinglayer::attribute::LineAttribute aLineAttribute(
227 aLineColor.getBColor(),
228 1.0 * getDiscreteUnit());
230 drawinglayer::primitive2d::Primitive2DContainer aContainer;
232 // filled polygon as BG (may get transparence for better look ?)
233 aContainer.push_back(
234 new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
235 aPolyPolygon,
236 aFillColor.getBColor()));
238 // outline polygon for visibility (may be accentuated shaded
239 // top/left, would require alternative creation)
240 aContainer.push_back(
241 new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
242 std::move(aPolyPolygon),
243 aLineAttribute));
245 // top-left line pattern (as grep-here-sign to signal
246 // that this construct may be also dragged by the user)
247 const double fLapLeft(aRange.getMinX() + fInnerDistance);
248 const double fLapRight(aRange.getMinX() + (aRange.getWidth() * 0.5) - fInnerDistance);
249 const double fLapUp(aRange.getMinY() - ((mfDiscreteDistance + mfDiscreteDistance * 0.666) * getDiscreteUnit()));
250 const double fLapDown(aRange.getMinY() - ((mfDiscreteDistance + mfDiscreteDistance * 0.333) * getDiscreteUnit()));
251 basegfx::B2DPolygon aPolygonLapUp;
252 aPolygonLapUp.append(basegfx::B2DPoint(fLapLeft, fLapUp));
253 aPolygonLapUp.append(basegfx::B2DPoint(fLapRight, fLapUp));
254 basegfx::B2DPolygon aPolygonLapDown;
255 aPolygonLapDown.append(basegfx::B2DPoint(fLapLeft, fLapDown));
256 aPolygonLapDown.append(basegfx::B2DPoint(fLapRight, fLapDown));
257 drawinglayer::attribute::StrokeAttribute aStrokeAttribute({ 2.0 * getDiscreteUnit(), 2.0 * getDiscreteUnit() });
259 aContainer.push_back(
260 new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
261 std::move(aPolygonLapUp),
262 aLineAttribute,
263 aStrokeAttribute));
265 aContainer.push_back(
266 new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
267 std::move(aPolygonLapDown),
268 aLineAttribute,
269 std::move(aStrokeAttribute)));
271 // add text last. May use darker text color, go for same color
272 // as accentuation line for now
273 if(bCreateLap && 0 != aTextAsPolyPolygon.count())
275 aContainer.push_back(
276 new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
277 std::move(aTextAsPolyPolygon),
278 aLineColor.getBColor()));
280 return new drawinglayer::primitive2d::GroupPrimitive2D(std::move(aContainer));
283 OverlayDiagramPrimitive::OverlayDiagramPrimitive(
284 const basegfx::B2DHomMatrix& rTransformation,
285 double fDiscreteDistance,
286 double fDiscreteGap,
287 Color const & rColor)
288 : drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D()
289 , maTransformation(rTransformation)
290 , mfDiscreteDistance(fDiscreteDistance)
291 , mfDiscreteGap(fDiscreteGap)
292 , maColor(rColor)
296 sal_uInt32 OverlayDiagramPrimitive::getPrimitive2DID() const
298 return PRIMITIVE2D_ID_OVERLAYDIAGRAMPRIMITIVE2D;
301 // helper object for DiagramOverlay
302 class OverlayDiagramFrame final : public sdr::overlay::OverlayObject
304 private:
305 basegfx::B2DHomMatrix maTransformation; // object dimensions
306 Color maColor; // base color
308 virtual drawinglayer::primitive2d::Primitive2DContainer createOverlayObjectPrimitive2DSequence() override;
310 public:
311 explicit OverlayDiagramFrame(
312 const basegfx::B2DHomMatrix& rTransformation,
313 Color const & rColor);
316 OverlayDiagramFrame::OverlayDiagramFrame(
317 const basegfx::B2DHomMatrix& rTransformation,
318 const Color& rColor)
319 : sdr::overlay::OverlayObject(rColor)
320 , maTransformation(rTransformation)
321 , maColor(rColor)
325 drawinglayer::primitive2d::Primitive2DContainer OverlayDiagramFrame::createOverlayObjectPrimitive2DSequence()
327 drawinglayer::primitive2d::Primitive2DContainer aReturnContainer;
329 if ( !officecfg::Office::Common::Misc::ExperimentalMode::get() )
330 return aReturnContainer;
332 if (getOverlayManager())
334 aReturnContainer = drawinglayer::primitive2d::Primitive2DContainer {
335 new OverlayDiagramPrimitive(
336 maTransformation,
337 8.0, // distance from geometry in pixels
338 8.0, // gap/width of visualization in pixels
339 maColor) };
342 return aReturnContainer;
345 } // end of anonymous namespace
347 namespace svx { namespace diagram {
349 void DiagramFrameHdl::clicked(const Point& /*rPnt*/)
351 // this may check for a direct hit at the text later
352 // and only then take action. That would require
353 // to evaluate & keep that (maybe during creation).
354 // For now, just trigger to open the Dialog
355 comphelper::dispatchCommand(u".uno:EditDiagram"_ustr, {});
358 void DiagramFrameHdl::CreateB2dIAObject()
360 // first throw away old one
361 GetRidOfIAObject();
363 SdrMarkView* pView = m_pHdlList->GetView();
365 if(!pView || pView->areMarkHandlesHidden())
366 return;
368 SdrPageView* pPageView = pView->GetSdrPageView();
370 if(!pPageView)
371 return;
373 for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
375 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
377 if(rPageWindow.GetPaintWindow().OutputToWindow())
379 const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
380 if (xManager.is())
382 OutputDevice& rOutDev(rPageWindow.GetPaintWindow().GetOutputDevice());
383 const StyleSettings& rStyles(rOutDev.GetSettings().GetStyleSettings());
384 Color aFillColor(rStyles.GetHighlightColor());
385 std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(
386 new OverlayDiagramFrame(
387 maTransformation,
388 aFillColor));
390 // OVERLAYMANAGER
391 insertNewlyCreatedOverlayObjectForSdrHdl(
392 std::move(pNewOverlayObject),
393 rPageWindow.GetObjectContact(),
394 *xManager);
400 DiagramFrameHdl::DiagramFrameHdl(const basegfx::B2DHomMatrix& rTransformation)
401 : SdrHdl(Point(), SdrHdlKind::Move)
402 , maTransformation(rTransformation)
406 IDiagramHelper::IDiagramHelper(bool bSelfCreated)
407 : mbUseDiagramThemeData(false)
408 , mbUseDiagramModelData(true)
409 , mbForceThemePtrRecreation(false)
410 , mbSelfCreated(bSelfCreated)
414 IDiagramHelper::~IDiagramHelper() {}
416 void IDiagramHelper::anchorToSdrObjGroup(SdrObjGroup& rTarget)
418 rTarget.mp_DiagramHelper.reset(this);
421 void IDiagramHelper::AddAdditionalVisualization(const SdrObjGroup& rTarget, SdrHdlList& rHdlList)
423 // create an extra frame visualization here
424 basegfx::B2DHomMatrix aTransformation;
425 basegfx::B2DPolyPolygon aPolyPolygon;
426 rTarget.TRGetBaseGeometry(aTransformation, aPolyPolygon);
428 std::unique_ptr<SdrHdl> pHdl(new DiagramFrameHdl(aTransformation));
429 rHdlList.AddHdl(std::move(pHdl));
432 }} // end of namespace
434 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */