/* -*- 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 <cppuhelper/queryinterface.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <vcl/svapp.hxx>
#include <tools/multisel.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 <attrib.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>
#include <scitems.hxx>
using namespace com::sun::star;
//! Clipping Marks
// no Which-ID here, Map only for PropertySetInfo
static std::span<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_SHOWNOTEAUTHOR, 0, cppu::UnoType<bool>::get(), 0, 0},
{ SC_UNO_SHOWFORMULASMARKS, 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},
};
return aViewOptPropertyMap_Impl;
}
constexpr OUString SCTABVIEWOBJ_SERVICE = u"com.sun.star.sheet.SpreadsheetView"_ustr;
constexpr OUString SCVIEWSETTINGS_SERVICE = u"com.sun.star.sheet.SpreadsheetViewSettings"_ustr;
SC_SIMPLE_SERVICE_INFO( ScViewPaneBase, u"ScViewPaneObj"_ustr, u"com.sun.star.sheet.SpreadsheetViewPane"_ustr )
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 )
{
uno::Any aReturn = ::cppu::queryInterface(rType,
static_cast<sheet::XViewPane*>(this),
static_cast<sheet::XCellRangeReferrer*>(this),
static_cast<view::XFormLayerAccess*>(this),
static_cast<view::XControlAccess*>(this),
static_cast<lang::XServiceInfo*>(this),
static_cast<lang::XTypeProvider*>(this));
if ( aReturn.hasValue() )
return aReturn;
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 = VCLUnoHelper::ConvertToAWTRect(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 )
{
uno::Any aReturn = ::cppu::queryInterface(rType,
static_cast<sheet::XSpreadsheetView*>(this),
static_cast<sheet::XEnhancedMouseClickBroadcaster*>(this),
static_cast<sheet::XActivationBroadcaster*>(this),
static_cast<container::XEnumerationAccess*>(this),
static_cast<container::XIndexAccess*>(this),
static_cast<container::XElementAccess*>(static_cast<container::XIndexAccess*>(this)),
static_cast<view::XSelectionSupplier*>(this),
static_cast<beans::XPropertySet*>(this),
static_cast<sheet::XViewSplitable*>(this),
static_cast<sheet::XViewFreezable*>(this),
static_cast<sheet::XRangeSelection*>(this),
static_cast<sheet::XSheetRange*>(this),
static_cast<sheet::XSelectedSheetsSupplier*>(this),
static_cast<datatransfer::XTransferableSupplier*>(this));
if ( aReturn.hasValue() )
return aReturn;
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);
aEvent.Source.set(xView, uno::UNO_QUERY);
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<sheet::XSheetRange>::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& rModel = rDrawView.GetModel();
sal_uInt16 nPageCount = rModel.GetPageCount();
for (sal_uInt16 i=0; i<nPageCount && !bFound; i++)
{
SdrPage* pPage = rModel.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 = dynamic_cast<ScCellRangesBase*>( xInterface.get() );
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::Any(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) )
{
// tdf#154803 - check if range is entirely merged
ScDocument& rDoc = pDocSh->GetDocument();
const ScMergeAttr* pMergeAttr = rDoc.GetAttr(aRange.aStart, ATTR_MERGE);
SCCOL nColSpan = 1;
SCROW nRowSpan = 1;
if (pMergeAttr && pMergeAttr->IsMerged())
{
nColSpan = pMergeAttr->GetColMerge();
nRowSpan = pMergeAttr->GetRowMerge();
}
// tdf#147122 - return cell object when a simple selection is entirely merged
if (aRange.aStart == aRange.aEnd
|| (aRange.aEnd.Col() - aRange.aStart.Col() == nColSpan - 1
&& aRange.aEnd.Row() - aRange.aStart.Row() == nRowSpan - 1))
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::Any(uno::Reference(cppu::getXWeak(pObj.get())));
}
uno::Any SAL_CALL ScTabViewObj::getSelectionFromString( const OUString& aStrRange )
{
ScDocShell* pDocSh = GetViewShell()->GetViewData().GetDocShell();
const sal_Int16 nTabCount = pDocSh->GetDocument().GetTableCount();
StringRangeEnumerator aRangeEnum(aStrRange , 0, nTabCount-1);
// iterate through sheet range
StringRangeEnumerator::Iterator aIter = aRangeEnum.begin();
StringRangeEnumerator::Iterator aEnd = aRangeEnum.end();
ScRangeListRef aRangeList = new ScRangeList;
while ( aIter != aEnd )
{
ScRange currentTab(SCCOL(0), SCROW(0), SCTAB(*aIter));
aRangeList->push_back(currentTab);
++aIter;
}
rtl::Reference<ScCellRangesBase> pObj = new ScCellRangesObj(pDocSh, *aRangeList);
// SetCursorOnly tells the range the specific cells selected are irrelevant - maybe could rename?
pObj->SetCursorOnly(true);
return uno::Any(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, u"com.sun.star.sheet.SpreadsheetViewPanesEnumeration"_ustr);
}
// 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::Any(xPane);
}
uno::Type SAL_CALL ScTabViewObj::getElementType()
{
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 = dynamic_cast<ScCellRangesBase*>( xActiveSheet.get() );
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);
double fHitLog = pActiveWin->PixelToLogic(Size(pDrawView->GetHitTolerancePixel(),0)).Width();
for (const rtl::Reference<SdrObject>& pObj : *pDrawPage)
{
if (SdrObjectPrimitiveHit(*pObj, aPos, {fHitLog, fHitLog}, *pDrawView->GetSdrPageView(), nullptr, false))
{
xTarget.set(pObj->getUnoShape(), uno::UNO_QUERY);
break;
}
}
}
}
}
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 = std::move(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 = getXWeak();
for (const auto& rListener : aMouseClickHandlers)
{
try
{
rListener->disposing(aEvent);
}
catch ( uno::Exception& )
{
}
}
aMouseClickHandlers.clear();
}
void ScTabViewObj::EndActivationListening()
{
lang::EventObject aEvent;
aEvent.Source = getXWeak();
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();
std::erase(aMouseClickHandlers, aListener);
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();
std::erase(aActivationListeners, aListener);
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(getXWeak());
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_SHOWNOTEAUTHOR )
aNewOpt.SetOption( VOPT_NOTEAUTHOR, ScUnoHelpFunctions::GetBoolFromAny( aValue ) );
else if ( aPropertyName == SC_UNO_SHOWFORMULASMARKS )
aNewOpt.SetOption( VOPT_FORMULAS_MARKS, 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_SHOWNOTEAUTHOR ) aRet <<= rOpt.GetOption( VOPT_NOTEAUTHOR );
else if ( aPropertyName == SC_UNO_SHOWFORMULASMARKS ) aRet <<= rOpt.GetOption( VOPT_FORMULAS_MARKS );
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 )
{
AbsoluteScreenPixelRectangle aRect = pActiveWin->GetWindowExtentsAbsolute();
aRet <<= VCLUnoHelper::ConvertToAWTRect(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(getXWeak());
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(getXWeak());
aEvent.RangeDescriptor = rText;
// copy on the stack because listener could remove itself
const RangeSelListeners listeners(aRangeSelListeners);
for (const auto& rListener : listeners)
rListener->done( aEvent );
}
void ScTabViewObj::RangeSelAborted( const OUString& rText )
{
sheet::RangeSelectionEvent aEvent;
aEvent.Source.set(getXWeak());
aEvent.RangeDescriptor = rText;
// copy on the stack because listener could remove itself
const RangeSelListeners listeners(aRangeSelListeners);
for (const auto& rListener : listeners)
rListener->aborted( aEvent );
}
void ScTabViewObj::RangeSelChanged( const OUString& rText )
{
sheet::RangeSelectionEvent aEvent;
aEvent.Source.set(getXWeak());
aEvent.RangeDescriptor = rText;
// copy on the stack because listener could remove itself
const std::vector<css::uno::Reference<css::sheet::XRangeSelectionChangeListener>> listener(aRangeChgListeners);
for (const auto& rListener : listener)
rListener->descriptorChanged( aEvent );
}
// XServiceInfo
OUString SAL_CALL ScTabViewObj::getImplementationName()
{
return u"ScTabViewObj"_ustr;
}
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
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)
{
uno::Any aReturn = ::cppu::queryInterface(rType,
static_cast<sheet::XSelectedSheetsSupplier*>(this));
if ( aReturn.hasValue() )
return aReturn;
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: */
↑ V530 The return value of function 'CallXScript' is required to be utilized.
↑ V530 The return value of function 'Execute' is required to be utilized.
↑ V530 The return value of function 'CallXScript' is required to be utilized.
↑ V530 The return value of function 'CallXScript' is required to be utilized.
↑ V1029 Numeric Truncation Error. Return value of the 'size' function is written to the 16-bit variable.
↑ V1029 Numeric Truncation Error. Return value of the 'size' function is written to the 16-bit variable.