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_chart2.hxx"
26 #include "PropertyHelper.hxx"
27 #include "ContainerHelper.hxx"
28 #include "macros.hxx"
29 #include <com/sun/star/beans/PropertyAttribute.hpp>
30 #include <com/sun/star/container/XNameContainer.hpp>
31 
32 #include <vector>
33 #include <algorithm>
34 #include <functional>
35 
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::beans;
38 using ::rtl::OUString;
39 using ::com::sun::star::uno::Any;
40 using ::com::sun::star::uno::Reference;
41 using ::com::sun::star::uno::Sequence;
42 
43 namespace
44 {
45 struct lcl_EqualsElement : public ::std::unary_function< OUString, bool >
46 {
lcl_EqualsElement__anon8f3fdcb80111::lcl_EqualsElement47     explicit lcl_EqualsElement( const Any & rValue, const Reference< container::XNameAccess > & xAccess )
48             : m_aValue( rValue ), m_xAccess( xAccess )
49     {
50         OSL_ASSERT( m_xAccess.is());
51     }
52 
operator ()__anon8f3fdcb80111::lcl_EqualsElement53     bool operator() ( const OUString & rName )
54     {
55         try
56         {
57             return (m_xAccess->getByName( rName ) == m_aValue);
58         }
59         catch( const uno::Exception & ex )
60         {
61             ASSERT_EXCEPTION( ex );
62         }
63         return false;
64     }
65 
66 private:
67     Any m_aValue;
68     Reference< container::XNameAccess > m_xAccess;
69 };
70 
71 struct lcl_StringMatches : public ::std::unary_function< OUString ,bool >
72 {
lcl_StringMatches__anon8f3fdcb80111::lcl_StringMatches73     lcl_StringMatches( const OUString & rCmpStr ) :
74             m_aCmpStr( rCmpStr )
75     {}
76 
operator ()__anon8f3fdcb80111::lcl_StringMatches77     bool operator() ( const OUString & rStr )
78     {
79         return rStr.match( m_aCmpStr );
80     }
81 
82 private:
83     OUString m_aCmpStr;
84 };
85 
86 struct lcl_OUStringRestToInt32 : public ::std::unary_function< OUString, sal_Int32 >
87 {
lcl_OUStringRestToInt32__anon8f3fdcb80111::lcl_OUStringRestToInt3288     lcl_OUStringRestToInt32( sal_Int32 nPrefixLength ) :
89             m_nPrefixLength( nPrefixLength )
90     {}
operator ()__anon8f3fdcb80111::lcl_OUStringRestToInt3291     sal_Int32 operator() ( const OUString & rStr )
92     {
93         if( m_nPrefixLength > rStr.getLength() )
94             return 0;
95         return rStr.copy( m_nPrefixLength ).toInt32( 10 /* radix */ );
96     }
97 private:
98     sal_Int32 m_nPrefixLength;
99 };
100 
101 /** adds a fill gradient, fill hatch, fill bitmap, fill transparency gradient,
102     line dash or line marker to the corresponding name container with a unique
103     name.
104 
105     @param rPrefix
106         The prefix used for automated name generation.
107 
108     @param rPreferredName
109         If this string is not empty it is used as name if it is unique in the
110         table. Otherwise a new name is generated using pPrefix.
111 
112     @return the new name under which the property was stored in the table
113 */
lcl_addNamedPropertyUniqueNameToTable(const Any & rValue,const Reference<container::XNameContainer> & xNameContainer,const OUString & rPrefix,const OUString & rPreferredName)114 OUString lcl_addNamedPropertyUniqueNameToTable(
115     const Any & rValue,
116     const Reference< container::XNameContainer > & xNameContainer,
117     const OUString & rPrefix,
118     const OUString & rPreferredName )
119 {
120     if( ! xNameContainer.is() ||
121         ! rValue.hasValue() ||
122         ( rValue.getValueType() != xNameContainer->getElementType()))
123         return rPreferredName;
124 
125     try
126     {
127         Reference< container::XNameAccess > xNameAccess( xNameContainer, uno::UNO_QUERY_THROW );
128         ::std::vector< OUString > aNames( ::chart::ContainerHelper::SequenceToVector( xNameAccess->getElementNames()));
129         ::std::vector< OUString >::const_iterator aIt(
130             ::std::find_if( aNames.begin(), aNames.end(), lcl_EqualsElement( rValue, xNameAccess )));
131 
132         // element not found in container
133         if( aIt == aNames.end())
134         {
135             OUString aUniqueName;
136 
137             // check if preferred name is already used
138             if( !rPreferredName.isEmpty() )
139             {
140                 aIt = ::std::find( aNames.begin(), aNames.end(), rPreferredName );
141                 if( aIt == aNames.end())
142                     aUniqueName = rPreferredName;
143             }
144 
145             if( aUniqueName.isEmpty() )
146             {
147                 // create a unique id using the prefix plus a number
148                 ::std::vector< sal_Int32 > aNumbers;
149                 ::std::vector< OUString >::iterator aNonConstIt(
150                     ::std::partition( aNames.begin(), aNames.end(), lcl_StringMatches( rPrefix )));
151                 ::std::transform( aNames.begin(), aNonConstIt,
152                                   back_inserter( aNumbers ),
153                                   lcl_OUStringRestToInt32( rPrefix.getLength() ));
154                 ::std::vector< sal_Int32 >::const_iterator aMaxIt(
155                     ::std::max_element( aNumbers.begin(), aNumbers.end()));
156 
157                 sal_Int32 nIndex = 1;
158                 if( aMaxIt != aNumbers.end())
159                     nIndex = (*aMaxIt) + 1;
160 
161                 aUniqueName = rPrefix + OUString::valueOf( nIndex );
162             }
163 
164             OSL_ASSERT( !aUniqueName.isEmpty() );
165             xNameContainer->insertByName( aUniqueName, rValue );
166             return aUniqueName;
167         }
168         else
169             // element found => return name
170             return *aIt;
171     }
172     catch( const uno::Exception & ex )
173     {
174         ASSERT_EXCEPTION( ex );
175     }
176 
177     return rPreferredName;
178 }
179 
180 } // anonymous namespace
181 
182 namespace chart
183 {
184 namespace PropertyHelper
185 {
186 
addLineDashUniqueNameToTable(const Any & rValue,const Reference<lang::XMultiServiceFactory> & xFact,const OUString & rPreferredName)187 OUString addLineDashUniqueNameToTable(
188     const Any & rValue,
189     const Reference< lang::XMultiServiceFactory > & xFact,
190     const OUString & rPreferredName )
191 {
192     if( xFact.is())
193     {
194         Reference< container::XNameContainer > xNameCnt(
195             xFact->createInstance( C2U( "com.sun.star.drawing.DashTable" )),
196             uno::UNO_QUERY );
197         if( xNameCnt.is())
198             return lcl_addNamedPropertyUniqueNameToTable(
199                 rValue, xNameCnt, C2U( "ChartDash " ), rPreferredName );
200     }
201     return OUString();
202 }
203 
addGradientUniqueNameToTable(const Any & rValue,const Reference<lang::XMultiServiceFactory> & xFact,const OUString & rPreferredName)204 OUString addGradientUniqueNameToTable(
205     const Any & rValue,
206     const Reference< lang::XMultiServiceFactory > & xFact,
207     const OUString & rPreferredName )
208 {
209     if( xFact.is())
210     {
211         Reference< container::XNameContainer > xNameCnt(
212             xFact->createInstance( C2U( "com.sun.star.drawing.GradientTable" )),
213             uno::UNO_QUERY );
214         if( xNameCnt.is())
215             return lcl_addNamedPropertyUniqueNameToTable(
216                 rValue, xNameCnt, C2U( "ChartGradient " ), rPreferredName );
217     }
218     return OUString();
219 }
220 
221 
addTransparencyGradientUniqueNameToTable(const Any & rValue,const Reference<lang::XMultiServiceFactory> & xFact,const OUString & rPreferredName)222 OUString addTransparencyGradientUniqueNameToTable(
223     const Any & rValue,
224     const Reference< lang::XMultiServiceFactory > & xFact,
225     const OUString & rPreferredName )
226 {
227     if( xFact.is())
228     {
229         Reference< container::XNameContainer > xNameCnt(
230             xFact->createInstance( C2U( "com.sun.star.drawing.TransparencyGradientTable" )),
231             uno::UNO_QUERY );
232         if( xNameCnt.is())
233             return lcl_addNamedPropertyUniqueNameToTable(
234                 rValue, xNameCnt, C2U( "ChartTransparencyGradient " ), rPreferredName );
235     }
236     return OUString();
237 }
238 
addHatchUniqueNameToTable(const Any & rValue,const Reference<lang::XMultiServiceFactory> & xFact,const OUString & rPreferredName)239 OUString addHatchUniqueNameToTable(
240     const Any & rValue,
241     const Reference< lang::XMultiServiceFactory > & xFact,
242     const OUString & rPreferredName )
243 {
244     if( xFact.is())
245     {
246         Reference< container::XNameContainer > xNameCnt(
247             xFact->createInstance( C2U( "com.sun.star.drawing.HatchTable" )),
248             uno::UNO_QUERY );
249         if( xNameCnt.is())
250             return lcl_addNamedPropertyUniqueNameToTable(
251                 rValue, xNameCnt, C2U( "ChartHatch " ), rPreferredName );
252     }
253     return OUString();
254 }
255 
addBitmapUniqueNameToTable(const Any & rValue,const Reference<lang::XMultiServiceFactory> & xFact,const OUString & rPreferredName)256 OUString addBitmapUniqueNameToTable(
257     const Any & rValue,
258     const Reference< lang::XMultiServiceFactory > & xFact,
259     const OUString & rPreferredName )
260 {
261     if( xFact.is())
262     {
263         Reference< container::XNameContainer > xNameCnt(
264             xFact->createInstance( C2U( "com.sun.star.drawing.BitmapTable" )),
265             uno::UNO_QUERY );
266         if( xNameCnt.is())
267             return lcl_addNamedPropertyUniqueNameToTable(
268                 rValue, xNameCnt, C2U( "ChartBitmap " ), rPreferredName );
269     }
270     return OUString();
271 }
272 
273 // ----------------------------------------
274 
setPropertyValueAny(tPropertyValueMap & rOutMap,tPropertyValueMapKey key,const uno::Any & rAny)275 void setPropertyValueAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const uno::Any & rAny )
276 {
277     tPropertyValueMap::iterator aIt( rOutMap.find( key ));
278     if( aIt == rOutMap.end())
279         rOutMap.insert( tPropertyValueMap::value_type( key, rAny ));
280     else
281         (*aIt).second = rAny;
282 }
283 
284 template<>
setPropertyValue(tPropertyValueMap & rOutMap,tPropertyValueMapKey key,const::com::sun::star::uno::Any & rAny)285     void setPropertyValue< ::com::sun::star::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const ::com::sun::star::uno::Any & rAny )
286 {
287     setPropertyValueAny( rOutMap, key, rAny );
288 }
289 
setPropertyValueDefaultAny(tPropertyValueMap & rOutMap,tPropertyValueMapKey key,const uno::Any & rAny)290 void setPropertyValueDefaultAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const uno::Any & rAny )
291 {
292     OSL_ENSURE( rOutMap.end() == rOutMap.find( key ), "Default already exists for property" );
293     setPropertyValue( rOutMap, key, rAny );
294 }
295 
296 template<>
setPropertyValueDefault(tPropertyValueMap & rOutMap,tPropertyValueMapKey key,const::com::sun::star::uno::Any & rAny)297     void setPropertyValueDefault< ::com::sun::star::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const ::com::sun::star::uno::Any & rAny )
298 {
299     setPropertyValueDefaultAny( rOutMap, key, rAny );
300 }
301 
302 
setEmptyPropertyValueDefault(tPropertyValueMap & rOutMap,tPropertyValueMapKey key)303 void setEmptyPropertyValueDefault( tPropertyValueMap & rOutMap, tPropertyValueMapKey key )
304 {
305     setPropertyValueDefault( rOutMap, key, uno::Any());
306 }
307 
308 } // namespace PropertyHelper
309 
310 } //  namespace chart
311