Files
libreoffice/sc/source/ui/unoobj/viewuno.cxx
Samuel Mehrbrodt d0cacf09a1 tdf#99708 Save formula bar height to document
Save the current state of the Calc formula bar to the document.
Number of visible lines is saved into the document settings
and restored when loading that document.

Also adds a UNO property, so that the formula bar height can be
changed via UNO.

Change-Id: Ifef0c9e42cb4f7465516629d2c22974367e0eb33
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133499
Tested-by: Jenkins
Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
2022-05-03 14:52:07 +02:00

2206 lines
75 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
#include <com/sun/star/awt/MouseButton.hpp>
#include <com/sun/star/drawing/ShapeCollection.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
#include <com/sun/star/util/VetoException.hpp>
#include <com/sun/star/view/DocumentZoomType.hpp>
#include <editeng/outliner.hxx>
#include <svx/svditer.hxx>
#include <svx/svdmark.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdpagv.hxx>
#include <svx/svdview.hxx>
#include <svx/unoshape.hxx>
#include <svx/fmshell.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/request.hxx>
#include <sfx2/viewfrm.hxx>
#include <comphelper/profilezone.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <toolkit/helper/convert.hxx>
#include <vcl/svapp.hxx>
#include <drawsh.hxx>
#include <drtxtob.hxx>
#include <transobj.hxx>
#include <editsh.hxx>
#include <viewuno.hxx>
#include <cellsuno.hxx>
#include <miscuno.hxx>
#include <tabvwsh.hxx>
#include <prevwsh.hxx>
#include <docsh.hxx>
#include <drwlayer.hxx>
#include <drawview.hxx>
#include <fupoor.hxx>
#include <sc.hrc>
#include <unonames.hxx>
#include <scmod.hxx>
#include <appoptio.hxx>
#include <gridwin.hxx>
#include <sheetevents.hxx>
#include <markdata.hxx>
#include <scextopt.hxx>
#include <preview.hxx>
#include <inputhdl.hxx>
#include <inputwin.hxx>
#include <svx/sdrhittesthelper.hxx>
#include <formatsh.hxx>
#include <sfx2/app.hxx>
using namespace com::sun::star;
//! Clipping Marks
// no Which-ID here, Map only for PropertySetInfo
static const SfxItemPropertyMapEntry* lcl_GetViewOptPropertyMap()
{
static const SfxItemPropertyMapEntry aViewOptPropertyMap_Impl[] =
{
{ OLD_UNO_COLROWHDR, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_GRIDCOLOR, 0, cppu::UnoType<sal_Int32>::get(), 0, 0},
{ SC_UNO_COLROWHDR, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_HORSCROLL, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHEETTABS, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_VERTSCROLL, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_HIDESPELL, 0, cppu::UnoType<bool>::get(), 0, 0}, /* deprecated #i91949 */
{ OLD_UNO_HORSCROLL, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_OUTLSYMB, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_VALUEHIGH, 0, cppu::UnoType<bool>::get(), 0, 0},
{ OLD_UNO_OUTLSYMB, 0, cppu::UnoType<bool>::get(), 0, 0},
{ OLD_UNO_SHEETTABS, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHOWANCHOR, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHOWCHARTS, 0, cppu::UnoType<sal_Int16>::get(), 0, 0},
{ SC_UNO_SHOWDRAW, 0, cppu::UnoType<sal_Int16>::get(), 0, 0},
{ SC_UNO_SHOWFORM, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHOWGRID, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHOWHELP, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHOWNOTES, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHOWOBJ, 0, cppu::UnoType<sal_Int16>::get(), 0, 0},
{ SC_UNO_SHOWPAGEBR, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHOWZERO, 0, cppu::UnoType<bool>::get(), 0, 0},
{ OLD_UNO_VALUEHIGH, 0, cppu::UnoType<bool>::get(), 0, 0},
{ OLD_UNO_VERTSCROLL, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_VISAREA, 0, cppu::UnoType<awt::Rectangle>::get(), 0, 0},
{ SC_UNO_ZOOMTYPE, 0, cppu::UnoType<sal_Int16>::get(), 0, 0},
{ SC_UNO_ZOOMVALUE, 0, cppu::UnoType<sal_Int16>::get(), 0, 0},
{ SC_UNO_VISAREASCREEN,0, cppu::UnoType<awt::Rectangle>::get(), 0, 0},
{ SC_UNO_FORMULABARHEIGHT,0,cppu::UnoType<sal_Int16>::get(), 0, 0},
{ u"", 0, css::uno::Type(), 0, 0 }
};
return aViewOptPropertyMap_Impl;
}
constexpr OUStringLiteral SCTABVIEWOBJ_SERVICE = u"com.sun.star.sheet.SpreadsheetView";
constexpr OUStringLiteral SCVIEWSETTINGS_SERVICE = u"com.sun.star.sheet.SpreadsheetViewSettings";
SC_SIMPLE_SERVICE_INFO( ScViewPaneBase, "ScViewPaneObj", "com.sun.star.sheet.SpreadsheetViewPane" )
ScViewPaneBase::ScViewPaneBase(ScTabViewShell* pViewSh, sal_uInt16 nP) :
pViewShell( pViewSh ),
nPane( nP )
{
if (pViewShell)
StartListening(*pViewShell);
}
ScViewPaneBase::~ScViewPaneBase()
{
SolarMutexGuard g;
if (pViewShell)
EndListening(*pViewShell);
}
void ScViewPaneBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
if ( rHint.GetId() == SfxHintId::Dying )
pViewShell = nullptr;
}
uno::Any SAL_CALL ScViewPaneBase::queryInterface( const uno::Type& rType )
{
SC_QUERYINTERFACE( sheet::XViewPane )
SC_QUERYINTERFACE( sheet::XCellRangeReferrer )
SC_QUERYINTERFACE( view::XFormLayerAccess )
SC_QUERYINTERFACE( view::XControlAccess )
SC_QUERYINTERFACE( lang::XServiceInfo )
SC_QUERYINTERFACE( lang::XTypeProvider )
return uno::Any(); // OWeakObject is in derived objects
}
uno::Sequence<uno::Type> SAL_CALL ScViewPaneBase::getTypes()
{
static const uno::Sequence<uno::Type> aTypes
{
cppu::UnoType<sheet::XViewPane>::get(),
cppu::UnoType<sheet::XCellRangeReferrer>::get(),
cppu::UnoType<view::XFormLayerAccess>::get(),
cppu::UnoType<lang::XServiceInfo>::get(),
cppu::UnoType<lang::XTypeProvider>::get(),
};
return aTypes;
}
uno::Sequence<sal_Int8> SAL_CALL ScViewPaneBase::getImplementationId()
{
return css::uno::Sequence<sal_Int8>();
}
// XViewPane
sal_Int32 SAL_CALL ScViewPaneBase::getFirstVisibleColumn()
{
SolarMutexGuard aGuard;
if (pViewShell)
{
ScViewData& rViewData = pViewShell->GetViewData();
ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ?
rViewData.GetActivePart() :
static_cast<ScSplitPos>(nPane);
ScHSplitPos eWhichH = WhichH( eWhich );
return rViewData.GetPosX( eWhichH );
}
OSL_FAIL("no View ?!?"); //! Exception?
return 0;
}
void SAL_CALL ScViewPaneBase::setFirstVisibleColumn(sal_Int32 nFirstVisibleColumn)
{
SolarMutexGuard aGuard;
if (pViewShell)
{
ScViewData& rViewData = pViewShell->GetViewData();
ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ?
rViewData.GetActivePart() :
static_cast<ScSplitPos>(nPane);
ScHSplitPos eWhichH = WhichH( eWhich );
tools::Long nDeltaX = static_cast<tools::Long>(nFirstVisibleColumn) - rViewData.GetPosX( eWhichH );
pViewShell->ScrollX( nDeltaX, eWhichH );
}
}
sal_Int32 SAL_CALL ScViewPaneBase::getFirstVisibleRow()
{
SolarMutexGuard aGuard;
if (pViewShell)
{
ScViewData& rViewData = pViewShell->GetViewData();
ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ?
rViewData.GetActivePart() :
static_cast<ScSplitPos>(nPane);
ScVSplitPos eWhichV = WhichV( eWhich );
return rViewData.GetPosY( eWhichV );
}
OSL_FAIL("no View ?!?"); //! Exception?
return 0;
}
void SAL_CALL ScViewPaneBase::setFirstVisibleRow( sal_Int32 nFirstVisibleRow )
{
SolarMutexGuard aGuard;
if (pViewShell)
{
ScViewData& rViewData = pViewShell->GetViewData();
ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ?
rViewData.GetActivePart() :
static_cast<ScSplitPos>(nPane);
ScVSplitPos eWhichV = WhichV( eWhich );
tools::Long nDeltaY = static_cast<tools::Long>(nFirstVisibleRow) - rViewData.GetPosY( eWhichV );
pViewShell->ScrollY( nDeltaY, eWhichV );
}
}
table::CellRangeAddress SAL_CALL ScViewPaneBase::getVisibleRange()
{
SolarMutexGuard aGuard;
table::CellRangeAddress aAdr;
if (pViewShell)
{
ScViewData& rViewData = pViewShell->GetViewData();
ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ?
rViewData.GetActivePart() :
static_cast<ScSplitPos>(nPane);
ScHSplitPos eWhichH = WhichH( eWhich );
ScVSplitPos eWhichV = WhichV( eWhich );
// VisibleCellsX returns only completely visible cells
// VisibleRange in Excel also partially visible ones
//! do the same ???
SCCOL nVisX = rViewData.VisibleCellsX( eWhichH );
SCROW nVisY = rViewData.VisibleCellsY( eWhichV );
if (!nVisX) nVisX = 1; // there has to be something in the range
if (!nVisY) nVisY = 1;
aAdr.Sheet = rViewData.GetTabNo();
aAdr.StartColumn = rViewData.GetPosX( eWhichH );
aAdr.StartRow = rViewData.GetPosY( eWhichV );
aAdr.EndColumn = aAdr.StartColumn + nVisX - 1;
aAdr.EndRow = aAdr.StartRow + nVisY - 1;
}
return aAdr;
}
// XCellRangeSource
uno::Reference<table::XCellRange> SAL_CALL ScViewPaneBase::getReferredCells()
{
SolarMutexGuard aGuard;
if (pViewShell)
{
ScDocShell* pDocSh = pViewShell->GetViewData().GetDocShell();
table::CellRangeAddress aAdr(getVisibleRange()); //! helper function with ScRange?
ScRange aRange( static_cast<SCCOL>(aAdr.StartColumn), static_cast<SCROW>(aAdr.StartRow), aAdr.Sheet,
static_cast<SCCOL>(aAdr.EndColumn), static_cast<SCROW>(aAdr.EndRow), aAdr.Sheet );
if ( aRange.aStart == aRange.aEnd )
return new ScCellObj( pDocSh, aRange.aStart );
else
return new ScCellRangeObj( pDocSh, aRange );
}
return nullptr;
}
namespace
{
bool lcl_prepareFormShellCall( ScTabViewShell* _pViewShell, sal_uInt16 _nPane, FmFormShell*& _rpFormShell, vcl::Window*& _rpWindow, SdrView*& _rpSdrView )
{
if ( !_pViewShell )
return false;
ScViewData& rViewData = _pViewShell->GetViewData();
ScSplitPos eWhich = ( _nPane == SC_VIEWPANE_ACTIVE ) ?
rViewData.GetActivePart() :
static_cast<ScSplitPos>(_nPane);
_rpWindow = _pViewShell->GetWindowByPos( eWhich );
_rpSdrView = _pViewShell->GetScDrawView();
_rpFormShell = _pViewShell->GetFormShell();
return ( _rpFormShell != nullptr ) && ( _rpSdrView != nullptr )&& ( _rpWindow != nullptr );
}
}
// XFormLayerAccess
uno::Reference< form::runtime::XFormController > SAL_CALL ScViewPaneBase::getFormController( const uno::Reference< form::XForm >& Form )
{
SolarMutexGuard aGuard;
uno::Reference< form::runtime::XFormController > xController;
vcl::Window* pWindow( nullptr );
SdrView* pSdrView( nullptr );
FmFormShell* pFormShell( nullptr );
if ( lcl_prepareFormShellCall( pViewShell, nPane, pFormShell, pWindow, pSdrView ) )
xController = FmFormShell::GetFormController( Form, *pSdrView, *pWindow->GetOutDev() );
return xController;
}
sal_Bool SAL_CALL ScViewPaneBase::isFormDesignMode( )
{
SolarMutexGuard aGuard;
bool bIsFormDesignMode( true );
FmFormShell* pFormShell( pViewShell ? pViewShell->GetFormShell() : nullptr );
if ( pFormShell )
bIsFormDesignMode = pFormShell->IsDesignMode();
return bIsFormDesignMode;
}
void SAL_CALL ScViewPaneBase::setFormDesignMode( sal_Bool DesignMode )
{
SolarMutexGuard aGuard;
vcl::Window* pWindow( nullptr );
SdrView* pSdrView( nullptr );
FmFormShell* pFormShell( nullptr );
if ( lcl_prepareFormShellCall( pViewShell, nPane, pFormShell, pWindow, pSdrView ) )
pFormShell->SetDesignMode( DesignMode );
}
// XControlAccess
uno::Reference<awt::XControl> SAL_CALL ScViewPaneBase::getControl(
const uno::Reference<awt::XControlModel>& xModel )
{
SolarMutexGuard aGuard;
uno::Reference<awt::XControl> xRet;
vcl::Window* pWindow( nullptr );
SdrView* pSdrView( nullptr );
FmFormShell* pFormShell( nullptr );
if ( lcl_prepareFormShellCall( pViewShell, nPane, pFormShell, pWindow, pSdrView ) )
pFormShell->GetFormControl( xModel, *pSdrView, *pWindow->GetOutDev(), xRet );
if ( !xRet.is() )
throw container::NoSuchElementException(); // no control found
return xRet;
}
awt::Rectangle ScViewPaneBase::GetVisArea() const
{
awt::Rectangle aVisArea;
if (pViewShell)
{
ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ?
pViewShell->GetViewData().GetActivePart() :
static_cast<ScSplitPos>(nPane);
ScGridWindow* pWindow = static_cast<ScGridWindow*>(pViewShell->GetWindowByPos(eWhich));
ScDocument& rDoc = pViewShell->GetViewData().GetDocument();
if (pWindow)
{
ScHSplitPos eWhichH = ((eWhich == SC_SPLIT_TOPLEFT) || (eWhich == SC_SPLIT_BOTTOMLEFT)) ?
SC_SPLIT_LEFT : SC_SPLIT_RIGHT;
ScVSplitPos eWhichV = ((eWhich == SC_SPLIT_TOPLEFT) || (eWhich == SC_SPLIT_TOPRIGHT)) ?
SC_SPLIT_TOP : SC_SPLIT_BOTTOM;
ScAddress aCell(pViewShell->GetViewData().GetPosX(eWhichH),
pViewShell->GetViewData().GetPosY(eWhichV),
pViewShell->GetViewData().GetTabNo());
tools::Rectangle aCellRect( rDoc.GetMMRect( aCell.Col(), aCell.Row(), aCell.Col(), aCell.Row(), aCell.Tab() ) );
Size aVisSize( pWindow->PixelToLogic( pWindow->GetSizePixel(), pWindow->GetDrawMapMode( true ) ) );
Point aVisPos( aCellRect.TopLeft() );
if ( rDoc.IsLayoutRTL( aCell.Tab() ) )
{
aVisPos = aCellRect.TopRight();
aVisPos.AdjustX( -(aVisSize.Width()) );
}
tools::Rectangle aVisRect( aVisPos, aVisSize );
aVisArea = AWTRectangle(aVisRect);
}
}
return aVisArea;
}
ScViewPaneObj::ScViewPaneObj(ScTabViewShell* pViewSh, sal_uInt16 nP) :
ScViewPaneBase( pViewSh, nP )
{
}
ScViewPaneObj::~ScViewPaneObj()
{
}
uno::Any SAL_CALL ScViewPaneObj::queryInterface( const uno::Type& rType )
{
// ScViewPaneBase has everything except OWeakObject
uno::Any aRet(ScViewPaneBase::queryInterface( rType ));
if (!aRet.hasValue())
aRet = OWeakObject::queryInterface( rType );
return aRet;
}
void SAL_CALL ScViewPaneObj::acquire() noexcept
{
OWeakObject::acquire();
}
void SAL_CALL ScViewPaneObj::release() noexcept
{
OWeakObject::release();
}
// We need default ctor for SMART_REFLECTION_IMPLEMENTATION
ScTabViewObj::ScTabViewObj( ScTabViewShell* pViewSh ) :
ScViewPaneBase( pViewSh, SC_VIEWPANE_ACTIVE ),
SfxBaseController( pViewSh ),
aPropSet( lcl_GetViewOptPropertyMap() ),
aMouseClickHandlers( 0 ),
aActivationListeners( 0 ),
nPreviousTab( 0 ),
bDrawSelModeSet(false),
bFilteredRangeSelection(false),
mbLeftMousePressed(false)
{
if (pViewSh)
nPreviousTab = pViewSh->GetViewData().GetTabNo();
}
ScTabViewObj::~ScTabViewObj()
{
//! Listening or something along that line
if (!aMouseClickHandlers.empty())
{
acquire();
EndMouseListening();
}
if (!aActivationListeners.empty())
{
acquire();
EndActivationListening();
}
}
uno::Any SAL_CALL ScTabViewObj::queryInterface( const uno::Type& rType )
{
SC_QUERYINTERFACE( sheet::XSpreadsheetView )
SC_QUERYINTERFACE( sheet::XEnhancedMouseClickBroadcaster )
SC_QUERYINTERFACE( sheet::XActivationBroadcaster )
SC_QUERYINTERFACE( container::XEnumerationAccess )
SC_QUERYINTERFACE( container::XIndexAccess )
SC_QUERY_MULTIPLE( container::XElementAccess, container::XIndexAccess )
SC_QUERYINTERFACE( view::XSelectionSupplier )
SC_QUERYINTERFACE( beans::XPropertySet )
SC_QUERYINTERFACE( sheet::XViewSplitable )
SC_QUERYINTERFACE( sheet::XViewFreezable )
SC_QUERYINTERFACE( sheet::XRangeSelection )
SC_QUERYINTERFACE( lang::XUnoTunnel )
SC_QUERYINTERFACE( datatransfer::XTransferableSupplier )
SC_QUERYINTERFACE( sheet::XSelectedSheetsSupplier )
uno::Any aRet(ScViewPaneBase::queryInterface( rType ));
if (!aRet.hasValue())
aRet = SfxBaseController::queryInterface( rType );
return aRet;
}
void SAL_CALL ScTabViewObj::acquire() noexcept
{
SfxBaseController::acquire();
}
void SAL_CALL ScTabViewObj::release() noexcept
{
SfxBaseController::release();
}
static void lcl_CallActivate( ScDocShell* pDocSh, SCTAB nTab, ScSheetEventId nEvent )
{
ScDocument& rDoc = pDocSh->GetDocument();
// when deleting a sheet, nPreviousTab can be invalid
// (could be handled with reference updates)
if (!rDoc.HasTable(nTab))
return;
const ScSheetEvents* pEvents = rDoc.GetSheetEvents(nTab);
if (pEvents)
{
const OUString* pScript = pEvents->GetScript(nEvent);
if (pScript)
{
uno::Any aRet;
uno::Sequence<uno::Any> aParams;
uno::Sequence<sal_Int16> aOutArgsIndex;
uno::Sequence<uno::Any> aOutArgs;
/*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
}
}
// execute VBA event handlers
try
{
uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( rDoc.GetVbaEventProcessor(), uno::UNO_SET_THROW );
// the parameter is the clicked object, as in the mousePressed call above
uno::Sequence< uno::Any > aArgs{ uno::Any(nTab) };
xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs );
}
catch( uno::Exception& )
{
}
}
void ScTabViewObj::SheetChanged( bool bSameTabButMoved )
{
if ( !GetViewShell() )
return;
ScViewData& rViewData = GetViewShell()->GetViewData();
ScDocShell* pDocSh = rViewData.GetDocShell();
if (!aActivationListeners.empty())
{
sheet::ActivationEvent aEvent;
uno::Reference< sheet::XSpreadsheetView > xView(this);
uno::Reference< uno::XInterface > xSource(xView, uno::UNO_QUERY);
aEvent.Source = xSource;
aEvent.ActiveSheet = new ScTableSheetObj(pDocSh, rViewData.GetTabNo());
// Listener's handler may remove it from the listeners list
for (size_t i = aActivationListeners.size(); i > 0; --i)
{
try
{
aActivationListeners[i - 1]->activeSpreadsheetChanged( aEvent );
}
catch( uno::Exception& )
{
aActivationListeners.erase(aActivationListeners.begin() + (i - 1));
}
}
}
/* Handle sheet events, but do not trigger event handlers, if the old
active sheet gets re-activated after inserting/deleting/moving a sheet. */
SCTAB nNewTab = rViewData.GetTabNo();
if ( !bSameTabButMoved && (nNewTab != nPreviousTab) )
{
lcl_CallActivate( pDocSh, nPreviousTab, ScSheetEventId::UNFOCUS );
lcl_CallActivate( pDocSh, nNewTab, ScSheetEventId::FOCUS );
}
nPreviousTab = nNewTab;
}
uno::Sequence<uno::Type> SAL_CALL ScTabViewObj::getTypes()
{
return comphelper::concatSequences(
ScViewPaneBase::getTypes(),
SfxBaseController::getTypes(),
uno::Sequence<uno::Type>
{
cppu::UnoType<sheet::XSpreadsheetView>::get(),
cppu::UnoType<container::XEnumerationAccess>::get(),
cppu::UnoType<container::XIndexAccess>::get(),
cppu::UnoType<view::XSelectionSupplier>::get(),
cppu::UnoType<beans::XPropertySet>::get(),
cppu::UnoType<sheet::XViewSplitable>::get(),
cppu::UnoType<sheet::XViewFreezable>::get(),
cppu::UnoType<sheet::XRangeSelection>::get(),
cppu::UnoType<lang::XUnoTunnel>::get(),
cppu::UnoType<sheet::XEnhancedMouseClickBroadcaster>::get(),
cppu::UnoType<sheet::XActivationBroadcaster>::get(),
cppu::UnoType<datatransfer::XTransferableSupplier>::get()
} );
}
uno::Sequence<sal_Int8> SAL_CALL ScTabViewObj::getImplementationId()
{
return css::uno::Sequence<sal_Int8>();
}
// XDocumentView
static bool lcl_TabInRanges( SCTAB nTab, const ScRangeList& rRanges )
{
for (size_t i = 0, nCount = rRanges.size(); i < nCount; ++i)
{
const ScRange & rRange = rRanges[ i ];
if ( nTab >= rRange.aStart.Tab() && nTab <= rRange.aEnd.Tab() )
return true;
}
return false;
}
static void lcl_ShowObject( ScTabViewShell& rViewSh, const ScDrawView& rDrawView, const SdrObject* pSelObj )
{
bool bFound = false;
SCTAB nObjectTab = 0;
SdrModel* pModel = rDrawView.GetModel();
sal_uInt16 nPageCount = pModel->GetPageCount();
for (sal_uInt16 i=0; i<nPageCount && !bFound; i++)
{
SdrPage* pPage = pModel->GetPage(i);
if (pPage)
{
SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
SdrObject* pObject = aIter.Next();
while (pObject && !bFound)
{
if ( pObject == pSelObj )
{
bFound = true;
nObjectTab = static_cast<SCTAB>(i);
}
pObject = aIter.Next();
}
}
}
if (bFound)
{
rViewSh.SetTabNo( nObjectTab );
rViewSh.ScrollToObject( pSelObj );
}
}
sal_Bool SAL_CALL ScTabViewObj::select( const uno::Any& aSelection )
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if ( !pViewSh )
return false;
//! Type of aSelection can be some specific interface instead of XInterface
bool bRet = false;
uno::Reference<uno::XInterface> xInterface(aSelection, uno::UNO_QUERY);
if ( !xInterface.is() ) //clear all selections
{
ScDrawView* pDrawView = pViewSh->GetScDrawView();
if (pDrawView)
{
pDrawView->ScEndTextEdit();
pDrawView->UnmarkAll();
}
else //#102232#; if there is no DrawView remove range selection
pViewSh->Unmark();
bRet = true;
}
if (bDrawSelModeSet) // remove DrawSelMode if set by API; if necessary it will be set again later
{
pViewSh->SetDrawSelMode(false);
pViewSh->UpdateLayerLocks();
bDrawSelModeSet = false;
}
if (bRet)
return bRet;
ScCellRangesBase* pRangesImp = comphelper::getFromUnoTunnel<ScCellRangesBase>( xInterface );
uno::Reference<drawing::XShapes> xShapeColl( xInterface, uno::UNO_QUERY );
uno::Reference<drawing::XShape> xShapeSel( xInterface, uno::UNO_QUERY );
SvxShape* pShapeImp = comphelper::getFromUnoTunnel<SvxShape>( xShapeSel );
if (pRangesImp) // Cell ranges
{
ScViewData& rViewData = pViewSh->GetViewData();
if ( rViewData.GetDocShell() == pRangesImp->GetDocShell() )
{
// perhaps remove drawing selection first
// (MarkListHasChanged removes sheet selection)
ScDrawView* pDrawView = pViewSh->GetScDrawView();
if (pDrawView)
{
pDrawView->ScEndTextEdit();
pDrawView->UnmarkAll();
}
FuPoor* pFunc = pViewSh->GetDrawFuncPtr();
if ( pFunc && pFunc->GetSlotID() != SID_OBJECT_SELECT )
{
// execute the slot of drawing function again -> switch off
SfxDispatcher* pDisp = pViewSh->GetDispatcher();
if (pDisp)
pDisp->Execute( pFunc->GetSlotID(), SfxCallMode::SYNCHRON );
}
pViewSh->SetDrawShell(false);
pViewSh->SetDrawSelMode(false); // after Dispatcher-Execute
// select ranges
const ScRangeList& rRanges = pRangesImp->GetRangeList();
size_t nRangeCount = rRanges.size();
// for empty range list, remove selection (cursor remains where it was)
if ( nRangeCount == 0 )
pViewSh->Unmark();
else if ( nRangeCount == 1 )
pViewSh->MarkRange( rRanges[ 0 ] );
else
{
// multiselection
const ScRange & rFirst = rRanges[ 0 ];
if ( !lcl_TabInRanges( rViewData.GetTabNo(), rRanges ) )
pViewSh->SetTabNo( rFirst.aStart.Tab() );
pViewSh->DoneBlockMode();
pViewSh->InitOwnBlockMode( rFirst ); /* TODO: or even the overall range? */
rViewData.GetMarkData().MarkFromRangeList( rRanges, true );
pViewSh->MarkDataChanged();
rViewData.GetDocShell()->PostPaintGridAll(); // Marks (old&new)
pViewSh->AlignToCursor( rFirst.aStart.Col(), rFirst.aStart.Row(),
SC_FOLLOW_JUMP );
pViewSh->SetCursor( rFirst.aStart.Col(), rFirst.aStart.Row() );
//! method of the view to select RangeList
}
bRet = true;
}
}
else if ( pShapeImp || xShapeColl.is() ) // Drawing-Layer
{
ScDrawView* pDrawView = pViewSh->GetScDrawView();
if (pDrawView)
{
pDrawView->ScEndTextEdit();
pDrawView->UnmarkAll();
if (pShapeImp) // single shape
{
SdrObject *pObj = pShapeImp->GetSdrObject();
if (pObj)
{
lcl_ShowObject( *pViewSh, *pDrawView, pObj );
SdrPageView* pPV = pDrawView->GetSdrPageView();
if ( pPV && pObj->getSdrPageFromSdrObject() == pPV->GetPage() )
{
pDrawView->MarkObj( pObj, pPV );
bRet = true;
}
}
}
else // Shape-Collection (xShapeColl is not 0)
{
// We'll switch to the sheet where the first object is
// and select all objects on that sheet
//!?throw exception when objects are on different sheets?
tools::Long nCount = xShapeColl->getCount();
if (nCount)
{
SdrPageView* pPV = nullptr;
bool bAllMarked(true);
for ( tools::Long i = 0; i < nCount; i++ )
{
uno::Reference<drawing::XShape> xShapeInt(xShapeColl->getByIndex(i), uno::UNO_QUERY);
if (xShapeInt.is())
{
SdrObject* pObj = SdrObject::getSdrObjectFromXShape( xShapeInt );
if (pObj)
{
if (!bDrawSelModeSet && (pObj->GetLayer() == SC_LAYER_BACK))
{
pViewSh->SetDrawSelMode(true);
pViewSh->UpdateLayerLocks();
bDrawSelModeSet = true;
}
if (!pPV) // first object
{
lcl_ShowObject( *pViewSh, *pDrawView, pObj );
pPV = pDrawView->GetSdrPageView();
}
if ( pPV && pObj->getSdrPageFromSdrObject() == pPV->GetPage() )
{
if (pDrawView->IsObjMarkable( pObj, pPV ))
pDrawView->MarkObj( pObj, pPV );
else
bAllMarked = false;
}
}
}
}
if (bAllMarked)
bRet = true;
}
else
bRet = true; // empty XShapes (all shapes are deselected)
}
if (bRet)
pViewSh->SetDrawShell(true);
}
}
if (!bRet)
throw lang::IllegalArgumentException();
return bRet;
}
uno::Reference<drawing::XShapes> ScTabViewShell::getSelectedXShapes()
{
uno::Reference<drawing::XShapes> xShapes;
SdrView* pSdrView = GetScDrawView();
if (pSdrView)
{
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
const size_t nMarkCount = rMarkList.GetMarkCount();
if (nMarkCount)
{
// generate ShapeCollection (like in SdXImpressView::getSelection in Draw)
// XInterfaceRef will be returned and it has to be UsrObject-XInterface
xShapes = drawing::ShapeCollection::create(comphelper::getProcessComponentContext());
for (size_t i = 0; i < nMarkCount; ++i)
{
SdrObject* pDrawObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
if (pDrawObj)
{
uno::Reference<drawing::XShape> xShape( pDrawObj->getUnoShape(), uno::UNO_QUERY );
if (xShape.is())
xShapes->add(xShape);
}
}
}
}
return xShapes;
}
uno::Any SAL_CALL ScTabViewObj::getSelection()
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
rtl::Reference<ScCellRangesBase> pObj;
if (pViewSh)
{
// is something selected in drawing layer?
uno::Reference<uno::XInterface> xRet(pViewSh->getSelectedXShapes());
if (xRet.is())
return uno::makeAny(xRet);
// otherwise sheet (cell) selection
ScViewData& rViewData = pViewSh->GetViewData();
ScDocShell* pDocSh = rViewData.GetDocShell();
const ScMarkData& rMark = rViewData.GetMarkData();
SCTAB nTabs = rMark.GetSelectCount();
ScRange aRange;
ScMarkType eMarkType = rViewData.GetSimpleArea(aRange);
if ( nTabs == 1 && (eMarkType == SC_MARK_SIMPLE) )
{
if (aRange.aStart == aRange.aEnd)
pObj = new ScCellObj( pDocSh, aRange.aStart );
else
pObj = new ScCellRangeObj( pDocSh, aRange );
}
else if ( nTabs == 1 && (eMarkType == SC_MARK_SIMPLE_FILTERED) )
{
ScMarkData aFilteredMark( rMark );
ScViewUtil::UnmarkFiltered( aFilteredMark, pDocSh->GetDocument());
ScRangeList aRangeList;
aFilteredMark.FillRangeListWithMarks( &aRangeList, false);
// Theoretically a selection may start and end on a filtered row.
switch ( aRangeList.size() )
{
case 0:
// No unfiltered row, we have to return some object, so
// here is one with no ranges.
pObj = new ScCellRangesObj( pDocSh, aRangeList );
break;
case 1:
{
const ScRange& rRange = aRangeList[ 0 ];
if (rRange.aStart == rRange.aEnd)
pObj = new ScCellObj( pDocSh, rRange.aStart );
else
pObj = new ScCellRangeObj( pDocSh, rRange );
}
break;
default:
pObj = new ScCellRangesObj( pDocSh, aRangeList );
}
}
else // multiselection
{
ScRangeListRef xRanges;
rViewData.GetMultiArea( xRanges );
// if there are more sheets, copy ranges
//! should this happen in ScMarkData::FillRangeListWithMarks already?
if ( nTabs > 1 )
rMark.ExtendRangeListTables( xRanges.get() );
pObj = new ScCellRangesObj( pDocSh, *xRanges );
}
if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
{
// remember if the selection was from the cursor position without anything selected
// (used when rendering the selection)
pObj->SetCursorOnly( true );
}
}
return uno::makeAny(uno::Reference<uno::XInterface>(static_cast<cppu::OWeakObject*>(pObj.get())));
}
// XEnumerationAccess
uno::Reference<container::XEnumeration> SAL_CALL ScTabViewObj::createEnumeration()
{
SolarMutexGuard aGuard;
return new ScIndexEnumeration(this, "com.sun.star.sheet.SpreadsheetViewPanesEnumeration");
}
// XIndexAccess
sal_Int32 SAL_CALL ScTabViewObj::getCount()
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
sal_uInt16 nPanes = 0;
if (pViewSh)
{
nPanes = 1;
ScViewData& rViewData = pViewSh->GetViewData();
if ( rViewData.GetHSplitMode() != SC_SPLIT_NONE )
nPanes *= 2;
if ( rViewData.GetVSplitMode() != SC_SPLIT_NONE )
nPanes *= 2;
}
return nPanes;
}
uno::Any SAL_CALL ScTabViewObj::getByIndex( sal_Int32 nIndex )
{
SolarMutexGuard aGuard;
uno::Reference<sheet::XViewPane> xPane(GetObjectByIndex_Impl(static_cast<sal_uInt16>(nIndex)));
if (!xPane.is())
throw lang::IndexOutOfBoundsException();
return uno::makeAny(xPane);
}
uno::Type SAL_CALL ScTabViewObj::getElementType()
{
SolarMutexGuard aGuard;
return cppu::UnoType<sheet::XViewPane>::get();
}
sal_Bool SAL_CALL ScTabViewObj::hasElements()
{
SolarMutexGuard aGuard;
return ( getCount() != 0 );
}
// XSpreadsheetView
rtl::Reference<ScViewPaneObj> ScTabViewObj::GetObjectByIndex_Impl(sal_uInt16 nIndex) const
{
static const ScSplitPos ePosHV[4] =
{ SC_SPLIT_TOPLEFT, SC_SPLIT_BOTTOMLEFT, SC_SPLIT_TOPRIGHT, SC_SPLIT_BOTTOMRIGHT };
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScSplitPos eWhich = SC_SPLIT_BOTTOMLEFT; // default position
bool bError = false;
ScViewData& rViewData = pViewSh->GetViewData();
bool bHor = ( rViewData.GetHSplitMode() != SC_SPLIT_NONE );
bool bVer = ( rViewData.GetVSplitMode() != SC_SPLIT_NONE );
if ( bHor && bVer )
{
// bottom left, bottom right, top left, top right - like in Excel
if ( nIndex < 4 )
eWhich = ePosHV[nIndex];
else
bError = true;
}
else if ( bHor )
{
if ( nIndex > 1 )
bError = true;
else if ( nIndex == 1 )
eWhich = SC_SPLIT_BOTTOMRIGHT;
// otherwise SC_SPLIT_BOTTOMLEFT
}
else if ( bVer )
{
if ( nIndex > 1 )
bError = true;
else if ( nIndex == 0 )
eWhich = SC_SPLIT_TOPLEFT;
// otherwise SC_SPLIT_BOTTOMLEFT
}
else if ( nIndex > 0 )
bError = true; // not split: only 0 is valid
if (!bError)
return new ScViewPaneObj( pViewSh, sal::static_int_cast<sal_uInt16>(eWhich) );
}
return nullptr;
}
uno::Reference<sheet::XSpreadsheet> SAL_CALL ScTabViewObj::getActiveSheet()
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScViewData& rViewData = pViewSh->GetViewData();
SCTAB nTab = rViewData.GetTabNo();
return new ScTableSheetObj( rViewData.GetDocShell(), nTab );
}
return nullptr;
}
// support expand (but not replace) the active sheet
void SAL_CALL ScTabViewObj::setActiveSheet( const uno::Reference<sheet::XSpreadsheet>& xActiveSheet )
{
SolarMutexGuard aGuard;
comphelper::ProfileZone aZone("setActiveSheet");
ScTabViewShell* pViewSh = GetViewShell();
if ( !(pViewSh && xActiveSheet.is()) )
return;
// XSpreadsheet and ScCellRangesBase -> has to be the same sheet
ScCellRangesBase* pRangesImp = comphelper::getFromUnoTunnel<ScCellRangesBase>( xActiveSheet );
if ( pRangesImp && pViewSh->GetViewData().GetDocShell() == pRangesImp->GetDocShell() )
{
const ScRangeList& rRanges = pRangesImp->GetRangeList();
if ( rRanges.size() == 1 )
{
SCTAB nNewTab = rRanges[ 0 ].aStart.Tab();
if ( pViewSh->GetViewData().GetDocument().HasTable(nNewTab) )
pViewSh->SetTabNo( nNewTab );
}
}
}
uno::Reference< uno::XInterface > ScTabViewObj::GetClickedObject(const Point& rPoint) const
{
uno::Reference< uno::XInterface > xTarget;
if (GetViewShell())
{
SCCOL nX;
SCROW nY;
ScViewData& rData = GetViewShell()->GetViewData();
ScSplitPos eSplitMode = rData.GetActivePart();
SCTAB nTab(rData.GetTabNo());
rData.GetPosFromPixel( rPoint.X(), rPoint.Y(), eSplitMode, nX, nY);
ScAddress aCellPos (nX, nY, nTab);
rtl::Reference<ScCellObj> pCellObj = new ScCellObj(rData.GetDocShell(), aCellPos);
xTarget.set(uno::Reference<table::XCell>(pCellObj), uno::UNO_QUERY);
ScDocument& rDoc = rData.GetDocument();
if (ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer())
{
SdrPage* pDrawPage = nullptr;
if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
SdrView* pDrawView = GetViewShell()->GetScDrawView();
if (pDrawPage && pDrawView && pDrawView->GetSdrPageView())
{
vcl::Window* pActiveWin = rData.GetActiveWin();
Point aPos = pActiveWin->PixelToLogic(rPoint);
sal_uInt16 nHitLog = static_cast<sal_uInt16>(pActiveWin->PixelToLogic(
Size(pDrawView->GetHitTolerancePixel(),0)).Width());
const size_t nCount(pDrawPage->GetObjCount());
bool bFound(false);
for (size_t i = 0; i < nCount && !bFound; ++i)
{
SdrObject* pObj = pDrawPage->GetObj(i);
if (pObj && SdrObjectPrimitiveHit(*pObj, aPos, nHitLog, *pDrawView->GetSdrPageView(), nullptr, false))
{
xTarget.set(pObj->getUnoShape(), uno::UNO_QUERY);
bFound = true;
}
}
}
}
}
return xTarget;
}
bool ScTabViewObj::IsMouseListening() const
{
if ( !aMouseClickHandlers.empty() )
return true;
// also include sheet events, because MousePressed must be called for them
ScViewData& rViewData = GetViewShell()->GetViewData();
ScDocument& rDoc = rViewData.GetDocument();
SCTAB nTab = rViewData.GetTabNo();
return
rDoc.HasSheetEventScript( nTab, ScSheetEventId::RIGHTCLICK, true ) ||
rDoc.HasSheetEventScript( nTab, ScSheetEventId::DOUBLECLICK, true ) ||
rDoc.HasSheetEventScript( nTab, ScSheetEventId::SELECT, true );
}
bool ScTabViewObj::MousePressed( const awt::MouseEvent& e )
{
bool bReturn(false);
if ( e.Buttons == css::awt::MouseButton::LEFT )
mbLeftMousePressed = true;
uno::Reference< uno::XInterface > xTarget = GetClickedObject(Point(e.X, e.Y));
if (!aMouseClickHandlers.empty() && xTarget.is())
{
awt::EnhancedMouseEvent aMouseEvent;
aMouseEvent.Buttons = e.Buttons;
aMouseEvent.X = e.X;
aMouseEvent.Y = e.Y;
aMouseEvent.ClickCount = e.ClickCount;
aMouseEvent.PopupTrigger = e.PopupTrigger;
aMouseEvent.Target = xTarget;
aMouseEvent.Modifiers = e.Modifiers;
// Listener's handler may remove it from the listeners list
for (size_t i = aMouseClickHandlers.size(); i > 0; --i)
{
try
{
if (!aMouseClickHandlers[i - 1]->mousePressed(aMouseEvent))
bReturn = true;
}
catch ( uno::Exception& )
{
aMouseClickHandlers.erase(aMouseClickHandlers.begin() + (i - 1));
}
}
}
// handle sheet events
bool bDoubleClick = ( e.Buttons == awt::MouseButton::LEFT && e.ClickCount == 2 );
bool bRightClick = ( e.Buttons == awt::MouseButton::RIGHT && e.ClickCount == 1 );
if ( ( bDoubleClick || bRightClick ) && !bReturn && xTarget.is())
{
ScSheetEventId nEvent = bDoubleClick ? ScSheetEventId::DOUBLECLICK : ScSheetEventId::RIGHTCLICK;
ScTabViewShell* pViewSh = GetViewShell();
ScViewData& rViewData = pViewSh->GetViewData();
ScDocShell* pDocSh = rViewData.GetDocShell();
ScDocument& rDoc = pDocSh->GetDocument();
SCTAB nTab = rViewData.GetTabNo();
const ScSheetEvents* pEvents = rDoc.GetSheetEvents(nTab);
if (pEvents)
{
const OUString* pScript = pEvents->GetScript(nEvent);
if (pScript)
{
// the macro parameter is the clicked object, as in the mousePressed call above
uno::Sequence<uno::Any> aParams{ uno::Any(xTarget) };
uno::Any aRet;
uno::Sequence<sal_Int16> aOutArgsIndex;
uno::Sequence<uno::Any> aOutArgs;
/*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
// look for a boolean return value of true
bool bRetValue = false;
if ((aRet >>= bRetValue) && bRetValue)
bReturn = true;
}
}
// execute VBA event handler
if (!bReturn && xTarget.is()) try
{
uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( rDoc.GetVbaEventProcessor(), uno::UNO_SET_THROW );
// the parameter is the clicked object, as in the mousePressed call above
uno::Sequence< uno::Any > aArgs{ uno::Any(xTarget) };
xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs );
}
catch( util::VetoException& )
{
bReturn = true;
}
catch( uno::Exception& )
{
}
}
return bReturn;
}
bool ScTabViewObj::MouseReleased( const awt::MouseEvent& e )
{
if ( e.Buttons == css::awt::MouseButton::LEFT )
{
try
{
ScTabViewShell* pViewSh = GetViewShell();
ScViewData& rViewData = pViewSh->GetViewData();
ScDocShell* pDocSh = rViewData.GetDocShell();
ScDocument& rDoc = pDocSh->GetDocument();
uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( rDoc.GetVbaEventProcessor(), uno::UNO_SET_THROW );
uno::Sequence< uno::Any > aArgs{ getSelection() };
xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( ScSheetEventId::SELECT ), aArgs );
}
catch( uno::Exception& )
{
}
mbLeftMousePressed = false;
}
bool bReturn(false);
if (!aMouseClickHandlers.empty())
{
uno::Reference< uno::XInterface > xTarget = GetClickedObject(Point(e.X, e.Y));
if (xTarget.is())
{
awt::EnhancedMouseEvent aMouseEvent;
aMouseEvent.Buttons = e.Buttons;
aMouseEvent.X = e.X;
aMouseEvent.Y = e.Y;
aMouseEvent.ClickCount = e.ClickCount;
aMouseEvent.PopupTrigger = e.PopupTrigger;
aMouseEvent.Target = xTarget;
aMouseEvent.Modifiers = e.Modifiers;
// Listener's handler may remove it from the listeners list
for (size_t i = aMouseClickHandlers.size(); i > 0; --i)
{
try
{
if (!aMouseClickHandlers[i - 1]->mouseReleased( aMouseEvent ))
bReturn = true;
}
catch ( uno::Exception& )
{
aMouseClickHandlers.erase(aMouseClickHandlers.begin() + (i - 1));
}
}
}
}
return bReturn;
}
// XEnhancedMouseClickBroadcaster
void ScTabViewObj::EndMouseListening()
{
lang::EventObject aEvent;
aEvent.Source = static_cast<cppu::OWeakObject*>(this);
for (const auto& rListener : aMouseClickHandlers)
{
try
{
rListener->disposing(aEvent);
}
catch ( uno::Exception& )
{
}
}
aMouseClickHandlers.clear();
}
void ScTabViewObj::EndActivationListening()
{
lang::EventObject aEvent;
aEvent.Source = static_cast<cppu::OWeakObject*>(this);
for (const auto& rListener : aActivationListeners)
{
try
{
rListener->disposing(aEvent);
}
catch ( uno::Exception& )
{
}
}
aActivationListeners.clear();
}
void SAL_CALL ScTabViewObj::addEnhancedMouseClickHandler( const uno::Reference< awt::XEnhancedMouseClickHandler >& aListener )
{
SolarMutexGuard aGuard;
if (aListener.is())
{
aMouseClickHandlers.push_back( aListener );
}
}
void SAL_CALL ScTabViewObj::removeEnhancedMouseClickHandler( const uno::Reference< awt::XEnhancedMouseClickHandler >& aListener )
{
SolarMutexGuard aGuard;
sal_uInt16 nCount = aMouseClickHandlers.size();
aMouseClickHandlers.erase(
std::remove(aMouseClickHandlers.begin(), aMouseClickHandlers.end(), aListener),
aMouseClickHandlers.end());
if (aMouseClickHandlers.empty() && (nCount > 0)) // only if last listener removed
EndMouseListening();
}
// XActivationBroadcaster
void SAL_CALL ScTabViewObj::addActivationEventListener( const uno::Reference< sheet::XActivationEventListener >& aListener )
{
SolarMutexGuard aGuard;
if (aListener.is())
{
aActivationListeners.push_back( aListener );
}
}
void SAL_CALL ScTabViewObj::removeActivationEventListener( const uno::Reference< sheet::XActivationEventListener >& aListener )
{
SolarMutexGuard aGuard;
sal_uInt16 nCount = aActivationListeners.size();
aActivationListeners.erase(
std::remove(aActivationListeners.begin(), aActivationListeners.end(), aListener),
aActivationListeners.end());
if (aActivationListeners.empty() && (nCount > 0)) // only if last listener removed
EndActivationListening();
}
sal_Int16 ScTabViewObj::GetZoom() const
{
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
const Fraction& rZoomY = pViewSh->GetViewData().GetZoomY(); // Y will be shown
return static_cast<sal_Int16>(tools::Long( rZoomY * 100 ));
}
return 0;
}
void ScTabViewObj::SetZoom(sal_Int16 nZoom)
{
ScTabViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
if ( nZoom != GetZoom() && nZoom != 0 )
{
if (!pViewSh->GetViewData().IsPagebreakMode())
{
ScModule* pScMod = SC_MOD();
ScAppOptions aNewOpt(pScMod->GetAppOptions());
aNewOpt.SetZoom( nZoom );
aNewOpt.SetZoomType( pViewSh->GetViewData().GetView()->GetZoomType() );
pScMod->SetAppOptions( aNewOpt );
}
}
Fraction aFract( nZoom, 100 );
pViewSh->SetZoom( aFract, aFract, true );
pViewSh->PaintGrid();
pViewSh->PaintTop();
pViewSh->PaintLeft();
pViewSh->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM );
pViewSh->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
pViewSh->GetViewFrame()->GetBindings().Invalidate(SID_ZOOM_IN);
pViewSh->GetViewFrame()->GetBindings().Invalidate(SID_ZOOM_OUT);
}
sal_Int16 ScTabViewObj::GetZoomType() const
{
sal_Int16 aZoomType = view::DocumentZoomType::OPTIMAL;
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
SvxZoomType eZoomType = pViewSh->GetViewData().GetView()->GetZoomType();
switch (eZoomType)
{
case SvxZoomType::PERCENT:
aZoomType = view::DocumentZoomType::BY_VALUE;
break;
case SvxZoomType::OPTIMAL:
aZoomType = view::DocumentZoomType::OPTIMAL;
break;
case SvxZoomType::WHOLEPAGE:
aZoomType = view::DocumentZoomType::ENTIRE_PAGE;
break;
case SvxZoomType::PAGEWIDTH:
aZoomType = view::DocumentZoomType::PAGE_WIDTH;
break;
case SvxZoomType::PAGEWIDTH_NOBORDER:
aZoomType = view::DocumentZoomType::PAGE_WIDTH_EXACT;
break;
}
}
return aZoomType;
}
void ScTabViewObj::SetZoomType(sal_Int16 aZoomType)
{
ScTabViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
ScDBFunc* pView = pViewSh->GetViewData().GetView();
if (!pView)
return;
SvxZoomType eZoomType;
switch (aZoomType)
{
case view::DocumentZoomType::BY_VALUE:
eZoomType = SvxZoomType::PERCENT;
break;
case view::DocumentZoomType::OPTIMAL:
eZoomType = SvxZoomType::OPTIMAL;
break;
case view::DocumentZoomType::ENTIRE_PAGE:
eZoomType = SvxZoomType::WHOLEPAGE;
break;
case view::DocumentZoomType::PAGE_WIDTH:
eZoomType = SvxZoomType::PAGEWIDTH;
break;
case view::DocumentZoomType::PAGE_WIDTH_EXACT:
eZoomType = SvxZoomType::PAGEWIDTH_NOBORDER;
break;
default:
eZoomType = SvxZoomType::OPTIMAL;
}
sal_Int16 nZoom(GetZoom());
sal_Int16 nOldZoom(nZoom);
if ( eZoomType == SvxZoomType::PERCENT )
{
if ( nZoom < MINZOOM ) nZoom = MINZOOM;
if ( nZoom > MAXZOOM ) nZoom = MAXZOOM;
}
else
nZoom = pView->CalcZoom( eZoomType, nOldZoom );
switch ( eZoomType )
{
case SvxZoomType::WHOLEPAGE:
case SvxZoomType::PAGEWIDTH:
pView->SetZoomType( eZoomType, true );
break;
default:
pView->SetZoomType( SvxZoomType::PERCENT, true );
}
SetZoom( nZoom );
}
sal_Bool SAL_CALL ScTabViewObj::getIsWindowSplit()
{
SolarMutexGuard aGuard;
// what menu slot SID_WINDOW_SPLIT does
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScViewData& rViewData = pViewSh->GetViewData();
return ( rViewData.GetHSplitMode() == SC_SPLIT_NORMAL ||
rViewData.GetVSplitMode() == SC_SPLIT_NORMAL );
}
return false;
}
sal_Bool SAL_CALL ScTabViewObj::hasFrozenPanes()
{
SolarMutexGuard aGuard;
// what menu slot SID_WINDOW_FIX does
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScViewData& rViewData = pViewSh->GetViewData();
return ( rViewData.GetHSplitMode() == SC_SPLIT_FIX ||
rViewData.GetVSplitMode() == SC_SPLIT_FIX );
}
return false;
}
sal_Int32 SAL_CALL ScTabViewObj::getSplitHorizontal()
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScViewData& rViewData = pViewSh->GetViewData();
if ( rViewData.GetHSplitMode() != SC_SPLIT_NONE )
return rViewData.GetHSplitPos();
}
return 0;
}
sal_Int32 SAL_CALL ScTabViewObj::getSplitVertical()
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScViewData& rViewData = pViewSh->GetViewData();
if ( rViewData.GetVSplitMode() != SC_SPLIT_NONE )
return rViewData.GetVSplitPos();
}
return 0;
}
sal_Int32 SAL_CALL ScTabViewObj::getSplitColumn()
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScViewData& rViewData = pViewSh->GetViewData();
if ( rViewData.GetHSplitMode() != SC_SPLIT_NONE )
{
tools::Long nSplit = rViewData.GetHSplitPos();
ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT;
if ( rViewData.GetVSplitMode() != SC_SPLIT_NONE )
ePos = SC_SPLIT_TOPLEFT;
SCCOL nCol;
SCROW nRow;
rViewData.GetPosFromPixel( nSplit, 0, ePos, nCol, nRow, false );
if ( nCol > 0 )
return nCol;
}
}
return 0;
}
sal_Int32 SAL_CALL ScTabViewObj::getSplitRow()
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScViewData& rViewData = pViewSh->GetViewData();
if ( rViewData.GetVSplitMode() != SC_SPLIT_NONE )
{
tools::Long nSplit = rViewData.GetVSplitPos();
// split vertically
SCCOL nCol;
SCROW nRow;
rViewData.GetPosFromPixel( 0, nSplit, SC_SPLIT_TOPLEFT, nCol, nRow, false );
if ( nRow > 0 )
return nRow;
}
}
return 0;
}
void SAL_CALL ScTabViewObj::splitAtPosition( sal_Int32 nPixelX, sal_Int32 nPixelY )
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
pViewSh->SplitAtPixel( Point( nPixelX, nPixelY ) );
pViewSh->FreezeSplitters( false );
pViewSh->InvalidateSplit();
}
}
void SAL_CALL ScTabViewObj::freezeAtPosition( sal_Int32 nColumns, sal_Int32 nRows )
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
// first, remove them all -> no stress with scrolling in the meantime
pViewSh->RemoveSplit();
Point aWinStart;
vcl::Window* pWin = pViewSh->GetWindowByPos( SC_SPLIT_BOTTOMLEFT );
if (pWin)
aWinStart = pWin->GetPosPixel();
ScViewData& rViewData = pViewSh->GetViewData();
Point aSplit(rViewData.GetScrPos( static_cast<SCCOL>(nColumns), static_cast<SCROW>(nRows), SC_SPLIT_BOTTOMLEFT, true ));
aSplit += aWinStart;
pViewSh->SplitAtPixel( aSplit );
pViewSh->FreezeSplitters( true );
pViewSh->InvalidateSplit();
}
void SAL_CALL ScTabViewObj::addSelectionChangeListener(
const uno::Reference<view::XSelectionChangeListener>& xListener )
{
SolarMutexGuard aGuard;
aSelectionChgListeners.push_back( xListener );
}
void SAL_CALL ScTabViewObj::removeSelectionChangeListener(
const uno::Reference< view::XSelectionChangeListener >& xListener )
{
SolarMutexGuard aGuard;
auto it = std::find(aSelectionChgListeners.begin(), aSelectionChgListeners.end(), xListener); //! why the hassle with queryInterface?
if (it != aSelectionChgListeners.end())
aSelectionChgListeners.erase(it);
}
void ScTabViewObj::SelectionChanged()
{
// Selection changed so end any style preview
// Note: executing this slot through the dispatcher
// will cause the style dialog to be raised so we go
// direct here
ScFormatShell aShell( GetViewShell()->GetViewData() );
SfxAllItemSet reqList( SfxGetpApp()->GetPool() );
SfxRequest aReq( SID_STYLE_END_PREVIEW, SfxCallMode::SLOT, reqList );
aShell.ExecuteStyle( aReq );
lang::EventObject aEvent;
aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
for (const auto& rListener : aSelectionChgListeners)
rListener->selectionChanged( aEvent );
// handle sheet events
ScTabViewShell* pViewSh = GetViewShell();
ScViewData& rViewData = pViewSh->GetViewData();
ScDocShell* pDocSh = rViewData.GetDocShell();
ScDocument& rDoc = pDocSh->GetDocument();
SCTAB nTab = rViewData.GetTabNo();
const ScSheetEvents* pEvents = rDoc.GetSheetEvents(nTab);
if (pEvents)
{
const OUString* pScript = pEvents->GetScript(ScSheetEventId::SELECT);
if (pScript)
{
// the macro parameter is the selection as returned by getSelection
uno::Sequence<uno::Any> aParams{ getSelection() };
uno::Any aRet;
uno::Sequence<sal_Int16> aOutArgsIndex;
uno::Sequence<uno::Any> aOutArgs;
/*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs );
}
}
SfxApplication::Get()->Broadcast( SfxHint( SfxHintId::ScSelectionChanged ) );
if ( mbLeftMousePressed ) // selection still in progress
return;
try
{
uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( rDoc.GetVbaEventProcessor(), uno::UNO_SET_THROW );
uno::Sequence< uno::Any > aArgs{ getSelection() };
xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( ScSheetEventId::SELECT ), aArgs );
}
catch( uno::Exception& )
{
}
}
// XPropertySet (view options)
//! provide those also in application?
uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTabViewObj::getPropertySetInfo()
{
SolarMutexGuard aGuard;
static uno::Reference<beans::XPropertySetInfo> aRef(
new SfxItemPropertySetInfo( aPropSet.getPropertyMap() ));
return aRef;
}
void SAL_CALL ScTabViewObj::setPropertyValue(
const OUString& aPropertyName, const uno::Any& aValue )
{
SolarMutexGuard aGuard;
if ( aPropertyName == SC_UNO_FILTERED_RANGE_SELECTION )
{
bFilteredRangeSelection = ScUnoHelpFunctions::GetBoolFromAny(aValue);
return;
}
ScTabViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
ScViewData& rViewData = pViewSh->GetViewData();
const ScViewOptions& rOldOpt = pViewSh->GetViewData().GetOptions();
ScViewOptions aNewOpt(rOldOpt);
if ( aPropertyName == SC_UNO_COLROWHDR || aPropertyName == OLD_UNO_COLROWHDR )
aNewOpt.SetOption( VOPT_HEADER, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_HORSCROLL || aPropertyName == OLD_UNO_HORSCROLL )
aNewOpt.SetOption( VOPT_HSCROLL, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_OUTLSYMB || aPropertyName == OLD_UNO_OUTLSYMB )
aNewOpt.SetOption( VOPT_OUTLINER, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHEETTABS || aPropertyName == OLD_UNO_SHEETTABS )
aNewOpt.SetOption( VOPT_TABCONTROLS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWANCHOR )
aNewOpt.SetOption( VOPT_ANCHOR, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWFORM )
aNewOpt.SetOption( VOPT_FORMULAS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWGRID )
aNewOpt.SetOption( VOPT_GRID, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWHELP )
aNewOpt.SetOption( VOPT_HELPLINES, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWNOTES )
aNewOpt.SetOption( VOPT_NOTES, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWPAGEBR )
aNewOpt.SetOption( VOPT_PAGEBREAKS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWZERO )
aNewOpt.SetOption( VOPT_NULLVALS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_VALUEHIGH || aPropertyName == OLD_UNO_VALUEHIGH )
aNewOpt.SetOption( VOPT_SYNTAX, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_VERTSCROLL || aPropertyName == OLD_UNO_VERTSCROLL )
aNewOpt.SetOption( VOPT_VSCROLL, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWOBJ )
{
sal_Int16 nIntVal = 0;
if ( aValue >>= nIntVal )
{
//#i80528# adapt to new range eventually
if(sal_Int16(VOBJ_MODE_HIDE) < nIntVal) nIntVal = sal_Int16(VOBJ_MODE_SHOW);
aNewOpt.SetObjMode( VOBJ_TYPE_OLE, static_cast<ScVObjMode>(nIntVal));
}
}
else if ( aPropertyName == SC_UNO_SHOWCHARTS )
{
sal_Int16 nIntVal = 0;
if ( aValue >>= nIntVal )
{
//#i80528# adapt to new range eventually
if(sal_Int16(VOBJ_MODE_HIDE) < nIntVal) nIntVal = sal_Int16(VOBJ_MODE_SHOW);
aNewOpt.SetObjMode( VOBJ_TYPE_CHART, static_cast<ScVObjMode>(nIntVal));
}
}
else if ( aPropertyName == SC_UNO_SHOWDRAW )
{
sal_Int16 nIntVal = 0;
if ( aValue >>= nIntVal )
{
//#i80528# adapt to new range eventually
if(sal_Int16(VOBJ_MODE_HIDE) < nIntVal) nIntVal = sal_Int16(VOBJ_MODE_SHOW);
aNewOpt.SetObjMode( VOBJ_TYPE_DRAW, static_cast<ScVObjMode>(nIntVal));
}
}
else if ( aPropertyName == SC_UNO_GRIDCOLOR )
{
Color nIntVal;
if ( aValue >>= nIntVal )
aNewOpt.SetGridColor( nIntVal, OUString() );
}
else if ( aPropertyName == SC_UNO_ZOOMTYPE )
{
sal_Int16 nIntVal = 0;
if ( aValue >>= nIntVal )
SetZoomType(nIntVal);
}
else if ( aPropertyName == SC_UNO_ZOOMVALUE )
{
sal_Int16 nIntVal = 0;
if ( aValue >>= nIntVal )
SetZoom(nIntVal);
}
else if ( aPropertyName == SC_UNO_FORMULABARHEIGHT )
{
sal_Int16 nIntVal = ScUnoHelpFunctions::GetInt16FromAny(aValue);
if (nIntVal > 0)
{
rViewData.SetFormulaBarLines(nIntVal);
// Notify formula bar about changed lines
ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
if (pInputHdl)
{
ScInputWindow* pInputWin = pInputHdl->GetInputWindow();
if (pInputWin)
pInputWin->NumLinesChanged();
}
}
}
// Options are set on the view and document (for new views),
// so that they remain during saving.
//! In the app (module) we need an extra options to tune that
//! (for new documents)
if ( aNewOpt == rOldOpt )
return;
rViewData.SetOptions( aNewOpt );
rViewData.GetDocument().SetViewOptions( aNewOpt );
rViewData.GetDocShell()->SetDocumentModified(); //! really?
pViewSh->UpdateFixPos();
pViewSh->PaintGrid();
pViewSh->PaintTop();
pViewSh->PaintLeft();
pViewSh->PaintExtras();
pViewSh->InvalidateBorder();
SfxBindings& rBindings = pViewSh->GetViewFrame()->GetBindings();
rBindings.Invalidate( FID_TOGGLEHEADERS ); // -> check in menu
rBindings.Invalidate( FID_TOGGLESYNTAX );
}
uno::Any SAL_CALL ScTabViewObj::getPropertyValue( const OUString& aPropertyName )
{
SolarMutexGuard aGuard;
uno::Any aRet;
if ( aPropertyName == SC_UNO_FILTERED_RANGE_SELECTION )
{
aRet <<= bFilteredRangeSelection;
return aRet;
}
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
{
ScViewData& rViewData = pViewSh->GetViewData();
const ScViewOptions& rOpt = rViewData.GetOptions();
if ( aPropertyName == SC_UNO_COLROWHDR || aPropertyName == OLD_UNO_COLROWHDR )
aRet <<= rOpt.GetOption( VOPT_HEADER );
else if ( aPropertyName == SC_UNO_HORSCROLL || aPropertyName == OLD_UNO_HORSCROLL )
aRet <<= rOpt.GetOption( VOPT_HSCROLL );
else if ( aPropertyName == SC_UNO_OUTLSYMB || aPropertyName == OLD_UNO_OUTLSYMB )
aRet <<= rOpt.GetOption( VOPT_OUTLINER );
else if ( aPropertyName == SC_UNO_SHEETTABS || aPropertyName == OLD_UNO_SHEETTABS )
aRet <<= rOpt.GetOption( VOPT_TABCONTROLS );
else if ( aPropertyName == SC_UNO_SHOWANCHOR ) aRet <<= rOpt.GetOption( VOPT_ANCHOR );
else if ( aPropertyName == SC_UNO_SHOWFORM ) aRet <<= rOpt.GetOption( VOPT_FORMULAS );
else if ( aPropertyName == SC_UNO_SHOWGRID ) aRet <<= rOpt.GetOption( VOPT_GRID );
else if ( aPropertyName == SC_UNO_SHOWHELP ) aRet <<= rOpt.GetOption( VOPT_HELPLINES );
else if ( aPropertyName == SC_UNO_SHOWNOTES ) aRet <<= rOpt.GetOption( VOPT_NOTES );
else if ( aPropertyName == SC_UNO_SHOWPAGEBR ) aRet <<= rOpt.GetOption( VOPT_PAGEBREAKS );
else if ( aPropertyName == SC_UNO_SHOWZERO ) aRet <<= rOpt.GetOption( VOPT_NULLVALS );
else if ( aPropertyName == SC_UNO_VALUEHIGH || aPropertyName == OLD_UNO_VALUEHIGH )
aRet <<= rOpt.GetOption( VOPT_SYNTAX );
else if ( aPropertyName == SC_UNO_VERTSCROLL || aPropertyName == OLD_UNO_VERTSCROLL )
aRet <<= rOpt.GetOption( VOPT_VSCROLL );
else if ( aPropertyName == SC_UNO_SHOWOBJ ) aRet <<= static_cast<sal_Int16>( rOpt.GetObjMode( VOBJ_TYPE_OLE ) );
else if ( aPropertyName == SC_UNO_SHOWCHARTS ) aRet <<= static_cast<sal_Int16>( rOpt.GetObjMode( VOBJ_TYPE_CHART ) );
else if ( aPropertyName == SC_UNO_SHOWDRAW ) aRet <<= static_cast<sal_Int16>( rOpt.GetObjMode( VOBJ_TYPE_DRAW ) );
else if ( aPropertyName == SC_UNO_GRIDCOLOR ) aRet <<= rOpt.GetGridColor();
else if ( aPropertyName == SC_UNO_VISAREA ) aRet <<= GetVisArea();
else if ( aPropertyName == SC_UNO_ZOOMTYPE ) aRet <<= GetZoomType();
else if ( aPropertyName == SC_UNO_ZOOMVALUE ) aRet <<= GetZoom();
else if ( aPropertyName == SC_UNO_FORMULABARHEIGHT ) aRet <<= rViewData.GetFormulaBarLines();
else if ( aPropertyName == SC_UNO_VISAREASCREEN )
{
vcl::Window* pActiveWin = rViewData.GetActiveWin();
if ( pActiveWin )
{
tools::Rectangle aRect = pActiveWin->GetWindowExtentsRelative( nullptr );
aRet <<= AWTRectangle( aRect );
}
}
}
return aRet;
}
void SAL_CALL ScTabViewObj::addPropertyChangeListener( const OUString& /* aPropertyName */,
const uno::Reference<beans::XPropertyChangeListener >& xListener )
{
SolarMutexGuard aGuard;
aPropertyChgListeners.push_back( xListener );
}
void SAL_CALL ScTabViewObj::removePropertyChangeListener( const OUString& /* aPropertyName */,
const uno::Reference<beans::XPropertyChangeListener >& xListener )
{
SolarMutexGuard aGuard;
auto it = std::find(aPropertyChgListeners.begin(), aPropertyChgListeners.end(), xListener); //! Why the nonsense with queryInterface?
if (it != aPropertyChgListeners.end())
aPropertyChgListeners.erase(it);
}
void SAL_CALL ScTabViewObj::addVetoableChangeListener( const OUString& /* PropertyName */,
const uno::Reference<beans::XVetoableChangeListener >& /* aListener */ )
{
}
void SAL_CALL ScTabViewObj::removeVetoableChangeListener( const OUString& /* PropertyName */,
const uno::Reference<beans::XVetoableChangeListener >& /* aListener */ )
{
}
void ScTabViewObj::VisAreaChanged()
{
beans::PropertyChangeEvent aEvent;
aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
for (const auto& rListener : aPropertyChgListeners)
rListener->propertyChange( aEvent );
}
// XRangeSelection
void SAL_CALL ScTabViewObj::startRangeSelection(
const uno::Sequence<beans::PropertyValue>& aArguments )
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return;
OUString aInitVal, aTitle;
bool bCloseOnButtonUp = false;
bool bSingleCell = false;
bool bMultiSelection = false;
OUString aStrVal;
for (const beans::PropertyValue& rProp : aArguments)
{
OUString aPropName(rProp.Name);
if (aPropName == SC_UNONAME_CLOSEONUP )
bCloseOnButtonUp = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
else if (aPropName == SC_UNONAME_TITLE )
{
if ( rProp.Value >>= aStrVal )
aTitle = aStrVal;
}
else if (aPropName == SC_UNONAME_INITVAL )
{
if ( rProp.Value >>= aStrVal )
aInitVal = aStrVal;
}
else if (aPropName == SC_UNONAME_SINGLECELL )
bSingleCell = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
else if (aPropName == SC_UNONAME_MULTISEL )
bMultiSelection = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
}
pViewSh->StartSimpleRefDialog( aTitle, aInitVal, bCloseOnButtonUp, bSingleCell, bMultiSelection );
}
void SAL_CALL ScTabViewObj::abortRangeSelection()
{
SolarMutexGuard aGuard;
ScTabViewShell* pViewSh = GetViewShell();
if (pViewSh)
pViewSh->StopSimpleRefDialog();
}
void SAL_CALL ScTabViewObj::addRangeSelectionListener(
const uno::Reference<sheet::XRangeSelectionListener>& xListener )
{
SolarMutexGuard aGuard;
aRangeSelListeners.push_back( xListener );
}
void SAL_CALL ScTabViewObj::removeRangeSelectionListener(
const uno::Reference<sheet::XRangeSelectionListener>& xListener )
{
SolarMutexGuard aGuard;
auto it = std::find(aRangeSelListeners.begin(), aRangeSelListeners.end(), xListener);
if (it != aRangeSelListeners.end())
aRangeSelListeners.erase(it);
}
void SAL_CALL ScTabViewObj::addRangeSelectionChangeListener(
const uno::Reference<sheet::XRangeSelectionChangeListener>& xListener )
{
SolarMutexGuard aGuard;
aRangeChgListeners.push_back( xListener );
}
void SAL_CALL ScTabViewObj::removeRangeSelectionChangeListener(
const uno::Reference<sheet::XRangeSelectionChangeListener>& xListener )
{
SolarMutexGuard aGuard;
auto it = std::find(aRangeChgListeners.begin(), aRangeChgListeners.end(), xListener);
if (it != aRangeChgListeners.end())
aRangeChgListeners.erase(it);
}
void ScTabViewObj::RangeSelDone( const OUString& rText )
{
sheet::RangeSelectionEvent aEvent;
aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
aEvent.RangeDescriptor = rText;
// copy on the stack because listener could remove itself
auto const listeners(aRangeSelListeners);
for (const auto& rListener : listeners)
rListener->done( aEvent );
}
void ScTabViewObj::RangeSelAborted( const OUString& rText )
{
sheet::RangeSelectionEvent aEvent;
aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
aEvent.RangeDescriptor = rText;
// copy on the stack because listener could remove itself
auto const listeners(aRangeSelListeners);
for (const auto& rListener : listeners)
rListener->aborted( aEvent );
}
void ScTabViewObj::RangeSelChanged( const OUString& rText )
{
sheet::RangeSelectionEvent aEvent;
aEvent.Source.set(static_cast<cppu::OWeakObject*>(this));
aEvent.RangeDescriptor = rText;
// copy on the stack because listener could remove itself
auto const listener(aRangeChgListeners);
for (const auto& rListener : listener)
rListener->descriptorChanged( aEvent );
}
// XServiceInfo
OUString SAL_CALL ScTabViewObj::getImplementationName()
{
return "ScTabViewObj";
}
sal_Bool SAL_CALL ScTabViewObj::supportsService( const OUString& rServiceName )
{
return cppu::supportsService(this, rServiceName);
}
uno::Sequence<OUString> SAL_CALL ScTabViewObj::getSupportedServiceNames()
{
return {SCTABVIEWOBJ_SERVICE, SCVIEWSETTINGS_SERVICE};
}
// XUnoTunnel
UNO3_GETIMPLEMENTATION_IMPL(ScTabViewObj);
css::uno::Reference< css::datatransfer::XTransferable > SAL_CALL ScTabViewObj::getTransferable()
{
SolarMutexGuard aGuard;
ScEditShell* pShell = dynamic_cast<ScEditShell*>( GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) );
if (pShell)
return pShell->GetEditView()->GetTransferable();
ScDrawTextObjectBar* pTextShell = dynamic_cast<ScDrawTextObjectBar*>( GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) );
if (pTextShell)
{
ScViewData& rViewData = GetViewShell()->GetViewData();
ScDrawView* pView = rViewData.GetScDrawView();
OutlinerView* pOutView = pView->GetTextEditOutlinerView();
if (pOutView)
return pOutView->GetEditView().GetTransferable();
}
ScDrawShell* pDrawShell = dynamic_cast<ScDrawShell*>( GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) );
if (pDrawShell)
return pDrawShell->GetDrawView()->CopyToTransferable();
return GetViewShell()->CopyToTransferable();
}
void SAL_CALL ScTabViewObj::insertTransferable( const css::uno::Reference< css::datatransfer::XTransferable >& xTrans )
{
SolarMutexGuard aGuard;
ScEditShell* pShell = dynamic_cast<ScEditShell*>( GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) );
if (pShell)
pShell->GetEditView()->InsertText( xTrans, OUString(), false );
else
{
ScDrawTextObjectBar* pTextShell = dynamic_cast<ScDrawTextObjectBar*>( GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) );
if (pTextShell)
{
ScViewData& rViewData = GetViewShell()->GetViewData();
ScDrawView* pView = rViewData.GetScDrawView();
OutlinerView* pOutView = pView->GetTextEditOutlinerView();
if ( pOutView )
{
pOutView->GetEditView().InsertText( xTrans, OUString(), false );
return;
}
}
GetViewShell()->PasteFromTransferable( xTrans );
}
}
namespace {
uno::Sequence<sal_Int32> toSequence(const ScMarkData::MarkedTabsType& rSelected)
{
uno::Sequence<sal_Int32> aRet(rSelected.size());
auto aRetRange = asNonConstRange(aRet);
size_t i = 0;
for (const auto& rTab : rSelected)
{
aRetRange[i] = static_cast<sal_Int32>(rTab);
++i;
}
return aRet;
}
}
uno::Sequence<sal_Int32> ScTabViewObj::getSelectedSheets()
{
ScTabViewShell* pViewSh = GetViewShell();
if (!pViewSh)
return uno::Sequence<sal_Int32>();
ScViewData& rViewData = pViewSh->GetViewData();
// #i95280# when printing from the shell, the view is never activated,
// so Excel view settings must also be evaluated here.
ScExtDocOptions* pExtOpt = rViewData.GetDocument().GetExtDocOptions();
if (pExtOpt && pExtOpt->IsChanged())
{
pViewSh->GetViewData().ReadExtOptions(*pExtOpt); // Excel view settings
pViewSh->SetTabNo(pViewSh->GetViewData().GetTabNo(), true);
pExtOpt->SetChanged(false);
}
return toSequence(rViewData.GetMarkData().GetSelectedTabs());
}
ScPreviewObj::ScPreviewObj(ScPreviewShell* pViewSh) :
SfxBaseController(pViewSh),
mpViewShell(pViewSh)
{
if (mpViewShell)
StartListening(*mpViewShell);
}
ScPreviewObj::~ScPreviewObj()
{
if (mpViewShell)
EndListening(*mpViewShell);
}
uno::Any ScPreviewObj::queryInterface(const uno::Type& rType)
{
SC_QUERYINTERFACE(sheet::XSelectedSheetsSupplier)
return SfxBaseController::queryInterface(rType);
}
void ScPreviewObj::acquire() noexcept
{
SfxBaseController::acquire();
}
void ScPreviewObj::release() noexcept
{
SfxBaseController::release();
}
void ScPreviewObj::Notify(SfxBroadcaster&, const SfxHint& rHint)
{
if (rHint.GetId() == SfxHintId::Dying)
mpViewShell = nullptr;
}
uno::Sequence<sal_Int32> ScPreviewObj::getSelectedSheets()
{
ScPreview* p = mpViewShell ? mpViewShell->GetPreview() : nullptr;
if (!p)
return uno::Sequence<sal_Int32>();
return toSequence(p->GetSelectedTabs());
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */