tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / svx / source / sdr / contact / viewcontact.cxx
blobe5a3b00d4d125e11eafabfbde816139e9caaefc8
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/sdr/contact/viewcontact.hxx>
21 #include <svx/sdr/contact/viewobjectcontact.hxx>
22 #include <svx/sdr/contact/objectcontact.hxx>
23 #include <basegfx/polygon/b2dpolygon.hxx>
24 #include <basegfx/polygon/b2dpolygontools.hxx>
25 #include <basegfx/color/bcolor.hxx>
26 #include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
27 #include <osl/diagnose.h>
28 #include <tools/debug.hxx>
30 namespace sdr::contact
32 // Create an Object-Specific ViewObjectContact, set ViewContact and
33 // ObjectContact. Always needs to return something. Default is to create
34 // a standard ViewObjectContact containing the given ObjectContact and *this
35 ViewObjectContact& ViewContact::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact)
37 return *(new ViewObjectContact(rObjectContact, *this));
40 ViewContact::ViewContact() {}
42 ViewContact::~ViewContact() { deleteAllVOCs(); }
44 void ViewContact::deleteAllVOCs()
46 // get rid of all VOCs
47 // #i84257# To avoid that each 'delete pCandidate' again uses
48 // the local RemoveViewObjectContact with a search and removal in the
49 // vector, simply copy and clear local vector.
50 std::vector<ViewObjectContact*> aLocalVOCList;
51 aLocalVOCList.swap(maViewObjectContactVector);
53 for (const auto& pCandidate : aLocalVOCList)
54 // ViewObjectContacts only make sense with View and Object contacts.
55 // When the contact to the SdrObject is deleted like in this case,
56 // all ViewObjectContacts can be deleted, too.
57 delete pCandidate;
59 // assert when there were new entries added during deletion
60 DBG_ASSERT(maViewObjectContactVector.empty(), "Corrupted ViewObjectContactList in VC (!)");
62 mxViewIndependentPrimitive2DSequence = drawinglayer::primitive2d::Primitive2DContainer();
65 // get an Object-specific ViewObjectContact for a specific
66 // ObjectContact (->View). Always needs to return something.
67 ViewObjectContact& ViewContact::GetViewObjectContact(ObjectContact& rObjectContact)
69 ViewObjectContact* pRetval = nullptr;
70 const sal_uInt32 nCount(maViewObjectContactVector.size());
72 // first search if there exists a VOC for the given OC
73 for (sal_uInt32 a(0); !pRetval && a < nCount; a++)
75 ViewObjectContact* pCandidate = maViewObjectContactVector[a];
76 assert(pCandidate && "Corrupted ViewObjectContactList (!)");
78 if (&(pCandidate->GetObjectContact()) == &rObjectContact)
80 pRetval = pCandidate;
84 if (!pRetval)
86 // create a new one. It's inserted to the local list from the
87 // ViewObjectContact constructor via AddViewObjectContact()
88 pRetval = &CreateObjectSpecificViewObjectContact(rObjectContact);
91 return *pRetval;
94 // A new ViewObjectContact was created and shall be remembered.
95 void ViewContact::AddViewObjectContact(ViewObjectContact& rVOContact)
97 maViewObjectContactVector.push_back(&rVOContact);
100 // A ViewObjectContact was deleted and shall be forgotten.
101 void ViewContact::RemoveViewObjectContact(ViewObjectContact& rVOContact)
103 std::vector<ViewObjectContact*>::iterator aFindResult = std::find(
104 maViewObjectContactVector.begin(), maViewObjectContactVector.end(), &rVOContact);
106 if (aFindResult != maViewObjectContactVector.end())
108 maViewObjectContactVector.erase(aFindResult);
112 // Test if this ViewContact has ViewObjectContacts at all. This can
113 // be used to test if this ViewContact is visualized ATM or not
114 bool ViewContact::HasViewObjectContacts() const
116 const sal_uInt32 nCount(maViewObjectContactVector.size());
118 for (sal_uInt32 a(0); a < nCount; a++)
120 if (!maViewObjectContactVector[a]->GetObjectContact().IsPreviewRenderer())
122 return true;
125 return false;
128 // Test if this ViewContact has ViewObjectContacts at all. This can
129 // be used to test if this ViewContact is visualized ATM or not
130 bool ViewContact::isAnimatedInAnyViewObjectContact() const
132 const sal_uInt32 nCount(maViewObjectContactVector.size());
134 for (sal_uInt32 a(0); a < nCount; a++)
136 if (maViewObjectContactVector[a]->isAnimated())
138 return true;
142 return false;
145 // Access to possible sub-hierarchy and parent. GetObjectCount() default is 0L
146 // and GetViewContact default pops up an assert since it's an error if
147 // GetObjectCount has a result != 0 and it's not overridden.
148 sal_uInt32 ViewContact::GetObjectCount() const
150 // no sub-objects
151 return 0;
154 ViewContact& ViewContact::GetViewContact(sal_uInt32 /*nIndex*/) const
156 // This is the default implementation; call would be an error
157 OSL_FAIL("ViewContact::GetViewContact: This call needs to be overridden when GetObjectCount() "
158 "can return results != 0 (!)");
159 return const_cast<ViewContact&>(*this);
162 ViewContact* ViewContact::GetParentContact() const
164 // default has no parent
165 return nullptr;
168 void ViewContact::ActionChildInserted(ViewContact& rChild)
170 // propagate change to all existing visualisations which
171 // will force a VOC for the new child and invalidate its range
172 const sal_uInt32 nCount(maViewObjectContactVector.size());
174 for (sal_uInt32 a(0); a < nCount; a++)
176 ViewObjectContact* pCandidate = maViewObjectContactVector[a];
177 DBG_ASSERT(pCandidate,
178 "ViewContact::GetViewObjectContact() invalid ViewObjectContactList (!)");
180 // take action at all VOCs. At the VOCs ObjectContact the initial
181 // rectangle will be invalidated at the associated OutputDevice.
182 pCandidate->ActionChildInserted(rChild);
186 // React on changes of the object of this ViewContact
187 void ViewContact::ActionChanged()
189 // propagate change to all existing VOCs. This will invalidate
190 // all drawn visualisations in all known views
191 const sal_uInt32 nCount(maViewObjectContactVector.size());
193 for (sal_uInt32 a(0); a < nCount; a++)
195 ViewObjectContact* pCandidate = maViewObjectContactVector[a];
196 DBG_ASSERT(pCandidate,
197 "ViewContact::GetViewObjectContact() invalid ViewObjectContactList (!)");
199 if (pCandidate)
201 pCandidate->ActionChanged();
206 // IASS: helper for IASS invalidates
207 void ViewContact::ActionChangedIfDifferentPageView(SdrPageView& rSdrPageView)
209 const sal_uInt32 nCount(maViewObjectContactVector.size());
211 for (sal_uInt32 a(0); a < nCount; a++)
213 ViewObjectContact* pCandidate = maViewObjectContactVector[a];
214 DBG_ASSERT(pCandidate,
215 "ViewContact::GetViewObjectContact() invalid ViewObjectContactList (!)");
217 if (pCandidate)
219 pCandidate->ActionChangedIfDifferentPageView(rSdrPageView);
224 bool ViewContact::hasMultipleViewObjectContacts() const
226 return maViewObjectContactVector.size() > 1;
229 // access to SdrObject and/or SdrPage. May return 0L like the default
230 // implementations do. Override as needed.
231 SdrObject* ViewContact::TryToGetSdrObject() const { return nullptr; }
233 // primitive stuff
235 void ViewContact::createViewIndependentPrimitive2DSequence(
236 drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const
238 // This is the default implementation and should never be called (see header). If this is called,
239 // someone implemented a ViewContact (VC) visualisation object without defining the visualisation by
240 // providing a sequence of primitives -> which cannot be correct.
241 // Since we have no access to any known model data here, the default implementation creates a yellow placeholder
242 // hairline polygon with a default size of (1000, 1000, 5000, 3000)
243 OSL_FAIL("ViewContact::createViewIndependentPrimitive2DSequence(): Never call the fallback "
244 "base implementation, this is always an error (!)");
245 basegfx::B2DPolygon aOutline(
246 basegfx::utils::createPolygonFromRect(basegfx::B2DRange(1000.0, 1000.0, 5000.0, 3000.0)));
247 const basegfx::BColor aYellow(1.0, 1.0, 0.0);
248 const drawinglayer::primitive2d::Primitive2DReference xReference(
249 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(std::move(aOutline), aYellow));
251 rVisitor.visit(xReference);
254 void ViewContact::getViewIndependentPrimitive2DContainer(
255 drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const
257 /* Local up-to-date checks. Create new list and compare.
258 We cannot just always use the new data because the old data has cached bitmaps in it e.g. see the document in tdf#146108.
260 drawinglayer::primitive2d::Primitive2DContainer xNew;
261 createViewIndependentPrimitive2DSequence(xNew);
263 if (!xNew.empty())
265 // allow evtl. embedding in object-specific infos, e.g. Name, Title, Description
266 xNew = embedToObjectSpecificInformation(std::move(xNew));
269 if (mxViewIndependentPrimitive2DSequence != xNew)
271 // has changed, copy content
272 const_cast<ViewContact*>(this)->mxViewIndependentPrimitive2DSequence = std::move(xNew);
275 // return current Primitive2DContainer
276 rVisitor.visit(mxViewIndependentPrimitive2DSequence);
279 // add Gluepoints (if available)
280 drawinglayer::primitive2d::Primitive2DContainer
281 ViewContact::createGluePointPrimitive2DSequence() const
283 // default returns empty reference
284 return drawinglayer::primitive2d::Primitive2DContainer();
287 drawinglayer::primitive2d::Primitive2DContainer ViewContact::embedToObjectSpecificInformation(
288 drawinglayer::primitive2d::Primitive2DContainer aSource) const
290 // nothing to do for default
291 return aSource;
294 basegfx::B2DRange
295 ViewContact::getRange(const drawinglayer::geometry::ViewInformation2D& /*rViewInfo2D*/) const
297 // Return empty range.
298 return basegfx::B2DRange();
301 void ViewContact::flushViewObjectContacts(bool bWithHierarchy)
303 if (bWithHierarchy)
305 // flush DrawingLayer hierarchy
306 const sal_uInt32 nCount(GetObjectCount());
308 for (sal_uInt32 a(0); a < nCount; a++)
310 ViewContact& rChild = GetViewContact(a);
311 rChild.flushViewObjectContacts(bWithHierarchy);
315 // delete local VOCs
316 deleteAllVOCs();
319 void ViewContact::getPrimitive2DSequenceHierarchyOfIndex(
320 sal_uInt32 a, DisplayInfo& rDisplayInfo, ObjectContact& rObjectContact,
321 drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor)
323 const ViewObjectContact& rCandidate(GetViewContact(a).GetViewObjectContact(rObjectContact));
324 rCandidate.getPrimitive2DSequenceHierarchy(rDisplayInfo, rVisitor);
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */