xref: /AOO41X/main/svx/source/sdr/contact/viewcontact.cxx (revision 025b059733df8a26f6b22068efe91c1a0b65ee8b)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include <svx/sdr/contact/viewcontact.hxx>
27 #include <svx/sdr/contact/viewobjectcontact.hxx>
28 #include <svx/sdr/contact/objectcontact.hxx>
29 #include <basegfx/polygon/b2dpolygon.hxx>
30 #include <basegfx/polygon/b2dpolygontools.hxx>
31 #include <basegfx/color/bcolor.hxx>
32 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
33 #include <basegfx/matrix/b2dhommatrix.hxx>
34 #include <svx/sdr/contact/objectcontactofpageview.hxx>
35 
36 //////////////////////////////////////////////////////////////////////////////
37 
38 namespace sdr
39 {
40     namespace contact
41     {
42         // Create a Object-Specific ViewObjectContact, set ViewContact and
43         // ObjectContact. Always needs to return something. Default is to create
44         // a standard ViewObjectContact containing the given ObjectContact and *this
CreateObjectSpecificViewObjectContact(ObjectContact & rObjectContact)45         ViewObjectContact& ViewContact::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact)
46         {
47             return *(new ViewObjectContact(rObjectContact, *this));
48         }
49 
ViewContact()50         ViewContact::ViewContact()
51         :   maViewObjectContactVector(),
52             mxViewIndependentPrimitive2DSequence()
53         {
54         }
55 
56         // Methods to react on start getting viewed or stop getting
57         // viewed. This info is derived from the count of members of
58         // registered ViewObjectContacts. Default does nothing.
StartGettingViewed()59         void ViewContact::StartGettingViewed()
60         {
61         }
62 
StopGettingViewed()63         void ViewContact::StopGettingViewed()
64         {
65         }
66 
~ViewContact()67         ViewContact::~ViewContact()
68         {
69             deleteAllVOCs();
70         }
71 
deleteAllVOCs()72         void ViewContact::deleteAllVOCs()
73         {
74             // get rid of all VOCs
75             // #i84257# To avoid that each 'delete pCandidate' again uses
76             // the local RemoveViewObjectContact with a search and removal in the
77             // vector, simply copy and clear local vector.
78             std::vector< ViewObjectContact* > aLocalVOCList(maViewObjectContactVector);
79             maViewObjectContactVector.clear();
80 
81             while(!aLocalVOCList.empty())
82             {
83                 ViewObjectContact* pCandidate = aLocalVOCList.back();
84                 aLocalVOCList.pop_back();
85                 DBG_ASSERT(pCandidate, "Corrupted ViewObjectContactList in VC (!)");
86 
87                 // ViewObjectContacts only make sense with View and Object contacts.
88                 // When the contact to the SdrObject is deleted like in this case,
89                 // all ViewObjectContacts can be deleted, too.
90                 delete pCandidate;
91             }
92 
93             // assert when there were new entries added during deletion
94             DBG_ASSERT(maViewObjectContactVector.empty(), "Corrupted ViewObjectContactList in VC (!)");
95         }
96 
97         // get a Object-specific ViewObjectContact for a specific
98         // ObjectContact (->View). Always needs to return something.
GetViewObjectContact(ObjectContact & rObjectContact)99         ViewObjectContact& ViewContact::GetViewObjectContact(ObjectContact& rObjectContact)
100         {
101             ViewObjectContact* pRetval = 0L;
102             const sal_uInt32 nCount(maViewObjectContactVector.size());
103 
104             // first search if there exists a VOC for the given OC
105             for(sal_uInt32 a(0); !pRetval && a < nCount; a++)
106             {
107                 ViewObjectContact* pCandidate = maViewObjectContactVector[a];
108                 DBG_ASSERT(pCandidate, "Corrupted ViewObjectContactList (!)");
109 
110                 if(&(pCandidate->GetObjectContact()) == &rObjectContact)
111                 {
112                     pRetval = pCandidate;
113                 }
114             }
115 
116             if(!pRetval)
117             {
118                 // create a new one. It's inserted to the local list from the
119                 // VieObjectContact constructor via AddViewObjectContact()
120                 pRetval = &CreateObjectSpecificViewObjectContact(rObjectContact);
121             }
122 
123             return *pRetval;
124         }
125 
126         // A new ViewObjectContact was created and shall be remembered.
AddViewObjectContact(ViewObjectContact & rVOContact)127         void ViewContact::AddViewObjectContact(ViewObjectContact& rVOContact)
128         {
129             maViewObjectContactVector.push_back(&rVOContact);
130 
131             if(1L == maViewObjectContactVector.size())
132             {
133                 StartGettingViewed();
134             }
135         }
136 
137         // A ViewObjectContact was deleted and shall be forgotten.
RemoveViewObjectContact(ViewObjectContact & rVOContact)138         void ViewContact::RemoveViewObjectContact(ViewObjectContact& rVOContact)
139         {
140             std::vector< ViewObjectContact* >::iterator aFindResult = std::find(maViewObjectContactVector.begin(), maViewObjectContactVector.end(), &rVOContact);
141 
142             if(aFindResult != maViewObjectContactVector.end())
143             {
144                 maViewObjectContactVector.erase(aFindResult);
145 
146                 if(maViewObjectContactVector.empty())
147                 {
148                     // This may need to get asynchron later since it eventually triggers
149                     // deletes of OCs where the VOC is still added.
150                     StopGettingViewed();
151                 }
152             }
153         }
154 
155         // Test if this ViewContact has ViewObjectContacts at all. This can
156         // be used to test if this ViewContact is visualized ATM or not
HasViewObjectContacts(bool bExcludePreviews) const157         bool ViewContact::HasViewObjectContacts(bool bExcludePreviews) const
158         {
159             const sal_uInt32 nCount(maViewObjectContactVector.size());
160 
161             if(bExcludePreviews)
162             {
163                 for(sal_uInt32 a(0); a < nCount; a++)
164                 {
165                     if(!maViewObjectContactVector[a]->GetObjectContact().IsPreviewRenderer())
166                     {
167                         return true;
168                     }
169                 }
170 
171                 return false;
172             }
173             else
174             {
175                 return (0L != nCount);
176             }
177         }
178 
179         // Test if this ViewContact has ViewObjectContacts at all. This can
180         // be used to test if this ViewContact is visualized ATM or not
isAnimatedInAnyViewObjectContact() const181         bool ViewContact::isAnimatedInAnyViewObjectContact() const
182         {
183             const sal_uInt32 nCount(maViewObjectContactVector.size());
184 
185             for(sal_uInt32 a(0); a < nCount; a++)
186             {
187                 if(maViewObjectContactVector[a]->isAnimated())
188                 {
189                     return true;
190                 }
191             }
192 
193             return false;
194         }
195 
196         // Access to possible sub-hierarchy and parent. GetObjectCount() default is 0L
197         // and GetViewContact default pops up an assert since it's an error if
198         // GetObjectCount has a result != 0 and it's not overloaded.
GetObjectCount() const199         sal_uInt32 ViewContact::GetObjectCount() const
200         {
201             // no sub-objects
202             return 0;
203         }
204 
GetViewContact(sal_uInt32) const205         ViewContact& ViewContact::GetViewContact(sal_uInt32 /*nIndex*/) const
206         {
207             // This is the default implementation; call would be an error
208             DBG_ERROR("ViewContact::GetViewContact: This call needs to be overloaded when GetObjectCount() can return results != 0 (!)");
209             return (ViewContact&)(*this);
210         }
211 
GetParentContact() const212         ViewContact* ViewContact::GetParentContact() const
213         {
214             // default has no parent
215             return 0;
216         }
217 
ActionChildInserted(ViewContact & rChild)218         void ViewContact::ActionChildInserted(ViewContact& rChild)
219         {
220             // propagate change to all exsisting visualisations which
221             // will force a VOC for the new child and invalidate it's range
222             const sal_uInt32 nCount(maViewObjectContactVector.size());
223 
224             for(sal_uInt32 a(0); a < nCount; a++)
225             {
226                 ViewObjectContact* pCandidate = maViewObjectContactVector[a];
227                 DBG_ASSERT(pCandidate, "ViewContact::GetViewObjectContact() invalid ViewObjectContactList (!)");
228 
229                 // take action at all VOCs. At the VOCs ObjectContact the initial
230                 // rectangle will be invalidated at the associated OutputDevice.
231                 pCandidate->ActionChildInserted(rChild);
232             }
233         }
234 
235         // React on changes of the object of this ViewContact
ActionChanged()236         void ViewContact::ActionChanged()
237         {
238             // propagate change to all existing VOCs. This will invalidate
239             // all drawn visualisations in all known views
240             const sal_uInt32 nCount(maViewObjectContactVector.size());
241 
242             for(sal_uInt32 a(0); a < nCount; a++)
243             {
244                 ViewObjectContact* pCandidate = maViewObjectContactVector[a];
245                 DBG_ASSERT(pCandidate, "ViewContact::GetViewObjectContact() invalid ViewObjectContactList (!)");
246 
247                 pCandidate->ActionChanged();
248             }
249         }
250 
251         // access to SdrObject and/or SdrPage. May return 0L like the default
252         // implementations do. Needs to be overloaded as needed.
TryToGetSdrObject() const253         SdrObject* ViewContact::TryToGetSdrObject() const
254         {
255             return 0L;
256         }
257 
TryToGetSdrPage() const258         SdrPage* ViewContact::TryToGetSdrPage() const
259         {
260             return 0L;
261         }
262 
263         //////////////////////////////////////////////////////////////////////////////
264         // primitive stuff
265 
createViewIndependentPrimitive2DSequence() const266         drawinglayer::primitive2d::Primitive2DSequence ViewContact::createViewIndependentPrimitive2DSequence() const
267         {
268             // This is the default impelemtation and should never be called (see header). If this is called,
269             // someone implemented a ViewContact (VC) visualisation object without defining the visualisation by
270             // providing a seqence of primitives -> which cannot be correct.
271             // Since we have no access to any known model data here, the default implementation creates a yellow placeholder
272             // hairline polygon with a default size of (1000, 1000, 5000, 3000)
273             DBG_ERROR("ViewContact::createViewIndependentPrimitive2DSequence(): Never call the fallback base implementation, this is always an error (!)");
274             const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(1000.0, 1000.0, 5000.0, 3000.0)));
275             const basegfx::BColor aYellow(1.0, 1.0, 0.0);
276             const drawinglayer::primitive2d::Primitive2DReference xReference(
277                 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOutline, aYellow));
278 
279             return drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
280         }
281 
getViewIndependentPrimitive2DSequence() const282         drawinglayer::primitive2d::Primitive2DSequence ViewContact::getViewIndependentPrimitive2DSequence() const
283         {
284             // local up-to-date checks. Create new list and compare.
285             drawinglayer::primitive2d::Primitive2DSequence xNew(createViewIndependentPrimitive2DSequence());
286 
287             if(xNew.hasElements())
288             {
289                 // allow evtl. embedding in object-specific infos, e.g. Name, Title, Description
290                 xNew = embedToObjectSpecificInformation(xNew);
291             }
292 
293             if(!drawinglayer::primitive2d::arePrimitive2DSequencesEqual(mxViewIndependentPrimitive2DSequence, xNew))
294             {
295                 // has changed, copy content
296                 const_cast< ViewContact* >(this)->mxViewIndependentPrimitive2DSequence = xNew;
297             }
298 
299             // return current Primitive2DSequence
300             return mxViewIndependentPrimitive2DSequence;
301         }
302 
303         // add Gluepoints (if available)
createGluePointPrimitive2DSequence() const304         drawinglayer::primitive2d::Primitive2DSequence ViewContact::createGluePointPrimitive2DSequence() const
305         {
306             // default returns empty reference
307             return drawinglayer::primitive2d::Primitive2DSequence();
308         }
309 
embedToObjectSpecificInformation(const drawinglayer::primitive2d::Primitive2DSequence & rSource) const310         drawinglayer::primitive2d::Primitive2DSequence ViewContact::embedToObjectSpecificInformation(const drawinglayer::primitive2d::Primitive2DSequence& rSource) const
311         {
312             // nothing to do for default
313             return rSource;
314         }
315 
flushViewObjectContacts(bool bWithHierarchy)316         void ViewContact::flushViewObjectContacts(bool bWithHierarchy)
317         {
318             if(bWithHierarchy)
319             {
320                 // flush DrawingLayer hierarchy
321                 const sal_uInt32 nCount(GetObjectCount());
322 
323                 for(sal_uInt32 a(0); a < nCount; a++)
324                 {
325                     ViewContact& rChild = GetViewContact(a);
326                     rChild.flushViewObjectContacts(bWithHierarchy);
327                 }
328             }
329 
330             // delete local VOCs
331             deleteAllVOCs();
332         }
333     } // end of namespace contact
334 } // end of namespace sdr
335 
336 //////////////////////////////////////////////////////////////////////////////
337 // eof
338