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 #include "proplist.hxx"
25
26 #include <rtl/ustrbuf.hxx>
27 #include <toolkit/dllapi.h>
28 #include <com/sun/star/awt/WindowAttribute.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/awt/XVclWindowPeer.hpp>
31 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
32 #include <tools/debug.hxx>
33
34 #include "helper.hxx"
35
36 #if TEST_LAYOUT && !defined( DBG_UTIL )
37 #undef DBG_ERROR
38 #define DBG_ERROR OSL_TRACE
39 #undef DBG_ERROR1
40 #define DBG_ERROR1 OSL_TRACE
41 #undef DBG_ERROR2
42 #define DBG_ERROR2 OSL_TRACE
43 #endif /* TEST_LAYOUT && !DBG_UTIL */
44
45 namespace layoutimpl
46 {
47
48 using namespace com::sun::star;
49 using rtl::OString;
50 using rtl::OUString;
51 using rtl::OUStringBuffer;
52
53 namespace prophlp
54 {
55
56 bool TOOLKIT_DLLPUBLIC
canHandleProps(const uno::Reference<uno::XInterface> & xPeer)57 canHandleProps( const uno::Reference< uno::XInterface > &xPeer )
58 {
59 uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY );
60 if ( xPropSet.is() )
61 return true;
62 uno::Reference< beans::XPropertySetInfo > xInfo( xPeer, uno::UNO_QUERY );
63 uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY );
64 return xInfo.is() && xVclPeer.is();
65 }
66
67 uno::Reference< beans::XPropertySetInfo > TOOLKIT_DLLPUBLIC
queryPropertyInfo(const uno::Reference<uno::XInterface> & xPeer)68 queryPropertyInfo(
69 const uno::Reference< uno::XInterface > &xPeer )
70 {
71 uno::Reference< beans::XPropertySetInfo > xInfo( xPeer, uno::UNO_QUERY );
72 if ( !xInfo.is() )
73 {
74 uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY );
75 if ( xPropSet.is() )
76 xInfo = xPropSet->getPropertySetInfo();
77 }
78 return xInfo;
79 }
80
81 void TOOLKIT_DLLPUBLIC
setProperty(const uno::Reference<uno::XInterface> & xPeer,const OUString & rName,uno::Any aValue)82 setProperty( const uno::Reference< uno::XInterface > &xPeer,
83 const OUString &rName, uno::Any aValue )
84 {
85 uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY );
86 if ( xVclPeer.is() )
87 xVclPeer->setProperty( rName, aValue );
88 else
89 {
90 uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY );
91 xPropSet->setPropertyValue( rName, aValue );
92 }
93 }
94
95 uno::Any TOOLKIT_DLLPUBLIC
getProperty(const uno::Reference<uno::XInterface> & xPeer,const OUString & rName)96 getProperty( const uno::Reference< uno::XInterface > &xPeer,
97 const OUString &rName )
98 {
99 uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY );
100 if ( xVclPeer.is() )
101 return xVclPeer->getProperty( rName );
102
103 uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY );
104 return xPropSet->getPropertyValue( rName );
105 }
106
107 } // namespace prophlp
108
109
110 /* Given a string and a type, it converts the string to the type, and returns
111 it encapsulated in Any. */
anyFromString(OUString const & value,uno::Type const & type)112 uno::Any anyFromString( OUString const& value, uno::Type const& type )
113 {
114 sal_Int16 radix = 10;
115 OUString intval = value;
116 if ( value.getLength() > 2 && value[0] == '0' && value[1] == 'x' )
117 intval = value.copy( 2 ), radix = 16;
118 else if ( value.getLength() > 1 && value[0] == '#' )
119 intval = value.copy( 1 ), radix = 16;
120 switch ( type.getTypeClass() )
121 {
122 case uno::TypeClass_CHAR:
123 return uno::makeAny( value.toChar() );
124 case uno::TypeClass_BOOLEAN:
125 if ( value == OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) ) )
126 return uno::makeAny( true );
127 else if ( value == OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) ) )
128 return uno::makeAny( false );
129 break; // ends switch, throws exception
130 case uno::TypeClass_BYTE:
131 return uno::makeAny( ( sal_uInt8 ) intval.toInt32( radix ) );
132 case uno::TypeClass_SHORT:
133 return uno::makeAny( ( sal_Int16 ) intval.toInt32( radix ) );
134 case uno::TypeClass_UNSIGNED_SHORT:
135 return uno::makeAny( ( sal_uInt16 ) intval.toInt32( radix ) );
136 case uno::TypeClass_ENUM:
137 return uno::makeAny( ( sal_Int16 ) intval.toInt32( radix ) );
138 case uno::TypeClass_LONG:
139 return uno::makeAny( ( sal_Int32 ) intval.toInt32( radix ) );
140 case uno::TypeClass_UNSIGNED_LONG:
141 return uno::makeAny( ( sal_uInt32 ) intval.toInt32( radix ) );
142 case uno::TypeClass_HYPER:
143 return uno::makeAny( ( sal_Int64 ) intval.toInt64( radix ) );
144 case uno::TypeClass_UNSIGNED_HYPER:
145 return uno::makeAny( ( sal_uInt16 ) intval.toInt64( radix ) );
146 case uno::TypeClass_FLOAT:
147 return uno::makeAny( value.toFloat() );
148 case uno::TypeClass_DOUBLE:
149 return uno::makeAny( value.toDouble() );
150 case uno::TypeClass_STRING:
151 return uno::makeAny( value );
152 case uno::TypeClass_CONSTANT:
153 return uno::makeAny( intval.toInt32( radix ) );
154 case uno::TypeClass_INTERFACE:
155 return uno::makeAny( loadGraphic( OUSTRING_CSTR( value ) ) );
156 case uno::TypeClass_SEQUENCE:
157 {
158 sal_Int32 i = 0;
159 bool escaped = false, first = true;
160 OUString item, token;
161 std::list< OUString > values;
162 do
163 {
164 token = value.getToken( 0, ':', i );
165
166 if ( !token.getLength() && !escaped )
167 {
168 escaped = true;
169 item += OUString( ':' );
170 }
171 else if ( escaped )
172 {
173 escaped = false;
174 item += token;
175 }
176 else
177 {
178 if ( !first )
179 values.push_back( item );
180 item = token;
181 }
182 first = false;
183 }
184 while ( i >= 0 );
185 if ( item.getLength() )
186 values.push_back( item );
187
188 uno::Sequence< OUString > seq( values.size() );
189 i = 0;
190 for ( std::list< OUString >::const_iterator it = values.begin();
191 it != values.end(); it++, i++ )
192 seq[ i ] = *it;
193
194 return uno::makeAny( seq );
195 }
196
197 default:
198 DBG_ERROR1( "ERROR: unknown property type of value: `%s'\n", OUSTRING_CSTR( value ) );
199 break;
200 }
201 throw uno::RuntimeException();
202 }
203
204 /* Converts the XML naming scheme to UNO's, for legacy compatibility
205 (so, ergo, "one-two-three-four" -> "OneTwoThreeFour"). */
toUnoNaming(OUString const & string)206 static OUString toUnoNaming ( OUString const &string )
207 {
208 OUStringBuffer buffer( string.getLength() );
209 sal_Unicode *str = string.pData->buffer;
210 bool capitalize = true;
211
212 for ( int i = 0; i < string.getLength(); i++ )
213 {
214 if ( i == 0 && str[0] == '_' )
215 /* Skip translate-me prefix. */
216 continue;
217 if ( str[i] == '-' )
218 capitalize = true;
219 else
220 {
221 if ( capitalize && str[i] >= 'a' && str[i] <= 'z' )
222 buffer.append( (sal_Unicode ) ( str[i] - 'a' + 'A' ) );
223 else
224 buffer.append( (sal_Unicode ) str[i] );
225 capitalize = false;
226 }
227 }
228
229 return buffer.makeStringAndClear();
230 }
231
232 /*
233 * convert incoming XML style property names, to AWT style property names.
234 * convert the values based on introspection information.
235 * apply to either an XPropertySet or an XPropertySetInfo | XVclWindowPeer
236 * aggregate.
237 */
238 void
setProperties(uno::Reference<uno::XInterface> const & xPeer,PropList const & rProps)239 setProperties( uno::Reference< uno::XInterface > const& xPeer,
240 PropList const& rProps )
241 {
242 if ( !prophlp::canHandleProps( xPeer ) )
243 {
244 DBG_ERROR( "Error: setProperties - bad handle ignoring props:\n" );
245 for ( PropList::const_iterator it = rProps.begin(); it != rProps.end();
246 it++ )
247 {
248 DBG_ERROR2( "%s=%s\n", OUSTRING_CSTR( it->first ), OUSTRING_CSTR( it->second ) );
249 }
250 return;
251 }
252
253 for ( PropList::const_iterator it = rProps.begin(); it != rProps.end();
254 it++ )
255 setProperty( xPeer, it->first, it->second );
256 }
257
258 void
setProperty(uno::Reference<uno::XInterface> const & xPeer,OUString const & attr,OUString const & value)259 setProperty( uno::Reference< uno::XInterface > const& xPeer,
260 OUString const& attr, OUString const& value )
261 {
262 OUString unoAttr = toUnoNaming( attr );
263
264 OSL_TRACE( "setting %s=%s", OUSTRING_CSTR( attr ), OUSTRING_CSTR( value ) );
265 // get a Property object
266 beans::Property prop;
267 try
268 {
269 uno::Reference< beans::XPropertySetInfo > xInfo
270 = prophlp::queryPropertyInfo( xPeer );
271 prop = xInfo->getPropertyByName( unoAttr );
272 }
273 catch( beans::UnknownPropertyException & )
274 {
275 DBG_ERROR1( "Warning: unknown attribute: `%s'\n", OUSTRING_CSTR( unoAttr ) );
276 return;
277 }
278
279 if ( prop.Name.getLength() <= 0 )
280 {
281 DBG_ERROR1( "Warning: missing prop: `%s'\n", OUSTRING_CSTR( unoAttr ) );
282 return;
283 }
284
285 // encapsulates value in an uno::Any
286 uno::Any any;
287 try
288 {
289 any = anyFromString( value, prop.Type );
290 }
291 catch( uno::RuntimeException & )
292 {
293 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 ) );
294 return;
295 }
296
297 // sets value on property
298 try
299 {
300 prophlp::setProperty( xPeer, unoAttr, any );
301 }
302 catch( ... )
303 {
304 DBG_ERROR2( "Warning: cannot set attribute %s to %s \n", OUSTRING_CSTR( unoAttr ), OUSTRING_CSTR( value ) );
305 }
306 }
307
308
309
310
311 struct AttributesMap
312 {
313 const char *name;
314 long value;
315 bool windowAttr;
316 };
317 static const AttributesMap attribsMap[] =
318 {
319 { "autohscroll", awt::VclWindowPeerAttribute::AUTOHSCROLL, false },
320 { "autovscroll", awt::VclWindowPeerAttribute::AUTOVSCROLL, false },
321 { "center", awt::VclWindowPeerAttribute::CENTER, false },
322 { "clipchildren", awt::VclWindowPeerAttribute::CLIPCHILDREN, false },
323 { "closeable", awt::WindowAttribute::CLOSEABLE, true },
324 { "defbutton", awt::VclWindowPeerAttribute::DEFBUTTON, false },
325 { "dropdown", awt::VclWindowPeerAttribute::DROPDOWN, false },
326 { "fullsize", awt::WindowAttribute::FULLSIZE, true }, //FIXME?
327 { "group", awt::VclWindowPeerAttribute::GROUP, false },
328 { "has_border", awt::WindowAttribute::BORDER, true },
329 { "hscroll", awt::VclWindowPeerAttribute::HSCROLL, false },
330 { "left", awt::VclWindowPeerAttribute::LEFT, false },
331 { "moveable", awt::WindowAttribute::MOVEABLE, true },
332 { "noborder", awt::VclWindowPeerAttribute::NOBORDER, false },
333 { "nolabel", awt::VclWindowPeerAttribute::NOLABEL, false },
334 { "optimumsize", awt::WindowAttribute::OPTIMUMSIZE, false },
335 { "readonly", awt::VclWindowPeerAttribute::READONLY, false },
336 { "right", awt::VclWindowPeerAttribute::RIGHT, false },
337 { "show", awt::WindowAttribute::SHOW, true },
338 { "sizeable", awt::WindowAttribute::SIZEABLE, true },
339 { "sort", awt::VclWindowPeerAttribute::SORT, false },
340 { "spin", awt::VclWindowPeerAttribute::SPIN, false },
341 { "vscroll", awt::VclWindowPeerAttribute::VSCROLL, false },
342
343 // cutting on OK, YES_NO_CANCEL and related obsite attributes...
344 };
345 static const int attribsMapLen = sizeof( attribsMap ) / sizeof( AttributesMap );
346
347 #if 0
348 long getAttribute( const OUString &rName, bool bTopWindow )
349 {
350
351 int min = 0, max = attribsMapLen - 1, mid, cmp;
352 do
353 {
354 mid = min +( max - min )/2;
355 cmp = rName.compareToAscii( attribsMap[ mid ].name );
356 if ( cmp > 0 )
357 min = mid+1;
358 else if ( cmp < 0 )
359 max = mid-1;
360 else
361 {
362 if ( bTopWindow || attribsMap[ mid ].value )
363 return attribsMap[ mid ].windowAttr;
364 return 0;
365 }
366 }
367 while ( min <= max );
368 return 0;
369 }
370 #endif
371
propsFromAttributes(const uno::Reference<xml::input::XAttributes> & xAttributes,PropList & rProps,sal_Int32 nNamespace)372 void propsFromAttributes( const uno::Reference<xml::input::XAttributes> & xAttributes,
373 PropList &rProps, sal_Int32 nNamespace )
374 {
375 sal_Int32 nAttrs = xAttributes->getLength();
376 for ( sal_Int32 i = 0; i < nAttrs; i++ )
377 {
378 if ( nNamespace != xAttributes->getUidByIndex( i ) )
379 continue;
380
381 std::pair< OUString, OUString > aElem
382 ( xAttributes->getLocalNameByIndex( i ),
383 xAttributes->getValueByIndex( i ) );
384
385 if ( aElem.first.getLength() > 0 ) // namespace bits ..
386 rProps.push_back( aElem );
387 }
388 }
389
390 bool
findAndRemove(const char * pAttr,PropList & rProps,OUString & rValue)391 findAndRemove( const char *pAttr, PropList &rProps, OUString &rValue )
392 {
393 PropList::iterator it;
394 OUString aName = OUString::createFromAscii( pAttr );
395
396 for ( it = rProps.begin(); it != rProps.end(); it++ )
397 {
398 if ( it->first.equalsIgnoreAsciiCase( aName )
399 || it->first.equalsIgnoreAsciiCase( OUString::createFromAscii ("_") + aName ) )
400 {
401 rValue = it->second;
402 rProps.erase( it );
403 return true;
404 }
405 }
406 rValue = OUString();
407 return false;
408 }
409
410 long
getAttributeProps(PropList & rProps)411 getAttributeProps( PropList &rProps )
412 {
413 long nAttrs = 0;
414 OUString aValue;
415
416 OUString trueStr( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
417
418 if ( findAndRemove( "show", rProps, aValue ) &&
419 aValue.equalsIgnoreAsciiCase(
420 OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) ) ) )
421 ;
422 else
423 nAttrs |= awt::WindowAttribute::SHOW;
424
425 for ( int i = 0; i < attribsMapLen; i++ )
426 {
427 if ( findAndRemove( attribsMap[i].name, rProps, aValue ) )
428 {
429 if ( aValue.equalsIgnoreAsciiCase( trueStr ) )
430 nAttrs |= attribsMap[i].value;
431 }
432 }
433
434 if ( findAndRemove( "align", rProps, aValue ) )
435 {
436 sal_Int32 nVal = aValue.toInt32();
437
438 if ( nVal == 0 /* PROPERTY_ALIGN_LEFT */ )
439 nAttrs |= awt::VclWindowPeerAttribute::LEFT;
440 else if ( nVal == 1 /* PROPERTY_ALIGN_CENTER */ )
441 nAttrs |= awt::VclWindowPeerAttribute::CENTER;
442 else if ( nVal == 2 )
443 nAttrs |= awt::VclWindowPeerAttribute::RIGHT;
444 }
445
446 return nAttrs;
447 }
448
449 }
450
451