1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_chart2.hxx" 30 #include "PropertyHelper.hxx" 31 #include "ContainerHelper.hxx" 32 #include "macros.hxx" 33 #include <com/sun/star/beans/PropertyAttribute.hpp> 34 #include <com/sun/star/container/XNameContainer.hpp> 35 36 #include <vector> 37 #include <algorithm> 38 #include <functional> 39 40 using namespace ::com::sun::star; 41 using namespace ::com::sun::star::beans; 42 using ::rtl::OUString; 43 using ::com::sun::star::uno::Any; 44 using ::com::sun::star::uno::Reference; 45 using ::com::sun::star::uno::Sequence; 46 47 namespace 48 { 49 struct lcl_EqualsElement : public ::std::unary_function< OUString, bool > 50 { 51 explicit lcl_EqualsElement( const Any & rValue, const Reference< container::XNameAccess > & xAccess ) 52 : m_aValue( rValue ), m_xAccess( xAccess ) 53 { 54 OSL_ASSERT( m_xAccess.is()); 55 } 56 57 bool operator() ( const OUString & rName ) 58 { 59 try 60 { 61 return (m_xAccess->getByName( rName ) == m_aValue); 62 } 63 catch( const uno::Exception & ex ) 64 { 65 ASSERT_EXCEPTION( ex ); 66 } 67 return false; 68 } 69 70 private: 71 Any m_aValue; 72 Reference< container::XNameAccess > m_xAccess; 73 }; 74 75 struct lcl_StringMatches : public ::std::unary_function< OUString ,bool > 76 { 77 lcl_StringMatches( const OUString & rCmpStr ) : 78 m_aCmpStr( rCmpStr ) 79 {} 80 81 bool operator() ( const OUString & rStr ) 82 { 83 return rStr.match( m_aCmpStr ); 84 } 85 86 private: 87 OUString m_aCmpStr; 88 }; 89 90 struct lcl_OUStringRestToInt32 : public ::std::unary_function< OUString, sal_Int32 > 91 { 92 lcl_OUStringRestToInt32( sal_Int32 nPrefixLength ) : 93 m_nPrefixLength( nPrefixLength ) 94 {} 95 sal_Int32 operator() ( const OUString & rStr ) 96 { 97 if( m_nPrefixLength > rStr.getLength() ) 98 return 0; 99 return rStr.copy( m_nPrefixLength ).toInt32( 10 /* radix */ ); 100 } 101 private: 102 sal_Int32 m_nPrefixLength; 103 }; 104 105 /** adds a fill gradient, fill hatch, fill bitmap, fill transparency gradient, 106 line dash or line marker to the corresponding name container with a unique 107 name. 108 109 @param rPrefix 110 The prefix used for automated name generation. 111 112 @param rPreferredName 113 If this string is not empty it is used as name if it is unique in the 114 table. Otherwise a new name is generated using pPrefix. 115 116 @return the new name under which the property was stored in the table 117 */ 118 OUString lcl_addNamedPropertyUniqueNameToTable( 119 const Any & rValue, 120 const Reference< container::XNameContainer > & xNameContainer, 121 const OUString & rPrefix, 122 const OUString & rPreferredName ) 123 { 124 if( ! xNameContainer.is() || 125 ! rValue.hasValue() || 126 ( rValue.getValueType() != xNameContainer->getElementType())) 127 return rPreferredName; 128 129 try 130 { 131 Reference< container::XNameAccess > xNameAccess( xNameContainer, uno::UNO_QUERY_THROW ); 132 ::std::vector< OUString > aNames( ::chart::ContainerHelper::SequenceToVector( xNameAccess->getElementNames())); 133 ::std::vector< OUString >::const_iterator aIt( 134 ::std::find_if( aNames.begin(), aNames.end(), lcl_EqualsElement( rValue, xNameAccess ))); 135 136 // element not found in container 137 if( aIt == aNames.end()) 138 { 139 OUString aUniqueName; 140 141 // check if preferred name is already used 142 if( rPreferredName.getLength()) 143 { 144 aIt = ::std::find( aNames.begin(), aNames.end(), rPreferredName ); 145 if( aIt == aNames.end()) 146 aUniqueName = rPreferredName; 147 } 148 149 if( ! aUniqueName.getLength()) 150 { 151 // create a unique id using the prefix plus a number 152 ::std::vector< sal_Int32 > aNumbers; 153 ::std::vector< OUString >::iterator aNonConstIt( 154 ::std::partition( aNames.begin(), aNames.end(), lcl_StringMatches( rPrefix ))); 155 ::std::transform( aNames.begin(), aNonConstIt, 156 back_inserter( aNumbers ), 157 lcl_OUStringRestToInt32( rPrefix.getLength() )); 158 ::std::vector< sal_Int32 >::const_iterator aMaxIt( 159 ::std::max_element( aNumbers.begin(), aNumbers.end())); 160 161 sal_Int32 nIndex = 1; 162 if( aMaxIt != aNumbers.end()) 163 nIndex = (*aMaxIt) + 1; 164 165 aUniqueName = rPrefix + OUString::valueOf( nIndex ); 166 } 167 168 OSL_ASSERT( aUniqueName.getLength()); 169 xNameContainer->insertByName( aUniqueName, rValue ); 170 return aUniqueName; 171 } 172 else 173 // element found => return name 174 return *aIt; 175 } 176 catch( const uno::Exception & ex ) 177 { 178 ASSERT_EXCEPTION( ex ); 179 } 180 181 return rPreferredName; 182 } 183 184 } // anonymous namespace 185 186 namespace chart 187 { 188 namespace PropertyHelper 189 { 190 191 OUString addLineDashUniqueNameToTable( 192 const Any & rValue, 193 const Reference< lang::XMultiServiceFactory > & xFact, 194 const OUString & rPreferredName ) 195 { 196 if( xFact.is()) 197 { 198 Reference< container::XNameContainer > xNameCnt( 199 xFact->createInstance( C2U( "com.sun.star.drawing.DashTable" )), 200 uno::UNO_QUERY ); 201 if( xNameCnt.is()) 202 return lcl_addNamedPropertyUniqueNameToTable( 203 rValue, xNameCnt, C2U( "ChartDash " ), rPreferredName ); 204 } 205 return OUString(); 206 } 207 208 OUString addGradientUniqueNameToTable( 209 const Any & rValue, 210 const Reference< lang::XMultiServiceFactory > & xFact, 211 const OUString & rPreferredName ) 212 { 213 if( xFact.is()) 214 { 215 Reference< container::XNameContainer > xNameCnt( 216 xFact->createInstance( C2U( "com.sun.star.drawing.GradientTable" )), 217 uno::UNO_QUERY ); 218 if( xNameCnt.is()) 219 return lcl_addNamedPropertyUniqueNameToTable( 220 rValue, xNameCnt, C2U( "ChartGradient " ), rPreferredName ); 221 } 222 return OUString(); 223 } 224 225 226 OUString addTransparencyGradientUniqueNameToTable( 227 const Any & rValue, 228 const Reference< lang::XMultiServiceFactory > & xFact, 229 const OUString & rPreferredName ) 230 { 231 if( xFact.is()) 232 { 233 Reference< container::XNameContainer > xNameCnt( 234 xFact->createInstance( C2U( "com.sun.star.drawing.TransparencyGradientTable" )), 235 uno::UNO_QUERY ); 236 if( xNameCnt.is()) 237 return lcl_addNamedPropertyUniqueNameToTable( 238 rValue, xNameCnt, C2U( "ChartTransparencyGradient " ), rPreferredName ); 239 } 240 return OUString(); 241 } 242 243 OUString addHatchUniqueNameToTable( 244 const Any & rValue, 245 const Reference< lang::XMultiServiceFactory > & xFact, 246 const OUString & rPreferredName ) 247 { 248 if( xFact.is()) 249 { 250 Reference< container::XNameContainer > xNameCnt( 251 xFact->createInstance( C2U( "com.sun.star.drawing.HatchTable" )), 252 uno::UNO_QUERY ); 253 if( xNameCnt.is()) 254 return lcl_addNamedPropertyUniqueNameToTable( 255 rValue, xNameCnt, C2U( "ChartHatch " ), rPreferredName ); 256 } 257 return OUString(); 258 } 259 260 OUString addBitmapUniqueNameToTable( 261 const Any & rValue, 262 const Reference< lang::XMultiServiceFactory > & xFact, 263 const OUString & rPreferredName ) 264 { 265 if( xFact.is()) 266 { 267 Reference< container::XNameContainer > xNameCnt( 268 xFact->createInstance( C2U( "com.sun.star.drawing.BitmapTable" )), 269 uno::UNO_QUERY ); 270 if( xNameCnt.is()) 271 return lcl_addNamedPropertyUniqueNameToTable( 272 rValue, xNameCnt, C2U( "ChartBitmap " ), rPreferredName ); 273 } 274 return OUString(); 275 } 276 277 // ---------------------------------------- 278 279 void setPropertyValueAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const uno::Any & rAny ) 280 { 281 tPropertyValueMap::iterator aIt( rOutMap.find( key )); 282 if( aIt == rOutMap.end()) 283 rOutMap.insert( tPropertyValueMap::value_type( key, rAny )); 284 else 285 (*aIt).second = rAny; 286 } 287 288 template<> 289 void setPropertyValue< ::com::sun::star::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const ::com::sun::star::uno::Any & rAny ) 290 { 291 setPropertyValueAny( rOutMap, key, rAny ); 292 } 293 294 void setPropertyValueDefaultAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const uno::Any & rAny ) 295 { 296 OSL_ENSURE( rOutMap.end() == rOutMap.find( key ), "Default already exists for property" ); 297 setPropertyValue( rOutMap, key, rAny ); 298 } 299 300 template<> 301 void setPropertyValueDefault< ::com::sun::star::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const ::com::sun::star::uno::Any & rAny ) 302 { 303 setPropertyValueDefaultAny( rOutMap, key, rAny ); 304 } 305 306 307 void setEmptyPropertyValueDefault( tPropertyValueMap & rOutMap, tPropertyValueMapKey key ) 308 { 309 setPropertyValueDefault( rOutMap, key, uno::Any()); 310 } 311 312 } // namespace PropertyHelper 313 314 } // namespace chart 315