From a43cc9ec8dde4f311bcf8ff96e6a26d56b2abdcf Mon Sep 17 00:00:00 2001 From: Noel Power Date: Wed, 17 Apr 2013 17:08:59 +0100 Subject: implement MultiPage, Page & TabStrip import for oox Change-Id: I1912c9550c12a971fcc7fdbc8bd623f18ccc40b8 --- oox/inc/oox/ole/axbinaryreader.hxx | 16 ++++-- oox/inc/oox/ole/axcontrol.hxx | 50 ++++++++++++++-- oox/source/ole/axbinaryreader.cxx | 11 +++- oox/source/ole/axcontrol.cxx | 115 +++++++++++++++++++++++++++++++++++++ oox/source/ole/vbacontrol.cxx | 63 ++++++++++++++++++-- 5 files changed, 240 insertions(+), 15 deletions(-) (limited to 'oox') diff --git a/oox/inc/oox/ole/axbinaryreader.hxx b/oox/inc/oox/ole/axbinaryreader.hxx index f734a307d895..b6a937d14c4c 100644 --- a/oox/inc/oox/ole/axbinaryreader.hxx +++ b/oox/inc/oox/ole/axbinaryreader.hxx @@ -87,7 +87,7 @@ private: typedef ::std::pair< sal_Int32, sal_Int32 > AxPairData; /** An array of string values as a property. */ -typedef ::std::vector< OUString > AxStringArray; +typedef ::std::vector< OUString > AxArrayString; // ============================================================================ @@ -112,6 +112,9 @@ public: /** Reads the next string property from the stream, if the respective flag in the property mask is set. */ void readStringProperty( OUString& orValue ); + /** Reads ArrayString, an array of fmString ( compressed or uncompressed ) + is read from the stream and inserted into rStrings */ + void readArrayStringProperty( std::vector< OUString >& rStrings ); /** Reads the next GUID property from the stream, if the respective flag in the property mask is set. The GUID will be enclosed in braces. */ void readGuidProperty( OUString& orGuid ); @@ -135,6 +138,9 @@ public: /** Skips the next string property in the stream, if the respective flag in the property mask is set. */ inline void skipStringProperty() { readStringProperty( maDummyString ); } + /** Skips the next ArrayString property in the stream, if the respective flag in + the property mask is set. */ + inline void skipArrayStringProperty() { readArrayStringProperty( maDummyArrayString ); } /** Skips the next GUID property in the stream, if the respective flag in the property mask is set. */ inline void skipGuidProperty() { readGuidProperty( maDummyString ); } @@ -185,11 +191,11 @@ private: }; /** Complex property for an array of strings. */ - struct StringArrayProperty : public ComplexProperty + struct ArrayStringProperty : public ComplexProperty { - AxStringArray& mrArray; + AxArrayString& mrArray; sal_uInt32 mnSize; - inline explicit StringArrayProperty( AxStringArray& rArray, sal_uInt32 nSize ) : + inline explicit ArrayStringProperty( AxArrayString& rArray, sal_uInt32 nSize ) : mrArray( rArray ), mnSize( nSize ) {} virtual bool readProperty( AxAlignedInputStream& rInStrm ); }; @@ -234,7 +240,7 @@ private: AxFontData maDummyFontData; ///< Dummy font for unsupported properties. StreamDataSequence maDummyPicData; ///< Dummy picture for unsupported properties. OUString maDummyString; ///< Dummy string for unsupported properties. - AxStringArray maDummyStringArray; ///< Dummy string array for unsupported properties. + AxArrayString maDummyArrayString; ///< Dummy strings for unsupported ArrayString properties. sal_Int64 mnPropFlags; ///< Flags specifying existing properties. sal_Int64 mnNextProp; ///< Next property to read. sal_Int64 mnPropsEnd; ///< End position of simple/large properties. diff --git a/oox/inc/oox/ole/axcontrol.hxx b/oox/inc/oox/ole/axcontrol.hxx index 6612ef3c497d..84e3a3ecbcdd 100644 --- a/oox/inc/oox/ole/axcontrol.hxx +++ b/oox/inc/oox/ole/axcontrol.hxx @@ -157,13 +157,13 @@ enum ApiControlType API_CONTROL_COMBOBOX, API_CONTROL_SPINBUTTON, API_CONTROL_SCROLLBAR, - API_CONTROL_TABSTRIP, + API_CONTROL_TABSTRIP, //11 API_CONTROL_PROGRESSBAR, API_CONTROL_GROUPBOX, - API_CONTROL_FRAME, - API_CONTROL_PAGE, - API_CONTROL_MULTIPAGE, - API_CONTROL_DIALOG + API_CONTROL_FRAME, // 14 + API_CONTROL_PAGE, // 15 + API_CONTROL_MULTIPAGE, // 16 + API_CONTROL_DIALOG // 17 }; // ============================================================================ @@ -600,6 +600,24 @@ private: bool mbPicTiling; ///< True = picture is repeated. }; +class OOX_DLLPUBLIC AxTabStripModel : public AxFontDataModel +{ +public: + explicit AxTabStripModel(); + + virtual bool importBinaryModel( BinaryInputStream& rInStrm ); + + virtual ApiControlType getControlType() const; + +public: + sal_uInt32 mnListIndex; + sal_uInt32 mnTabStyle; + sal_uInt32 mnTabData; + sal_uInt32 mnVariousPropertyBits; + std::vector< ::rtl::OUString > maItems; // captions for each tab + std::vector< ::rtl::OUString > maTabNames; // names for each tab +}; + // ============================================================================ /** Base class for a Forms 2.0 morph data control. */ @@ -853,6 +871,28 @@ public: virtual void convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const; }; +class OOX_DLLPUBLIC AxPageModel : public AxContainerModelBase +{ +public: + explicit AxPageModel(); + + virtual ApiControlType getControlType() const; + virtual void convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const; +}; + +class OOX_DLLPUBLIC AxMultiPageModel : public AxContainerModelBase +{ +public: + explicit AxMultiPageModel(); + + virtual ApiControlType getControlType() const; + virtual bool importPageAndMultiPageProperties( BinaryInputStream& rInStrm, sal_Int32 nPages ); + virtual void convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const; + std::vector mnIDs; + sal_uInt32 mnActiveTab; + sal_uInt32 mnTabStyle; +}; + // ============================================================================ diff --git a/oox/source/ole/axbinaryreader.cxx b/oox/source/ole/axbinaryreader.cxx index 1e4c626d1224..b78f428794fd 100644 --- a/oox/source/ole/axbinaryreader.cxx +++ b/oox/source/ole/axbinaryreader.cxx @@ -144,7 +144,7 @@ bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& return lclReadString( rInStrm, mrValue, mnSize, false ); } -bool AxBinaryPropertyReader::StringArrayProperty::readProperty( AxAlignedInputStream& rInStrm ) +bool AxBinaryPropertyReader::ArrayStringProperty::readProperty( AxAlignedInputStream& rInStrm ) { sal_Int64 nEndPos = rInStrm.tell() + mnSize; while( rInStrm.tell() < nEndPos ) @@ -214,6 +214,15 @@ void AxBinaryPropertyReader::readStringProperty( OUString& orValue ) } } +void AxBinaryPropertyReader::readArrayStringProperty( std::vector& orValue ) +{ + if( startNextProperty() ) + { + sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >(); + maLargeProps.push_back( ComplexPropVector::value_type( new ArrayStringProperty( orValue, nSize ) ) ); + } +} + void AxBinaryPropertyReader::readGuidProperty( OUString& orGuid ) { if( startNextProperty() ) diff --git a/oox/source/ole/axcontrol.cxx b/oox/source/ole/axcontrol.cxx index bbb8a5f249a7..38b959e7c9f5 100644 --- a/oox/source/ole/axcontrol.cxx +++ b/oox/source/ole/axcontrol.cxx @@ -1351,6 +1351,53 @@ void AxImageModel::convertProperties( PropertyMap& rPropMap, const ControlConver // ============================================================================ +AxTabStripModel::AxTabStripModel() : + mnListIndex( 0 ), + mnTabStyle( 0 ), + mnTabData( 0 ), + mnVariousPropertyBits( 0 ) +{ +} + +bool AxTabStripModel::importBinaryModel( BinaryInputStream& rInStrm ) +{ + // not worth reading much here, basically we are interested + // in whether we have tabs, the width, the height and the + // captions, everything else we can pretty much discard ( for now ) + AxBinaryPropertyReader aReader( rInStrm ); + aReader.readIntProperty< sal_uInt32 >( mnListIndex ); // ListIndex + aReader.skipIntProperty< sal_uInt32 >(); // Backcolor + aReader.skipIntProperty< sal_uInt32 >(); // ForeColor + aReader.skipUndefinedProperty(); + aReader.readPairProperty( maSize ); + aReader.readArrayStringProperty( maItems ); + aReader.skipIntProperty< sal_uInt8 >(); // MousePointer + aReader.skipUndefinedProperty(); + aReader.skipIntProperty< sal_uInt32 >(); // TabOrientation + aReader.readIntProperty< sal_uInt32 >(mnTabStyle); // TabStyle + aReader.skipBoolProperty(); // MultiRow + aReader.skipIntProperty< sal_uInt32 >(); // TabFixedWidth + aReader.skipIntProperty< sal_uInt32 >(); // TabFixedHeight + aReader.skipBoolProperty(); // ToolTips + aReader.skipUndefinedProperty(); + aReader.skipArrayStringProperty(); // ToolTip strings + aReader.skipUndefinedProperty(); + aReader.readArrayStringProperty( maTabNames ); // Tab names + aReader.readIntProperty< sal_uInt32 >(mnVariousPropertyBits); // VariousPropertyBits + aReader.skipBoolProperty();// NewVersion + aReader.skipIntProperty< sal_uInt32 >(); // TabsAllocated + aReader.skipArrayStringProperty(); // Tags + aReader.readIntProperty(mnTabData); // TabData + aReader.skipArrayStringProperty(); // Accelerators + aReader.skipPictureProperty(); // Mouse Icon + return aReader.finalizeImport() && AxFontDataModel::importBinaryModel( rInStrm ); +} + +ApiControlType AxTabStripModel::getControlType() const +{ + return API_CONTROL_TABSTRIP; +} + AxMorphDataModelBase::AxMorphDataModelBase() : mnTextColor( AX_SYSCOLOR_WINDOWTEXT ), mnBackColor( AX_SYSCOLOR_WINDOWBACK ), @@ -2385,6 +2432,74 @@ void AxFrameModel::convertProperties( PropertyMap& rPropMap, const ControlConver AxContainerModelBase::convertProperties( rPropMap, rConv ); } +AxPageModel::AxPageModel() +{ +} + +ApiControlType AxPageModel::getControlType() const +{ + return API_CONTROL_PAGE; +} + +void AxPageModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const +{ + rPropMap.setProperty( PROP_Title, maCaption ); + rConv.convertColor( rPropMap, PROP_BackgroundColor, mnBackColor ); + rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_CONTAINER_ENABLED ) ); + AxContainerModelBase::convertProperties( rPropMap, rConv ); +} + +AxMultiPageModel::AxMultiPageModel() : + mnActiveTab( 0 ), + mnTabStyle( AX_TABSTRIP_TABS ) +{ +} + +ApiControlType AxMultiPageModel::getControlType() const +{ + return API_CONTROL_MULTIPAGE; +} + + +bool AxMultiPageModel::importPageAndMultiPageProperties( BinaryInputStream& rInStrm, sal_Int32 nPages ) +{ + // PageProperties + for ( sal_Int32 nPage = 0; nPage < nPages; ++nPage ) + { + AxBinaryPropertyReader aReader( rInStrm ); + aReader.skipUndefinedProperty(); + aReader.skipIntProperty< sal_uInt32 >(); // TransistionEffect + aReader.skipIntProperty< sal_uInt32 >(); // TransitionPeriod + } + // MultiPageProperties + AxBinaryPropertyReader aReader( rInStrm ); + sal_uInt32 nPageCount = 0; + aReader.skipUndefinedProperty(); + aReader.readIntProperty< sal_uInt32 >(nPageCount); // PageCount + aReader.skipIntProperty< sal_uInt32 >(); //ID + + // IDs + for ( sal_uInt32 count = 0; count < nPageCount; ++count ) + { + sal_Int32 nID = 0; + rInStrm >> nID; + mnIDs.push_back( nID ); + } + return true; +} + +void AxMultiPageModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const +{ + rPropMap.setProperty( PROP_Title, maCaption ); + rPropMap.setProperty( PROP_MultiPageValue, mnActiveTab + 1); + rConv.convertColor( rPropMap, PROP_BackgroundColor, mnBackColor ); + rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_CONTAINER_ENABLED ) ); + rPropMap.setProperty( PROP_Decoration, mnTabStyle != AX_TABSTRIP_NONE ); + + AxContainerModelBase::convertProperties( rPropMap, rConv ); +} + + // ============================================================================ AxUserFormModel::AxUserFormModel() diff --git a/oox/source/ole/vbacontrol.cxx b/oox/source/ole/vbacontrol.cxx index ad6eaf5b438a..073f64e676a5 100644 --- a/oox/source/ole/vbacontrol.cxx +++ b/oox/source/ole/vbacontrol.cxx @@ -36,6 +36,7 @@ #include "oox/helper/storagebase.hxx" #include "oox/helper/textinputstream.hxx" #include "oox/ole/vbahelper.hxx" +#include namespace oox { namespace ole { @@ -259,10 +260,13 @@ ControlModelRef VbaSiteModel::createControlModel( const AxClassTable& rClassTabl case VBA_SITE_COMBOBOX: xCtrlModel.reset( new AxComboBoxModel ); break; case VBA_SITE_SPINBUTTON: xCtrlModel.reset( new AxSpinButtonModel ); break; case VBA_SITE_SCROLLBAR: xCtrlModel.reset( new AxScrollBarModel ); break; - case VBA_SITE_TABSTRIP: break; + case VBA_SITE_TABSTRIP: xCtrlModel.reset( new AxTabStripModel ); + break; case VBA_SITE_FRAME: xCtrlModel.reset( new AxFrameModel ); break; - case VBA_SITE_MULTIPAGE: break; - case VBA_SITE_FORM: break; + case VBA_SITE_MULTIPAGE: xCtrlModel.reset( new AxMultiPageModel ); + break; + case VBA_SITE_FORM: xCtrlModel.reset( new AxPageModel ); + break; default: OSL_FAIL( "VbaSiteModel::createControlModel - unknown type index" ); } } @@ -405,7 +409,6 @@ void VbaFormControl::importStorage( StorageBase& rStrg, const AxClassTable& rCla maControls vector). Ignore failure of importSiteModels() but try to import as much controls as possible. */ importEmbeddedSiteModels( aFStrm ); - /* Open the 'o' stream containing models of embedded simple controls. Stream may be empty or missing, if this control contains no controls or only container controls. */ @@ -417,6 +420,58 @@ void VbaFormControl::importStorage( StorageBase& rStrg, const AxClassTable& rCla maControls.forEachMem( &VbaFormControl::importModelOrStorage, ::boost::ref( aOStrm ), ::boost::ref( rStrg ), ::boost::cref( maClassTable ) ); + // Special handling for multi-page which has non-standard + // containment and additionally needs to re-order Page children + if ( pContainerModel->getControlType() == API_CONTROL_MULTIPAGE ) + { + AxMultiPageModel* pMultiPage = dynamic_cast< AxMultiPageModel* >( pContainerModel ); + if ( pMultiPage ) + { + BinaryXInputStream aXStrm( rStrg.openInputStream( "x" ), true ); + pMultiPage->importPageAndMultiPageProperties( aXStrm, maControls.size() ); + } + typedef boost::unordered_map< sal_uInt32, ::boost::shared_ptr< VbaFormControl > > IdToPageMap; + IdToPageMap idToPage; + VbaFormControlVector::iterator it = maControls.begin(); + VbaFormControlVector::iterator it_end = maControls.end(); + typedef std::vector< sal_uInt32 > UInt32Array; + AxArrayString sCaptions; + + for ( ; it != it_end; ++it ) + { + if ( (*it)->mxCtrlModel->getControlType() == API_CONTROL_PAGE ) + { + VbaSiteModelRef xPageSiteRef = (*it)->mxSiteModel; + if ( xPageSiteRef.get() ) + idToPage[ xPageSiteRef->getId() ] = (*it); + } + else + { + AxTabStripModel* pTabStrip = static_cast ( (*it)->mxCtrlModel.get() ); + sCaptions = pTabStrip->maItems; + pMultiPage->mnActiveTab = pTabStrip->mnListIndex; + pMultiPage->mnTabStyle = pTabStrip->mnTabStyle; + } + } + // apply caption/titles to pages + UInt32Array::iterator itCtrlId = pMultiPage->mnIDs.begin(); + UInt32Array::iterator itCtrlId_end = pMultiPage->mnIDs.end(); + AxArrayString::iterator itCaption = sCaptions.begin(); + + maControls.clear(); + // need to sort the controls according to the order of the ids + for ( sal_Int32 index = 1 ; ( sCaptions.size() == idToPage.size() ) && itCtrlId != itCtrlId_end; ++itCtrlId, ++itCaption, ++index ) + { + IdToPageMap::iterator iter = idToPage.find( *itCtrlId ); + if ( iter != idToPage.end() ) + { + AxPageModel* pPage = static_cast ( iter->second->mxCtrlModel.get() ); + + pPage->importProperty( XML_Caption, *itCaption ); + maControls.push_back( iter->second ); + } + } + } /* Reorder the controls (sorts all option buttons of an option group together), and move all children of all embedded frames (group boxes) to this control (UNO group boxes cannot contain -- cgit