LibreOffice Module svx (master)  1
customshapeitem.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 
20 #include <sal/config.h>
21 
22 #include <o3tl/any.hxx>
23 #include <svx/sdasitm.hxx>
24 
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 
27 using namespace ::std;
28 using namespace com::sun::star;
29 
30 
33 {}
34 
35 SdrCustomShapeGeometryItem::SdrCustomShapeGeometryItem( const uno::Sequence< beans::PropertyValue >& rVal )
37 {
38  sal_Int32 i, j;
39  aPropSeq = rVal;
40 
41  for ( i = 0; i < aPropSeq.getLength(); i++ )
42  {
43  beans::PropertyValue& rPropVal = aPropSeq[ i ];
44  std::pair<PropertyHashMap::iterator, bool> const ret(
45  aPropHashMap.insert(std::make_pair(rPropVal.Name, i)));
46  assert(ret.second); // serious bug: duplicate xml attribute exported
47  if (!ret.second)
48  {
49  throw uno::RuntimeException(
50  "CustomShapeGeometry has duplicate property " + rPropVal.Name);
51  }
52  if (auto rPropSeq = o3tl::tryAccess<uno::Sequence<beans::PropertyValue>>(
53  rPropVal.Value))
54  {
55  for ( j = 0; j < rPropSeq->getLength(); j++ )
56  {
57  beans::PropertyValue const & rPropVal2 = (*rPropSeq)[ j ];
58  aPropPairHashMap[ PropertyPair( rPropVal.Name, rPropVal2.Name ) ] = j;
59  }
60  }
61  }
62 }
63 
64 css::uno::Any* SdrCustomShapeGeometryItem::GetPropertyValueByName( const OUString& rPropName )
65 {
66  css::uno::Any* pRet = nullptr;
67  PropertyHashMap::iterator aHashIter( aPropHashMap.find( rPropName ) );
68  if ( aHashIter != aPropHashMap.end() )
69  pRet = &aPropSeq[ (*aHashIter).second ].Value;
70  return pRet;
71 }
72 
73 const css::uno::Any* SdrCustomShapeGeometryItem::GetPropertyValueByName( const OUString& rPropName ) const
74 {
75  const css::uno::Any* pRet = nullptr;
76  PropertyHashMap::const_iterator aHashIter( aPropHashMap.find( rPropName ) );
77  if ( aHashIter != aPropHashMap.end() )
78  pRet = &aPropSeq[ (*aHashIter).second ].Value;
79  return pRet;
80 }
81 
82 css::uno::Any* SdrCustomShapeGeometryItem::GetPropertyValueByName( const OUString& rSequenceName, const OUString& rPropName )
83 {
84  css::uno::Any* pRet = nullptr;
85  css::uno::Any* pSeqAny = GetPropertyValueByName( rSequenceName );
86  if ( pSeqAny )
87  {
88  if ( auto rSecSequence = o3tl::tryAccess<css::uno::Sequence<beans::PropertyValue>>(*pSeqAny) )
89  {
90  PropertyPairHashMap::iterator aHashIter( aPropPairHashMap.find( PropertyPair( rSequenceName, rPropName ) ) );
91  if ( aHashIter != aPropPairHashMap.end() )
92  {
93  pRet = &const_cast<css::uno::Sequence<css::beans::PropertyValue> &>(*rSecSequence)[ (*aHashIter).second ].Value;
94  }
95  }
96  }
97  return pRet;
98 }
99 
100 const css::uno::Any* SdrCustomShapeGeometryItem::GetPropertyValueByName( const OUString& rSequenceName, const OUString& rPropName ) const
101 {
102  const css::uno::Any* pRet = nullptr;
103  const css::uno::Any* pSeqAny = GetPropertyValueByName( rSequenceName );
104  if ( pSeqAny )
105  {
106  if ( auto rSecSequence = o3tl::tryAccess<css::uno::Sequence<beans::PropertyValue>>(*pSeqAny) )
107  {
108  PropertyPairHashMap::const_iterator aHashIter( aPropPairHashMap.find( PropertyPair( rSequenceName, rPropName ) ) );
109  if ( aHashIter != aPropPairHashMap.end() )
110  {
111  pRet = &(*rSecSequence)[ (*aHashIter).second ].Value;
112  }
113  }
114  }
115  return pRet;
116 }
117 
118 void SdrCustomShapeGeometryItem::SetPropertyValue( const css::beans::PropertyValue& rPropVal )
119 {
120  css::uno::Any* pAny = GetPropertyValueByName( rPropVal.Name );
121  if ( pAny )
122  { // property is already available
123  if ( auto rSecSequence = o3tl::tryAccess<css::uno::Sequence<beans::PropertyValue>>(*pAny) )
124  { // old property is a sequence->each entry has to be removed from the HashPairMap
125  for ( auto const & i : *rSecSequence )
126  {
127  PropertyPairHashMap::iterator aHashIter( aPropPairHashMap.find( PropertyPair( rPropVal.Name, i.Name ) ) );
128  if ( aHashIter != aPropPairHashMap.end() )
129  aPropPairHashMap.erase( aHashIter );
130  }
131  }
132  *pAny = rPropVal.Value;
133  if ( auto rSecSequence = o3tl::tryAccess<css::uno::Sequence<beans::PropertyValue>>(*pAny) )
134  { // the new property is a sequence->each entry has to be inserted into the HashPairMap
135  for ( sal_Int32 i = 0; i < rSecSequence->getLength(); i++ )
136  {
137  beans::PropertyValue const & rPropVal2 = (*rSecSequence)[ i ];
138  aPropPairHashMap[ PropertyPair( rPropVal.Name, rPropVal2.Name ) ] = i;
139  }
140  }
141  }
142  else
143  { // it's a new property
144  assert(std::none_of(aPropSeq.begin(), aPropSeq.end(),
145  [&rPropVal](beans::PropertyValue const& rVal)
146  { return rVal.Name == rPropVal.Name; } ));
147  sal_uInt32 nIndex = aPropSeq.getLength();
148  aPropSeq.realloc( nIndex + 1 );
149  aPropSeq[ nIndex ] = rPropVal ;
150 
151  aPropHashMap[ rPropVal.Name ] = nIndex;
152  }
153 }
154 
155 void SdrCustomShapeGeometryItem::SetPropertyValue( const OUString& rSequenceName, const css::beans::PropertyValue& rPropVal )
156 {
157  css::uno::Any* pAny = GetPropertyValueByName( rSequenceName, rPropVal.Name );
158  if ( pAny ) // just replacing
159  *pAny = rPropVal.Value;
160  else
161  {
162  css::uno::Any* pSeqAny = GetPropertyValueByName( rSequenceName );
163  if( pSeqAny == nullptr )
164  {
165  css::uno::Sequence < beans::PropertyValue > aSeq;
166  beans::PropertyValue aValue;
167  aValue.Name = rSequenceName;
168  aValue.Value <<= aSeq;
169 
170  assert(std::none_of(aPropSeq.begin(), aPropSeq.end(),
171  [&rSequenceName](beans::PropertyValue const& rV)
172  { return rV.Name == rSequenceName; } ));
173  sal_uInt32 nIndex = aPropSeq.getLength();
174  aPropSeq.realloc( nIndex + 1 );
175  aPropSeq[ nIndex ] = aValue;
176  aPropHashMap[ rSequenceName ] = nIndex;
177 
178  pSeqAny = &aPropSeq[ nIndex ].Value;
179  }
180 
181  if (auto pSecSequence = o3tl::tryAccess<css::uno::Sequence<beans::PropertyValue>>(*pSeqAny))
182  {
183  PropertyPairHashMap::iterator aHashIter(
184  aPropPairHashMap.find(PropertyPair(rSequenceName, rPropVal.Name)));
185  auto& rSeq = const_cast<css::uno::Sequence<css::beans::PropertyValue>&>(*pSecSequence);
186  if (aHashIter != aPropPairHashMap.end())
187  {
188  rSeq[(*aHashIter).second].Value = rPropVal.Value;
189  }
190  else
191  {
192  const sal_Int32 nCount = pSecSequence->getLength();
193  rSeq.realloc(nCount + 1);
194  rSeq[nCount] = rPropVal;
195 
196  aPropPairHashMap[PropertyPair(rSequenceName, rPropVal.Name)] = nCount;
197  }
198  }
199  }
200 }
201 
202 void SdrCustomShapeGeometryItem::ClearPropertyValue( const OUString& rPropName )
203 {
204  if ( aPropSeq.hasElements() )
205  {
206  PropertyHashMap::iterator aHashIter( aPropHashMap.find( rPropName ) );
207  if ( aHashIter != aPropHashMap.end() )
208  {
209  css::uno::Any& rSeqAny = aPropSeq[(*aHashIter).second].Value;
210  if (auto pSecSequence
211  = o3tl::tryAccess<css::uno::Sequence<beans::PropertyValue>>(rSeqAny))
212  {
213  for (const auto& rPropVal : *pSecSequence)
214  {
215  auto _aHashIter(aPropPairHashMap.find(PropertyPair(rPropName, rPropVal.Name)));
216  if (_aHashIter != aPropPairHashMap.end())
217  aPropPairHashMap.erase(_aHashIter); // removing property from pair hashmap
218  }
219  }
220  sal_Int32 nLength = aPropSeq.getLength();
221  if ( nLength )
222  {
223  sal_Int32 nIndex = (*aHashIter).second;
224  if ( nIndex != ( nLength - 1 ) ) // resizing sequence
225  {
226  PropertyHashMap::iterator aHashIter2( aPropHashMap.find( aPropSeq[ nLength - 1 ].Name ) );
227  (*aHashIter2).second = nIndex;
228  aPropSeq[ nIndex ] = aPropSeq[ nLength - 1 ];
229  }
230  aPropSeq.realloc( nLength - 1 );
231  }
232  aPropHashMap.erase( aHashIter ); // removing property from hashmap
233  }
234  }
235 }
236 
238 {
239 }
241 {
242  bool bRet = SfxPoolItem::operator==( rCmp );
243  if ( bRet )
244  bRet = static_cast<const SdrCustomShapeGeometryItem&>(rCmp).aPropSeq == aPropSeq;
245  return bRet;
246 }
247 
249  SfxItemPresentation ePresentation, MapUnit /*eCoreMetric*/,
250  MapUnit /*ePresentationMetric*/, OUString &rText, const IntlWrapper&) const
251 {
252  rText += " ";
253  if ( ePresentation == SfxItemPresentation::Complete )
254  {
255  rText = " " + rText;
256  return true;
257  }
258  else if ( ePresentation == SfxItemPresentation::Nameless )
259  return true;
260  return false;
261 }
262 
264 {
265  return new SdrCustomShapeGeometryItem( aPropSeq );
266 }
267 
269 {
270  rVal <<= aPropSeq;
271  return true;
272 }
273 
274 bool SdrCustomShapeGeometryItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
275 {
276  if ( ! ( rVal >>= aPropSeq ) )
277  return false;
278 
279  for (sal_Int32 i = 0; i < aPropSeq.getLength(); ++i)
280  {
281  const auto& rName = aPropSeq[i].Name;
282  bool isDuplicated = std::any_of(std::next(aPropSeq.begin(), i + 1), aPropSeq.end(),
283  [&rName](const css::beans::PropertyValue& rProp) { return rProp.Name == rName; });
284  if (isDuplicated)
285  {
286  assert(false); // serious bug: duplicate xml attribute exported
287  OUString const name(aPropSeq[i].Name);
288  aPropSeq.realloc(0);
289  throw uno::RuntimeException(
290  "CustomShapeGeometry has duplicate property " + name);
291  }
292  }
293  return true;
294 }
295 
296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetPropertyValue(const css::beans::PropertyValue &rPropVal)
sal_Int32 nIndex
virtual bool GetPresentation(SfxItemPresentation ePresentation, MapUnit eCoreMetric, MapUnit ePresentationMetric, OUString &rText, const IntlWrapper &) const override
virtual bool operator==(const SfxPoolItem &) const =0
PropertyPairHashMap aPropPairHashMap
Definition: sdasitm.hxx:47
OUString Name
virtual bool QueryValue(css::uno::Any &rVal, sal_uInt8 nMemberId=0) const override
virtual bool operator==(const SfxPoolItem &) const override
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
int nCount
std::enable_if< !(detail::IsDerivedReference< T >::value||detail::IsUnoSequenceType< T >::value||std::is_base_of< css::uno::XInterface, T >::value), typename detail::Optional< T >::type >::type tryAccess(css::uno::Any const &any)
std::pair< const OUString, const OUString > PropertyPair
Definition: sdasitm.hxx:36
SfxItemPresentation
constexpr TypedWhichId< SdrCustomShapeGeometryItem > SDRATTR_CUSTOMSHAPE_GEOMETRY(SDRATTR_CUSTOMSHAPE_FIRST+2)
int i
css::uno::Sequence< css::beans::PropertyValue > aPropSeq
Definition: sdasitm.hxx:49
virtual ~SdrCustomShapeGeometryItem() override
PropertyHashMap aPropHashMap
Definition: sdasitm.hxx:46
virtual SdrCustomShapeGeometryItem * Clone(SfxItemPool *pPool=nullptr) const override
virtual bool PutValue(const css::uno::Any &rVal, sal_uInt8 nMemberId) override
unsigned char sal_uInt8
const char * name
Sequence< sal_Int8 > aSeq
css::uno::Any * GetPropertyValueByName(const OUString &rPropName)
MapUnit
sal_Int32 nLength
void ClearPropertyValue(const OUString &rPropertyName)