diff --git sc/source/filter/excel/xiescher.cxx sc/source/filter/excel/xiescher.cxx index 43de9ef..749b1fd 100644 --- sc/source/filter/excel/xiescher.cxx +++ sc/source/filter/excel/xiescher.cxx @@ -101,6 +101,7 @@ #include "xichart.hxx" #include "xicontent.hxx" +#include "xlescher.hxx" using ::rtl::OUString; using ::rtl::OUStringBuffer; using ::com::sun::star::uno::Reference; @@ -305,7 +306,7 @@ XclImpDrawObjBase::~XclImpDrawObjBase() { } -XclImpDrawObjRef XclImpDrawObjBase::ReadObjCmo( XclImpStream& rStrm ) +XclImpDrawObjRef XclImpDrawObjBase::ReadObjCmo( XclImpObjectManager& rObjMgr, XclImpStream& rStrm ) { XclImpDrawObjRef xDrawObj; @@ -338,7 +339,7 @@ XclImpDrawObjRef XclImpDrawObjBase::ReadObjCmo( XclImpStream& rStrm ) case EXC_OBJ_CMO_COMBOBOX: case EXC_OBJ_CMO_SPIN: case EXC_OBJ_CMO_SCROLLBAR: - xDrawObj.reset( new XclImpTbxControlObj( rStrm.GetRoot() ) ); + xDrawObj.reset( new XclImpTbxControlObj( rObjMgr, rStrm.GetRoot() ) ); break; case EXC_OBJ_CMO_PICTURE: xDrawObj.reset( new XclImpOleObj( rStrm.GetRoot() ) ); @@ -650,23 +651,31 @@ ScfPropertySet XclImpControlObjHelper::GetControlPropSet() const return ScfPropertySet( mxCtrlModel ); } -void XclImpControlObjHelper::ConvertSheetLinks( const XclImpRoot& rRoot, SdrObject& /* rSdrObj */ ) const +// get service factory from Calc document +Reference< XMultiServiceFactory > lclGetFactoryFromRoot( const XclImpRoot& rRoot ) { // get service factory from Calc document Reference< XMultiServiceFactory > xFactory; if( SfxObjectShell* pDocShell = rRoot.GetDocShell() ) xFactory.set( pDocShell->GetModel(), UNO_QUERY ); + return xFactory; +} + +void XclImpControlObjHelper::ConvertSheetLinks( const XclImpRoot& rRoot, const ScfRef< ScAddress >& rxCellLink ) const +{ + Reference< XMultiServiceFactory > xFactory = lclGetFactoryFromRoot( rRoot ); + if( !mxCtrlModel.is() || !xFactory.is() ) return; // *** cell link *** ------------------------------------------------------ Reference< XBindableValue > xBindable( mxCtrlModel, UNO_QUERY ); - if( mxCellLink.is() && xBindable.is() ) + if( rxCellLink.is() && xBindable.is() ) { // create argument sequence for createInstanceWithArguments() CellAddress aApiAddress; - ScUnoConversion::FillApiAddress( aApiAddress, *mxCellLink ); + ScUnoConversion::FillApiAddress( aApiAddress, *rxCellLink ); NamedValue aValue; aValue.Name = CREATE_OUSTRING( SC_UNONAME_BOUNDCELL ); @@ -703,14 +712,24 @@ void XclImpControlObjHelper::ConvertSheetLinks( const XclImpRoot& rRoot, SdrObje xBindable->setValueBinding( xBinding ); } + +} + +void XclImpControlObjHelper::ConvertSheetLinks( const XclImpRoot& rRoot, const ScfRef< ScRange >& rxSrcRange ) const +{ + Reference< XMultiServiceFactory > xFactory = lclGetFactoryFromRoot( rRoot ); + + if( !mxCtrlModel.is() || !xFactory.is() ) + return; + // *** source range *** --------------------------------------------------- Reference< XListEntrySink > xEntrySink( mxCtrlModel, UNO_QUERY ); - if( mxSrcRange.is() && xEntrySink.is() ) + if( rxSrcRange.is() && xEntrySink.is() ) { // create argument sequence for createInstanceWithArguments() CellRangeAddress aApiRange; - ScUnoConversion::FillApiRange( aApiRange, *mxSrcRange ); + ScUnoConversion::FillApiRange( aApiRange, *rxSrcRange ); NamedValue aValue; aValue.Name = CREATE_OUSTRING( SC_UNONAME_CELLRANGE ); @@ -735,13 +754,27 @@ void XclImpControlObjHelper::ConvertSheetLinks( const XclImpRoot& rRoot, SdrObje if( xEntrySource.is() ) xEntrySink->setListEntrySource( xEntrySource ); } + +} + +void XclImpControlObjHelper::ConvertSheetLinks( const XclImpRoot& rRoot, SdrObject& /* rSdrObj */ ) const +{ + // *** cell link *** ------------------------------------------------------ + + ConvertSheetLinks( rRoot, mxCellLink ); + + // *** source range *** --------------------------------------------------- + + ConvertSheetLinks( rRoot, mxSrcRange ); } // ---------------------------------------------------------------------------- -XclImpTbxControlObj::XclImpTbxControlObj( const XclImpRoot& rRoot ) : +XclImpTbxControlObj::XclImpTbxControlObj( XclImpObjectManager& rObjMgr, const XclImpRoot& rRoot ) : XclImpDrawingObj( rRoot, true ), XclImpControlObjHelper( EXC_CTRL_BINDPOSITION ), + mrObjManager( rObjMgr ), + mbGroupLeader( false ), mnState( EXC_OBJ_CBLS_STATE_UNCHECK ), mnSelEntry( 0 ), mnSelType( EXC_OBJ_LBS_SEL_SIMPLE ), @@ -777,6 +810,9 @@ void XclImpTbxControlObj::ReadSubRecord( XclImpStream& rStrm, sal_uInt16 nSubRec case EXC_ID_OBJ_FTGBODATA: ReadGboData( rStrm ); break; + case EXC_ID_OBJ_FTRBODATA: + ReadRboData( rStrm ); + break; default: XclImpDrawObjBase::ReadSubRecord( rStrm, nSubRecId, nSubRecSize ); } @@ -815,7 +851,6 @@ void XclImpTbxControlObj::DoProcessSdrObj( SdrObject& rSdrObj ) const namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect; namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation; - using ::com::sun::star::style::VerticalAlignment_MIDDLE; // control name, printable, sheet links ----------------------------------- @@ -856,24 +891,29 @@ void XclImpTbxControlObj::DoProcessSdrObj( SdrObject& rSdrObj ) const case EXC_OBJ_CMO_CHECKBOX: case EXC_OBJ_CMO_OPTIONBUTTON: { - bool bCheckBox = GetObjType() == EXC_OBJ_CMO_CHECKBOX; - - sal_Int16 nApiState = 0; - switch( mnState ) + if( GetObjType() == EXC_OBJ_CMO_CHECKBOX ) + SetCBRBCommonProps(); + else { - case EXC_OBJ_CBLS_STATE_UNCHECK: nApiState = 0; break; - case EXC_OBJ_CBLS_STATE_CHECK: nApiState = 1; break; - case EXC_OBJ_CBLS_STATE_TRI: nApiState = bCheckBox ? 2 : 1; break; + XclImpTbxControlObj* pTbxObj = dynamic_cast< XclImpTbxControlObj* >( mrObjManager.FindDrawObj( mNextRBInGroupId ).get() ); + if ( ( pTbxObj && pTbxObj->mbGroupLeader ) ) + { + // Group has terminated + // traverse each RadioButton in group and + // a) apply the groupname + // b) propagate the linked cell from the lead radiobutton + // c) apply the correct Ref value + XclImpTbxControlObj* pLeader = pTbxObj; + XclObjId rLeaderId = pLeader->GetObjId(); + sal_Int32 nRefVal = 1; + do + { + pTbxObj->ApplyGroupingBits( *pLeader, nRefVal++ ); + pTbxObj = dynamic_cast< XclImpTbxControlObj* >( mrObjManager.FindDrawObj( pTbxObj->mNextRBInGroupId ).get() ); + } while ( pTbxObj && !pTbxObj->mbGroupLeader ); + } + } - if( bCheckBox ) - aPropSet.SetBoolProperty( CREATE_OUSTRING( "TriState" ), nApiState == 2 ); - aPropSet.SetProperty( CREATE_OUSTRING( "DefaultState" ), nApiState ); - - sal_Int16 nApiBorder = mbFlatButton ? AwtVisualEffect::FLAT : AwtVisualEffect::LOOK3D; - aPropSet.SetProperty( CREATE_OUSTRING( "VisualEffect" ), nApiBorder ); - - // #i40279# always centered vertically - aPropSet.SetProperty( CREATE_OUSTRING( "VerticalAlign" ), VerticalAlignment_MIDDLE ); } break; @@ -1023,6 +1063,45 @@ void XclImpTbxControlObj::ReadLbsData( XclImpStream& rStrm ) } } +void XclImpTbxControlObj::ApplyGroupingBits( XclImpTbxControlObj& rLeadRB, sal_Int32 nRefVal ) +{ + ScfPropertySet aProps = GetControlPropSet(); + // shape Id is formed from object id + sheet id + rtl::OUString sGroupName = rtl::OUString::valueOf( static_cast< sal_Int32 >( rLeadRB.GetShapeId() ) ); + aProps.SetStringProperty( CREATE_OUSTRING( "GroupName" ), sGroupName ); + aProps.SetStringProperty( CREATE_OUSTRING( "RefValue" ), rtl::OUString::valueOf( nRefVal ) ); + // propagate cell link info + if ( rLeadRB.HasCellLink() && !HasCellLink() ) + { + ScfRef< ScAddress > xAddress( new ScAddress( *rLeadRB.GetCellLink() ) ); + ConvertSheetLinks( GetRoot(), xAddress ); + } + SetCBRBCommonProps(); +} + +void XclImpTbxControlObj::SetCBRBCommonProps() const +{ + sal_Int16 nApiState = 0; + bool bCheckBox = ( GetObjType() == EXC_OBJ_CMO_CHECKBOX ); + switch( mnState ) + { + case EXC_OBJ_CBLS_STATE_UNCHECK: nApiState = 0; break; + case EXC_OBJ_CBLS_STATE_CHECK: nApiState = 1; break; + case EXC_OBJ_CBLS_STATE_TRI: nApiState = bCheckBox ? 2 : 1; break; + } + ScfPropertySet aPropSet = GetControlPropSet(); + if ( bCheckBox ) + aPropSet.SetBoolProperty( CREATE_OUSTRING( "TriState" ), nApiState == 2 ); + namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect; + using ::com::sun::star::style::VerticalAlignment_MIDDLE; + + aPropSet.SetProperty( CREATE_OUSTRING( "DefaultState" ), nApiState ); + sal_Int16 nApiBorder = mbFlatButton ? AwtVisualEffect::FLAT : AwtVisualEffect::LOOK3D; + aPropSet.SetProperty( CREATE_OUSTRING( "VisualEffect" ), nApiBorder ); + // #i40279# always centered vertically + aPropSet.SetProperty( CREATE_OUSTRING( "VerticalAlign" ), VerticalAlignment_MIDDLE ); +} + void XclImpTbxControlObj::ReadSbs( XclImpStream& rStrm ) { sal_uInt16 nOrient, nStyle; @@ -1043,6 +1122,17 @@ void XclImpTbxControlObj::ReadGboData( XclImpStream& rStrm ) mbFlatBorder = ::get_flag( nStyle, EXC_OBJ_GBO_FLAT ); } +void XclImpTbxControlObj::ReadRboData( XclImpStream& rStrm ) +{ + sal_Int16 mnNextRBInGroup; + rStrm >> mnNextRBInGroup; + sal_uInt8 nGroupLeader; + rStrm >> nGroupLeader; + sal_uInt8 unknown; + rStrm >> unknown; + mbGroupLeader = ( nGroupLeader & 0x1 ); + mNextRBInGroupId = XclObjId( GetScTab(), mnNextRBInGroup ); +} // ---------------------------------------------------------------------------- XclImpOleObj::XclImpOleObj( const XclImpRoot& rRoot ) : @@ -2143,7 +2233,7 @@ void XclImpObjectManager::ReadObj8( XclImpStream& rStrm ) break; case EXC_ID_OBJ_FTCMO: DBG_ASSERT( !xDrawObj, "XclImpObjectManager::ReadObj8 - multiple FTCMO subrecords" ); - xDrawObj = XclImpDrawObjBase::ReadObjCmo( rStrm ); + xDrawObj = XclImpDrawObjBase::ReadObjCmo( *this, rStrm ); bLoop = xDrawObj.is(); break; default: diff --git sc/source/filter/inc/xiescher.hxx sc/source/filter/inc/xiescher.hxx index b66314b..ea8a91b 100644 --- sc/source/filter/inc/xiescher.hxx +++ sc/source/filter/inc/xiescher.hxx @@ -84,7 +84,7 @@ public: virtual ~XclImpDrawObjBase(); /** Reads the FTCMO subrecord (common object data) in an OBJ record, returns a new object. */ - static XclImpDrawObjRef ReadObjCmo( XclImpStream& rStrm ); + static XclImpDrawObjRef ReadObjCmo( XclImpObjectManager& rObjMrg, XclImpStream& rStrm ); /** Reads the contents of the specified subrecord of an OBJ record from stream. */ virtual void ReadSubRecord( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ); /** Reads the client anchor from an msofbtClientAnchor Escher record. */ @@ -242,6 +242,9 @@ protected: ScfPropertySet GetControlPropSet() const; /** Tries to set a spreadsheet cell link and source range link at the passed form control. */ void ConvertSheetLinks( const XclImpRoot& rRoot, SdrObject& rSdrObj ) const; + void ConvertSheetLinks( const XclImpRoot& rRoot, const ScfRef< ScAddress >& rxCellLink ) const; + void ConvertSheetLinks( const XclImpRoot& rRoot, const ScfRef< ScRange >& rxSrcRange ) const; + ScAddress* GetCellLink(){ return mxCellLink.get(); } private: XControlModelRef mxCtrlModel; /// Model of the created form control object. @@ -256,7 +259,7 @@ private: class XclImpTbxControlObj : public XclImpDrawingObj, public XclImpControlObjHelper { public: - explicit XclImpTbxControlObj( const XclImpRoot& rRoot ); + explicit XclImpTbxControlObj( XclImpObjectManager& rObjMgr, const XclImpRoot& rRoot ); /** Reads the contents of the specified subrecord of an OBJ record from stream. */ virtual void ReadSubRecord( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ); @@ -283,8 +286,15 @@ private: void ReadSbs( XclImpStream& rStrm ); /** Reads the contents of the ftGboData sub structure in an OBJ record. */ void ReadGboData( XclImpStream& rStrm ); + /** Reads the contents of the ftRboData sub structure in an OBJ record. */ + void ReadRboData( XclImpStream& rStrm ); private: + void SetCBRBCommonProps() const; + void ApplyGroupingBits( XclImpTbxControlObj& rTbxObj, sal_Int32 nRefVal ); + XclImpObjectManager& mrObjManager; + bool mbGroupLeader; /// Identifies start of group + XclObjId mNextRBInGroupId; /// ScfInt16Vec maMultiSel; /// Indexes of all selected entries in a multi selection. sal_uInt16 mnState; /// Checked/unchecked state. sal_Int16 mnSelEntry; /// Index of selected entry (1-based). diff --git sc/source/filter/inc/xlescher.hxx sc/source/filter/inc/xlescher.hxx index 4750b4a..b80eaae 100644 --- sc/source/filter/inc/xlescher.hxx +++ sc/source/filter/inc/xlescher.hxx @@ -64,6 +64,7 @@ const sal_uInt16 EXC_ID_OBJ_FTCBLS = 0x000A; /// Check box/radio butt const sal_uInt16 EXC_ID_OBJ_FTSBS = 0x000C; /// Scroll bar data. const sal_uInt16 EXC_ID_OBJ_FTSBSFMLA = 0x000E; /// Scroll bar/list box/combo box cell link. const sal_uInt16 EXC_ID_OBJ_FTGBODATA = 0x000F; /// Group box data. +const sal_uInt16 EXC_ID_OBJ_FTRBODATA = 0x0011; /// Radiobutton data. const sal_uInt16 EXC_ID_OBJ_FTLBSDATA = 0x0013; /// List box/combo box data. const sal_uInt16 EXC_ID_OBJ_FTCBLSFMLA = 0x0014; /// Check box/radio button cell link. const sal_uInt16 EXC_ID_OBJ_FTCMO = 0x0015; /// Common object settings.