| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "proplist.hxx" |
| |
| #include <rtl/ustrbuf.hxx> |
| #include <toolkit/dllapi.h> |
| #include <com/sun/star/awt/WindowAttribute.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/awt/XVclWindowPeer.hpp> |
| #include <com/sun/star/awt/VclWindowPeerAttribute.hpp> |
| #include <tools/debug.hxx> |
| |
| #include "helper.hxx" |
| |
| #if TEST_LAYOUT && !defined( DBG_UTIL ) |
| #undef DBG_ERROR |
| #define DBG_ERROR OSL_TRACE |
| #undef DBG_ERROR1 |
| #define DBG_ERROR1 OSL_TRACE |
| #undef DBG_ERROR2 |
| #define DBG_ERROR2 OSL_TRACE |
| #endif /* TEST_LAYOUT && !DBG_UTIL */ |
| |
| namespace layoutimpl |
| { |
| |
| using namespace com::sun::star; |
| using rtl::OString; |
| using rtl::OUString; |
| using rtl::OUStringBuffer; |
| |
| namespace prophlp |
| { |
| |
| bool TOOLKIT_DLLPUBLIC |
| canHandleProps( const uno::Reference< uno::XInterface > &xPeer ) |
| { |
| uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY ); |
| if ( xPropSet.is() ) |
| return true; |
| uno::Reference< beans::XPropertySetInfo > xInfo( xPeer, uno::UNO_QUERY ); |
| uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY ); |
| return xInfo.is() && xVclPeer.is(); |
| } |
| |
| uno::Reference< beans::XPropertySetInfo > TOOLKIT_DLLPUBLIC |
| queryPropertyInfo( |
| const uno::Reference< uno::XInterface > &xPeer ) |
| { |
| uno::Reference< beans::XPropertySetInfo > xInfo( xPeer, uno::UNO_QUERY ); |
| if ( !xInfo.is() ) |
| { |
| uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY ); |
| if ( xPropSet.is() ) |
| xInfo = xPropSet->getPropertySetInfo(); |
| } |
| return xInfo; |
| } |
| |
| void TOOLKIT_DLLPUBLIC |
| setProperty( const uno::Reference< uno::XInterface > &xPeer, |
| const OUString &rName, uno::Any aValue ) |
| { |
| uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY ); |
| if ( xVclPeer.is() ) |
| xVclPeer->setProperty( rName, aValue ); |
| else |
| { |
| uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY ); |
| xPropSet->setPropertyValue( rName, aValue ); |
| } |
| } |
| |
| uno::Any TOOLKIT_DLLPUBLIC |
| getProperty( const uno::Reference< uno::XInterface > &xPeer, |
| const OUString &rName ) |
| { |
| uno::Reference< awt::XVclWindowPeer> xVclPeer( xPeer, uno::UNO_QUERY ); |
| if ( xVclPeer.is() ) |
| return xVclPeer->getProperty( rName ); |
| |
| uno::Reference< beans::XPropertySet > xPropSet( xPeer, uno::UNO_QUERY ); |
| return xPropSet->getPropertyValue( rName ); |
| } |
| |
| } // namespace prophlp |
| |
| |
| /* Given a string and a type, it converts the string to the type, and returns |
| it encapsulated in Any. */ |
| uno::Any anyFromString( OUString const& value, uno::Type const& type ) |
| { |
| sal_Int16 radix = 10; |
| OUString intval = value; |
| if ( value.getLength() > 2 && value[0] == '0' && value[1] == 'x' ) |
| intval = value.copy( 2 ), radix = 16; |
| else if ( value.getLength() > 1 && value[0] == '#' ) |
| intval = value.copy( 1 ), radix = 16; |
| switch ( type.getTypeClass() ) |
| { |
| case uno::TypeClass_CHAR: |
| return uno::makeAny( value.toChar() ); |
| case uno::TypeClass_BOOLEAN: |
| if ( value == OUString( RTL_CONSTASCII_USTRINGPARAM( "true" ) ) ) |
| return uno::makeAny( true ); |
| else if ( value == OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) ) ) |
| return uno::makeAny( false ); |
| break; // ends switch, throws exception |
| case uno::TypeClass_BYTE: |
| return uno::makeAny( ( sal_uInt8 ) intval.toInt32( radix ) ); |
| case uno::TypeClass_SHORT: |
| return uno::makeAny( ( sal_Int16 ) intval.toInt32( radix ) ); |
| case uno::TypeClass_UNSIGNED_SHORT: |
| return uno::makeAny( ( sal_uInt16 ) intval.toInt32( radix ) ); |
| case uno::TypeClass_ENUM: |
| return uno::makeAny( ( sal_Int16 ) intval.toInt32( radix ) ); |
| case uno::TypeClass_LONG: |
| return uno::makeAny( ( sal_Int32 ) intval.toInt32( radix ) ); |
| case uno::TypeClass_UNSIGNED_LONG: |
| return uno::makeAny( ( sal_uInt32 ) intval.toInt32( radix ) ); |
| case uno::TypeClass_HYPER: |
| return uno::makeAny( ( sal_Int64 ) intval.toInt64( radix ) ); |
| case uno::TypeClass_UNSIGNED_HYPER: |
| return uno::makeAny( ( sal_uInt16 ) intval.toInt64( radix ) ); |
| case uno::TypeClass_FLOAT: |
| return uno::makeAny( value.toFloat() ); |
| case uno::TypeClass_DOUBLE: |
| return uno::makeAny( value.toDouble() ); |
| case uno::TypeClass_STRING: |
| return uno::makeAny( value ); |
| case uno::TypeClass_CONSTANT: |
| return uno::makeAny( intval.toInt32( radix ) ); |
| case uno::TypeClass_INTERFACE: |
| return uno::makeAny( loadGraphic( OUSTRING_CSTR( value ) ) ); |
| case uno::TypeClass_SEQUENCE: |
| { |
| sal_Int32 i = 0; |
| bool escaped = false, first = true; |
| OUString item, token; |
| std::list< OUString > values; |
| do |
| { |
| token = value.getToken( 0, ':', i ); |
| |
| if ( !token.getLength() && !escaped ) |
| { |
| escaped = true; |
| item += OUString( ':' ); |
| } |
| else if ( escaped ) |
| { |
| escaped = false; |
| item += token; |
| } |
| else |
| { |
| if ( !first ) |
| values.push_back( item ); |
| item = token; |
| } |
| first = false; |
| } |
| while ( i >= 0 ); |
| if ( item.getLength() ) |
| values.push_back( item ); |
| |
| uno::Sequence< OUString > seq( values.size() ); |
| i = 0; |
| for ( std::list< OUString >::const_iterator it = values.begin(); |
| it != values.end(); it++, i++ ) |
| seq[ i ] = *it; |
| |
| return uno::makeAny( seq ); |
| } |
| |
| default: |
| DBG_ERROR1( "ERROR: unknown property type of value: `%s'\n", OUSTRING_CSTR( value ) ); |
| break; |
| } |
| throw uno::RuntimeException(); |
| } |
| |
| /* Converts the XML naming scheme to UNO's, for legacy compatibility |
| (so, ergo, "one-two-three-four" -> "OneTwoThreeFour"). */ |
| static OUString toUnoNaming ( OUString const &string ) |
| { |
| OUStringBuffer buffer( string.getLength() ); |
| sal_Unicode *str = string.pData->buffer; |
| bool capitalize = true; |
| |
| for ( int i = 0; i < string.getLength(); i++ ) |
| { |
| if ( i == 0 && str[0] == '_' ) |
| /* Skip translate-me prefix. */ |
| continue; |
| if ( str[i] == '-' ) |
| capitalize = true; |
| else |
| { |
| if ( capitalize && str[i] >= 'a' && str[i] <= 'z' ) |
| buffer.append( (sal_Unicode ) ( str[i] - 'a' + 'A' ) ); |
| else |
| buffer.append( (sal_Unicode ) str[i] ); |
| capitalize = false; |
| } |
| } |
| |
| return buffer.makeStringAndClear(); |
| } |
| |
| /* |
| * convert incoming XML style property names, to AWT style property names. |
| * convert the values based on introspection information. |
| * apply to either an XPropertySet or an XPropertySetInfo | XVclWindowPeer |
| * aggregate. |
| */ |
| void |
| setProperties( uno::Reference< uno::XInterface > const& xPeer, |
| PropList const& rProps ) |
| { |
| if ( !prophlp::canHandleProps( xPeer ) ) |
| { |
| DBG_ERROR( "Error: setProperties - bad handle ignoring props:\n" ); |
| for ( PropList::const_iterator it = rProps.begin(); it != rProps.end(); |
| it++ ) |
| { |
| DBG_ERROR2( "%s=%s\n", OUSTRING_CSTR( it->first ), OUSTRING_CSTR( it->second ) ); |
| } |
| return; |
| } |
| |
| for ( PropList::const_iterator it = rProps.begin(); it != rProps.end(); |
| it++ ) |
| setProperty( xPeer, it->first, it->second ); |
| } |
| |
| void |
| setProperty( uno::Reference< uno::XInterface > const& xPeer, |
| OUString const& attr, OUString const& value ) |
| { |
| OUString unoAttr = toUnoNaming( attr ); |
| |
| OSL_TRACE( "setting %s=%s", OUSTRING_CSTR( attr ), OUSTRING_CSTR( value ) ); |
| // get a Property object |
| beans::Property prop; |
| try |
| { |
| uno::Reference< beans::XPropertySetInfo > xInfo |
| = prophlp::queryPropertyInfo( xPeer ); |
| prop = xInfo->getPropertyByName( unoAttr ); |
| } |
| catch( beans::UnknownPropertyException & ) |
| { |
| DBG_ERROR1( "Warning: unknown attribute: `%s'\n", OUSTRING_CSTR( unoAttr ) ); |
| return; |
| } |
| |
| if ( prop.Name.getLength() <= 0 ) |
| { |
| DBG_ERROR1( "Warning: missing prop: `%s'\n", OUSTRING_CSTR( unoAttr ) ); |
| return; |
| } |
| |
| // encapsulates value in an uno::Any |
| uno::Any any; |
| try |
| { |
| any = anyFromString( value, prop.Type ); |
| } |
| catch( uno::RuntimeException & ) |
| { |
| 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 ) ); |
| return; |
| } |
| |
| // sets value on property |
| try |
| { |
| prophlp::setProperty( xPeer, unoAttr, any ); |
| } |
| catch( ... ) |
| { |
| DBG_ERROR2( "Warning: cannot set attribute %s to %s \n", OUSTRING_CSTR( unoAttr ), OUSTRING_CSTR( value ) ); |
| } |
| } |
| |
| |
| |
| |
| struct AttributesMap |
| { |
| const char *name; |
| long value; |
| bool windowAttr; |
| }; |
| static const AttributesMap attribsMap[] = |
| { |
| { "autohscroll", awt::VclWindowPeerAttribute::AUTOHSCROLL, false }, |
| { "autovscroll", awt::VclWindowPeerAttribute::AUTOVSCROLL, false }, |
| { "center", awt::VclWindowPeerAttribute::CENTER, false }, |
| { "clipchildren", awt::VclWindowPeerAttribute::CLIPCHILDREN, false }, |
| { "closeable", awt::WindowAttribute::CLOSEABLE, true }, |
| { "defbutton", awt::VclWindowPeerAttribute::DEFBUTTON, false }, |
| { "dropdown", awt::VclWindowPeerAttribute::DROPDOWN, false }, |
| { "fullsize", awt::WindowAttribute::FULLSIZE, true }, //FIXME? |
| { "group", awt::VclWindowPeerAttribute::GROUP, false }, |
| { "has_border", awt::WindowAttribute::BORDER, true }, |
| { "hscroll", awt::VclWindowPeerAttribute::HSCROLL, false }, |
| { "left", awt::VclWindowPeerAttribute::LEFT, false }, |
| { "moveable", awt::WindowAttribute::MOVEABLE, true }, |
| { "noborder", awt::VclWindowPeerAttribute::NOBORDER, false }, |
| { "nolabel", awt::VclWindowPeerAttribute::NOLABEL, false }, |
| { "optimumsize", awt::WindowAttribute::OPTIMUMSIZE, false }, |
| { "readonly", awt::VclWindowPeerAttribute::READONLY, false }, |
| { "right", awt::VclWindowPeerAttribute::RIGHT, false }, |
| { "show", awt::WindowAttribute::SHOW, true }, |
| { "sizeable", awt::WindowAttribute::SIZEABLE, true }, |
| { "sort", awt::VclWindowPeerAttribute::SORT, false }, |
| { "spin", awt::VclWindowPeerAttribute::SPIN, false }, |
| { "vscroll", awt::VclWindowPeerAttribute::VSCROLL, false }, |
| |
| // cutting on OK, YES_NO_CANCEL and related obsite attributes... |
| }; |
| static const int attribsMapLen = sizeof( attribsMap ) / sizeof( AttributesMap ); |
| |
| #if 0 |
| long getAttribute( const OUString &rName, bool bTopWindow ) |
| { |
| |
| int min = 0, max = attribsMapLen - 1, mid, cmp; |
| do |
| { |
| mid = min +( max - min )/2; |
| cmp = rName.compareToAscii( attribsMap[ mid ].name ); |
| if ( cmp > 0 ) |
| min = mid+1; |
| else if ( cmp < 0 ) |
| max = mid-1; |
| else |
| { |
| if ( bTopWindow || attribsMap[ mid ].value ) |
| return attribsMap[ mid ].windowAttr; |
| return 0; |
| } |
| } |
| while ( min <= max ); |
| return 0; |
| } |
| #endif |
| |
| void propsFromAttributes( const uno::Reference<xml::input::XAttributes> & xAttributes, |
| PropList &rProps, sal_Int32 nNamespace ) |
| { |
| sal_Int32 nAttrs = xAttributes->getLength(); |
| for ( sal_Int32 i = 0; i < nAttrs; i++ ) |
| { |
| if ( nNamespace != xAttributes->getUidByIndex( i ) ) |
| continue; |
| |
| std::pair< OUString, OUString > aElem |
| ( xAttributes->getLocalNameByIndex( i ), |
| xAttributes->getValueByIndex( i ) ); |
| |
| if ( aElem.first.getLength() > 0 ) // namespace bits .. |
| rProps.push_back( aElem ); |
| } |
| } |
| |
| bool |
| findAndRemove( const char *pAttr, PropList &rProps, OUString &rValue ) |
| { |
| PropList::iterator it; |
| OUString aName = OUString::createFromAscii( pAttr ); |
| |
| for ( it = rProps.begin(); it != rProps.end(); it++ ) |
| { |
| if ( it->first.equalsIgnoreAsciiCase( aName ) |
| || it->first.equalsIgnoreAsciiCase( OUString::createFromAscii ("_") + aName ) ) |
| { |
| rValue = it->second; |
| rProps.erase( it ); |
| return true; |
| } |
| } |
| rValue = OUString(); |
| return false; |
| } |
| |
| long |
| getAttributeProps( PropList &rProps ) |
| { |
| long nAttrs = 0; |
| OUString aValue; |
| |
| OUString trueStr( RTL_CONSTASCII_USTRINGPARAM( "true" ) ); |
| |
| if ( findAndRemove( "show", rProps, aValue ) && |
| aValue.equalsIgnoreAsciiCase( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "false" ) ) ) ) |
| ; |
| else |
| nAttrs |= awt::WindowAttribute::SHOW; |
| |
| for ( int i = 0; i < attribsMapLen; i++ ) |
| { |
| if ( findAndRemove( attribsMap[i].name, rProps, aValue ) ) |
| { |
| if ( aValue.equalsIgnoreAsciiCase( trueStr ) ) |
| nAttrs |= attribsMap[i].value; |
| } |
| } |
| |
| if ( findAndRemove( "align", rProps, aValue ) ) |
| { |
| sal_Int32 nVal = aValue.toInt32(); |
| |
| if ( nVal == 0 /* PROPERTY_ALIGN_LEFT */ ) |
| nAttrs |= awt::VclWindowPeerAttribute::LEFT; |
| else if ( nVal == 1 /* PROPERTY_ALIGN_CENTER */ ) |
| nAttrs |= awt::VclWindowPeerAttribute::CENTER; |
| else if ( nVal == 2 ) |
| nAttrs |= awt::VclWindowPeerAttribute::RIGHT; |
| } |
| |
| return nAttrs; |
| } |
| |
| } |
| |