From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- reportdesign/source/ui/report/ViewsWindow.cxx | 1673 +++++++++++++++++++++++++ 1 file changed, 1673 insertions(+) create mode 100644 reportdesign/source/ui/report/ViewsWindow.cxx (limited to 'reportdesign/source/ui/report/ViewsWindow.cxx') diff --git a/reportdesign/source/ui/report/ViewsWindow.cxx b/reportdesign/source/ui/report/ViewsWindow.cxx new file mode 100644 index 000000000..b5ce7a48f --- /dev/null +++ b/reportdesign/source/ui/report/ViewsWindow.cxx @@ -0,0 +1,1673 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rptui +{ +#define DEFAUL_MOVE_SIZE 100 + +using namespace ::com::sun::star; +using namespace ::comphelper; + +static bool lcl_getNewRectSize(const tools::Rectangle& _aObjRect,tools::Long& _nXMov, tools::Long& _nYMov,SdrObject const * _pObj,SdrView const * _pView, ControlModification _nControlModification) +{ + bool bMoveAllowed = _nXMov != 0 || _nYMov != 0; + if ( bMoveAllowed ) + { + tools::Rectangle aNewRect = _aObjRect; + SdrObject* pOverlappedObj = nullptr; + do + { + aNewRect = _aObjRect; + switch(_nControlModification) + { + case ControlModification::HEIGHT_GREATEST: + case ControlModification::WIDTH_GREATEST: + aNewRect.setWidth(_nXMov); + aNewRect.setHeight(_nYMov); + break; + default: + aNewRect.Move(_nXMov,_nYMov); + break; + } + if (dynamic_cast(_pObj) != nullptr || dynamic_cast(_pObj) != nullptr) + { + pOverlappedObj = isOver(aNewRect,*_pObj->getSdrPageFromSdrObject(),*_pView,true,_pObj); + if ( pOverlappedObj && _pObj != pOverlappedObj ) + { + tools::Rectangle aOverlappingRect = pOverlappedObj->GetSnapRect(); + sal_Int32 nXTemp = _nXMov; + sal_Int32 nYTemp = _nYMov; + switch(_nControlModification) + { + case ControlModification::LEFT: + nXTemp += aOverlappingRect.Right() - aNewRect.Left(); + bMoveAllowed = _nXMov != nXTemp; + break; + case ControlModification::RIGHT: + nXTemp += aOverlappingRect.Left() - aNewRect.Right(); + bMoveAllowed = _nXMov != nXTemp; + break; + case ControlModification::TOP: + nYTemp += aOverlappingRect.Bottom() - aNewRect.Top(); + bMoveAllowed = _nYMov != nYTemp; + break; + case ControlModification::BOTTOM: + nYTemp += aOverlappingRect.Top() - aNewRect.Bottom(); + bMoveAllowed = _nYMov != nYTemp; + break; + case ControlModification::CENTER_HORIZONTAL: + if ( _aObjRect.Left() < aOverlappingRect.Left() ) + nXTemp += aOverlappingRect.Left() - aNewRect.Left() - aNewRect.getWidth(); + else + nXTemp += aOverlappingRect.Right() - aNewRect.Left(); + bMoveAllowed = _nXMov != nXTemp; + break; + case ControlModification::CENTER_VERTICAL: + if ( _aObjRect.Top() < aOverlappingRect.Top() ) + nYTemp += aOverlappingRect.Top() - aNewRect.Top() - aNewRect.getHeight(); + else + nYTemp += aOverlappingRect.Bottom() - aNewRect.Top(); + bMoveAllowed = _nYMov != nYTemp; + break; + case ControlModification::HEIGHT_GREATEST: + case ControlModification::WIDTH_GREATEST: + { + tools::Rectangle aIntersectionRect = aNewRect.GetIntersection(aOverlappingRect); + if ( !aIntersectionRect.IsEmpty() ) + { + if ( _nControlModification == ControlModification::WIDTH_GREATEST ) + { + if ( aNewRect.Left() < aIntersectionRect.Left() ) + { + aNewRect.SetRight( aIntersectionRect.Left() ); + } + else if ( aNewRect.Left() < aIntersectionRect.Right() ) + { + aNewRect.SetLeft( aIntersectionRect.Right() ); + } + } + else if ( _nControlModification == ControlModification::HEIGHT_GREATEST ) + { + if ( aNewRect.Top() < aIntersectionRect.Top() ) + { + aNewRect.SetBottom( aIntersectionRect.Top() ); + } + else if ( aNewRect.Top() < aIntersectionRect.Bottom() ) + { + aNewRect.SetTop( aIntersectionRect.Bottom() ); + } + } + nYTemp = aNewRect.getHeight(); + bMoveAllowed = _nYMov != nYTemp; + nXTemp = aNewRect.getWidth(); + bMoveAllowed = bMoveAllowed && _nXMov != nXTemp; + } + } + break; + default: + break; + } + + _nXMov = nXTemp; + _nYMov = nYTemp; + } + else + pOverlappedObj = nullptr; + } + } + while ( pOverlappedObj && bMoveAllowed ); + } + return bMoveAllowed; +} + +OViewsWindow::OViewsWindow( OReportWindow* _pReportWindow) + : Window( _pReportWindow,WB_DIALOGCONTROL) + , m_pParent(_pReportWindow) + , m_bInUnmark(false) +{ + SetPaintTransparent(true); + SetMapMode(MapMode(MapUnit::Map100thMM)); + m_aColorConfig.AddListener(this); + ImplInitSettings(); +} + +OViewsWindow::~OViewsWindow() +{ + disposeOnce(); +} + +void OViewsWindow::dispose() +{ + m_aColorConfig.RemoveListener(this); + for (auto& rxSection : m_aSections) + rxSection.disposeAndClear(); + m_aSections.clear(); + m_pParent.clear(); + vcl::Window::dispose(); +} + +void OViewsWindow::impl_resizeSectionWindow(OSectionWindow& _rSectionWindow,Point& _rStartPoint,bool _bSet) +{ + const uno::Reference< report::XSection> xSection = _rSectionWindow.getReportSection().getSection(); + + Size aSectionSize = _rSectionWindow.LogicToPixel( Size( 0,xSection->getHeight() ) ); + aSectionSize.setWidth( getView()->GetTotalWidth() ); + + const sal_Int32 nMinHeight = _rSectionWindow.getStartMarker().getMinHeight(); + if ( _rSectionWindow.getStartMarker().isCollapsed() || nMinHeight > aSectionSize.Height() ) + { + aSectionSize.setHeight( nMinHeight ); + } + aSectionSize.AdjustHeight(static_cast(StyleSettings::GetSplitSize() * static_cast(_rSectionWindow.GetMapMode().GetScaleY())) ); + + if ( _bSet ) + _rSectionWindow.SetPosSizePixel(_rStartPoint,aSectionSize); + + _rStartPoint.AdjustY(aSectionSize.Height() ); +} + + +void OViewsWindow::resize(const OSectionWindow& _rSectionWindow) +{ + bool bSet = false; + Point aStartPoint; + for (VclPtr const & pSectionWindow : m_aSections) + { + if ( pSectionWindow == &_rSectionWindow ) + { + aStartPoint = pSectionWindow->GetPosPixel(); + bSet = true; + } + + if ( bSet ) + { + impl_resizeSectionWindow(*pSectionWindow,aStartPoint,bSet); + static const InvalidateFlags nIn = InvalidateFlags::Update | InvalidateFlags::Transparent; + pSectionWindow->getStartMarker().Invalidate( nIn ); // InvalidateFlags::NoErase |InvalidateFlags::NoChildren| InvalidateFlags::Transparent + pSectionWindow->getEndMarker().Invalidate( nIn ); + } + } + m_pParent->notifySizeChanged(); +} + +void OViewsWindow::Resize() +{ + Window::Resize(); + if ( !m_aSections.empty() ) + { + const Point aOffset(m_pParent->getThumbPos()); + Point aStartPoint(0,-aOffset.Y()); + for (VclPtr const & pSectionWindow : m_aSections) + { + impl_resizeSectionWindow(*pSectionWindow,aStartPoint,true); + } + } +} + +void OViewsWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + Window::Paint(rRenderContext, rRect); + + rRenderContext.SetBackground(); + rRenderContext.SetFillColor(Application::GetSettings().GetStyleSettings().GetDialogColor()); + rRenderContext.SetTextFillColor(Application::GetSettings().GetStyleSettings().GetDialogColor()); + + Size aOut(GetOutputSizePixel()); + tools::Long nStartWidth = tools::Long(REPORT_STARTMARKER_WIDTH * rRenderContext.GetMapMode().GetScaleX()); + + aOut.AdjustWidth( -nStartWidth ); + aOut = rRenderContext.PixelToLogic(aOut); + + tools::Rectangle aRect(rRenderContext.PixelToLogic(Point(nStartWidth,0)), aOut); + Wallpaper aWall(m_aColorConfig.GetColorValue(::svtools::APPBACKGROUND).nColor); + rRenderContext.DrawWallpaper(aRect, aWall); +} + +void OViewsWindow::ImplInitSettings() +{ + EnableChildTransparentMode(); +} + +void OViewsWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + ImplInitSettings(); + Invalidate(); + } +} + +void OViewsWindow::addSection(const uno::Reference< report::XSection >& _xSection,const OUString& _sColorEntry,sal_uInt16 _nPosition) +{ + VclPtrInstance pSectionWindow(this,_xSection,_sColorEntry); + m_aSections.insert(getIteratorAtPos(_nPosition) , TSectionsMap::value_type(pSectionWindow)); + m_pParent->setMarked(&pSectionWindow->getReportSection().getSectionView(),m_aSections.size() == 1); + Resize(); +} + +void OViewsWindow::removeSection(sal_uInt16 _nPosition) +{ + if ( _nPosition < m_aSections.size() ) + { + TSectionsMap::iterator aPos = getIteratorAtPos(_nPosition); + TSectionsMap::const_iterator aNew = getIteratorAtPos(_nPosition == 0 ? _nPosition+1: _nPosition - 1); + + m_pParent->getReportView()->UpdatePropertyBrowserDelayed((*aNew)->getReportSection().getSectionView()); + + aPos->disposeAndClear(); + m_aSections.erase(aPos); + Resize(); + } +} + +void OViewsWindow::toggleGrid(bool _bVisible) +{ + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [_bVisible] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().SetGridVisible(_bVisible); + }); + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().Window::Invalidate(InvalidateFlags::NoErase); + }); +} + +sal_Int32 OViewsWindow::getTotalHeight() const +{ + return std::accumulate(m_aSections.begin(), m_aSections.end(), sal_Int32(0), + [](const sal_Int32 nHeight, const VclPtr& rxSection) { return nHeight + rxSection->GetSizePixel().Height(); }); +} + +sal_uInt16 OViewsWindow::getSectionCount() const +{ + return static_cast(m_aSections.size()); +} + +void OViewsWindow::SetInsertObj( SdrObjKind eObj,const OUString& _sShapeType ) +{ + for (const auto& rxSection : m_aSections) + rxSection->getReportSection().getSectionView().SetCurrentObj( eObj, SdrInventor::ReportDesign ); + + m_sShapeType = _sShapeType; +} + + +void OViewsWindow::SetMode( DlgEdMode eNewMode ) +{ + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [&eNewMode] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().SetMode(eNewMode); + }); +} + +bool OViewsWindow::HasSelection() const +{ + return std::any_of(m_aSections.begin(), m_aSections.end(), + [](const VclPtr& rxSection) { return rxSection->getReportSection().getSectionView().AreObjectsMarked(); }); +} + +void OViewsWindow::Delete() +{ + m_bInUnmark = true; + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().Delete(); + }); + m_bInUnmark = false; +} + +void OViewsWindow::Copy() +{ + uno::Sequence< beans::NamedValue > aAllreadyCopiedObjects; + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [&aAllreadyCopiedObjects] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().Copy(aAllreadyCopiedObjects); + }); + + rtl::Reference pCopy = new OReportExchange(aAllreadyCopiedObjects); + pCopy->CopyToClipboard(this); +} + +void OViewsWindow::Paste() +{ + TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(this)); + OReportExchange::TSectionElements aCopies = OReportExchange::extractCopies(aTransferData); + if ( aCopies.getLength() > 1 ) + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [&aCopies] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().Paste(aCopies); + }); + else + { + OSectionWindow* pMarkedSection = getMarkedSection(); + if ( pMarkedSection ) + pMarkedSection->getReportSection().Paste(aCopies,true); + } +} + +OSectionWindow* OViewsWindow::getSectionWindow(const uno::Reference< report::XSection>& _xSection) const +{ + OSL_ENSURE(_xSection.is(),"Section is NULL!"); + + OSectionWindow* pSectionWindow = nullptr; + for (VclPtr const & p : m_aSections) + { + if (p->getReportSection().getSection() == _xSection) + { + pSectionWindow = p.get(); + break; + } + } + + return pSectionWindow; +} + + +OSectionWindow* OViewsWindow::getMarkedSection(NearSectionAccess nsa) const +{ + OSectionWindow* pRet = nullptr; + TSectionsMap::const_iterator aIter = m_aSections.begin(); + TSectionsMap::const_iterator aEnd = m_aSections.end(); + sal_uInt32 nCurrentPosition = 0; + for (; aIter != aEnd ; ++aIter) + { + if ( (*aIter)->getStartMarker().isMarked() ) + { + if (nsa == CURRENT) + { + pRet = aIter->get(); + break; + } + else if ( nsa == PREVIOUS ) + { + if (nCurrentPosition > 0) + { + pRet = (--aIter)->get(); + if (pRet == nullptr) + { + pRet = m_aSections.begin()->get(); + } + } + else + { + // if we are out of bounds return the first one + pRet = m_aSections.begin()->get(); + } + break; + } + else if ( nsa == POST ) + { + sal_uInt32 nSize = m_aSections.size(); + if ((nCurrentPosition + 1) < nSize) + { + pRet = (++aIter)->get(); + if (pRet == nullptr) + { + pRet = (--aEnd)->get(); + } + } + else + { + // if we are out of bounds return the last one + pRet = (--aEnd)->get(); + } + break; + } + } + ++nCurrentPosition; + } + + return pRet; +} + +void OViewsWindow::markSection(const sal_uInt16 _nPos) +{ + if ( _nPos < m_aSections.size() ) + m_pParent->setMarked(m_aSections[_nPos]->getReportSection().getSection(),true); +} + +bool OViewsWindow::IsPasteAllowed() const +{ + TransferableDataHelper aTransferData( TransferableDataHelper::CreateFromSystemClipboard( const_cast< OViewsWindow* >( this ) ) ); + return aTransferData.HasFormat(OReportExchange::getDescriptorFormatId()); +} + +void OViewsWindow::SelectAll(const SdrObjKind _nObjectType) +{ + m_bInUnmark = true; + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [&_nObjectType] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().SelectAll(_nObjectType); + }); + m_bInUnmark = false; +} + +void OViewsWindow::unmarkAllObjects(OSectionView const * _pSectionView) +{ + if ( m_bInUnmark ) + return; + + m_bInUnmark = true; + for (const auto& rxSection : m_aSections) + { + if ( &rxSection->getReportSection().getSectionView() != _pSectionView ) + { + rxSection->getReportSection().deactivateOle(); + rxSection->getReportSection().getSectionView().UnmarkAllObj(); + } + } + m_bInUnmark = false; +} + +void OViewsWindow::ConfigurationChanged( utl::ConfigurationBroadcaster*, ConfigurationHints) +{ + ImplInitSettings(); + Invalidate(); +} + +void OViewsWindow::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeft() ) + { + GrabFocus(); + const uno::Sequence< beans::PropertyValue> aArgs; + getView()->getReportView()->getController().executeChecked(SID_SELECT_REPORT,aArgs); + } + Window::MouseButtonDown(rMEvt); +} + +void OViewsWindow::showRuler(bool _bShow) +{ + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [_bShow] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getStartMarker().showRuler(_bShow); + }); + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getStartMarker().Window::Invalidate(InvalidateFlags::NoErase); + }); +} + +void OViewsWindow::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( !rMEvt.IsLeft() ) + return; + + auto aIter = std::find_if(m_aSections.begin(), m_aSections.end(), + [](const VclPtr& rxSection) { return rxSection->getReportSection().getSectionView().AreObjectsMarked(); }); + if (aIter != m_aSections.end()) + { + (*aIter)->getReportSection().MouseButtonUp(rMEvt); + } + + // remove special insert mode + for (const auto& rxSection : m_aSections) + { + rxSection->getReportSection().getPage()->resetSpecialMode(); + } +} + +bool OViewsWindow::handleKeyEvent(const KeyEvent& _rEvent) +{ + bool bRet = false; + for (const auto& rxSection : m_aSections) + { + if ( rxSection->getStartMarker().isMarked() ) + { + bRet = rxSection->getReportSection().handleKeyEvent(_rEvent); + } + } + return bRet; +} + +OViewsWindow::TSectionsMap::iterator OViewsWindow::getIteratorAtPos(sal_uInt16 _nPos) +{ + TSectionsMap::iterator aRet = m_aSections.end(); + if ( _nPos < m_aSections.size() ) + aRet = m_aSections.begin() + _nPos; + return aRet; +} + +void OViewsWindow::setMarked(OSectionView const * _pSectionView, bool _bMark) +{ + OSL_ENSURE(_pSectionView != nullptr,"SectionView is NULL!"); + if ( _pSectionView ) + setMarked(_pSectionView->getReportSection()->getSection(),_bMark); +} + +void OViewsWindow::setMarked(const uno::Reference< report::XSection>& _xSection, bool _bMark) +{ + for (const auto& rxSection : m_aSections) + { + if ( rxSection->getReportSection().getSection() != _xSection ) + { + rxSection->setMarked(false); + } + else if ( rxSection->getStartMarker().isMarked() != _bMark ) + { + rxSection->setMarked(_bMark); + } + } +} + +void OViewsWindow::setMarked(const uno::Sequence< uno::Reference< report::XReportComponent> >& _aShapes, bool _bMark) +{ + bool bFirst = true; + for(const uno::Reference< report::XReportComponent>& rShape : _aShapes) + { + const uno::Reference< report::XSection> xSection = rShape->getSection(); + if ( xSection.is() ) + { + if ( bFirst ) + { + bFirst = false; + m_pParent->setMarked(xSection,_bMark); + } + OSectionWindow* pSectionWindow = getSectionWindow(xSection); + if ( pSectionWindow ) + { + SdrObject* pObject = SdrObject::getSdrObjectFromXShape( rShape ); + OSL_ENSURE( pObject, "OViewsWindow::setMarked: no SdrObject for the shape!" ); + if ( pObject ) + pSectionWindow->getReportSection().getSectionView().MarkObj( pObject, pSectionWindow->getReportSection().getSectionView().GetSdrPageView(), !_bMark ); + } + } + } +} + +void OViewsWindow::collectRectangles(TRectangleMap& _rSortRectangles) +{ + for (const auto& rxSection : m_aSections) + { + OSectionView& rView = rxSection->getReportSection().getSectionView(); + if ( rView.AreObjectsMarked() ) + { + rView.SortMarkedObjects(); + const size_t nCount = rView.GetMarkedObjectCount(); + for (size_t i=0; i < nCount; ++i) + { + const SdrMark* pM = rView.GetSdrMarkByIndex(i); + SdrObject* pObj = pM->GetMarkedSdrObj(); + tools::Rectangle aObjRect(pObj->GetSnapRect()); + _rSortRectangles.emplace(aObjRect,TRectangleMap::mapped_type(pObj,&rView)); + } + } + } +} + +void OViewsWindow::collectBoundResizeRect(const TRectangleMap& _rSortRectangles, ControlModification _nControlModification,bool _bAlignAtSection, tools::Rectangle& _rBound, tools::Rectangle& _rResize) +{ + bool bOnlyOnce = false; + for (const auto& [aObjRect, rObjViewPair] : _rSortRectangles) + { + if ( _rResize.IsEmpty() ) + _rResize = aObjRect; + switch(_nControlModification) + { + case ControlModification::WIDTH_SMALLEST: + if ( _rResize.getWidth() > aObjRect.getWidth() ) + _rResize = aObjRect; + break; + case ControlModification::HEIGHT_SMALLEST: + if ( _rResize.getHeight() > aObjRect.getHeight() ) + _rResize = aObjRect; + break; + case ControlModification::WIDTH_GREATEST: + if ( _rResize.getWidth() < aObjRect.getWidth() ) + _rResize = aObjRect; + break; + case ControlModification::HEIGHT_GREATEST: + if ( _rResize.getHeight() < aObjRect.getHeight() ) + _rResize = aObjRect; + break; + default: break; + } + + SdrObjTransformInfoRec aInfo; + const SdrObject* pObj = rObjViewPair.first; + pObj->TakeObjInfo(aInfo); + bool bHasFixed = !aInfo.bMoveAllowed || pObj->IsMoveProtect(); + if ( bHasFixed ) + _rBound.Union(aObjRect); + else + { + if ( _bAlignAtSection || _rSortRectangles.size() == 1 ) + { // align single object at the page + if ( ! bOnlyOnce ) + { + bOnlyOnce = true; + OReportSection* pReportSection = rObjViewPair.second->getReportSection(); + const uno::Reference< report::XSection>& xSection = pReportSection->getSection(); + try + { + uno::Reference xReportDefinition = xSection->getReportDefinition(); + _rBound.Union(tools::Rectangle(getStyleProperty(xReportDefinition,PROPERTY_LEFTMARGIN),0, + getStyleProperty(xReportDefinition,PROPERTY_PAPERSIZE).Width - getStyleProperty(xReportDefinition,PROPERTY_RIGHTMARGIN), + xSection->getHeight())); + } + catch(const uno::Exception &){} + } + } + else + { + _rBound.Union(rObjViewPair.second->GetMarkedObjRect()); + } + } + } +} + +void OViewsWindow::alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection) +{ + if ( _nControlModification == ControlModification::NONE ) + return; + + Point aRefPoint; + RectangleLess::CompareMode eCompareMode = RectangleLess::POS_LEFT; + switch (_nControlModification) + { + case ControlModification::TOP : eCompareMode = RectangleLess::POS_UPPER; break; + case ControlModification::BOTTOM: eCompareMode = RectangleLess::POS_DOWN; break; + case ControlModification::LEFT : eCompareMode = RectangleLess::POS_LEFT; break; + case ControlModification::RIGHT : eCompareMode = RectangleLess::POS_RIGHT; break; + case ControlModification::CENTER_HORIZONTAL : + case ControlModification::CENTER_VERTICAL : + { + eCompareMode = (ControlModification::CENTER_VERTICAL == _nControlModification) ? RectangleLess::POS_CENTER_VERTICAL : RectangleLess::POS_CENTER_HORIZONTAL; + uno::Reference xSection = (*m_aSections.begin())->getReportSection().getSection(); + uno::Reference xReportDefinition = xSection->getReportDefinition(); + aRefPoint = tools::Rectangle(getStyleProperty(xReportDefinition,PROPERTY_LEFTMARGIN),0, + getStyleProperty(xReportDefinition,PROPERTY_PAPERSIZE).Width - getStyleProperty(xReportDefinition,PROPERTY_RIGHTMARGIN), + xSection->getHeight()).Center(); + } + break; + default: break; + } + RectangleLess aCompare(eCompareMode,aRefPoint); + TRectangleMap aSortRectangles(aCompare); + collectRectangles(aSortRectangles); + + tools::Rectangle aBound; + tools::Rectangle aResize; + collectBoundResizeRect(aSortRectangles,_nControlModification,_bAlignAtSection,aBound,aResize); + + bool bMove = true; + + auto aGetFun = ::std::mem_fn(&tools::Rectangle::Bottom); + auto aSetFun = ::std::mem_fn(&tools::Rectangle::SetBottom); + auto aRefFun = ::std::mem_fn(&tools::Rectangle::Top); + TRectangleMap::const_iterator aRectIter = aSortRectangles.begin(); + TRectangleMap::const_iterator aRectEnd = aSortRectangles.end(); + for (;aRectIter != aRectEnd ; ++aRectIter) + { + tools::Rectangle aObjRect = aRectIter->first; + SdrObject* pObj = aRectIter->second.first; + SdrView* pView = aRectIter->second.second; + Point aCenter(aBound.Center()); + SdrObjTransformInfoRec aInfo; + pObj->TakeObjInfo(aInfo); + if (aInfo.bMoveAllowed && !pObj->IsMoveProtect()) + { + tools::Long nXMov = 0; + tools::Long nYMov = 0; + tools::Long* pValue = &nXMov; + switch(_nControlModification) + { + case ControlModification::TOP : + aGetFun = ::std::mem_fn(&tools::Rectangle::Top); + aSetFun = ::std::mem_fn(&tools::Rectangle::SetTop); + aRefFun = ::std::mem_fn(&tools::Rectangle::Bottom); + pValue = &nYMov; + break; + case ControlModification::BOTTOM: + // defaults are already set + pValue = &nYMov; + break; + case ControlModification::CENTER_VERTICAL: + nYMov = aCenter.Y() - aObjRect.Center().Y(); + pValue = &nYMov; + bMove = false; + break; + case ControlModification::RIGHT : + aGetFun = ::std::mem_fn(&tools::Rectangle::Right); + aSetFun = ::std::mem_fn(&tools::Rectangle::SetRight); + aRefFun = ::std::mem_fn(&tools::Rectangle::Left); + break; + case ControlModification::CENTER_HORIZONTAL: + nXMov = aCenter.X() - aObjRect.Center().X(); + bMove = false; + break; + case ControlModification::LEFT : + aGetFun = ::std::mem_fn(&tools::Rectangle::Left); + aSetFun = ::std::mem_fn(&tools::Rectangle::SetLeft); + aRefFun = ::std::mem_fn(&tools::Rectangle::Right); + break; + default: + bMove = false; + break; + } + if ( bMove ) + { + tools::Rectangle aTest = aObjRect; + aSetFun(&aTest, aGetFun(&aBound)); + TRectangleMap::const_iterator aInterSectRectIter = aSortRectangles.begin(); + for (; aInterSectRectIter != aRectIter; ++aInterSectRectIter) + { + if ( pView == aInterSectRectIter->second.second && (dynamic_cast(aInterSectRectIter->second.first) || dynamic_cast(aInterSectRectIter->second.first))) + { + SdrObject* pPreviousObj = aInterSectRectIter->second.first; + tools::Rectangle aIntersectRect = aTest.GetIntersection( pPreviousObj->GetSnapRect()); + if ( !aIntersectRect.IsEmpty() && (aIntersectRect.Left() != aIntersectRect.Right() && aIntersectRect.Top() != aIntersectRect.Bottom() ) ) + { + *pValue = aRefFun(&aIntersectRect) - aGetFun(&aObjRect); + break; + } + } + } + if ( aInterSectRectIter == aRectIter ) + *pValue = aGetFun(&aBound) - aGetFun(&aObjRect); + } + + if ( lcl_getNewRectSize(aObjRect,nXMov,nYMov,pObj,pView,_nControlModification) ) + { + const Size aSize(nXMov,nYMov); + pView->AddUndo(pView->GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,aSize)); + pObj->Move(aSize); + aObjRect = pObj->GetSnapRect(); + } + + // resizing control + if ( !aResize.IsEmpty() && aObjRect != aResize ) + { + nXMov = aResize.getWidth(); + nYMov = aResize.getHeight(); + switch(_nControlModification) + { + case ControlModification::WIDTH_GREATEST: + case ControlModification::HEIGHT_GREATEST: + if ( _nControlModification == ControlModification::HEIGHT_GREATEST ) + nXMov = aObjRect.getWidth(); + else if ( _nControlModification == ControlModification::WIDTH_GREATEST ) + nYMov = aObjRect.getHeight(); + lcl_getNewRectSize(aObjRect,nXMov,nYMov,pObj,pView,_nControlModification); + [[fallthrough]]; + case ControlModification::WIDTH_SMALLEST: + case ControlModification::HEIGHT_SMALLEST: + pView->AddUndo( pView->GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj)); + { + OObjectBase* pObjBase = dynamic_cast(pObj); + OSL_ENSURE(pObjBase,"Where comes this object from?"); + if ( pObjBase ) + { + if ( _nControlModification == ControlModification::WIDTH_SMALLEST || _nControlModification == ControlModification::WIDTH_GREATEST ) + pObjBase->getReportComponent()->setSize(awt::Size(nXMov,aObjRect.getHeight())); + else if ( _nControlModification == ControlModification::HEIGHT_GREATEST || _nControlModification == ControlModification::HEIGHT_SMALLEST ) + pObjBase->getReportComponent()->setSize(awt::Size(aObjRect.getWidth(),nYMov)); + } + } + break; + default: + break; + } + } + } + pView->AdjustMarkHdl(); + } +} + +void OViewsWindow::createDefault() +{ + OSectionWindow* pMarkedSection = getMarkedSection(); + if ( pMarkedSection ) + pMarkedSection->getReportSection().createDefault(m_sShapeType); +} + +void OViewsWindow::setGridSnap(bool bOn) +{ + for (const auto& rxSection : m_aSections) + { + rxSection->getReportSection().getSectionView().SetGridSnap(bOn); + rxSection->getReportSection().Invalidate(); + } +} + +void OViewsWindow::setDragStripes(bool bOn) +{ + for (const auto& rxSection : m_aSections) + rxSection->getReportSection().getSectionView().SetDragStripes(bOn); +} + +sal_uInt16 OViewsWindow::getPosition(const OSectionWindow* _pSectionWindow) const +{ + auto aIter = std::find_if(m_aSections.begin(), m_aSections.end(), + [&_pSectionWindow](const VclPtr& rxSection) { return _pSectionWindow == rxSection.get(); }); + return static_cast(std::distance(m_aSections.begin(), aIter)); +} + +OSectionWindow* OViewsWindow::getSectionWindow(const sal_uInt16 _nPos) const +{ + OSectionWindow* aReturn = nullptr; + + if ( _nPos < m_aSections.size() ) + aReturn = m_aSections[_nPos].get(); + + return aReturn; +} + +namespace +{ + enum SectionViewAction + { + eEndDragObj, + eEndAction, + eForceToAnotherPage, + eBreakAction + }; + class ApplySectionViewAction + { + private: + SectionViewAction m_eAction; + + public: + explicit ApplySectionViewAction() + : m_eAction(eEndDragObj) + { + } + + explicit ApplySectionViewAction(SectionViewAction _eAction) + : m_eAction(_eAction) + { + } + + void operator() ( const OViewsWindow::TSectionsMap::value_type& _rhs ) + { + OSectionView& rView( _rhs->getReportSection().getSectionView() ); + switch ( m_eAction ) + { + case eEndDragObj: + rView.EndDragObj(); + break; + case eEndAction: + if ( rView.IsAction() ) + rView.EndAction ( ); + break; + case eForceToAnotherPage: + rView.ForceMarkedToAnotherPage(); + break; + case eBreakAction: + if ( rView.IsAction() ) + rView.BrkAction ( ); + break; + // default: + + } + } + }; +} + +void OViewsWindow::BrkAction() +{ + EndDragObj_removeInvisibleObjects(); + ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eBreakAction) ); +} + +void OViewsWindow::BegDragObj_createInvisibleObjectAtPosition(const tools::Rectangle& _aRect, const OSectionView& _rSection) +{ + Point aNewPos(0,0); + + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + rReportSection.getPage()->setSpecialMode(); + OSectionView& rView = rReportSection.getSectionView(); + + if ( &rView != &_rSection ) + { + SdrObject *pNewObj = new SdrUnoObj( + rView.getSdrModelFromSdrView(), + "com.sun.star.form.component.FixedText"); + + pNewObj->SetLogicRect(_aRect); + pNewObj->Move(Size(0, aNewPos.Y())); + bool bChanged = rView.GetModel()->IsChanged(); + rReportSection.getPage()->InsertObject(pNewObj); + rView.GetModel()->SetChanged(bChanged); + m_aBegDragTempList.push_back(pNewObj); + + rView.MarkObj( pNewObj, rView.GetSdrPageView() ); + } + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aNewPos.AdjustY( -nSectionHeight ); + } +} + +void OViewsWindow::BegDragObj(const Point& _aPnt, SdrHdl* _pHdl,const OSectionView* _pSection) +{ + SAL_INFO( + "reportdesign", "Clickpoint X:" << _aPnt.X() << " Y:" << _aPnt.Y()); + + m_aBegDragTempList.clear(); + + // Calculate the absolute clickpoint in the views + Point aAbsolutePnt = _aPnt; + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + OSectionView* pView = &rReportSection.getSectionView(); + if (pView == _pSection) + break; + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aAbsolutePnt.AdjustY(nSectionHeight ); + } + m_aDragDelta = Point(SAL_MAX_INT32, SAL_MAX_INT32); + SAL_INFO( + "reportdesign", + "Absolute X:" << aAbsolutePnt.X() << " Y:" << aAbsolutePnt.Y()); + + // Create drag lines over all viewable Views + // Therefore we need to identify the marked objects + // and create temporary objects on all other views at the same position + // relative to its occurrence. + + int nViewCount = 0; + Point aNewObjPos(0,0); + Point aLeftTop(SAL_MAX_INT32, SAL_MAX_INT32); + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + + OSectionView& rView = rReportSection.getSectionView(); + + if ( rView.AreObjectsMarked() ) + { + const size_t nCount = rView.GetMarkedObjectCount(); + for (size_t i=0; i < nCount; ++i) + { + const SdrMark* pM = rView.GetSdrMarkByIndex(i); + SdrObject* pObj = pM->GetMarkedSdrObj(); + if (::std::find(m_aBegDragTempList.begin(),m_aBegDragTempList.end(),pObj) == m_aBegDragTempList.end()) + { + tools::Rectangle aRect( pObj->GetCurrentBoundRect() ); + aRect.Move(0, aNewObjPos.Y()); + + aLeftTop.setX( ::std::min( aRect.Left(), aLeftTop.X() ) ); + aLeftTop.setY( ::std::min( aRect.Top(), aLeftTop.Y() ) ); + + SAL_INFO( + "reportdesign", + "createInvisible X:" << aRect.Left() << " Y:" + << aRect.Top() << " on View #" << nViewCount); + + BegDragObj_createInvisibleObjectAtPosition(aRect, rView); + } + } + } + ++nViewCount; + tools::Rectangle aClipRect = rView.GetWorkArea(); + aClipRect.SetTop( -aNewObjPos.Y() ); + rView.SetWorkArea( aClipRect ); + + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aNewObjPos.AdjustY(nSectionHeight ); + } + + const sal_Int32 nDeltaX = std::abs(aLeftTop.X() - aAbsolutePnt.X()); + const sal_Int32 nDeltaY = std::abs(aLeftTop.Y() - aAbsolutePnt.Y()); + m_aDragDelta.setX( nDeltaX ); + m_aDragDelta.setY( nDeltaY ); + + Point aNewPos = aAbsolutePnt; + + const short nDrgLog = static_cast(PixelToLogic(Size(3,0)).Width()); + nViewCount = 0; + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + + SdrHdl* pHdl = _pHdl; + if ( pHdl ) + { + if ( &rReportSection.getSectionView() != _pSection ) + { + const SdrHdlList& rHdlList = rReportSection.getSectionView().GetHdlList(); + pHdl = rHdlList.GetHdl(_pHdl->GetKind()); + } + } + SAL_INFO( + "reportdesign", + "X:" << aNewPos.X() << " Y:" << aNewPos.Y() << " on View#" + << nViewCount++); + rReportSection.getSectionView().BegDragObj(aNewPos, nullptr, pHdl, nDrgLog); + + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aNewPos.AdjustY( -nSectionHeight ); + } +} + + +void OViewsWindow::ForceMarkedToAnotherPage() +{ + ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eForceToAnotherPage ) ); +} + +void OViewsWindow::BegMarkObj(const Point& _aPnt,const OSectionView* _pSection) +{ + bool bAdd = true; + Point aNewPos = _aPnt; + + tools::Long nLastSectionHeight = 0; + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + if ( &rReportSection.getSectionView() == _pSection ) + { + bAdd = false; + aNewPos = _aPnt; // 2,2 + } + else if ( bAdd ) + { + const tools::Long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aNewPos.AdjustY(nSectionHeight ); + } + else + { + aNewPos.AdjustY( -nLastSectionHeight ); + } + rReportSection.getSectionView().BegMarkObj ( aNewPos ); + nLastSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + } +} + +OSectionView* OViewsWindow::getSectionRelativeToPosition(const OSectionView* _pSection,Point& _rPnt) +{ + OSectionView* pSection = nullptr; + TSectionsMap::const_iterator aIter = m_aSections.begin(); + const TSectionsMap::const_iterator aEnd = m_aSections.end(); + aIter = std::find_if(aIter, aEnd, [&_pSection](const VclPtr& rxSection) { + return &rxSection->getReportSection().getSectionView() == _pSection; }); + sal_Int32 nCount = static_cast(std::distance(m_aSections.cbegin(), aIter)); + OSL_ENSURE(aIter != aEnd,"This can never happen!"); + if ( _rPnt.Y() < 0 ) + { + if ( nCount ) + --aIter; + for (; nCount && (_rPnt.Y() < 0); --nCount) + { + OReportSection& rReportSection = (*aIter)->getReportSection(); + const sal_Int32 nHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + _rPnt.AdjustY(nHeight ); + if ( (nCount -1) > 0 && (_rPnt.Y() < 0) ) + --aIter; + } + if ( nCount == 0 ) + pSection = &(*m_aSections.begin())->getReportSection().getSectionView(); + else + pSection = &(*aIter)->getReportSection().getSectionView(); + } + else + { + for (; aIter != aEnd; ++aIter) + { + OReportSection& rReportSection = (*aIter)->getReportSection(); + const tools::Long nHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + if ( (_rPnt.Y() - nHeight) < 0 ) + break; + _rPnt.AdjustY( -nHeight ); + } + if ( aIter != aEnd ) + pSection = &(*aIter)->getReportSection().getSectionView(); + else + pSection = &(*(aEnd-1))->getReportSection().getSectionView(); + } + + return pSection; +} + +void OViewsWindow::EndDragObj_removeInvisibleObjects() +{ + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + rReportSection.getPage()->resetSpecialMode(); + } +} + +void OViewsWindow::EndDragObj(bool _bControlKeyPressed, const OSectionView* _pSection, const Point& _aPnt) +{ + const OUString sUndoAction = RptResId(RID_STR_UNDO_CHANGEPOSITION); + const UndoContext aUndoContext( getView()->getReportView()->getController().getUndoManager(), sUndoAction ); + + Point aNewPos = _aPnt; + OSectionView* pInSection = getSectionRelativeToPosition(_pSection, aNewPos); + if (!_bControlKeyPressed && + _pSection && !_pSection->IsDragResize() && /* Not in resize mode */ + _pSection != pInSection) + { + EndDragObj_removeInvisibleObjects(); + + // we need to manipulate the current clickpoint, we subtract the old delta from BeginDrag + aNewPos -= m_aDragDelta; + + uno::Sequence< beans::NamedValue > aAllreadyCopiedObjects; + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + if ( pInSection != &rReportSection.getSectionView() ) + { + rReportSection.getSectionView().BrkAction(); + rReportSection.Copy(aAllreadyCopiedObjects,true); + } + else + pInSection->EndDragObj(); + } + + if ( aAllreadyCopiedObjects.hasElements() ) + { + try + { + uno::Reference xReportDefinition = getView()->getReportView()->getController().getReportDefinition(); + const sal_Int32 nLeftMargin = getStyleProperty(xReportDefinition,PROPERTY_LEFTMARGIN); + const sal_Int32 nRightMargin = getStyleProperty(xReportDefinition,PROPERTY_RIGHTMARGIN); + const sal_Int32 nPaperWidth = getStyleProperty(xReportDefinition,PROPERTY_PAPERSIZE).Width; + + if ( aNewPos.X() < nLeftMargin ) + aNewPos.setX( nLeftMargin ); + if ( aNewPos.Y() < 0 ) + aNewPos.setY( 0 ); + + Point aPrevious; + for (beans::NamedValue const & namedVal : std::as_const(aAllreadyCopiedObjects)) + { + uno::Sequence< uno::Reference > aClones; + namedVal.Value >>= aClones; + uno::Reference* pColIter = aClones.getArray(); + const uno::Reference* pColEnd = pColIter + aClones.getLength(); + + // move the cloned Components to new positions + for (; pColIter != pColEnd; ++pColIter) + { + uno::Reference< report::XReportComponent> xRC(*pColIter); + aPrevious = VCLPoint(xRC->getPosition()); + awt::Size aSize = xRC->getSize(); + + if ( aNewPos.X() < nLeftMargin ) + { + aNewPos.setX( nLeftMargin ); + } + else if ( (aNewPos.X() + aSize.Width) > (nPaperWidth - nRightMargin) ) + { + aNewPos.setX( nPaperWidth - nRightMargin - aSize.Width ); + } + if ( aNewPos.Y() < 0 ) + { + aNewPos.setY( 0 ); + } + if ( aNewPos.X() < 0 ) + { + aSize.Width += aNewPos.X(); + aNewPos.setX( 0 ); + xRC->setSize(aSize); + } + xRC->setPosition(AWTPoint(aNewPos)); + if ( (pColIter+1) != pColEnd ) + { + // bring aNewPos to the position of the next object + uno::Reference< report::XReportComponent> xRCNext = *(pColIter + 1); + Point aNextPosition = VCLPoint(xRCNext->getPosition()); + aNewPos += aNextPosition - aPrevious; + } + } + } + } + catch(uno::Exception&) + { + } + pInSection->getReportSection()->Paste(aAllreadyCopiedObjects,true); + } + } + else + { + ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction() ); + EndDragObj_removeInvisibleObjects(); + } + m_aDragDelta = Point(SAL_MAX_INT32, SAL_MAX_INT32); +} + +void OViewsWindow::EndAction() +{ + ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eEndAction) ); +} + +void OViewsWindow::MovAction(const Point& _aPnt,const OSectionView* _pSection, bool _bControlKeySet) +{ + Point aRealMousePos = _aPnt; + Point aCurrentSectionPos; + SAL_INFO( + "reportdesign", + "X:" << aRealMousePos.X() << " Y:" << aRealMousePos.Y()); + + Point aHdlPos; + SdrHdl* pHdl = _pSection->GetDragHdl(); + if ( pHdl ) + { + aHdlPos = pHdl->GetPos(); + } + + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + if ( &rReportSection.getSectionView() == _pSection ) + break; + const tools::Long nSectionHeight = rxSection->PixelToLogic(rReportSection.GetOutputSizePixel()).Height(); + aCurrentSectionPos.AdjustY(nSectionHeight ); + } + aRealMousePos += aCurrentSectionPos; + + // If control key is pressed the work area is limited to the section with the current selection. + Point aPosForWorkArea(0,0); + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + OSectionView& rView = rReportSection.getSectionView(); + const tools::Long nSectionHeight = rxSection->PixelToLogic(rxSection->GetOutputSizePixel()).Height(); + + if (_bControlKeySet) + { + tools::Rectangle aClipRect = rView.GetWorkArea(); + aClipRect.SetTop( aCurrentSectionPos.Y() - aPosForWorkArea.Y() ); + aClipRect.SetBottom( aClipRect.Top() + nSectionHeight ); + rView.SetWorkArea( aClipRect ); + } + else + { + tools::Rectangle aClipRect = rView.GetWorkArea(); + aClipRect.SetTop( -aPosForWorkArea.Y() ); + rView.SetWorkArea( aClipRect ); + } + aPosForWorkArea.AdjustY(nSectionHeight ); + } + + + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + SdrHdl* pCurrentHdl = rReportSection.getSectionView().GetDragHdl(); + if ( pCurrentHdl && aRealMousePos.Y() > 0 ) + aRealMousePos = _aPnt + pCurrentHdl->GetPos() - aHdlPos; + rReportSection.getSectionView().MovAction ( aRealMousePos ); + const tools::Long nSectionHeight = rxSection->PixelToLogic(rxSection->GetOutputSizePixel()).Height(); + aRealMousePos.AdjustY( -nSectionHeight ); + } +} + +bool OViewsWindow::IsAction() const +{ + return std::any_of(m_aSections.begin(), m_aSections.end(), + [](const VclPtr& rxSection) { return rxSection->getReportSection().getSectionView().IsAction(); }); +} + +bool OViewsWindow::IsDragObj() const +{ + return std::any_of(m_aSections.begin(), m_aSections.end(), + [](const VclPtr& rxSection) { return rxSection->getReportSection().getSectionView().IsAction(); }); +} + +sal_uInt32 OViewsWindow::getMarkedObjectCount() const +{ + return std::accumulate(m_aSections.begin(), m_aSections.end(), sal_uInt32(0), + [](const sal_uInt32 nCount, const VclPtr& rxSection) { + return nCount + static_cast(rxSection->getReportSection().getSectionView().GetMarkedObjectCount()); }); +} + +void OViewsWindow::handleKey(const vcl::KeyCode& _rCode) +{ + const sal_uInt16 nCode = _rCode.GetCode(); + if ( _rCode.IsMod1() ) + { + // scroll page + OScrollWindowHelper* pScrollWindow = getView()->getScrollWindow(); + ScrollBar& rScrollBar = ( nCode == KEY_LEFT || nCode == KEY_RIGHT ) ? pScrollWindow->GetHScroll() : pScrollWindow->GetVScroll(); + if ( rScrollBar.IsVisible() ) + rScrollBar.DoScrollAction(( nCode == KEY_RIGHT || nCode == KEY_UP ) ? ScrollType::LineUp : ScrollType::LineDown ); + return; + } + + for (const auto& rxSection : m_aSections) + { + OReportSection& rReportSection = rxSection->getReportSection(); + tools::Long nX = 0; + tools::Long nY = 0; + + if ( nCode == KEY_UP ) + nY = -1; + else if ( nCode == KEY_DOWN ) + nY = 1; + else if ( nCode == KEY_LEFT ) + nX = -1; + else if ( nCode == KEY_RIGHT ) + nX = 1; + + if ( rReportSection.getSectionView().AreObjectsMarked() ) + { + if ( _rCode.IsMod2() ) + { + // move in 1 pixel distance + const Size aPixelSize = rReportSection.PixelToLogic( Size( 1, 1 ) ); + nX *= aPixelSize.Width(); + nY *= aPixelSize.Height(); + } + else + { + // move in 1 mm distance + nX *= DEFAUL_MOVE_SIZE; + nY *= DEFAUL_MOVE_SIZE; + } + + OSectionView& rView = rReportSection.getSectionView(); + const SdrHdlList& rHdlList = rView.GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + + if ( pHdl == nullptr ) + { + // no handle selected + if ( rView.IsMoveAllowed() ) + { + // restrict movement to work area + tools::Rectangle rWorkArea = rView.GetWorkArea(); + rWorkArea.AdjustRight( 1 ); + + if ( !rWorkArea.IsEmpty() ) + { + if ( rWorkArea.Top() < 0 ) + rWorkArea.SetTop( 0 ); + tools::Rectangle aMarkRect( rView.GetMarkedObjRect() ); + aMarkRect.Move( nX, nY ); + + if ( !rWorkArea.Contains( aMarkRect ) ) + { + if ( aMarkRect.Left() < rWorkArea.Left() ) + nX += rWorkArea.Left() - aMarkRect.Left(); + + if ( aMarkRect.Right() > rWorkArea.Right() ) + nX -= aMarkRect.Right() - rWorkArea.Right(); + + if ( aMarkRect.Top() < rWorkArea.Top() ) + nY += rWorkArea.Top() - aMarkRect.Top(); + + if ( aMarkRect.Bottom() > rWorkArea.Bottom() ) + nY -= aMarkRect.Bottom() - rWorkArea.Bottom(); + } + bool bCheck = false; + const SdrMarkList& rMarkList = rView.GetMarkedObjectList(); + for (size_t i = 0; !bCheck && i < rMarkList.GetMarkCount(); ++i ) + { + SdrMark* pMark = rMarkList.GetMark(i); + bCheck = dynamic_cast(pMark->GetMarkedSdrObj()) != nullptr|| dynamic_cast(pMark->GetMarkedSdrObj()); + } + + + if ( bCheck ) + { + SdrObject* pOverlapped = isOver(aMarkRect,*rReportSection.getPage(),rView); + if ( pOverlapped ) + { + do + { + tools::Rectangle aOver = pOverlapped->GetLastBoundRect(); + Point aPos; + if ( nCode == KEY_UP ) + { + aPos.setX( aMarkRect.Left() ); + aPos.setY( aOver.Top() - aMarkRect.getHeight() ); + nY += (aPos.Y() - aMarkRect.Top()); + } + else if ( nCode == KEY_DOWN ) + { + aPos.setX( aMarkRect.Left() ); + aPos.setY( aOver.Bottom() ); + nY += (aPos.Y() - aMarkRect.Top()); + } + else if ( nCode == KEY_LEFT ) + { + aPos.setX( aOver.Left() - aMarkRect.getWidth() ); + aPos.setY( aMarkRect.Top() ); + nX += (aPos.X() - aMarkRect.Left()); + } + else if ( nCode == KEY_RIGHT ) + { + aPos.setX( aOver.Right() ); + aPos.setY( aMarkRect.Top() ); + nX += (aPos.X() - aMarkRect.Left()); + } + + aMarkRect.SetPos(aPos); + if ( !rWorkArea.Contains( aMarkRect ) ) + { + break; + } + pOverlapped = isOver(aMarkRect,*rReportSection.getPage(),rView); + } + while(pOverlapped != nullptr); + if (pOverlapped != nullptr) + break; + } + } + } + + if ( nX != 0 || nY != 0 ) + { + rView.MoveAllMarked( Size( nX, nY ) ); + rView.MakeVisible( rView.GetAllMarkedRect(), rReportSection); + } + } + } + else // pHdl != nullptr + { + // move the handle + if (nX || nY) + { + const Point aStartPoint( pHdl->GetPos() ); + const Point aEndPoint( pHdl->GetPos() + Point( nX, nY ) ); + const SdrDragStat& rDragStat = rView.GetDragStat(); + + // start dragging + rView.BegDragObj( aStartPoint, nullptr, pHdl, 0 ); + + if ( rView.IsDragObj() ) + { + const bool bWasNoSnap = rDragStat.IsNoSnap(); + const bool bWasSnapEnabled = rView.IsSnapEnabled(); + + // switch snapping off + if ( !bWasNoSnap ) + const_cast(rDragStat).SetNoSnap(); + if ( bWasSnapEnabled ) + rView.SetSnapEnabled( false ); + + tools::Rectangle aNewRect; + bool bCheck = false; + const SdrMarkList& rMarkList = rView.GetMarkedObjectList(); + for (size_t i = 0; !bCheck && i < rMarkList.GetMarkCount(); ++i ) + { + SdrMark* pMark = rMarkList.GetMark(i); + bCheck = dynamic_cast(pMark->GetMarkedSdrObj()) != nullptr || dynamic_cast(pMark->GetMarkedSdrObj()) != nullptr; + if ( bCheck ) + aNewRect.Union(pMark->GetMarkedSdrObj()->GetLastBoundRect()); + } + + switch(pHdl->GetKind()) + { + case SdrHdlKind::Left: + case SdrHdlKind::UpperLeft: + case SdrHdlKind::LowerLeft: + case SdrHdlKind::Upper: + aNewRect.AdjustLeft(nX ); + aNewRect.AdjustTop(nY ); + break; + case SdrHdlKind::UpperRight: + case SdrHdlKind::Right: + case SdrHdlKind::LowerRight: + case SdrHdlKind::Lower: + aNewRect.setWidth(aNewRect.getWidth() + nX); + aNewRect.setHeight(aNewRect.getHeight() + nY); + break; + default: + break; + } + if ( !(bCheck && isOver(aNewRect,*rReportSection.getPage(),rView)) ) + rView.MovAction(aEndPoint); + rView.EndDragObj(); + + // restore snap + if ( !bWasNoSnap ) + const_cast(rDragStat).SetNoSnap( bWasNoSnap ); + if ( bWasSnapEnabled ) + rView.SetSnapEnabled( bWasSnapEnabled ); + } + + // make moved handle visible + const tools::Rectangle aVisRect( aEndPoint - Point( DEFAUL_MOVE_SIZE, DEFAUL_MOVE_SIZE ), Size( 200, 200 ) ); + rView.MakeVisible( aVisRect, rReportSection); + } + } + rView.AdjustMarkHdl(); + } + } +} + +void OViewsWindow::stopScrollTimer() +{ + ::std::for_each(m_aSections.begin(),m_aSections.end(), + [] (const TSectionsMap::value_type& sectionPtr) { + sectionPtr->getReportSection().stopScrollTimer(); + }); +} + +void OViewsWindow::fillCollapsedSections(::std::vector& _rCollapsedPositions) const +{ + sal_uInt16 i = 0; + for (const auto& rxSection : m_aSections) + { + if ( rxSection->getStartMarker().isCollapsed() ) + _rCollapsedPositions.push_back(i); + ++i; + } +} + +void OViewsWindow::collapseSections(const uno::Sequence< beans::PropertyValue>& _aCollapsedSections) +{ + for (const beans::PropertyValue& rSection : _aCollapsedSections) + { + sal_uInt16 nPos = sal_uInt16(-1); + if ( (rSection.Value >>= nPos) && nPos < m_aSections.size() ) + { + m_aSections[nPos]->setCollapsed(true); + } + } +} + +void OViewsWindow::zoom(const Fraction& _aZoom) +{ + const MapMode& aMapMode = GetMapMode(); + + Fraction aStartWidth(tools::Long(REPORT_STARTMARKER_WIDTH)); + if ( _aZoom < aMapMode.GetScaleX() ) + aStartWidth *= aMapMode.GetScaleX(); + else + aStartWidth *= _aZoom; + + setZoomFactor(_aZoom,*this); + + for (const auto& rxSection : m_aSections) + { + rxSection->zoom(_aZoom); + } + + Resize(); + + Size aOut = GetOutputSizePixel(); + aOut.setWidth( tools::Long(aStartWidth) ); + aOut = PixelToLogic(aOut); + + tools::Rectangle aRect(PixelToLogic(Point(0,0)),aOut); + Invalidate(aRect, InvalidateFlags::NoChildren); +} + +void OViewsWindow::scrollChildren(const Point& _aThumbPos) +{ + const Point aPos(PixelToLogic(_aThumbPos)); + { + MapMode aMapMode = GetMapMode(); + const Point aOld = aMapMode.GetOrigin(); + aMapMode.SetOrigin(m_pParent->GetMapMode().GetOrigin()); + + const Point aPosY(m_pParent->PixelToLogic(_aThumbPos,aMapMode)); + + aMapMode.SetOrigin( Point(aOld.X() , - aPosY.Y())); + SetMapMode( aMapMode ); + Scroll(0, -( aOld.Y() + aPosY.Y()),ScrollFlags::Children); + } + + for (const auto& rxSection : m_aSections) + { + rxSection->scrollChildren(aPos.X()); + } +} + +void OViewsWindow::fillControlModelSelection(::std::vector< uno::Reference< uno::XInterface > >& _rSelection) const +{ + for (const auto& rxSection : m_aSections) + { + rxSection->getReportSection().fillControlModelSelection(_rSelection); + } +} + +} // rptui + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3