office-gobmx/chart2/source/tools/ImplUndoManager.cxx
Rüdiger Timm 01a82c74b6 INTEGRATION: CWS rptchart02 (1.5.60); FILE MERGED
2008/04/16 06:35:58 oj 1.5.60.2: RESYNC: (1.5-1.6); FILE MERGED
2008/04/15 12:50:19 oj 1.5.60.1: use comphelper copyProperties
2008-06-16 11:56:27 +00:00

479 lines
14 KiB
C++

/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: ImplUndoManager.cxx,v $
* $Revision: 1.7 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include "ImplUndoManager.hxx"
#include "DisposeHelper.hxx"
#include "CommonFunctors.hxx"
#include "ControllerLockGuard.hxx"
#include "PropertyHelper.hxx"
#include "DataSourceHelper.hxx"
#include <com/sun/star/chart/XChartDataArray.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/chart2/XInternalDataProvider.hpp>
#include <com/sun/star/chart2/XTitled.hpp>
#include <com/sun/star/util/XCloneable.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <boost/bind.hpp>
#include <algorithm>
using namespace ::com::sun::star;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;
using ::com::sun::star::chart::XChartDataArray;
namespace chart
{
namespace impl
{
void ImplApplyDataToModel(
Reference< frame::XModel > & xInOutModelToChange,
const Reference< chart2::XInternalDataProvider > & xData )
{
Reference< chart2::XChartDocument > xDoc( xInOutModelToChange, uno::UNO_QUERY );
OSL_ASSERT( xDoc.is() && xDoc->hasInternalDataProvider());
// copy data from stored internal data provider
if( xDoc.is() && xDoc->hasInternalDataProvider())
{
Reference< XChartDataArray > xCurrentData( xDoc->getDataProvider(), uno::UNO_QUERY );
Reference< XChartDataArray > xSavedData( xData, uno::UNO_QUERY );
if( xCurrentData.is() && xSavedData.is())
{
xCurrentData->setData( xSavedData->getData());
xCurrentData->setRowDescriptions( xSavedData->getRowDescriptions());
xCurrentData->setColumnDescriptions( xSavedData->getColumnDescriptions());
}
}
}
// ----------------------------------------
UndoElement::UndoElement(
const OUString & rActionString,
const Reference< frame::XModel > & xModel ) :
m_aActionString( rActionString )
{
initialize( xModel );
}
UndoElement::UndoElement(
const Reference< frame::XModel > & xModel )
{
initialize( xModel );
}
UndoElement::UndoElement( const UndoElement & rOther ) :
m_aActionString( rOther.m_aActionString )
{
initialize( rOther.m_xModel );
}
UndoElement::~UndoElement()
{}
void UndoElement::initialize( const Reference< frame::XModel > & xModel )
{
m_xModel.set( UndoElement::cloneModel( xModel ));
}
void UndoElement::dispose()
{
Reference< lang::XComponent > xComp( m_xModel, uno::UNO_QUERY );
if( xComp.is())
xComp->dispose();
m_xModel.set( 0 );
}
void UndoElement::applyToModel(
Reference< frame::XModel > & xInOutModelToChange )
{
UndoElement::applyModelContentToModel( xInOutModelToChange, m_xModel );
}
UndoElement * UndoElement::createFromModel(
const Reference< frame::XModel > & xModel )
{
return new UndoElement( getActionString(), xModel );
}
void UndoElement::setActionString( const ::rtl::OUString & rActionString )
{
m_aActionString = rActionString;
}
OUString UndoElement::getActionString() const
{
return m_aActionString;
}
// static
Reference< frame::XModel > UndoElement::cloneModel( const Reference< frame::XModel > & xModel )
{
Reference< frame::XModel > xResult;
uno::Reference< util::XCloneable > xCloneable( xModel, uno::UNO_QUERY );
OSL_ENSURE( xCloneable.is(), "Cannot clone model" );
if( xCloneable.is())
xResult.set( xCloneable->createClone(), uno::UNO_QUERY );
return xResult;
}
// static
void UndoElement::applyModelContentToModel(
Reference< frame::XModel > & xInOutModelToChange,
const Reference< frame::XModel > & xModelToCopyFrom,
const Reference< chart2::XInternalDataProvider > & xData /* = 0 */ )
{
if( xModelToCopyFrom.is() && xInOutModelToChange.is())
{
try
{
// /-- loccked controllers of destination
ControllerLockGuard aLockedControllers( xInOutModelToChange );
Reference< chart2::XChartDocument > xSource( xModelToCopyFrom, uno::UNO_QUERY_THROW );
Reference< chart2::XChartDocument > xDestination( xInOutModelToChange, uno::UNO_QUERY_THROW );
// diagram
xDestination->setFirstDiagram( xSource->getFirstDiagram());
// main title
Reference< chart2::XTitled > xDestinationTitled( xDestination, uno::UNO_QUERY_THROW );
Reference< chart2::XTitled > xSourceTitled( xSource, uno::UNO_QUERY_THROW );
xDestinationTitled->setTitleObject( xSourceTitled->getTitleObject());
// page background
comphelper::copyProperties(
xSource->getPageBackground(),
xDestination->getPageBackground() );
// apply data (not applied in standard Undo)
if( xData.is())
ImplApplyDataToModel( xInOutModelToChange, xData );
// register all sequences at the internal data provider to get adapted
// indexes when columns are added/removed
if( xDestination->hasInternalDataProvider())
{
Reference< chart2::XInternalDataProvider > xNewDataProvider( xDestination->getDataProvider(), uno::UNO_QUERY );
Reference< chart2::data::XDataSource > xUsedData( DataSourceHelper::getUsedData( xInOutModelToChange ));
if( xUsedData.is() && xNewDataProvider.is())
{
Sequence< Reference< chart2::data::XLabeledDataSequence > > aData( xUsedData->getDataSequences());
for( sal_Int32 i=0; i<aData.getLength(); ++i )
{
xNewDataProvider->registerDataSequenceForChanges( aData[i]->getValues());
xNewDataProvider->registerDataSequenceForChanges( aData[i]->getLabel());
}
}
}
// restore modify status
Reference< util::XModifiable > xSourceMod( xSource, uno::UNO_QUERY );
Reference< util::XModifiable > xDestMod( xDestination, uno::UNO_QUERY );
if( xSourceMod.is() && xDestMod.is() &&
! xSourceMod->isModified() )
{
xDestMod->setModified( sal_False );
}
// \-- loccked controllers of destination
}
catch( uno::Exception & )
{
}
}
}
// ----------------------------------------
UndoElementWithData::UndoElementWithData(
const OUString & rActionString,
const Reference< frame::XModel > & xModel ) :
UndoElement( rActionString, xModel )
{
initializeData();
}
UndoElementWithData::UndoElementWithData(
const Reference< frame::XModel > & xModel ) :
UndoElement( xModel )
{
initializeData();
}
UndoElementWithData::UndoElementWithData(
const UndoElementWithData & rOther ) :
UndoElement( rOther )
{
initializeData();
}
UndoElementWithData::~UndoElementWithData()
{}
void UndoElementWithData::initializeData()
{
try
{
Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY_THROW );
OSL_ASSERT( xChartDoc->hasInternalDataProvider());
if( xChartDoc->hasInternalDataProvider())
{
Reference< util::XCloneable > xCloneable( xChartDoc->getDataProvider(), uno::UNO_QUERY );
OSL_ENSURE( xCloneable.is(), "Cannot clone data" );
if( xCloneable.is())
m_xData.set( xCloneable->createClone(), uno::UNO_QUERY );
}
}
catch( uno::Exception & )
{
}
}
void UndoElementWithData::dispose()
{
UndoElement::dispose();
m_xData.set( 0 );
}
void UndoElementWithData::applyToModel(
Reference< frame::XModel > & xInOutModelToChange )
{
UndoElement::applyModelContentToModel( xInOutModelToChange, m_xModel, m_xData );
}
UndoElement * UndoElementWithData::createFromModel(
const Reference< frame::XModel > & xModel )
{
return new UndoElementWithData( getActionString(), xModel );
}
// ========================================
// ----------------------------------------
UndoElementWithSelection::UndoElementWithSelection(
const OUString & rActionString,
const Reference< frame::XModel > & xModel ) :
UndoElement( rActionString, xModel )
{
initialize( xModel );
}
UndoElementWithSelection::UndoElementWithSelection(
const Reference< frame::XModel > & xModel ) :
UndoElement( xModel )
{
initialize( xModel );
}
UndoElementWithSelection::UndoElementWithSelection(
const UndoElementWithSelection & rOther ) :
UndoElement( rOther )
{
initialize( rOther.m_xModel );
}
UndoElementWithSelection::~UndoElementWithSelection()
{}
void UndoElementWithSelection::initialize( const Reference< frame::XModel > & xModel )
{
try
{
uno::Reference< view::XSelectionSupplier > xSelSupp( xModel->getCurrentController(), uno::UNO_QUERY );
OSL_ASSERT( xSelSupp.is() );
if( xSelSupp.is() )
m_aSelection = xSelSupp->getSelection();
}
catch( const uno::Exception & )
{
}
}
void UndoElementWithSelection::dispose()
{
UndoElement::dispose();
m_aSelection.clear();
}
void UndoElementWithSelection::applyToModel(
Reference< frame::XModel > & xInOutModelToChange )
{
UndoElement::applyModelContentToModel( xInOutModelToChange, m_xModel );
Reference< view::XSelectionSupplier > xCurrentSelectionSuppl( xInOutModelToChange->getCurrentController(), uno::UNO_QUERY );
OSL_ASSERT( xCurrentSelectionSuppl.is() );
if( xCurrentSelectionSuppl.is())
xCurrentSelectionSuppl->select( m_aSelection );
}
UndoElement * UndoElementWithSelection::createFromModel(
const Reference< frame::XModel > & xModel )
{
return new UndoElementWithSelection( getActionString(), xModel );
}
// ========================================
UndoStack::UndoStack() :
m_nSizeLimit( 1000 )
{
}
UndoStack::~UndoStack()
{
disposeAndClear();
}
void UndoStack::pop()
{
if( ! empty())
{
top()->dispose();
delete top();
m_aStack.pop_back();
}
}
void UndoStack::push( UndoElement * pElement )
{
m_aStack.push_back( pElement );
applyLimitation();
}
UndoElement * UndoStack::top() const
{
return m_aStack.back();
}
OUString UndoStack::topUndoString() const
{
if( ! empty())
return top()->getActionString();
return OUString();
}
Sequence< OUString > UndoStack::getUndoStrings() const
{
sal_Int32 nSize( static_cast< sal_Int32 >( m_aStack.size()));
Sequence< OUString > aResult( nSize );
for( sal_Int32 i=0; i<nSize; ++i )
aResult[i] = m_aStack[i]->getActionString();
return aResult;
}
bool UndoStack::empty() const
{
return m_aStack.empty();
}
void UndoStack::disposeAndClear()
{
::std::for_each( m_aStack.begin(), m_aStack.end(), ::boost::mem_fn( & UndoElement::dispose ));
::std::for_each( m_aStack.begin(), m_aStack.end(), CommonFunctors::DeletePtr< UndoElement >() );
m_aStack.clear();
}
void UndoStack::limitSize( sal_Int32 nMaxSize )
{
m_nSizeLimit = nMaxSize;
applyLimitation();
}
sal_Int32 UndoStack::getCurrentLimitation() const
{
return m_nSizeLimit;
}
void UndoStack::applyLimitation()
{
if( m_aStack.size() > static_cast< sal_uInt32 >( m_nSizeLimit ))
{
tUndoStackType::iterator aBegin( m_aStack.begin());
tUndoStackType::iterator aEnd( aBegin + (m_aStack.size() - m_nSizeLimit));
// dispose and remove all undo elements that are over the limit
::std::for_each( aBegin, aEnd, ::boost::mem_fn( & UndoElement::dispose ));
::std::for_each( aBegin, aEnd, CommonFunctors::DeletePtr< UndoElement >() );
m_aStack.erase( aBegin, aEnd );
}
}
// ================================================================================
namespace
{
static const OUString aUndoStepsPropName( RTL_CONSTASCII_USTRINGPARAM("Steps"));
} // anonymous namespace
UndoStepsConfigItem::UndoStepsConfigItem( ConfigItemListener & rListener ) :
::utl::ConfigItem( OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/Undo"))),
m_rListener( rListener )
{
EnableNotification( Sequence< OUString >( & aUndoStepsPropName, 1 ));
}
UndoStepsConfigItem::~UndoStepsConfigItem()
{
}
void UndoStepsConfigItem::Notify( const Sequence< OUString > & aPropertyNames )
{
for( sal_Int32 nIdx=0; nIdx<aPropertyNames.getLength(); ++nIdx )
{
if( aPropertyNames[nIdx].equals( aUndoStepsPropName ))
m_rListener.notify( aPropertyNames[nIdx] );
}
}
// mtehod is not const, because GetProperties is not const
sal_Int32 UndoStepsConfigItem::getUndoSteps()
{
sal_Int32 nSteps = -1;
Sequence< uno::Any > aValues(
GetProperties( Sequence< OUString >( & aUndoStepsPropName, 1 )));
if( aValues.getLength())
aValues[0] >>= nSteps;
return nSteps;
}
} // namespace impl
} // namespace chart