merge the formfield patch from ooo-build
[ooovba.git] / toolkit / source / layout / core / proplist.cxx
blob483730ba2710a0af55256d189c931096a2455aa5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile$
11 * $Revision$
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include "proplist.hxx"
34 #include <rtl/ustrbuf.hxx>
35 #include <toolkit/dllapi.h>
36 #include <com/sun/star/awt/WindowAttribute.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/awt/XVclWindowPeer.hpp>
39 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
40 #include <tools/debug.hxx>
42 #include "helper.hxx"
44 #if TEST_LAYOUT && !defined( DBG_UTIL )
45 #undef DBG_ERROR
46 #define DBG_ERROR OSL_TRACE
47 #undef DBG_ERROR1
48 #define DBG_ERROR1 OSL_TRACE
49 #undef DBG_ERROR2
50 #define DBG_ERROR2 OSL_TRACE
51 #endif /* TEST_LAYOUT && !DBG_UTIL */
53 namespace layoutimpl
56 using namespace com::sun::star;
57 using rtl::OString;
58 using rtl::OUString;
59 using rtl::OUStringBuffer;
61 namespace prophlp
64 bool TOOLKIT_DLLPUBLIC
65 canHandleProps( const uno::Reference< uno::XInterface > &xPeer )
67 uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY );
68 if ( xPropSet.is() )
69 return true;
70 uno::Reference< beans::XPropertySetInfo > xInfo( xPeer, uno::UNO_QUERY );
71 uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY );
72 return xInfo.is() && xVclPeer.is();
75 uno::Reference< beans::XPropertySetInfo > TOOLKIT_DLLPUBLIC
76 queryPropertyInfo(
77 const uno::Reference< uno::XInterface > &xPeer )
79 uno::Reference< beans::XPropertySetInfo > xInfo( xPeer, uno::UNO_QUERY );
80 if ( !xInfo.is() )
82 uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY );
83 if ( xPropSet.is() )
84 xInfo = xPropSet->getPropertySetInfo();
86 return xInfo;
89 void TOOLKIT_DLLPUBLIC
90 setProperty( const uno::Reference< uno::XInterface > &xPeer,
91 const OUString &rName, uno::Any aValue )
93 uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY );
94 if ( xVclPeer.is() )
95 xVclPeer->setProperty( rName, aValue );
96 else
98 uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY );
99 xPropSet->setPropertyValue( rName, aValue );
103 uno::Any TOOLKIT_DLLPUBLIC
104 getProperty( const uno::Reference< uno::XInterface > &xPeer,
105 const OUString &rName )
107 uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY );
108 if ( xVclPeer.is() )
109 return xVclPeer->getProperty( rName );
111 uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY );
112 return xPropSet->getPropertyValue( rName );
115 } // namespace prophlp
118 /* Given a string and a type, it converts the string to the type, and returns
119 it encapsulated in Any. */
120 uno::Any anyFromString( OUString const& value, uno::Type const& type )
122 sal_Int16 radix = 10;
123 OUString intval = value;
124 if ( value.getLength() > 2 && value[0] == '0' && value[1] == 'x' )
125 intval = value.copy( 2 ), radix = 16;
126 else if ( value.getLength() > 1 && value[0] == '#' )
127 intval = value.copy( 1 ), radix = 16;
128 switch ( type.getTypeClass() )
130 case uno::TypeClass_CHAR:
131 return uno::makeAny( value.toChar() );
132 case uno::TypeClass_BOOLEAN:
133 if ( value == OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) ) )
134 return uno::makeAny( true );
135 else if ( value == OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) ) )
136 return uno::makeAny( false );
137 break; // ends switch, throws exception
138 case uno::TypeClass_BYTE:
139 return uno::makeAny( ( sal_uInt8 ) intval.toInt32( radix ) );
140 case uno::TypeClass_SHORT:
141 return uno::makeAny( ( sal_Int16 ) intval.toInt32( radix ) );
142 case uno::TypeClass_UNSIGNED_SHORT:
143 return uno::makeAny( ( sal_uInt16 ) intval.toInt32( radix ) );
144 case uno::TypeClass_ENUM:
145 return uno::makeAny( ( sal_Int16 ) intval.toInt32( radix ) );
146 case uno::TypeClass_LONG:
147 return uno::makeAny( ( sal_Int32 ) intval.toInt32( radix ) );
148 case uno::TypeClass_UNSIGNED_LONG:
149 return uno::makeAny( ( sal_uInt32 ) intval.toInt32( radix ) );
150 case uno::TypeClass_HYPER:
151 return uno::makeAny( ( sal_Int64 ) intval.toInt64( radix ) );
152 case uno::TypeClass_UNSIGNED_HYPER:
153 return uno::makeAny( ( sal_uInt16 ) intval.toInt64( radix ) );
154 case uno::TypeClass_FLOAT:
155 return uno::makeAny( value.toFloat() );
156 case uno::TypeClass_DOUBLE:
157 return uno::makeAny( value.toDouble() );
158 case uno::TypeClass_STRING:
159 return uno::makeAny( value );
160 case uno::TypeClass_CONSTANT:
161 return uno::makeAny( intval.toInt32( radix ) );
162 case uno::TypeClass_INTERFACE:
163 return uno::makeAny( loadGraphic( OUSTRING_CSTR( value ) ) );
164 case uno::TypeClass_SEQUENCE:
166 sal_Int32 i = 0;
167 bool escaped = false, first = true;
168 OUString item, token;
169 std::list< OUString > values;
172 token = value.getToken( 0, ':', i );
174 if ( !token.getLength() && !escaped )
176 escaped = true;
177 item += OUString( ':' );
179 else if ( escaped )
181 escaped = false;
182 item += token;
184 else
186 if ( !first )
187 values.push_back( item );
188 item = token;
190 first = false;
192 while ( i >= 0 );
193 if ( item.getLength() )
194 values.push_back( item );
196 uno::Sequence< OUString > seq( values.size() );
197 i = 0;
198 for ( std::list< OUString >::const_iterator it = values.begin();
199 it != values.end(); it++, i++ )
200 seq[ i ] = *it;
202 return uno::makeAny( seq );
205 default:
206 DBG_ERROR1( "ERROR: unknown property type of value: `%s'\n", OUSTRING_CSTR( value ) );
207 break;
209 throw uno::RuntimeException();
212 /* Converts the XML naming scheme to UNO's, for legacy compatibility
213 (so, ergo, "one-two-three-four" -> "OneTwoThreeFour"). */
214 static OUString toUnoNaming ( OUString const &string )
216 OUStringBuffer buffer( string.getLength() );
217 sal_Unicode *str = string.pData->buffer;
218 bool capitalize = true;
220 for ( int i = 0; i < string.getLength(); i++ )
222 if ( i == 0 && str[0] == '_' )
223 /* Skip translate-me prefix. */
224 continue;
225 if ( str[i] == '-' )
226 capitalize = true;
227 else
229 if ( capitalize && str[i] >= 'a' && str[i] <= 'z' )
230 buffer.append( (sal_Unicode ) ( str[i] - 'a' + 'A' ) );
231 else
232 buffer.append( (sal_Unicode ) str[i] );
233 capitalize = false;
237 return buffer.makeStringAndClear();
241 * convert incoming XML style property names, to AWT style property names.
242 * convert the values based on introspection information.
243 * apply to either an XPropertySet or an XPropertySetInfo | XVclWindowPeer
244 * aggregate.
246 void
247 setProperties( uno::Reference< uno::XInterface > const& xPeer,
248 PropList const& rProps )
250 if ( !prophlp::canHandleProps( xPeer ) )
252 DBG_ERROR( "Error: setProperties - bad handle ignoring props:\n" );
253 for ( PropList::const_iterator it = rProps.begin(); it != rProps.end();
254 it++ )
256 DBG_ERROR2( "%s=%s\n", OUSTRING_CSTR( it->first ), OUSTRING_CSTR( it->second ) );
258 return;
261 for ( PropList::const_iterator it = rProps.begin(); it != rProps.end();
262 it++ )
263 setProperty( xPeer, it->first, it->second );
266 void
267 setProperty( uno::Reference< uno::XInterface > const& xPeer,
268 OUString const& attr, OUString const& value )
270 OUString unoAttr = toUnoNaming( attr );
272 OSL_TRACE( "setting %s=%s", OUSTRING_CSTR( attr ), OUSTRING_CSTR( value ) );
273 // get a Property object
274 beans::Property prop;
277 uno::Reference< beans::XPropertySetInfo > xInfo
278 = prophlp::queryPropertyInfo( xPeer );
279 prop = xInfo->getPropertyByName( unoAttr );
281 catch( beans::UnknownPropertyException & )
283 DBG_ERROR1( "Warning: unknown attribute: `%s'\n", OUSTRING_CSTR( unoAttr ) );
284 return;
287 if ( prop.Name.getLength() <= 0 )
289 DBG_ERROR1( "Warning: missing prop: `%s'\n", OUSTRING_CSTR( unoAttr ) );
290 return;
293 // encapsulates value in an uno::Any
294 uno::Any any;
297 any = anyFromString( value, prop.Type );
299 catch( uno::RuntimeException & )
301 DBG_ERROR5( "Warning: %s( %s )( %s ) attribute is of type %s( rejected: %s )\n", OUSTRING_CSTR( unoAttr ), OUSTRING_CSTR( value ), OUSTRING_CSTR( prop.Name ), OUSTRING_CSTR( prop.Type.getTypeName() ), OUSTRING_CSTR( value ) );
302 return;
305 // sets value on property
308 prophlp::setProperty( xPeer, unoAttr, any );
310 catch( ... )
312 DBG_ERROR2( "Warning: cannot set attribute %s to %s \n", OUSTRING_CSTR( unoAttr ), OUSTRING_CSTR( value ) );
319 struct AttributesMap
321 const char *name;
322 long value;
323 bool windowAttr;
325 static const AttributesMap attribsMap[] =
327 { "autohscroll", awt::VclWindowPeerAttribute::AUTOHSCROLL, false },
328 { "autovscroll", awt::VclWindowPeerAttribute::AUTOVSCROLL, false },
329 { "center", awt::VclWindowPeerAttribute::CENTER, false },
330 { "clipchildren", awt::VclWindowPeerAttribute::CLIPCHILDREN, false },
331 { "closeable", awt::WindowAttribute::CLOSEABLE, true },
332 { "defbutton", awt::VclWindowPeerAttribute::DEFBUTTON, false },
333 { "dropdown", awt::VclWindowPeerAttribute::DROPDOWN, false },
334 { "fullsize", awt::WindowAttribute::FULLSIZE, true }, //FIXME?
335 { "group", awt::VclWindowPeerAttribute::GROUP, false },
336 { "has_border", awt::WindowAttribute::BORDER, true },
337 { "hscroll", awt::VclWindowPeerAttribute::HSCROLL, false },
338 { "left", awt::VclWindowPeerAttribute::LEFT, false },
339 { "moveable", awt::WindowAttribute::MOVEABLE, true },
340 { "noborder", awt::VclWindowPeerAttribute::NOBORDER, false },
341 { "nolabel", awt::VclWindowPeerAttribute::NOLABEL, false },
342 { "optimumsize", awt::WindowAttribute::OPTIMUMSIZE, false },
343 { "readonly", awt::VclWindowPeerAttribute::READONLY, false },
344 { "right", awt::VclWindowPeerAttribute::RIGHT, false },
345 { "show", awt::WindowAttribute::SHOW, true },
346 { "sizeable", awt::WindowAttribute::SIZEABLE, true },
347 { "sort", awt::VclWindowPeerAttribute::SORT, false },
348 { "spin", awt::VclWindowPeerAttribute::SPIN, false },
349 { "vscroll", awt::VclWindowPeerAttribute::VSCROLL, false },
351 // cutting on OK, YES_NO_CANCEL and related obsite attributes...
353 static const int attribsMapLen = sizeof( attribsMap ) / sizeof( AttributesMap );
355 #if 0
356 long getAttribute( const OUString &rName, bool bTopWindow )
359 int min = 0, max = attribsMapLen - 1, mid, cmp;
362 mid = min +( max - min )/2;
363 cmp = rName.compareToAscii( attribsMap[ mid ].name );
364 if ( cmp > 0 )
365 min = mid+1;
366 else if ( cmp < 0 )
367 max = mid-1;
368 else
370 if ( bTopWindow || attribsMap[ mid ].value )
371 return attribsMap[ mid ].windowAttr;
372 return 0;
375 while ( min <= max );
376 return 0;
378 #endif
380 void propsFromAttributes( const uno::Reference<xml::input::XAttributes> & xAttributes,
381 PropList &rProps, sal_Int32 nNamespace )
383 sal_Int32 nAttrs = xAttributes->getLength();
384 for ( sal_Int32 i = 0; i < nAttrs; i++ )
386 if ( nNamespace != xAttributes->getUidByIndex( i ) )
387 continue;
389 std::pair< OUString, OUString > aElem
390 ( xAttributes->getLocalNameByIndex( i ),
391 xAttributes->getValueByIndex( i ) );
393 if ( aElem.first.getLength() > 0 ) // namespace bits ..
394 rProps.push_back( aElem );
398 bool
399 findAndRemove( const char *pAttr, PropList &rProps, OUString &rValue )
401 PropList::iterator it;
402 OUString aName = OUString::createFromAscii( pAttr );
404 for ( it = rProps.begin(); it != rProps.end(); it++ )
406 if ( it->first.equalsIgnoreAsciiCase( aName )
407 || it->first.equalsIgnoreAsciiCase( OUString::createFromAscii ("_") + aName ) )
409 rValue = it->second;
410 rProps.erase( it );
411 return true;
414 rValue = OUString();
415 return false;
418 long
419 getAttributeProps( PropList &rProps )
421 long nAttrs = 0;
422 OUString aValue;
424 OUString trueStr( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
426 if ( findAndRemove( "show", rProps, aValue ) &&
427 aValue.equalsIgnoreAsciiCase(
428 OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) ) ) )
430 else
431 nAttrs |= awt::WindowAttribute::SHOW;
433 for ( int i = 0; i < attribsMapLen; i++ )
435 if ( findAndRemove( attribsMap[i].name, rProps, aValue ) )
437 if ( aValue.equalsIgnoreAsciiCase( trueStr ) )
438 nAttrs |= attribsMap[i].value;
442 if ( findAndRemove( "align", rProps, aValue ) )
444 sal_Int32 nVal = aValue.toInt32();
446 if ( nVal == 0 /* PROPERTY_ALIGN_LEFT */ )
447 nAttrs |= awt::VclWindowPeerAttribute::LEFT;
448 else if ( nVal == 1 /* PROPERTY_ALIGN_CENTER */ )
449 nAttrs |= awt::VclWindowPeerAttribute::CENTER;
450 else if ( nVal == 2 )
451 nAttrs |= awt::VclWindowPeerAttribute::RIGHT;
454 return nAttrs;