LibreOffice Module svx (master)  1
viewcontact.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
25 #include <basegfx/color/bcolor.hxx>
27 #include <osl/diagnose.h>
28 #include <tools/debug.hxx>
29 
30 namespace sdr::contact
31 {
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
36 {
37  return *(new ViewObjectContact(rObjectContact, *this));
38 }
39 
41 
43 
45 {
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);
52 
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;
58 
59  // assert when there were new entries added during deletion
60  DBG_ASSERT(maViewObjectContactVector.empty(), "Corrupted ViewObjectContactList in VC (!)");
61 }
62 
63 // get an Object-specific ViewObjectContact for a specific
64 // ObjectContact (->View). Always needs to return something.
66 {
67  ViewObjectContact* pRetval = nullptr;
68  const sal_uInt32 nCount(maViewObjectContactVector.size());
69 
70  // first search if there exists a VOC for the given OC
71  for (sal_uInt32 a(0); !pRetval && a < nCount; a++)
72  {
74  DBG_ASSERT(pCandidate, "Corrupted ViewObjectContactList (!)");
75 
76  if (&(pCandidate->GetObjectContact()) == &rObjectContact)
77  {
78  pRetval = pCandidate;
79  }
80  }
81 
82  if (!pRetval)
83  {
84  // create a new one. It's inserted to the local list from the
85  // ViewObjectContact constructor via AddViewObjectContact()
86  pRetval = &CreateObjectSpecificViewObjectContact(rObjectContact);
87  }
88 
89  return *pRetval;
90 }
91 
92 // A new ViewObjectContact was created and shall be remembered.
94 {
95  maViewObjectContactVector.push_back(&rVOContact);
96 }
97 
98 // A ViewObjectContact was deleted and shall be forgotten.
100 {
101  std::vector<ViewObjectContact*>::iterator aFindResult = std::find(
102  maViewObjectContactVector.begin(), maViewObjectContactVector.end(), &rVOContact);
103 
104  if (aFindResult != maViewObjectContactVector.end())
105  {
106  maViewObjectContactVector.erase(aFindResult);
107  }
108 }
109 
110 // Test if this ViewContact has ViewObjectContacts at all. This can
111 // be used to test if this ViewContact is visualized ATM or not
113 {
114  const sal_uInt32 nCount(maViewObjectContactVector.size());
115 
116  for (sal_uInt32 a(0); a < nCount; a++)
117  {
118  if (!maViewObjectContactVector[a]->GetObjectContact().IsPreviewRenderer())
119  {
120  return true;
121  }
122  }
123  return false;
124 }
125 
126 // Test if this ViewContact has ViewObjectContacts at all. This can
127 // be used to test if this ViewContact is visualized ATM or not
129 {
130  const sal_uInt32 nCount(maViewObjectContactVector.size());
131 
132  for (sal_uInt32 a(0); a < nCount; a++)
133  {
134  if (maViewObjectContactVector[a]->isAnimated())
135  {
136  return true;
137  }
138  }
139 
140  return false;
141 }
142 
143 // Access to possible sub-hierarchy and parent. GetObjectCount() default is 0L
144 // and GetViewContact default pops up an assert since it's an error if
145 // GetObjectCount has a result != 0 and it's not overridden.
146 sal_uInt32 ViewContact::GetObjectCount() const
147 {
148  // no sub-objects
149  return 0;
150 }
151 
152 ViewContact& ViewContact::GetViewContact(sal_uInt32 /*nIndex*/) const
153 {
154  // This is the default implementation; call would be an error
155  OSL_FAIL("ViewContact::GetViewContact: This call needs to be overridden when GetObjectCount() "
156  "can return results != 0 (!)");
157  return const_cast<ViewContact&>(*this);
158 }
159 
161 {
162  // default has no parent
163  return nullptr;
164 }
165 
167 {
168  // propagate change to all existing visualisations which
169  // will force a VOC for the new child and invalidate its range
170  const sal_uInt32 nCount(maViewObjectContactVector.size());
171 
172  for (sal_uInt32 a(0); a < nCount; a++)
173  {
175  DBG_ASSERT(pCandidate,
176  "ViewContact::GetViewObjectContact() invalid ViewObjectContactList (!)");
177 
178  // take action at all VOCs. At the VOCs ObjectContact the initial
179  // rectangle will be invalidated at the associated OutputDevice.
180  pCandidate->ActionChildInserted(rChild);
181  }
182 }
183 
184 // React on changes of the object of this ViewContact
186 {
187  // propagate change to all existing VOCs. This will invalidate
188  // all drawn visualisations in all known views
189  const sal_uInt32 nCount(maViewObjectContactVector.size());
190 
191  for (sal_uInt32 a(0); a < nCount; a++)
192  {
194  DBG_ASSERT(pCandidate,
195  "ViewContact::GetViewObjectContact() invalid ViewObjectContactList (!)");
196 
197  if (pCandidate)
198  {
199  pCandidate->ActionChanged();
200  }
201  }
202 }
203 
204 // access to SdrObject and/or SdrPage. May return 0L like the default
205 // implementations do. Override as needed.
206 SdrObject* ViewContact::TryToGetSdrObject() const { return nullptr; }
207 
208 // primitive stuff
209 
212 {
213  // This is the default implementation and should never be called (see header). If this is called,
214  // someone implemented a ViewContact (VC) visualisation object without defining the visualisation by
215  // providing a sequence of primitives -> which cannot be correct.
216  // Since we have no access to any known model data here, the default implementation creates a yellow placeholder
217  // hairline polygon with a default size of (1000, 1000, 5000, 3000)
218  OSL_FAIL("ViewContact::createViewIndependentPrimitive2DSequence(): Never call the fallback "
219  "base implementation, this is always an error (!)");
220  const basegfx::B2DPolygon aOutline(
221  basegfx::utils::createPolygonFromRect(basegfx::B2DRange(1000.0, 1000.0, 5000.0, 3000.0)));
222  const basegfx::BColor aYellow(1.0, 1.0, 0.0);
225 
226  rVisitor.visit(xReference);
227 }
228 
231 {
232  /* Local up-to-date checks. Create new list and compare.
233  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.
234  */
237 
238  if (!xNew.empty())
239  {
240  // allow evtl. embedding in object-specific infos, e.g. Name, Title, Description
241  xNew = embedToObjectSpecificInformation(std::move(xNew));
242  }
243 
245  {
246  // has changed, copy content
247  const_cast<ViewContact*>(this)->mxViewIndependentPrimitive2DSequence = std::move(xNew);
248  }
249 
250  // return current Primitive2DContainer
252 }
253 
254 // add Gluepoints (if available)
257 {
258  // default returns empty reference
260 }
261 
264 {
265  // nothing to do for default
266  return aSource;
267 }
268 
271 {
272  // Return empty range.
273  return basegfx::B2DRange();
274 }
275 
276 void ViewContact::flushViewObjectContacts(bool bWithHierarchy)
277 {
278  if (bWithHierarchy)
279  {
280  // flush DrawingLayer hierarchy
281  const sal_uInt32 nCount(GetObjectCount());
282 
283  for (sal_uInt32 a(0); a < nCount; a++)
284  {
285  ViewContact& rChild = GetViewContact(a);
286  rChild.flushViewObjectContacts(bWithHierarchy);
287  }
288  }
289 
290  // delete local VOCs
291  deleteAllVOCs();
292 }
293 }
294 
295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void ActionChildInserted(ViewContact &rChild)
std::vector< ViewObjectContact * > maViewObjectContactVector
Definition: viewcontact.hxx:47
virtual ViewContact * GetParentContact() const
virtual SdrObject * TryToGetSdrObject() const
bool isAnimatedInAnyViewObjectContact() const
friend class ViewObjectContact
Definition: viewcontact.hxx:41
ViewObjectContact & GetViewObjectContact(ObjectContact &rObjectContact)
Definition: viewcontact.cxx:65
virtual drawinglayer::primitive2d::Primitive2DContainer createGluePointPrimitive2DSequence() const
virtual basegfx::B2DRange getRange(const drawinglayer::geometry::ViewInformation2D &rViewInfo2D) const
void AddViewObjectContact(ViewObjectContact &rVOContact)
Definition: viewcontact.cxx:93
int nCount
ObjectContact & GetObjectContact() const
bool HasViewObjectContacts() const
#define DBG_ASSERT(sCon, aError)
uno_Any a
virtual void visit(const Primitive2DReference &)=0
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
virtual ViewObjectContact & CreateObjectSpecificViewObjectContact(ObjectContact &rObjectContact)
Definition: viewcontact.cxx:35
void flushViewObjectContacts(bool bWithHierarchy=true)
Abstract DrawObject.
Definition: svdobj.hxx:259
virtual void ActionChanged()
void ActionChildInserted(ViewContact &rChild)
virtual sal_uInt32 GetObjectCount() const
void getViewIndependentPrimitive2DContainer(drawinglayer::primitive2d::Primitive2DDecompositionVisitor &rVisitor) const
virtual ViewContact & GetViewContact(sal_uInt32 nIndex) const
void RemoveViewObjectContact(ViewObjectContact &rVOContact)
Definition: viewcontact.cxx:99
virtual drawinglayer::primitive2d::Primitive2DContainer embedToObjectSpecificInformation(drawinglayer::primitive2d::Primitive2DContainer rSource) const
drawinglayer::primitive2d::Primitive2DContainer mxViewIndependentPrimitive2DSequence
Definition: viewcontact.hxx:52
virtual void createViewIndependentPrimitive2DSequence(drawinglayer::primitive2d::Primitive2DDecompositionVisitor &rVisitor) const