| /************************************************************** |
| * |
| * 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. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| #include "xeescher.hxx" |
| |
| #include <com/sun/star/lang/XServiceInfo.hpp> |
| #include <com/sun/star/frame/XModel.hpp> |
| #include <com/sun/star/form/FormComponentType.hpp> |
| #include <com/sun/star/awt/VisualEffect.hpp> |
| #include <com/sun/star/awt/ScrollBarOrientation.hpp> |
| #include <com/sun/star/drawing/XShape.hpp> |
| #include <com/sun/star/form/binding/XBindableValue.hpp> |
| #include <com/sun/star/form/binding/XValueBinding.hpp> |
| #include <com/sun/star/form/binding/XListEntrySink.hpp> |
| #include <com/sun/star/form/binding/XListEntrySource.hpp> |
| #include <com/sun/star/script/ScriptEventDescriptor.hpp> |
| |
| #include <set> |
| #include <rtl/ustrbuf.h> |
| #include <vcl/bmpacc.hxx> |
| #include <svx/svdoole2.hxx> |
| #include <svx/svdocapt.hxx> |
| #include <editeng/outlobj.hxx> |
| #include <editeng/editobj.hxx> |
| #include <unotools/tempfile.hxx> |
| #include <unotools/ucbstreamhelper.hxx> |
| |
| #include "editutil.hxx" |
| #include "unonames.hxx" |
| #include "convuno.hxx" |
| #include "postit.hxx" |
| |
| #include "fapihelper.hxx" |
| #include "xechart.hxx" |
| #include "xeformula.hxx" |
| #include "xelink.hxx" |
| #include "xename.hxx" |
| #include "xestyle.hxx" |
| |
| using namespace ::oox; |
| |
| using ::rtl::OString; |
| using ::rtl::OUString; |
| using ::rtl::OUStringBuffer; |
| using ::com::sun::star::uno::UNO_QUERY; |
| using ::com::sun::star::uno::Reference; |
| using ::com::sun::star::uno::Sequence; |
| using ::com::sun::star::lang::XServiceInfo; |
| using ::com::sun::star::beans::XPropertySet; |
| using ::com::sun::star::drawing::XShape; |
| using ::com::sun::star::drawing::XShapes; |
| using ::com::sun::star::frame::XModel; |
| using ::com::sun::star::embed::XEmbeddedObject; |
| using ::com::sun::star::awt::XControlModel; |
| using ::com::sun::star::form::binding::XBindableValue; |
| using ::com::sun::star::form::binding::XValueBinding; |
| using ::com::sun::star::form::binding::XListEntrySink; |
| using ::com::sun::star::form::binding::XListEntrySource; |
| using ::com::sun::star::script::ScriptEventDescriptor; |
| using ::com::sun::star::table::CellAddress; |
| using ::com::sun::star::table::CellRangeAddress; |
| |
| // Escher client anchor ======================================================= |
| |
| XclExpDffAnchorBase::XclExpDffAnchorBase( const XclExpRoot& rRoot, sal_uInt16 nFlags ) : |
| XclExpRoot( rRoot ), |
| mnFlags( nFlags ) |
| { |
| } |
| |
| void XclExpDffAnchorBase::SetFlags( const SdrObject& rSdrObj ) |
| { |
| ImplSetFlags( rSdrObj ); |
| } |
| |
| void XclExpDffAnchorBase::SetSdrObject( const SdrObject& rSdrObj ) |
| { |
| ImplSetFlags( rSdrObj ); |
| ImplCalcAnchorRect( rSdrObj.GetCurrentBoundRect(), MAP_100TH_MM ); |
| } |
| |
| void XclExpDffAnchorBase::WriteDffData( EscherEx& rEscherEx ) const |
| { |
| rEscherEx.AddAtom( 18, ESCHER_ClientAnchor ); |
| rEscherEx.GetStream() << mnFlags << maAnchor; |
| } |
| |
| void XclExpDffAnchorBase::WriteData( EscherEx& rEscherEx, const Rectangle& rRect ) |
| { |
| // the passed rectangle is in twips |
| ImplCalcAnchorRect( rRect, MAP_TWIP ); |
| WriteDffData( rEscherEx ); |
| } |
| |
| void XclExpDffAnchorBase::ImplSetFlags( const SdrObject& ) |
| { |
| OSL_ENSURE( false, "XclExpDffAnchorBase::ImplSetFlags - not implemented" ); |
| } |
| |
| void XclExpDffAnchorBase::ImplCalcAnchorRect( const Rectangle&, MapUnit ) |
| { |
| OSL_ENSURE( false, "XclExpDffAnchorBase::ImplCalcAnchorRect - not implemented" ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpDffSheetAnchor::XclExpDffSheetAnchor( const XclExpRoot& rRoot ) : |
| XclExpDffAnchorBase( rRoot ), |
| mnScTab( rRoot.GetCurrScTab() ) |
| { |
| } |
| |
| void XclExpDffSheetAnchor::ImplSetFlags( const SdrObject& rSdrObj ) |
| { |
| // Special case "page anchor" (X==0,Y==1) -> lock pos and size. |
| const Point& rPos = rSdrObj.GetAnchorPos(); |
| mnFlags = ((rPos.X() == 0) && (rPos.Y() == 1)) ? EXC_ESC_ANCHOR_LOCKED : 0; |
| } |
| |
| void XclExpDffSheetAnchor::ImplCalcAnchorRect( const Rectangle& rRect, MapUnit eMapUnit ) |
| { |
| maAnchor.SetRect( GetRoot(), mnScTab, rRect, eMapUnit ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpDffEmbeddedAnchor::XclExpDffEmbeddedAnchor( const XclExpRoot& rRoot, |
| const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY ) : |
| XclExpDffAnchorBase( rRoot ), |
| maPageSize( rPageSize ), |
| mnScaleX( nScaleX ), |
| mnScaleY( nScaleY ) |
| { |
| } |
| |
| void XclExpDffEmbeddedAnchor::ImplSetFlags( const SdrObject& /*rSdrObj*/ ) |
| { |
| // TODO (unsupported feature): fixed size |
| } |
| |
| void XclExpDffEmbeddedAnchor::ImplCalcAnchorRect( const Rectangle& rRect, MapUnit eMapUnit ) |
| { |
| maAnchor.SetRect( maPageSize, mnScaleX, mnScaleY, rRect, eMapUnit, true ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpDffNoteAnchor::XclExpDffNoteAnchor( const XclExpRoot& rRoot, const Rectangle& rRect ) : |
| XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_SIZELOCKED ) |
| { |
| maAnchor.SetRect( rRoot, rRoot.GetCurrScTab(), rRect, MAP_100TH_MM ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpDffDropDownAnchor::XclExpDffDropDownAnchor( const XclExpRoot& rRoot, const ScAddress& rScPos ) : |
| XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_POSLOCKED ) |
| { |
| GetAddressConverter().ConvertAddress( maAnchor.maFirst, rScPos, true ); |
| maAnchor.maLast.mnCol = maAnchor.maFirst.mnCol + 1; |
| maAnchor.maLast.mnRow = maAnchor.maFirst.mnRow + 1; |
| maAnchor.mnLX = maAnchor.mnTY = maAnchor.mnRX = maAnchor.mnBY = 0; |
| } |
| |
| // MSODRAWING* records ======================================================== |
| |
| XclExpMsoDrawingBase::XclExpMsoDrawingBase( XclEscherEx& rEscherEx, sal_uInt16 nRecId ) : |
| XclExpRecord( nRecId ), |
| mrEscherEx( rEscherEx ), |
| mnFragmentKey( rEscherEx.InitNextDffFragment() ) |
| { |
| } |
| |
| void XclExpMsoDrawingBase::WriteBody( XclExpStream& rStrm ) |
| { |
| OSL_ENSURE( mrEscherEx.GetStreamPos() == mrEscherEx.GetDffFragmentPos( mnFragmentKey ), |
| "XclExpMsoDrawingBase::WriteBody - DFF stream position mismatch" ); |
| rStrm.CopyFromStream( mrEscherEx.GetStream(), mrEscherEx.GetDffFragmentSize( mnFragmentKey ) ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpMsoDrawingGroup::XclExpMsoDrawingGroup( XclEscherEx& rEscherEx ) : |
| XclExpMsoDrawingBase( rEscherEx, EXC_ID_MSODRAWINGGROUP ) |
| { |
| SvStream& rDffStrm = mrEscherEx.GetStream(); |
| |
| // write the DGGCONTAINER with some default settings |
| mrEscherEx.OpenContainer( ESCHER_DggContainer ); |
| |
| // TODO: stuff the OPT atom with our own document defaults? |
| static const sal_uInt8 spnDffOpt[] = { |
| 0xBF, 0x00, 0x08, 0x00, 0x08, 0x00, 0x81, 0x01, |
| 0x09, 0x00, 0x00, 0x08, 0xC0, 0x01, 0x40, 0x00, |
| 0x00, 0x08 |
| }; |
| mrEscherEx.AddAtom( sizeof( spnDffOpt ), ESCHER_OPT, 3, 3 ); |
| rDffStrm.Write( spnDffOpt, sizeof( spnDffOpt ) ); |
| |
| // SPLITMENUCOLORS contains colors in toolbar |
| static const sal_uInt8 spnDffSplitMenuColors[] = { |
| 0x0D, 0x00, 0x00, 0x08, 0x0C, 0x00, 0x00, 0x08, |
| 0x17, 0x00, 0x00, 0x08, 0xF7, 0x00, 0x00, 0x10 |
| }; |
| mrEscherEx.AddAtom( sizeof( spnDffSplitMenuColors ), ESCHER_SplitMenuColors, 0, 4 ); |
| rDffStrm.Write( spnDffSplitMenuColors, sizeof( spnDffSplitMenuColors ) ); |
| |
| // close the DGGCONTAINER |
| mrEscherEx.CloseContainer(); |
| mrEscherEx.UpdateDffFragmentEnd(); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpMsoDrawing::XclExpMsoDrawing( XclEscherEx& rEscherEx ) : |
| XclExpMsoDrawingBase( rEscherEx, EXC_ID_MSODRAWING ) |
| { |
| } |
| |
| // ============================================================================ |
| |
| XclExpImgData::XclExpImgData( const Graphic& rGraphic, sal_uInt16 nRecId ) : |
| maGraphic( rGraphic ), |
| mnRecId( nRecId ) |
| { |
| } |
| |
| void XclExpImgData::Save( XclExpStream& rStrm ) |
| { |
| Bitmap aBmp = maGraphic.GetBitmap(); |
| if( aBmp.GetBitCount() != 24 ) |
| aBmp.Convert( BMP_CONVERSION_24BIT ); |
| |
| if( BitmapReadAccess* pAccess = aBmp.AcquireReadAccess() ) |
| { |
| sal_Int32 nWidth = ::std::min< sal_Int32 >( pAccess->Width(), 0xFFFF ); |
| sal_Int32 nHeight = ::std::min< sal_Int32 >( pAccess->Height(), 0xFFFF ); |
| if( (nWidth > 0) && (nHeight > 0) ) |
| { |
| sal_uInt8 nPadding = static_cast< sal_uInt8 >( nWidth & 0x03 ); |
| sal_uInt32 nTmpSize = static_cast< sal_uInt32 >( (nWidth * 3 + nPadding) * nHeight + 12 ); |
| |
| rStrm.StartRecord( mnRecId, nTmpSize + 4 ); |
| |
| rStrm << EXC_IMGDATA_BMP // BMP format |
| << EXC_IMGDATA_WIN // Windows |
| << nTmpSize // size after _this_ field |
| << sal_uInt32( 12 ) // BITMAPCOREHEADER size |
| << static_cast< sal_uInt16 >( nWidth ) // width |
| << static_cast< sal_uInt16 >( nHeight ) // height |
| << sal_uInt16( 1 ) // planes |
| << sal_uInt16( 24 ); // bits per pixel |
| |
| for( sal_Int32 nY = nHeight - 1; nY >= 0; --nY ) |
| { |
| for( sal_Int32 nX = 0; nX < nWidth; ++nX ) |
| { |
| const BitmapColor& rBmpColor = pAccess->GetPixel( nY, nX ); |
| rStrm << rBmpColor.GetBlue() << rBmpColor.GetGreen() << rBmpColor.GetRed(); |
| } |
| rStrm.WriteZeroBytes( nPadding ); |
| } |
| |
| rStrm.EndRecord(); |
| } |
| aBmp.ReleaseAccess( pAccess ); |
| } |
| } |
| |
| // ============================================================================ |
| |
| XclExpControlHelper::XclExpControlHelper( const XclExpRoot& rRoot ) : |
| XclExpRoot( rRoot ), |
| mnEntryCount( 0 ) |
| { |
| } |
| |
| XclExpControlHelper::~XclExpControlHelper() |
| { |
| } |
| |
| void XclExpControlHelper::ConvertSheetLinks( Reference< XShape > xShape ) |
| { |
| mxCellLink.reset(); |
| mxSrcRange.reset(); |
| mnEntryCount = 0; |
| |
| // get control model |
| Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape ); |
| if( !xCtrlModel.is() ) |
| return; |
| |
| // *** cell link *** ------------------------------------------------------ |
| |
| Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY ); |
| if( xBindable.is() ) |
| { |
| Reference< XServiceInfo > xServInfo( xBindable->getValueBinding(), UNO_QUERY ); |
| if( xServInfo.is() && xServInfo->supportsService( CREATE_OUSTRING( SC_SERVICENAME_VALBIND ) ) ) |
| { |
| ScfPropertySet aBindProp( xServInfo ); |
| CellAddress aApiAddress; |
| if( aBindProp.GetProperty( aApiAddress, CREATE_OUSTRING( SC_UNONAME_BOUNDCELL ) ) ) |
| { |
| ScAddress aCellLink; |
| ScUnoConversion::FillScAddress( aCellLink, aApiAddress ); |
| if( GetTabInfo().IsExportTab( aCellLink.Tab() ) ) |
| mxCellLink = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aCellLink ); |
| } |
| } |
| } |
| |
| // *** source range *** --------------------------------------------------- |
| |
| Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY ); |
| if( xEntrySink.is() ) |
| { |
| Reference< XServiceInfo > xServInfo( xEntrySink->getListEntrySource(), UNO_QUERY ); |
| if( xServInfo.is() && xServInfo->supportsService( CREATE_OUSTRING( SC_SERVICENAME_LISTSOURCE ) ) ) |
| { |
| ScfPropertySet aSinkProp( xServInfo ); |
| CellRangeAddress aApiRange; |
| if( aSinkProp.GetProperty( aApiRange, CREATE_OUSTRING( SC_UNONAME_CELLRANGE ) ) ) |
| { |
| ScRange aSrcRange; |
| ScUnoConversion::FillScRange( aSrcRange, aApiRange ); |
| if( (aSrcRange.aStart.Tab() == aSrcRange.aEnd.Tab()) && GetTabInfo().IsExportTab( aSrcRange.aStart.Tab() ) ) |
| mxSrcRange = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aSrcRange ); |
| mnEntryCount = static_cast< sal_uInt16 >( aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1 ); |
| } |
| } |
| } |
| } |
| |
| void XclExpControlHelper::WriteFormula( XclExpStream& rStrm, const XclTokenArray& rTokArr ) const |
| { |
| sal_uInt16 nFmlaSize = rTokArr.GetSize(); |
| rStrm << nFmlaSize << sal_uInt32( 0 ); |
| rTokArr.WriteArray( rStrm ); |
| if( nFmlaSize & 1 ) // pad to 16-bit |
| rStrm << sal_uInt8( 0 ); |
| } |
| |
| void XclExpControlHelper::WriteFormulaSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId, const XclTokenArray& rTokArr ) const |
| { |
| rStrm.StartRecord( nSubRecId, (rTokArr.GetSize() + 5) & ~1 ); |
| WriteFormula( rStrm, rTokArr ); |
| rStrm.EndRecord(); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| //delete for exporting OCX |
| //#if EXC_EXP_OCX_CTRL |
| |
| XclExpOcxControlObj::XclExpOcxControlObj( XclExpObjectManager& rObjMgr, Reference< XShape > xShape, |
| const Rectangle* pChildAnchor, const String& rClassName, sal_uInt32 nStrmStart, sal_uInt32 nStrmSize ) : |
| XclObj( rObjMgr, EXC_OBJTYPE_PICTURE, true ), |
| XclExpControlHelper( rObjMgr.GetRoot() ), |
| maClassName( rClassName ), |
| mnStrmStart( nStrmStart ), |
| mnStrmSize( nStrmSize ) |
| { |
| ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) ); |
| |
| // OBJ record flags |
| SetLocked( sal_True ); |
| SetPrintable( aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "Printable" ) ) ); |
| SetAutoFill( sal_False ); |
| SetAutoLine( sal_False ); |
| |
| // fill DFF property set |
| mrEscherEx.OpenContainer( ESCHER_SpContainer ); |
| mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVESPT | SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_OLESHAPE ); |
| Rectangle aDummyRect; |
| EscherPropertyContainer aPropOpt( mrEscherEx.GetGraphicProvider(), mrEscherEx.QueryPictureStream(), aDummyRect ); |
| aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); // bool field |
| aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 ); |
| aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field |
| |
| // #i51348# name of the control, may overwrite shape name |
| OUString aCtrlName; |
| if( aCtrlProp.GetProperty( aCtrlName, CREATE_OUSTRING( "Name" ) ) && (aCtrlName.getLength() > 0) ) |
| aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName ); |
| |
| // meta file |
| //! TODO - needs check |
| Reference< XPropertySet > xShapePS( xShape, UNO_QUERY ); |
| if( xShapePS.is() && aPropOpt.CreateGraphicProperties( xShapePS, CREATE_STRING( "MetaFile" ), sal_False ) ) |
| { |
| sal_uInt32 nBlipId; |
| if( aPropOpt.GetOpt( ESCHER_Prop_pib, nBlipId ) ) |
| aPropOpt.AddOpt( ESCHER_Prop_pictureId, nBlipId ); |
| } |
| |
| // write DFF property set to stream |
| aPropOpt.Commit( mrEscherEx.GetStream() ); |
| |
| // anchor |
| ImplWriteAnchor( GetRoot(), SdrObject::getSdrObjectFromXShape( xShape ), pChildAnchor ); |
| |
| mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record |
| mrEscherEx.CloseContainer(); // ESCHER_SpContainer |
| mrEscherEx.UpdateDffFragmentEnd(); |
| |
| // spreadsheet links |
| ConvertSheetLinks( xShape ); |
| } |
| |
| void XclExpOcxControlObj::WriteSubRecs( XclExpStream& rStrm ) |
| { |
| // OBJCF - clipboard format |
| rStrm.StartRecord( EXC_ID_OBJCF, 2 ); |
| rStrm << sal_uInt16( 2 ); |
| rStrm.EndRecord(); |
| |
| // OBJFLAGS |
| rStrm.StartRecord( EXC_ID_OBJFLAGS, 2 ); |
| rStrm << sal_uInt16( 0x0031 ); |
| rStrm.EndRecord(); |
| |
| // OBJPICTFMLA |
| XclExpString aClass( maClassName ); |
| sal_uInt16 nClassNameSize = static_cast< sal_uInt16 >( aClass.GetSize() ); |
| sal_uInt16 nClassNamePad = nClassNameSize & 1; |
| sal_uInt16 nFirstPartSize = 12 + nClassNameSize + nClassNamePad; |
| |
| const XclTokenArray* pCellLink = GetCellLinkTokArr(); |
| sal_uInt16 nCellLinkSize = pCellLink ? ((pCellLink->GetSize() + 7) & 0xFFFE) : 0; |
| |
| const XclTokenArray* pSrcRange = GetSourceRangeTokArr(); |
| sal_uInt16 nSrcRangeSize = pSrcRange ? ((pSrcRange->GetSize() + 7) & 0xFFFE) : 0; |
| |
| sal_uInt16 nPictFmlaSize = nFirstPartSize + nCellLinkSize + nSrcRangeSize + 18; |
| rStrm.StartRecord( EXC_ID_OBJPICTFMLA, nPictFmlaSize ); |
| |
| rStrm << sal_uInt16( nFirstPartSize ) // size of first part |
| << sal_uInt16( 5 ) // formula size |
| << sal_uInt32( 0 ) // unknown ID |
| << sal_uInt8( 0x02 ) << sal_uInt32( 0 ) // tTbl token with unknown ID |
| << sal_uInt8( 3 ) // pad to word |
| << aClass; // "Forms.***.1" |
| rStrm.WriteZeroBytes( nClassNamePad ); // pad to word |
| rStrm << mnStrmStart // start in 'Ctls' stream |
| << mnStrmSize // size in 'Ctls' stream |
| << sal_uInt32( 0 ); // class ID size |
| // cell link |
| rStrm << nCellLinkSize; |
| if( pCellLink ) |
| WriteFormula( rStrm, *pCellLink ); |
| // list source range |
| rStrm << nSrcRangeSize; |
| if( pSrcRange ) |
| WriteFormula( rStrm, *pSrcRange ); |
| |
| rStrm.EndRecord(); |
| } |
| |
| //#else |
| |
| XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rObjMgr, Reference< XShape > xShape, const Rectangle* pChildAnchor ) : |
| XclObj( rObjMgr, EXC_OBJTYPE_UNKNOWN, true ), |
| XclExpControlHelper( rObjMgr.GetRoot() ), |
| mnHeight( 0 ), |
| mnState( 0 ), |
| mnLineCount( 0 ), |
| mnSelEntry( 0 ), |
| mnScrollValue( 0 ), |
| mnScrollMin( 0 ), |
| mnScrollMax( 100 ), |
| mnScrollStep( 1 ), |
| mnScrollPage( 10 ), |
| mbFlatButton( false ), |
| mbFlatBorder( false ), |
| mbMultiSel( false ), |
| mbScrollHor( false ) |
| { |
| namespace FormCompType = ::com::sun::star::form::FormComponentType; |
| namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect; |
| namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation; |
| |
| ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) ); |
| if( !xShape.is() || !aCtrlProp.Is() ) |
| return; |
| |
| mnHeight = xShape->getSize().Height; |
| if( mnHeight <= 0 ) |
| return; |
| |
| // control type |
| sal_Int16 nClassId = 0; |
| if( aCtrlProp.GetProperty( nClassId, CREATE_OUSTRING( "ClassId" ) ) ) |
| { |
| switch( nClassId ) |
| { |
| case FormCompType::COMMANDBUTTON: mnObjType = EXC_OBJTYPE_BUTTON; meEventType = EXC_TBX_EVENT_ACTION; break; |
| case FormCompType::RADIOBUTTON: mnObjType = EXC_OBJTYPE_OPTIONBUTTON; meEventType = EXC_TBX_EVENT_ACTION; break; |
| case FormCompType::CHECKBOX: mnObjType = EXC_OBJTYPE_CHECKBOX; meEventType = EXC_TBX_EVENT_ACTION; break; |
| case FormCompType::LISTBOX: mnObjType = EXC_OBJTYPE_LISTBOX; meEventType = EXC_TBX_EVENT_CHANGE; break; |
| case FormCompType::COMBOBOX: mnObjType = EXC_OBJTYPE_DROPDOWN; meEventType = EXC_TBX_EVENT_CHANGE; break; |
| case FormCompType::GROUPBOX: mnObjType = EXC_OBJTYPE_GROUPBOX; meEventType = EXC_TBX_EVENT_MOUSE; break; |
| case FormCompType::FIXEDTEXT: mnObjType = EXC_OBJTYPE_LABEL; meEventType = EXC_TBX_EVENT_MOUSE; break; |
| case FormCompType::SCROLLBAR: mnObjType = EXC_OBJTYPE_SCROLLBAR; meEventType = EXC_TBX_EVENT_VALUE; break; |
| case FormCompType::SPINBUTTON: mnObjType = EXC_OBJTYPE_SPIN; meEventType = EXC_TBX_EVENT_VALUE; break; |
| } |
| } |
| if( mnObjType == EXC_OBJTYPE_UNKNOWN ) |
| return; |
| |
| // OBJ record flags |
| SetLocked( sal_True ); |
| SetPrintable( aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "Printable" ) ) ); |
| SetAutoFill( sal_False ); |
| SetAutoLine( sal_False ); |
| |
| // fill DFF property set |
| mrEscherEx.OpenContainer( ESCHER_SpContainer ); |
| mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT ); |
| EscherPropertyContainer aPropOpt; |
| bool bVisible = aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "EnableVisible" ) ); |
| aPropOpt.AddOpt( ESCHER_Prop_fPrint, bVisible ? 0x00080000 : 0x00080002 ); // visible flag |
| |
| aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01000100 ); // bool field |
| aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 ); // Text ID |
| aPropOpt.AddOpt( ESCHER_Prop_WrapText, 0x00000001 ); |
| aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x001A0008 ); // bool field |
| aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00100000 ); // bool field |
| aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field |
| |
| // #i51348# name of the control, may overwrite shape name |
| OUString aCtrlName; |
| if( aCtrlProp.GetProperty( aCtrlName, CREATE_OUSTRING( "Name" ) ) && (aCtrlName.getLength() > 0) ) |
| aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName ); |
| |
| //Export description as alt text |
| if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) ) |
| { |
| String aAltTxt( pSdrObj->GetDescription(), 0, MSPROP_DESCRIPTION_MAX_LEN ); |
| aPropOpt.AddOpt( ESCHER_Prop_wzDescription, aAltTxt ); |
| } |
| |
| // write DFF property set to stream |
| aPropOpt.Commit( mrEscherEx.GetStream() ); |
| |
| // anchor |
| ImplWriteAnchor( GetRoot(), SdrObject::getSdrObjectFromXShape( xShape ), pChildAnchor ); |
| |
| mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record |
| mrEscherEx.UpdateDffFragmentEnd(); |
| |
| // control label |
| OUString aString; |
| if( aCtrlProp.GetProperty( aString, CREATE_OUSTRING( "Label" ) ) ) |
| { |
| /* Be sure to construct the MSODRAWING record containing the |
| ClientTextbox atom after the base OBJ's MSODRAWING record data is |
| completed. */ |
| pClientTextbox = new XclExpMsoDrawing( mrEscherEx ); |
| mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox ); // TXO record |
| mrEscherEx.UpdateDffFragmentEnd(); |
| |
| sal_uInt16 nXclFont = EXC_FONT_APP; |
| if( aString.getLength() > 0 ) |
| { |
| XclFontData aFontData; |
| GetFontPropSetHelper().ReadFontProperties( aFontData, aCtrlProp, EXC_FONTPROPSET_CONTROL ); |
| if( (aFontData.maName.Len() > 0) && (aFontData.mnHeight > 0) ) |
| nXclFont = GetFontBuffer().Insert( aFontData, EXC_COLOR_CTRLTEXT ); |
| } |
| |
| pTxo = new XclTxo( aString, nXclFont ); |
| pTxo->SetHorAlign( (mnObjType == EXC_OBJTYPE_BUTTON) ? EXC_OBJ_HOR_CENTER : EXC_OBJ_HOR_LEFT ); |
| pTxo->SetVerAlign( EXC_OBJ_VER_CENTER ); |
| } |
| |
| mrEscherEx.CloseContainer(); // ESCHER_SpContainer |
| |
| // other properties |
| aCtrlProp.GetProperty( mnLineCount, CREATE_OUSTRING( "LineCount" ) ); |
| |
| // border style |
| sal_Int16 nApiButton = AwtVisualEffect::LOOK3D; |
| sal_Int16 nApiBorder = AwtVisualEffect::LOOK3D; |
| switch( nClassId ) |
| { |
| case FormCompType::LISTBOX: |
| case FormCompType::COMBOBOX: |
| aCtrlProp.GetProperty( nApiBorder, CREATE_OUSTRING( "Border" ) ); |
| break; |
| case FormCompType::CHECKBOX: |
| case FormCompType::RADIOBUTTON: |
| aCtrlProp.GetProperty( nApiButton, CREATE_OUSTRING( "VisualEffect" ) ); |
| nApiBorder = AwtVisualEffect::NONE; |
| break; |
| // Push button cannot be set to flat in Excel |
| case FormCompType::COMMANDBUTTON: |
| nApiBorder = AwtVisualEffect::LOOK3D; |
| break; |
| // Label does not support a border in Excel |
| case FormCompType::FIXEDTEXT: |
| nApiBorder = AwtVisualEffect::NONE; |
| break; |
| /* Scroll bar and spin button have a "Border" property, but it is |
| really used for a border, and not for own 3D/flat look (#i34712#). */ |
| case FormCompType::SCROLLBAR: |
| case FormCompType::SPINBUTTON: |
| nApiButton = AwtVisualEffect::LOOK3D; |
| nApiBorder = AwtVisualEffect::NONE; |
| break; |
| // Group box does not support flat style (#i34712#) |
| case FormCompType::GROUPBOX: |
| nApiBorder = AwtVisualEffect::LOOK3D; |
| break; |
| } |
| mbFlatButton = nApiButton != AwtVisualEffect::LOOK3D; |
| mbFlatBorder = nApiBorder != AwtVisualEffect::LOOK3D; |
| |
| // control state |
| sal_Int16 nApiState = 0; |
| if( aCtrlProp.GetProperty( nApiState, CREATE_OUSTRING( "State" ) ) ) |
| { |
| switch( nApiState ) |
| { |
| case 0: mnState = EXC_OBJ_CHECKBOX_UNCHECKED; break; |
| case 1: mnState = EXC_OBJ_CHECKBOX_CHECKED; break; |
| case 2: mnState = EXC_OBJ_CHECKBOX_TRISTATE; break; |
| } |
| } |
| |
| // special control contents |
| switch( nClassId ) |
| { |
| case FormCompType::LISTBOX: |
| { |
| mbMultiSel = aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "MultiSelection" ) ); |
| Sequence< sal_Int16 > aSelection; |
| if( aCtrlProp.GetProperty( aSelection, CREATE_OUSTRING( "SelectedItems" ) ) ) |
| { |
| sal_Int32 nLen = aSelection.getLength(); |
| if( nLen > 0 ) |
| { |
| mnSelEntry = aSelection[ 0 ] + 1; |
| maMultiSel.resize( nLen ); |
| const sal_Int16* pnBegin = aSelection.getConstArray(); |
| ::std::copy( pnBegin, pnBegin + nLen, maMultiSel.begin() ); |
| } |
| } |
| |
| // convert listbox with dropdown button to Excel dropdown |
| if( aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "Dropdown" ) ) ) |
| mnObjType = EXC_OBJTYPE_DROPDOWN; |
| } |
| break; |
| |
| case FormCompType::COMBOBOX: |
| { |
| Sequence< OUString > aStringList; |
| OUString aDefText; |
| if( aCtrlProp.GetProperty( aStringList, CREATE_OUSTRING( "StringItemList" ) ) && |
| aCtrlProp.GetProperty( aDefText, CREATE_OUSTRING( "Text" ) ) && |
| aStringList.getLength() && aDefText.getLength() ) |
| { |
| const OUString* pBegin = aStringList.getConstArray(); |
| const OUString* pEnd = pBegin + aStringList.getLength(); |
| const OUString* pString = ::std::find( pBegin, pEnd, aDefText ); |
| if( pString != pEnd ) |
| mnSelEntry = static_cast< sal_Int16 >( pString - pBegin + 1 ); // 1-based |
| if( mnSelEntry > 0 ) |
| maMultiSel.resize( 1, mnSelEntry - 1 ); |
| } |
| |
| // convert combobox without dropdown button to Excel listbox |
| if( !aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "Dropdown" ) ) ) |
| mnObjType = EXC_OBJTYPE_LISTBOX; |
| } |
| break; |
| |
| case FormCompType::SCROLLBAR: |
| { |
| sal_Int32 nApiValue = 0; |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "ScrollValueMin" ) ) ) |
| mnScrollMin = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "ScrollValueMax" ) ) ) |
| mnScrollMax = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, EXC_OBJ_SCROLLBAR_MIN ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "ScrollValue" ) ) ) |
| mnScrollValue = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, mnScrollMax ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "LineIncrement" ) ) ) |
| mnScrollStep = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "BlockIncrement" ) ) ) |
| mnScrollPage = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "Orientation" ) ) ) |
| mbScrollHor = nApiValue == AwtScrollOrient::HORIZONTAL; |
| } |
| break; |
| |
| case FormCompType::SPINBUTTON: |
| { |
| sal_Int32 nApiValue = 0; |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "SpinValueMin" ) ) ) |
| mnScrollMin = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "SpinValueMax" ) ) ) |
| mnScrollMax = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, EXC_OBJ_SCROLLBAR_MAX ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "SpinValue" ) ) ) |
| mnScrollValue = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, mnScrollMax ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "SpinIncrement" ) ) ) |
| mnScrollStep = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX ); |
| if( aCtrlProp.GetProperty( nApiValue, CREATE_OUSTRING( "Orientation" ) ) ) |
| mbScrollHor = nApiValue == AwtScrollOrient::HORIZONTAL; |
| } |
| break; |
| } |
| |
| // spreadsheet links |
| ConvertSheetLinks( xShape ); |
| } |
| |
| bool XclExpTbxControlObj::SetMacroLink( const ScriptEventDescriptor& rEvent ) |
| { |
| String aMacroName = XclControlHelper::ExtractFromMacroDescriptor( rEvent, meEventType ); |
| if( aMacroName.Len() ) |
| { |
| sal_uInt16 nExtSheet = GetLocalLinkManager().FindExtSheet( EXC_EXTSH_OWNDOC ); |
| sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( aMacroName, true, false ); |
| mxMacroLink = GetFormulaCompiler().CreateNameXFormula( nExtSheet, nNameIdx ); |
| return true; |
| } |
| return false; |
| } |
| |
| void XclExpTbxControlObj::WriteSubRecs( XclExpStream& rStrm ) |
| { |
| switch( mnObjType ) |
| { |
| // *** Push buttons, labels *** |
| |
| case EXC_OBJTYPE_BUTTON: |
| case EXC_OBJTYPE_LABEL: |
| // ftMacro - macro link |
| WriteMacroSubRec( rStrm ); |
| break; |
| |
| // *** Check boxes, option buttons *** |
| |
| case EXC_OBJTYPE_CHECKBOX: |
| case EXC_OBJTYPE_OPTIONBUTTON: |
| { |
| // ftCbls - box properties |
| sal_uInt16 nStyle = 0; |
| ::set_flag( nStyle, EXC_OBJ_CHECKBOX_FLAT, mbFlatButton ); |
| |
| rStrm.StartRecord( EXC_ID_OBJCBLS, 12 ); |
| rStrm << mnState; |
| rStrm.WriteZeroBytes( 8 ); |
| rStrm << nStyle; |
| rStrm.EndRecord(); |
| |
| // ftMacro - macro link |
| WriteMacroSubRec( rStrm ); |
| // ftCblsFmla subrecord - cell link |
| WriteCellLinkSubRec( rStrm, EXC_ID_OBJCBLSFMLA ); |
| |
| // ftCblsData subrecord - box properties, again |
| rStrm.StartRecord( EXC_ID_OBJCBLS, 8 ); |
| rStrm << mnState; |
| rStrm.WriteZeroBytes( 4 ); |
| rStrm << nStyle; |
| rStrm.EndRecord(); |
| } |
| break; |
| |
| // *** List boxes, combo boxes *** |
| |
| case EXC_OBJTYPE_LISTBOX: |
| case EXC_OBJTYPE_DROPDOWN: |
| { |
| sal_uInt16 nEntryCount = GetSourceEntryCount(); |
| |
| // ftSbs subrecord - Scroll bars |
| sal_Int32 nLineHeight = XclTools::GetHmmFromTwips( 200 ); // always 10pt |
| if( mnObjType == EXC_OBJTYPE_LISTBOX ) |
| mnLineCount = static_cast< sal_uInt16 >( mnHeight / nLineHeight ); |
| mnScrollValue = 0; |
| mnScrollMin = 0; |
| sal_uInt16 nInvisLines = (nEntryCount >= mnLineCount) ? (nEntryCount - mnLineCount) : 0; |
| mnScrollMax = limit_cast< sal_uInt16 >( nInvisLines, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX ); |
| mnScrollStep = 1; |
| mnScrollPage = limit_cast< sal_uInt16 >( mnLineCount, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX ); |
| mbScrollHor = false; |
| WriteSbs( rStrm ); |
| |
| // ftMacro - macro link |
| WriteMacroSubRec( rStrm ); |
| // ftSbsFmla subrecord - cell link |
| WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA ); |
| |
| // ftLbsData - source data range and box properties |
| sal_uInt16 nStyle = 0; |
| ::insert_value( nStyle, mbMultiSel ? EXC_OBJ_LISTBOX_MULTI : EXC_OBJ_LISTBOX_SINGLE, 4, 2 ); |
| ::set_flag( nStyle, EXC_OBJ_LISTBOX_FLAT, mbFlatBorder ); |
| |
| rStrm.StartRecord( EXC_ID_OBJLBSDATA, 0 ); |
| |
| if( const XclTokenArray* pSrcRange = GetSourceRangeTokArr() ) |
| { |
| rStrm << static_cast< sal_uInt16 >( (pSrcRange->GetSize() + 7) & 0xFFFE ); |
| WriteFormula( rStrm, *pSrcRange ); |
| } |
| else |
| rStrm << sal_uInt16( 0 ); |
| |
| rStrm << nEntryCount << mnSelEntry << nStyle << sal_uInt16( 0 ); |
| if( mnObjType == EXC_OBJTYPE_LISTBOX ) |
| { |
| if( nEntryCount ) |
| { |
| ScfUInt8Vec aSelEx( nEntryCount, 0 ); |
| for( ScfInt16Vec::const_iterator aIt = maMultiSel.begin(), aEnd = maMultiSel.end(); aIt != aEnd; ++aIt ) |
| if( *aIt < nEntryCount ) |
| aSelEx[ *aIt ] = 1; |
| rStrm.Write( &aSelEx[ 0 ], aSelEx.size() ); |
| } |
| } |
| else if( mnObjType == EXC_OBJTYPE_DROPDOWN ) |
| { |
| rStrm << sal_uInt16( 0 ) << mnLineCount << sal_uInt16( 0 ) << sal_uInt16( 0 ); |
| } |
| |
| rStrm.EndRecord(); |
| } |
| break; |
| |
| // *** Spin buttons, scrollbars *** |
| |
| case EXC_OBJTYPE_SPIN: |
| case EXC_OBJTYPE_SCROLLBAR: |
| { |
| // ftSbs subrecord - scroll bars |
| WriteSbs( rStrm ); |
| // ftMacro - macro link |
| WriteMacroSubRec( rStrm ); |
| // ftSbsFmla subrecord - cell link |
| WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA ); |
| } |
| break; |
| |
| // *** Group boxes *** |
| |
| case EXC_OBJTYPE_GROUPBOX: |
| { |
| // ftMacro - macro link |
| WriteMacroSubRec( rStrm ); |
| |
| // ftGboData subrecord - group box properties |
| sal_uInt16 nStyle = 0; |
| ::set_flag( nStyle, EXC_OBJ_GROUPBOX_FLAT, mbFlatBorder ); |
| |
| rStrm.StartRecord( EXC_ID_OBJGBODATA, 6 ); |
| rStrm << sal_uInt32( 0 ) |
| << nStyle; |
| rStrm.EndRecord(); |
| } |
| break; |
| } |
| } |
| |
| void XclExpTbxControlObj::WriteMacroSubRec( XclExpStream& rStrm ) |
| { |
| if( mxMacroLink.is() ) |
| WriteFormulaSubRec( rStrm, EXC_ID_OBJMACRO, *mxMacroLink ); |
| } |
| |
| void XclExpTbxControlObj::WriteCellLinkSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId ) |
| { |
| if( const XclTokenArray* pCellLink = GetCellLinkTokArr() ) |
| WriteFormulaSubRec( rStrm, nSubRecId, *pCellLink ); |
| } |
| |
| void XclExpTbxControlObj::WriteSbs( XclExpStream& rStrm ) |
| { |
| sal_uInt16 nOrient = 0; |
| ::set_flag( nOrient, EXC_OBJ_SCROLLBAR_HOR, mbScrollHor ); |
| sal_uInt16 nStyle = EXC_OBJ_SCROLLBAR_DEFFLAGS; |
| ::set_flag( nStyle, EXC_OBJ_SCROLLBAR_FLAT, mbFlatButton ); |
| |
| rStrm.StartRecord( EXC_ID_OBJSBS, 20 ); |
| rStrm << sal_uInt32( 0 ) // reserved |
| << mnScrollValue // thumb position |
| << mnScrollMin // thumb min pos |
| << mnScrollMax // thumb max pos |
| << mnScrollStep // line increment |
| << mnScrollPage // page increment |
| << nOrient // 0 = vertical, 1 = horizontal |
| << sal_uInt16( 15 ) // thumb width |
| << nStyle; // flags/style |
| rStrm.EndRecord(); |
| } |
| |
| //#endif |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape > xShape, const Rectangle* pChildAnchor ) : |
| XclObj( rObjMgr, EXC_OBJTYPE_CHART ), |
| XclExpRoot( rObjMgr.GetRoot() ) |
| { |
| // create the MSODRAWING record contents for the chart object |
| mrEscherEx.OpenContainer( ESCHER_SpContainer ); |
| mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT ); |
| EscherPropertyContainer aPropOpt; |
| aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01040104 ); |
| aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); |
| aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x0800004E ); |
| aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x0800004D ); |
| aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 ); |
| aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x0800004D ); |
| aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 ); |
| aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x00020000 ); |
| aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 ); |
| aPropOpt.Commit( mrEscherEx.GetStream() ); |
| |
| // anchor |
| SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ); |
| ImplWriteAnchor( GetRoot(), pSdrObj, pChildAnchor ); |
| |
| // client data (the following OBJ record) |
| mrEscherEx.AddAtom( 0, ESCHER_ClientData ); |
| mrEscherEx.CloseContainer(); // ESCHER_SpContainer |
| mrEscherEx.UpdateDffFragmentEnd(); |
| |
| // load the chart OLE object |
| if( SdrOle2Obj* pSdrOleObj = dynamic_cast< SdrOle2Obj* >( pSdrObj ) ) |
| svt::EmbeddedObjectRef::TryRunningState( pSdrOleObj->GetObjRef() ); |
| |
| // create the chart substream object |
| ScfPropertySet aShapeProp( xShape ); |
| Reference< XModel > xModel; |
| aShapeProp.GetProperty( xModel, CREATE_OUSTRING( "Model" ) ); |
| ::com::sun::star::awt::Rectangle aBoundRect; |
| aShapeProp.GetProperty( aBoundRect, CREATE_OUSTRING( "BoundRect" ) ); |
| Rectangle aChartRect( Point( aBoundRect.X, aBoundRect.Y ), Size( aBoundRect.Width, aBoundRect.Height ) ); |
| mxChart.reset( new XclExpChart( GetRoot(), xModel, aChartRect ) ); |
| } |
| |
| XclExpChartObj::~XclExpChartObj() |
| { |
| } |
| |
| void XclExpChartObj::Save( XclExpStream& rStrm ) |
| { |
| // content of OBJ record |
| XclObj::Save( rStrm ); |
| // chart substream |
| mxChart->Save( rStrm ); |
| } |
| |
| // ============================================================================ |
| |
| XclExpNote::XclExpNote( const XclExpRoot& rRoot, const ScAddress& rScPos, |
| const ScPostIt* pScNote, const String& rAddText ) : |
| XclExpRecord( EXC_ID_NOTE ), |
| maScPos( rScPos ), |
| mnObjId( EXC_OBJ_INVALID_ID ), |
| mbVisible( pScNote && pScNote->IsCaptionShown() ) |
| { |
| // get the main note text |
| String aNoteText; |
| if( pScNote ) |
| aNoteText = pScNote->GetText(); |
| // append additional text |
| ScGlobal::AddToken( aNoteText, rAddText, '\n', 2 ); |
| maOrigNoteText = aNoteText; |
| |
| // initialize record dependent on BIFF type |
| switch( rRoot.GetBiff() ) |
| { |
| case EXC_BIFF5: |
| maNoteText = ByteString( aNoteText, rRoot.GetTextEncoding() ); |
| break; |
| |
| case EXC_BIFF8: |
| { |
| // TODO: additional text |
| if( pScNote ) |
| if( SdrCaptionObj* pCaption = pScNote->GetOrCreateCaption( maScPos ) ) |
| if( const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() ) |
| mnObjId = rRoot.GetObjectManager().AddObj( new XclObjComment( rRoot.GetObjectManager(), pCaption->GetLogicRect(), pOPO->GetTextObject(), pCaption, mbVisible ) ); |
| |
| SetRecSize( 9 + maAuthor.GetSize() ); |
| } |
| break; |
| |
| default: DBG_ERROR_BIFF(); |
| } |
| } |
| |
| void XclExpNote::Save( XclExpStream& rStrm ) |
| { |
| switch( rStrm.GetRoot().GetBiff() ) |
| { |
| case EXC_BIFF5: |
| { |
| // write the NOTE record directly, there may be the need to create more than one |
| const sal_Char* pcBuffer = maNoteText.GetBuffer(); |
| sal_uInt16 nCharsLeft = static_cast< sal_uInt16 >( maNoteText.Len() ); |
| |
| while( nCharsLeft ) |
| { |
| sal_uInt16 nWriteChars = ::std::min( nCharsLeft, EXC_NOTE5_MAXLEN ); |
| |
| rStrm.StartRecord( EXC_ID_NOTE, 6 + nWriteChars ); |
| if( pcBuffer == maNoteText.GetBuffer() ) |
| { |
| // first record: row, col, length of complete text |
| rStrm << static_cast< sal_uInt16 >( maScPos.Row() ) |
| << static_cast< sal_uInt16 >( maScPos.Col() ) |
| << nCharsLeft; // still contains full length |
| } |
| else |
| { |
| // next records: -1, 0, length of current text segment |
| rStrm << sal_uInt16( 0xFFFF ) |
| << sal_uInt16( 0 ) |
| << nWriteChars; |
| } |
| rStrm.Write( pcBuffer, nWriteChars ); |
| rStrm.EndRecord(); |
| |
| pcBuffer += nWriteChars; |
| nCharsLeft = nCharsLeft - nWriteChars; |
| } |
| } |
| break; |
| |
| case EXC_BIFF8: |
| if( mnObjId != EXC_OBJ_INVALID_ID ) |
| XclExpRecord::Save( rStrm ); |
| break; |
| |
| default: DBG_ERROR_BIFF(); |
| } |
| } |
| |
| void XclExpNote::WriteBody( XclExpStream& rStrm ) |
| { |
| // BIFF5/BIFF7 is written separately |
| DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 ); |
| |
| sal_uInt16 nFlags = 0; |
| ::set_flag( nFlags, EXC_NOTE_VISIBLE, mbVisible ); |
| |
| rStrm << static_cast< sal_uInt16 >( maScPos.Row() ) |
| << static_cast< sal_uInt16 >( maScPos.Col() ) |
| << nFlags |
| << mnObjId |
| << maAuthor |
| << sal_uInt8( 0 ); |
| } |
| |
| void XclExpNote::WriteXml( sal_Int32 nAuthorId, XclExpXmlStream& rStrm ) |
| { |
| sax_fastparser::FSHelperPtr rComments = rStrm.GetCurrentStream(); |
| |
| rComments->startElement( XML_comment, |
| XML_ref, XclXmlUtils::ToOString( maScPos ).getStr(), |
| XML_authorId, OString::valueOf( nAuthorId ).getStr(), |
| // OOXTODO: XML_guid, |
| FSEND ); |
| rComments->startElement( XML_text, FSEND ); |
| // OOXTODO: phoneticPr, rPh, r |
| rComments->startElement( XML_t, FSEND ); |
| rComments->writeEscaped( XclXmlUtils::ToOUString( maOrigNoteText ) ); |
| rComments->endElement ( XML_t ); |
| rComments->endElement( XML_text ); |
| rComments->endElement( XML_comment ); |
| } |
| |
| // ============================================================================ |
| |
| XclExpComments::XclExpComments( SCTAB nTab, XclExpRecordList< XclExpNote >& rNotes ) |
| : mnTab( nTab ), mrNotes( rNotes ) |
| { |
| } |
| |
| struct OUStringLess : public std::binary_function<OUString, OUString, bool> |
| { |
| bool operator()(const OUString& x, const OUString& y) const |
| { |
| return x.compareTo( y ) <= 0; |
| } |
| }; |
| |
| void XclExpComments::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| if( mrNotes.IsEmpty() ) |
| return; |
| |
| sax_fastparser::FSHelperPtr rComments = rStrm.CreateOutputStream( |
| XclXmlUtils::GetStreamName( "xl/", "comments", mnTab + 1 ), |
| XclXmlUtils::GetStreamName( "../", "comments", mnTab + 1 ), |
| rStrm.GetCurrentStream()->getOutputStream(), |
| "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml", |
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" ); |
| rStrm.PushStream( rComments ); |
| |
| rComments->startElement( XML_comments, |
| XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main", |
| FSEND ); |
| rComments->startElement( XML_authors, FSEND ); |
| |
| typedef std::set< OUString, OUStringLess > Authors; |
| Authors aAuthors; |
| |
| size_t nNotes = mrNotes.GetSize(); |
| for( size_t i = 0; i < nNotes; ++i ) |
| { |
| aAuthors.insert( XclXmlUtils::ToOUString( mrNotes.GetRecord( i )->GetAuthor() ) ); |
| } |
| |
| for( Authors::const_iterator b = aAuthors.begin(), e = aAuthors.end(); b != e; ++b ) |
| { |
| rComments->startElement( XML_author, FSEND ); |
| rComments->writeEscaped( *b ); |
| rComments->endElement( XML_author ); |
| } |
| |
| rComments->endElement( XML_authors ); |
| rComments->startElement( XML_commentList, FSEND ); |
| |
| Authors::const_iterator aAuthorsBegin = aAuthors.begin(); |
| for( size_t i = 0; i < nNotes; ++i ) |
| { |
| XclExpNoteList::RecordRefType xNote = mrNotes.GetRecord( i ); |
| Authors::const_iterator aAuthor = aAuthors.find( |
| XclXmlUtils::ToOUString( xNote->GetAuthor() ) ); |
| sal_Int32 nAuthorId = distance( aAuthorsBegin, aAuthor ); |
| xNote->WriteXml( nAuthorId, rStrm ); |
| } |
| |
| rComments->endElement( XML_commentList ); |
| rComments->endElement( XML_comments ); |
| |
| rStrm.PopStream(); |
| } |
| |
| // object manager ============================================================= |
| |
| XclExpObjectManager::XclExpObjectManager( const XclExpRoot& rRoot ) : |
| XclExpRoot( rRoot ) |
| { |
| InitStream( true ); |
| mxEscherEx.reset( new XclEscherEx( GetRoot(), *this, *mxDffStrm ) ); |
| } |
| |
| XclExpObjectManager::XclExpObjectManager( const XclExpObjectManager& rParent ) : |
| XclExpRoot( rParent.GetRoot() ) |
| { |
| InitStream( false ); |
| mxEscherEx.reset( new XclEscherEx( GetRoot(), *this, *mxDffStrm, rParent.mxEscherEx.get() ) ); |
| } |
| |
| XclExpObjectManager::~XclExpObjectManager() |
| { |
| } |
| |
| XclExpDffAnchorBase* XclExpObjectManager::CreateDffAnchor() const |
| { |
| return new XclExpDffSheetAnchor( GetRoot() ); |
| } |
| |
| ScfRef< XclExpRecordBase > XclExpObjectManager::CreateDrawingGroup() |
| { |
| return ScfRef< XclExpRecordBase >( new XclExpMsoDrawingGroup( *mxEscherEx ) ); |
| } |
| |
| void XclExpObjectManager::StartSheet() |
| { |
| mxObjList.reset( new XclExpObjList( GetRoot(), *mxEscherEx ) ); |
| } |
| |
| ScfRef< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( SdrPage* pSdrPage ) |
| { |
| if( pSdrPage ) |
| mxEscherEx->AddSdrPage( *pSdrPage ); |
| // #106213# the first dummy object may still be open |
| DBG_ASSERT( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" ); |
| while( mxEscherEx->GetGroupLevel() ) |
| mxEscherEx->LeaveGroup(); |
| mxObjList->EndSheet(); |
| return mxObjList; |
| } |
| |
| ScfRef< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const Reference< XShapes >& rxShapes ) |
| { |
| if( rxShapes.is() ) |
| mxEscherEx->AddUnoShapes( rxShapes ); |
| // #106213# the first dummy object may still be open |
| DBG_ASSERT( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" ); |
| while( mxEscherEx->GetGroupLevel() ) |
| mxEscherEx->LeaveGroup(); |
| mxObjList->EndSheet(); |
| return mxObjList; |
| } |
| |
| void XclExpObjectManager::EndDocument() |
| { |
| mxEscherEx->EndDocument(); |
| } |
| |
| XclExpMsoDrawing* XclExpObjectManager::GetMsodrawingPerSheet() |
| { |
| return mxObjList->GetMsodrawingPerSheet(); |
| } |
| |
| bool XclExpObjectManager::HasObj() const |
| { |
| return mxObjList->Count() > 0; |
| } |
| |
| sal_uInt16 XclExpObjectManager::AddObj( XclObj* pObjRec ) |
| { |
| return mxObjList->Add( pObjRec ); |
| } |
| |
| XclObj* XclExpObjectManager::RemoveLastObj() |
| { |
| XclObj* pLastObj = static_cast< XclObj* >( mxObjList->Last() ); |
| mxObjList->Remove(); // remove current, which is the Last() |
| return pLastObj; |
| } |
| |
| void XclExpObjectManager::InitStream( bool bTempFile ) |
| { |
| if( bTempFile ) |
| { |
| mxTempFile.reset( new ::utl::TempFile ); |
| if( mxTempFile->IsValid() ) |
| { |
| mxTempFile->EnableKillingFile(); |
| mxDffStrm.reset( ::utl::UcbStreamHelper::CreateStream( mxTempFile->GetURL(), STREAM_STD_READWRITE ) ); |
| } |
| } |
| |
| if( !mxDffStrm.get() ) |
| mxDffStrm.reset( new SvMemoryStream ); |
| |
| mxDffStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpEmbeddedObjectManager::XclExpEmbeddedObjectManager( |
| const XclExpObjectManager& rParent, const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY ) : |
| XclExpObjectManager( rParent ), |
| maPageSize( rPageSize ), |
| mnScaleX( nScaleX ), |
| mnScaleY( nScaleY ) |
| { |
| } |
| |
| XclExpDffAnchorBase* XclExpEmbeddedObjectManager::CreateDffAnchor() const |
| { |
| return new XclExpDffEmbeddedAnchor( GetRoot(), maPageSize, mnScaleX, mnScaleY ); |
| } |
| |
| // ============================================================================ |
| |