bump product version to 6.3.0.0.beta1
[LibreOffice.git] / reportdesign / source / ui / report / ViewsWindow.cxx
blob6204f2808d8e1b347a69517432bcb555936b714a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <ViewsWindow.hxx>
21 #include <ScrollHelper.hxx>
22 #include <UndoActions.hxx>
23 #include <ReportWindow.hxx>
24 #include <DesignView.hxx>
25 #include <svtools/colorcfg.hxx>
26 #include <ReportController.hxx>
27 #include <UITools.hxx>
28 #include <RptDef.hxx>
29 #include <strings.hrc>
30 #include <SectionView.hxx>
31 #include <ReportSection.hxx>
32 #include <strings.hxx>
33 #include <rptui_slotid.hrc>
34 #include <dlgedclip.hxx>
35 #include <ColorChanger.hxx>
36 #include <RptObject.hxx>
37 #include <EndMarker.hxx>
38 #include <sal/log.hxx>
39 #include <svx/svdpagv.hxx>
40 #include <svx/unoshape.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/settings.hxx>
43 #include <core_resource.hxx>
44 #include <svx/svdundo.hxx>
45 #include <toolkit/helper/convert.hxx>
46 #include <algorithm>
47 #include <cstdlib>
48 #include <numeric>
50 namespace rptui
52 #define DEFAUL_MOVE_SIZE 100
54 using namespace ::com::sun::star;
55 using namespace ::comphelper;
57 static bool lcl_getNewRectSize(const tools::Rectangle& _aObjRect,long& _nXMov, long& _nYMov,SdrObject const * _pObj,SdrView const * _pView, ControlModification _nControlModification)
59 bool bMoveAllowed = _nXMov != 0 || _nYMov != 0;
60 if ( bMoveAllowed )
62 tools::Rectangle aNewRect = _aObjRect;
63 SdrObject* pOverlappedObj = nullptr;
66 aNewRect = _aObjRect;
67 switch(_nControlModification)
69 case ControlModification::HEIGHT_GREATEST:
70 case ControlModification::WIDTH_GREATEST:
71 aNewRect.setWidth(_nXMov);
72 aNewRect.setHeight(_nYMov);
73 break;
74 default:
75 aNewRect.Move(_nXMov,_nYMov);
76 break;
78 if (dynamic_cast<OUnoObject const *>(_pObj) != nullptr || dynamic_cast<OOle2Obj const *>(_pObj) != nullptr)
80 pOverlappedObj = isOver(aNewRect,*_pObj->getSdrPageFromSdrObject(),*_pView,true,_pObj);
81 if ( pOverlappedObj && _pObj != pOverlappedObj )
83 tools::Rectangle aOverlappingRect = pOverlappedObj->GetSnapRect();
84 sal_Int32 nXTemp = _nXMov;
85 sal_Int32 nYTemp = _nYMov;
86 switch(_nControlModification)
88 case ControlModification::LEFT:
89 nXTemp += aOverlappingRect.Right() - aNewRect.Left();
90 bMoveAllowed = _nXMov != nXTemp;
91 break;
92 case ControlModification::RIGHT:
93 nXTemp += aOverlappingRect.Left() - aNewRect.Right();
94 bMoveAllowed = _nXMov != nXTemp;
95 break;
96 case ControlModification::TOP:
97 nYTemp += aOverlappingRect.Bottom() - aNewRect.Top();
98 bMoveAllowed = _nYMov != nYTemp;
99 break;
100 case ControlModification::BOTTOM:
101 nYTemp += aOverlappingRect.Top() - aNewRect.Bottom();
102 bMoveAllowed = _nYMov != nYTemp;
103 break;
104 case ControlModification::CENTER_HORIZONTAL:
105 if ( _aObjRect.Left() < aOverlappingRect.Left() )
106 nXTemp += aOverlappingRect.Left() - aNewRect.Left() - aNewRect.getWidth();
107 else
108 nXTemp += aOverlappingRect.Right() - aNewRect.Left();
109 bMoveAllowed = _nXMov != nXTemp;
110 break;
111 case ControlModification::CENTER_VERTICAL:
112 if ( _aObjRect.Top() < aOverlappingRect.Top() )
113 nYTemp += aOverlappingRect.Top() - aNewRect.Top() - aNewRect.getHeight();
114 else
115 nYTemp += aOverlappingRect.Bottom() - aNewRect.Top();
116 bMoveAllowed = _nYMov != nYTemp;
117 break;
118 case ControlModification::HEIGHT_GREATEST:
119 case ControlModification::WIDTH_GREATEST:
121 tools::Rectangle aIntersectionRect = aNewRect.GetIntersection(aOverlappingRect);
122 if ( !aIntersectionRect.IsEmpty() )
124 if ( _nControlModification == ControlModification::WIDTH_GREATEST )
126 if ( aNewRect.Left() < aIntersectionRect.Left() )
128 aNewRect.SetRight( aIntersectionRect.Left() );
130 else if ( aNewRect.Left() < aIntersectionRect.Right() )
132 aNewRect.SetLeft( aIntersectionRect.Right() );
135 else if ( _nControlModification == ControlModification::HEIGHT_GREATEST )
137 if ( aNewRect.Top() < aIntersectionRect.Top() )
139 aNewRect.SetBottom( aIntersectionRect.Top() );
141 else if ( aNewRect.Top() < aIntersectionRect.Bottom() )
143 aNewRect.SetTop( aIntersectionRect.Bottom() );
146 nYTemp = aNewRect.getHeight();
147 bMoveAllowed = _nYMov != nYTemp;
148 nXTemp = aNewRect.getWidth();
149 bMoveAllowed = bMoveAllowed && _nXMov != nXTemp;
152 break;
153 default:
154 break;
157 _nXMov = nXTemp;
158 _nYMov = nYTemp;
160 else
161 pOverlappedObj = nullptr;
164 while ( pOverlappedObj && bMoveAllowed );
166 return bMoveAllowed;
169 OViewsWindow::OViewsWindow( OReportWindow* _pReportWindow)
170 : Window( _pReportWindow,WB_DIALOGCONTROL)
171 , m_pParent(_pReportWindow)
172 , m_bInUnmark(false)
174 SetPaintTransparent(true);
175 SetMapMode(MapMode(MapUnit::Map100thMM));
176 m_aColorConfig.AddListener(this);
177 ImplInitSettings();
180 OViewsWindow::~OViewsWindow()
182 disposeOnce();
185 void OViewsWindow::dispose()
187 m_aColorConfig.RemoveListener(this);
188 for (auto& rxSection : m_aSections)
189 rxSection.disposeAndClear();
190 m_aSections.clear();
191 m_pParent.clear();
192 vcl::Window::dispose();
195 void OViewsWindow::impl_resizeSectionWindow(OSectionWindow& _rSectionWindow,Point& _rStartPoint,bool _bSet)
197 const uno::Reference< report::XSection> xSection = _rSectionWindow.getReportSection().getSection();
199 Size aSectionSize = _rSectionWindow.LogicToPixel( Size( 0,xSection->getHeight() ) );
200 aSectionSize.setWidth( getView()->GetTotalWidth() );
202 const sal_Int32 nMinHeight = _rSectionWindow.getStartMarker().getMinHeight();
203 if ( _rSectionWindow.getStartMarker().isCollapsed() || nMinHeight > aSectionSize.Height() )
205 aSectionSize.setHeight( nMinHeight );
207 aSectionSize.AdjustHeight(static_cast<long>(StyleSettings::GetSplitSize() * static_cast<double>(_rSectionWindow.GetMapMode().GetScaleY())) );
209 if ( _bSet )
210 _rSectionWindow.SetPosSizePixel(_rStartPoint,aSectionSize);
212 _rStartPoint.AdjustY(aSectionSize.Height() );
216 void OViewsWindow::resize(const OSectionWindow& _rSectionWindow)
218 bool bSet = false;
219 Point aStartPoint;
220 for (VclPtr<OSectionWindow> const & pSectionWindow : m_aSections)
222 if ( pSectionWindow == &_rSectionWindow )
224 aStartPoint = pSectionWindow->GetPosPixel();
225 bSet = true;
228 if ( bSet )
230 impl_resizeSectionWindow(*pSectionWindow,aStartPoint,bSet);
231 static const InvalidateFlags nIn = InvalidateFlags::Update | InvalidateFlags::Transparent;
232 pSectionWindow->getStartMarker().Invalidate( nIn ); // InvalidateFlags::NoErase |InvalidateFlags::NoChildren| InvalidateFlags::Transparent
233 pSectionWindow->getEndMarker().Invalidate( nIn );
236 m_pParent->notifySizeChanged();
239 void OViewsWindow::Resize()
241 Window::Resize();
242 if ( !m_aSections.empty() )
244 const Point aOffset(m_pParent->getThumbPos());
245 Point aStartPoint(0,-aOffset.Y());
246 for (VclPtr<OSectionWindow> const & pSectionWindow : m_aSections)
248 impl_resizeSectionWindow(*pSectionWindow,aStartPoint,true);
253 void OViewsWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
255 Window::Paint(rRenderContext, rRect);
257 rRenderContext.SetBackground();
258 rRenderContext.SetFillColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
259 rRenderContext.SetTextFillColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
261 Size aOut(GetOutputSizePixel());
262 long nStartWidth = long(REPORT_STARTMARKER_WIDTH * rRenderContext.GetMapMode().GetScaleX());
264 aOut.AdjustWidth( -nStartWidth );
265 aOut = rRenderContext.PixelToLogic(aOut);
267 tools::Rectangle aRect(rRenderContext.PixelToLogic(Point(nStartWidth,0)), aOut);
268 Wallpaper aWall(m_aColorConfig.GetColorValue(::svtools::APPBACKGROUND).nColor);
269 rRenderContext.DrawWallpaper(aRect, aWall);
272 void OViewsWindow::ImplInitSettings()
274 EnableChildTransparentMode();
277 void OViewsWindow::DataChanged( const DataChangedEvent& rDCEvt )
279 Window::DataChanged( rDCEvt );
281 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
282 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
284 ImplInitSettings();
285 Invalidate();
289 void OViewsWindow::addSection(const uno::Reference< report::XSection >& _xSection,const OUString& _sColorEntry,sal_uInt16 _nPosition)
291 VclPtrInstance<OSectionWindow> pSectionWindow(this,_xSection,_sColorEntry);
292 m_aSections.insert(getIteratorAtPos(_nPosition) , TSectionsMap::value_type(pSectionWindow));
293 m_pParent->setMarked(&pSectionWindow->getReportSection().getSectionView(),m_aSections.size() == 1);
294 Resize();
297 void OViewsWindow::removeSection(sal_uInt16 _nPosition)
299 if ( _nPosition < m_aSections.size() )
301 TSectionsMap::iterator aPos = getIteratorAtPos(_nPosition);
302 TSectionsMap::const_iterator aNew = getIteratorAtPos(_nPosition == 0 ? _nPosition+1: _nPosition - 1);
304 m_pParent->getReportView()->UpdatePropertyBrowserDelayed((*aNew)->getReportSection().getSectionView());
306 aPos->disposeAndClear();
307 m_aSections.erase(aPos);
308 Resize();
312 void OViewsWindow::toggleGrid(bool _bVisible)
314 ::std::for_each(m_aSections.begin(),m_aSections.end(),
315 [_bVisible] (const TSectionsMap::value_type& sectionPtr) {
316 sectionPtr->getReportSection().SetGridVisible(_bVisible);
318 ::std::for_each(m_aSections.begin(),m_aSections.end(),
319 [] (const TSectionsMap::value_type& sectionPtr) {
320 sectionPtr->getReportSection().Window::Invalidate(InvalidateFlags::NoErase);
324 sal_Int32 OViewsWindow::getTotalHeight() const
326 return std::accumulate(m_aSections.begin(), m_aSections.end(), sal_Int32(0),
327 [](const sal_Int32 nHeight, const VclPtr<OSectionWindow>& rxSection) { return nHeight + rxSection->GetSizePixel().Height(); });
330 sal_uInt16 OViewsWindow::getSectionCount() const
332 return static_cast<sal_uInt16>(m_aSections.size());
335 void OViewsWindow::SetInsertObj( sal_uInt16 eObj,const OUString& _sShapeType )
337 for (const auto& rxSection : m_aSections)
338 rxSection->getReportSection().getSectionView().SetCurrentObj( eObj, SdrInventor::ReportDesign );
340 m_sShapeType = _sShapeType;
344 void OViewsWindow::SetMode( DlgEdMode eNewMode )
346 ::std::for_each(m_aSections.begin(),m_aSections.end(),
347 [&eNewMode] (const TSectionsMap::value_type& sectionPtr) {
348 sectionPtr->getReportSection().SetMode(eNewMode);
352 bool OViewsWindow::HasSelection() const
354 return std::any_of(m_aSections.begin(), m_aSections.end(),
355 [](const VclPtr<OSectionWindow>& rxSection) { return rxSection->getReportSection().getSectionView().AreObjectsMarked(); });
358 void OViewsWindow::Delete()
360 m_bInUnmark = true;
361 ::std::for_each(m_aSections.begin(),m_aSections.end(),
362 [] (const TSectionsMap::value_type& sectionPtr) {
363 sectionPtr->getReportSection().Delete();
365 m_bInUnmark = false;
368 void OViewsWindow::Copy()
370 uno::Sequence< beans::NamedValue > aAllreadyCopiedObjects;
371 ::std::for_each(m_aSections.begin(),m_aSections.end(),
372 [&aAllreadyCopiedObjects] (const TSectionsMap::value_type& sectionPtr) {
373 sectionPtr->getReportSection().Copy(aAllreadyCopiedObjects);
376 rtl::Reference<OReportExchange> pCopy = new OReportExchange(aAllreadyCopiedObjects);
377 pCopy->CopyToClipboard(this);
380 void OViewsWindow::Paste()
382 TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(this));
383 OReportExchange::TSectionElements aCopies = OReportExchange::extractCopies(aTransferData);
384 if ( aCopies.getLength() > 1 )
385 ::std::for_each(m_aSections.begin(),m_aSections.end(),
386 [&aCopies] (const TSectionsMap::value_type& sectionPtr) {
387 sectionPtr->getReportSection().Paste(aCopies);
389 else
391 OSectionWindow* pMarkedSection = getMarkedSection();
392 if ( pMarkedSection )
393 pMarkedSection->getReportSection().Paste(aCopies,true);
397 OSectionWindow* OViewsWindow::getSectionWindow(const uno::Reference< report::XSection>& _xSection) const
399 OSL_ENSURE(_xSection.is(),"Section is NULL!");
401 OSectionWindow* pSectionWindow = nullptr;
402 for (VclPtr<OSectionWindow> const & p : m_aSections)
404 if (p->getReportSection().getSection() == _xSection)
406 pSectionWindow = p.get();
407 break;
411 return pSectionWindow;
415 OSectionWindow* OViewsWindow::getMarkedSection(NearSectionAccess nsa) const
417 OSectionWindow* pRet = nullptr;
418 TSectionsMap::const_iterator aIter = m_aSections.begin();
419 TSectionsMap::const_iterator aEnd = m_aSections.end();
420 sal_uInt32 nCurrentPosition = 0;
421 for (; aIter != aEnd ; ++aIter)
423 if ( (*aIter)->getStartMarker().isMarked() )
425 if (nsa == CURRENT)
427 pRet = aIter->get();
428 break;
430 else if ( nsa == PREVIOUS )
432 if (nCurrentPosition > 0)
434 pRet = (--aIter)->get();
435 if (pRet == nullptr)
437 pRet = m_aSections.begin()->get();
440 else
442 // if we are out of bounds return the first one
443 pRet = m_aSections.begin()->get();
445 break;
447 else if ( nsa == POST )
449 sal_uInt32 nSize = m_aSections.size();
450 if ((nCurrentPosition + 1) < nSize)
452 pRet = (++aIter)->get();
453 if (pRet == nullptr)
455 pRet = (--aEnd)->get();
458 else
460 // if we are out of bounds return the last one
461 pRet = (--aEnd)->get();
463 break;
466 ++nCurrentPosition;
469 return pRet;
472 void OViewsWindow::markSection(const sal_uInt16 _nPos)
474 if ( _nPos < m_aSections.size() )
475 m_pParent->setMarked(m_aSections[_nPos]->getReportSection().getSection(),true);
478 bool OViewsWindow::IsPasteAllowed() const
480 TransferableDataHelper aTransferData( TransferableDataHelper::CreateFromSystemClipboard( const_cast< OViewsWindow* >( this ) ) );
481 return aTransferData.HasFormat(OReportExchange::getDescriptorFormatId());
484 void OViewsWindow::SelectAll(const sal_uInt16 _nObjectType)
486 m_bInUnmark = true;
487 ::std::for_each(m_aSections.begin(),m_aSections.end(),
488 [&_nObjectType] (const TSectionsMap::value_type& sectionPtr) {
489 sectionPtr->getReportSection().SelectAll(_nObjectType);
491 m_bInUnmark = false;
494 void OViewsWindow::unmarkAllObjects(OSectionView const * _pSectionView)
496 if ( !m_bInUnmark )
498 m_bInUnmark = true;
499 for (const auto& rxSection : m_aSections)
501 if ( &rxSection->getReportSection().getSectionView() != _pSectionView )
503 rxSection->getReportSection().deactivateOle();
504 rxSection->getReportSection().getSectionView().UnmarkAllObj();
507 m_bInUnmark = false;
511 void OViewsWindow::ConfigurationChanged( utl::ConfigurationBroadcaster*, ConfigurationHints)
513 ImplInitSettings();
514 Invalidate();
517 void OViewsWindow::MouseButtonDown( const MouseEvent& rMEvt )
519 if ( rMEvt.IsLeft() )
521 GrabFocus();
522 const uno::Sequence< beans::PropertyValue> aArgs;
523 getView()->getReportView()->getController().executeChecked(SID_SELECT_REPORT,aArgs);
525 Window::MouseButtonDown(rMEvt);
528 void OViewsWindow::showRuler(bool _bShow)
530 ::std::for_each(m_aSections.begin(),m_aSections.end(),
531 [_bShow] (const TSectionsMap::value_type& sectionPtr) {
532 sectionPtr->getStartMarker().showRuler(_bShow);
534 ::std::for_each(m_aSections.begin(),m_aSections.end(),
535 [] (const TSectionsMap::value_type& sectionPtr) {
536 sectionPtr->getStartMarker().Window::Invalidate(InvalidateFlags::NoErase);
540 void OViewsWindow::MouseButtonUp( const MouseEvent& rMEvt )
542 if ( rMEvt.IsLeft() )
544 auto aIter = std::find_if(m_aSections.begin(), m_aSections.end(),
545 [](const VclPtr<OSectionWindow>& rxSection) { return rxSection->getReportSection().getSectionView().AreObjectsMarked(); });
546 if (aIter != m_aSections.end())
548 (*aIter)->getReportSection().MouseButtonUp(rMEvt);
551 // remove special insert mode
552 for (const auto& rxSection : m_aSections)
554 rxSection->getReportSection().getPage()->resetSpecialMode();
559 bool OViewsWindow::handleKeyEvent(const KeyEvent& _rEvent)
561 bool bRet = false;
562 for (const auto& rxSection : m_aSections)
564 if ( rxSection->getStartMarker().isMarked() )
566 bRet = rxSection->getReportSection().handleKeyEvent(_rEvent);
569 return bRet;
572 OViewsWindow::TSectionsMap::iterator OViewsWindow::getIteratorAtPos(sal_uInt16 _nPos)
574 TSectionsMap::iterator aRet = m_aSections.end();
575 if ( _nPos < m_aSections.size() )
576 aRet = m_aSections.begin() + _nPos;
577 return aRet;
580 void OViewsWindow::setMarked(OSectionView const * _pSectionView, bool _bMark)
582 OSL_ENSURE(_pSectionView != nullptr,"SectionView is NULL!");
583 if ( _pSectionView )
584 setMarked(_pSectionView->getReportSection()->getSection(),_bMark);
587 void OViewsWindow::setMarked(const uno::Reference< report::XSection>& _xSection, bool _bMark)
589 for (const auto& rxSection : m_aSections)
591 if ( rxSection->getReportSection().getSection() != _xSection )
593 rxSection->setMarked(false);
595 else if ( rxSection->getStartMarker().isMarked() != _bMark )
597 rxSection->setMarked(_bMark);
602 void OViewsWindow::setMarked(const uno::Sequence< uno::Reference< report::XReportComponent> >& _aShapes, bool _bMark)
604 bool bFirst = true;
605 const uno::Reference< report::XReportComponent>* pIter = _aShapes.getConstArray();
606 const uno::Reference< report::XReportComponent>* pEnd = pIter + _aShapes.getLength();
607 for(;pIter != pEnd;++pIter)
609 const uno::Reference< report::XSection> xSection = (*pIter)->getSection();
610 if ( xSection.is() )
612 if ( bFirst )
614 bFirst = false;
615 m_pParent->setMarked(xSection,_bMark);
617 OSectionWindow* pSectionWindow = getSectionWindow(xSection);
618 if ( pSectionWindow )
620 SvxShape* pShape = SvxShape::getImplementation( *pIter );
621 SdrObject* pObject = pShape ? pShape->GetSdrObject() : nullptr;
622 OSL_ENSURE( pObject, "OViewsWindow::setMarked: no SdrObject for the shape!" );
623 if ( pObject )
624 pSectionWindow->getReportSection().getSectionView().MarkObj( pObject, pSectionWindow->getReportSection().getSectionView().GetSdrPageView(), !_bMark );
630 void OViewsWindow::collectRectangles(TRectangleMap& _rSortRectangles)
632 for (const auto& rxSection : m_aSections)
634 OSectionView& rView = rxSection->getReportSection().getSectionView();
635 if ( rView.AreObjectsMarked() )
637 rView.SortMarkedObjects();
638 const size_t nCount = rView.GetMarkedObjectCount();
639 for (size_t i=0; i < nCount; ++i)
641 const SdrMark* pM = rView.GetSdrMarkByIndex(i);
642 SdrObject* pObj = pM->GetMarkedSdrObj();
643 tools::Rectangle aObjRect(pObj->GetSnapRect());
644 _rSortRectangles.emplace(aObjRect,TRectangleMap::mapped_type(pObj,&rView));
650 void OViewsWindow::collectBoundResizeRect(const TRectangleMap& _rSortRectangles, ControlModification _nControlModification,bool _bAlignAtSection, tools::Rectangle& _rBound, tools::Rectangle& _rResize)
652 bool bOnlyOnce = false;
653 for (const auto& [aObjRect, rObjViewPair] : _rSortRectangles)
655 if ( _rResize.IsEmpty() )
656 _rResize = aObjRect;
657 switch(_nControlModification)
659 case ControlModification::WIDTH_SMALLEST:
660 if ( _rResize.getWidth() > aObjRect.getWidth() )
661 _rResize = aObjRect;
662 break;
663 case ControlModification::HEIGHT_SMALLEST:
664 if ( _rResize.getHeight() > aObjRect.getHeight() )
665 _rResize = aObjRect;
666 break;
667 case ControlModification::WIDTH_GREATEST:
668 if ( _rResize.getWidth() < aObjRect.getWidth() )
669 _rResize = aObjRect;
670 break;
671 case ControlModification::HEIGHT_GREATEST:
672 if ( _rResize.getHeight() < aObjRect.getHeight() )
673 _rResize = aObjRect;
674 break;
675 default: break;
678 SdrObjTransformInfoRec aInfo;
679 const SdrObject* pObj = rObjViewPair.first;
680 pObj->TakeObjInfo(aInfo);
681 bool bHasFixed = !aInfo.bMoveAllowed || pObj->IsMoveProtect();
682 if ( bHasFixed )
683 _rBound.Union(aObjRect);
684 else
686 if ( _bAlignAtSection || _rSortRectangles.size() == 1 )
687 { // align single object at the page
688 if ( ! bOnlyOnce )
690 bOnlyOnce = true;
691 OReportSection* pReportSection = rObjViewPair.second->getReportSection();
692 const uno::Reference< report::XSection>& xSection = pReportSection->getSection();
695 uno::Reference<report::XReportDefinition> xReportDefinition = xSection->getReportDefinition();
696 _rBound.Union(tools::Rectangle(getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN),0,
697 getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width - getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN),
698 xSection->getHeight()));
700 catch(const uno::Exception &){}
703 else
705 _rBound.Union(rObjViewPair.second->GetMarkedObjRect());
711 void OViewsWindow::alignMarkedObjects(ControlModification _nControlModification, bool _bAlignAtSection)
713 if ( _nControlModification == ControlModification::NONE )
714 return;
716 Point aRefPoint;
717 RectangleLess::CompareMode eCompareMode = RectangleLess::POS_LEFT;
718 switch (_nControlModification)
720 case ControlModification::TOP : eCompareMode = RectangleLess::POS_UPPER; break;
721 case ControlModification::BOTTOM: eCompareMode = RectangleLess::POS_DOWN; break;
722 case ControlModification::LEFT : eCompareMode = RectangleLess::POS_LEFT; break;
723 case ControlModification::RIGHT : eCompareMode = RectangleLess::POS_RIGHT; break;
724 case ControlModification::CENTER_HORIZONTAL :
725 case ControlModification::CENTER_VERTICAL :
727 eCompareMode = (ControlModification::CENTER_VERTICAL == _nControlModification) ? RectangleLess::POS_CENTER_VERTICAL : RectangleLess::POS_CENTER_HORIZONTAL;
728 uno::Reference<report::XSection> xSection = (*m_aSections.begin())->getReportSection().getSection();
729 uno::Reference<report::XReportDefinition> xReportDefinition = xSection->getReportDefinition();
730 aRefPoint = tools::Rectangle(getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN),0,
731 getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width - getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN),
732 xSection->getHeight()).Center();
734 break;
735 default: break;
737 RectangleLess aCompare(eCompareMode,aRefPoint);
738 TRectangleMap aSortRectangles(aCompare);
739 collectRectangles(aSortRectangles);
741 tools::Rectangle aBound;
742 tools::Rectangle aResize;
743 collectBoundResizeRect(aSortRectangles,_nControlModification,_bAlignAtSection,aBound,aResize);
745 bool bMove = true;
747 auto aGetFun = ::std::mem_fn(&tools::Rectangle::Bottom);
748 auto aSetFun = ::std::mem_fn(&tools::Rectangle::SetBottom);
749 auto aRefFun = ::std::mem_fn(&tools::Rectangle::Top);
750 TRectangleMap::const_iterator aRectIter = aSortRectangles.begin();
751 TRectangleMap::const_iterator aRectEnd = aSortRectangles.end();
752 for (;aRectIter != aRectEnd ; ++aRectIter)
754 tools::Rectangle aObjRect = aRectIter->first;
755 SdrObject* pObj = aRectIter->second.first;
756 SdrView* pView = aRectIter->second.second;
757 Point aCenter(aBound.Center());
758 SdrObjTransformInfoRec aInfo;
759 pObj->TakeObjInfo(aInfo);
760 if (aInfo.bMoveAllowed && !pObj->IsMoveProtect())
762 long nXMov = 0;
763 long nYMov = 0;
764 long* pValue = &nXMov;
765 switch(_nControlModification)
767 case ControlModification::TOP :
768 aGetFun = ::std::mem_fn(&tools::Rectangle::Top);
769 aSetFun = ::std::mem_fn(&tools::Rectangle::SetTop);
770 aRefFun = ::std::mem_fn(&tools::Rectangle::Bottom);
771 pValue = &nYMov;
772 break;
773 case ControlModification::BOTTOM:
774 // defaults are already set
775 pValue = &nYMov;
776 break;
777 case ControlModification::CENTER_VERTICAL:
778 nYMov = aCenter.Y() - aObjRect.Center().Y();
779 pValue = &nYMov;
780 bMove = false;
781 break;
782 case ControlModification::RIGHT :
783 aGetFun = ::std::mem_fn(&tools::Rectangle::Right);
784 aSetFun = ::std::mem_fn(&tools::Rectangle::SetRight);
785 aRefFun = ::std::mem_fn(&tools::Rectangle::Left);
786 break;
787 case ControlModification::CENTER_HORIZONTAL:
788 nXMov = aCenter.X() - aObjRect.Center().X();
789 bMove = false;
790 break;
791 case ControlModification::LEFT :
792 aGetFun = ::std::mem_fn(&tools::Rectangle::Left);
793 aSetFun = ::std::mem_fn(&tools::Rectangle::SetLeft);
794 aRefFun = ::std::mem_fn(&tools::Rectangle::Right);
795 break;
796 default:
797 bMove = false;
798 break;
800 if ( bMove )
802 tools::Rectangle aTest = aObjRect;
803 aSetFun(&aTest, aGetFun(&aBound));
804 TRectangleMap::const_iterator aInterSectRectIter = aSortRectangles.begin();
805 for (; aInterSectRectIter != aRectIter; ++aInterSectRectIter)
807 if ( pView == aInterSectRectIter->second.second && (dynamic_cast<OUnoObject*>(aInterSectRectIter->second.first) || dynamic_cast<OOle2Obj*>(aInterSectRectIter->second.first)))
809 SdrObject* pPreviousObj = aInterSectRectIter->second.first;
810 tools::Rectangle aIntersectRect = aTest.GetIntersection( pPreviousObj->GetSnapRect());
811 if ( !aIntersectRect.IsEmpty() && (aIntersectRect.Left() != aIntersectRect.Right() && aIntersectRect.Top() != aIntersectRect.Bottom() ) )
813 *pValue = aRefFun(&aIntersectRect) - aGetFun(&aObjRect);
814 break;
818 if ( aInterSectRectIter == aRectIter )
819 *pValue = aGetFun(&aBound) - aGetFun(&aObjRect);
822 if ( lcl_getNewRectSize(aObjRect,nXMov,nYMov,pObj,pView,_nControlModification) )
824 const Size aSize(nXMov,nYMov);
825 pView->AddUndo(pView->GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,aSize));
826 pObj->Move(aSize);
827 aObjRect = pObj->GetSnapRect();
830 // resizing control
831 if ( !aResize.IsEmpty() && aObjRect != aResize )
833 nXMov = aResize.getWidth();
834 nYMov = aResize.getHeight();
835 switch(_nControlModification)
837 case ControlModification::WIDTH_GREATEST:
838 case ControlModification::HEIGHT_GREATEST:
839 if ( _nControlModification == ControlModification::HEIGHT_GREATEST )
840 nXMov = aObjRect.getWidth();
841 else if ( _nControlModification == ControlModification::WIDTH_GREATEST )
842 nYMov = aObjRect.getHeight();
843 lcl_getNewRectSize(aObjRect,nXMov,nYMov,pObj,pView,_nControlModification);
844 [[fallthrough]];
845 case ControlModification::WIDTH_SMALLEST:
846 case ControlModification::HEIGHT_SMALLEST:
847 pView->AddUndo( pView->GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
849 OObjectBase* pObjBase = dynamic_cast<OObjectBase*>(pObj);
850 OSL_ENSURE(pObjBase,"Where comes this object from?");
851 if ( pObjBase )
853 if ( _nControlModification == ControlModification::WIDTH_SMALLEST || _nControlModification == ControlModification::WIDTH_GREATEST )
854 pObjBase->getReportComponent()->setSize(awt::Size(nXMov,aObjRect.getHeight()));
855 else if ( _nControlModification == ControlModification::HEIGHT_GREATEST || _nControlModification == ControlModification::HEIGHT_SMALLEST )
856 pObjBase->getReportComponent()->setSize(awt::Size(aObjRect.getWidth(),nYMov));
859 break;
860 default:
861 break;
865 pView->AdjustMarkHdl();
869 void OViewsWindow::createDefault()
871 OSectionWindow* pMarkedSection = getMarkedSection();
872 if ( pMarkedSection )
873 pMarkedSection->getReportSection().createDefault(m_sShapeType);
876 void OViewsWindow::setGridSnap(bool bOn)
878 for (const auto& rxSection : m_aSections)
880 rxSection->getReportSection().getSectionView().SetGridSnap(bOn);
881 rxSection->getReportSection().Invalidate();
885 void OViewsWindow::setDragStripes(bool bOn)
887 for (const auto& rxSection : m_aSections)
888 rxSection->getReportSection().getSectionView().SetDragStripes(bOn);
891 sal_uInt16 OViewsWindow::getPosition(const OSectionWindow* _pSectionWindow) const
893 auto aIter = std::find_if(m_aSections.begin(), m_aSections.end(),
894 [&_pSectionWindow](const VclPtr<OSectionWindow>& rxSection) { return _pSectionWindow == rxSection.get(); });
895 return static_cast<sal_uInt16>(std::distance(m_aSections.begin(), aIter));
898 OSectionWindow* OViewsWindow::getSectionWindow(const sal_uInt16 _nPos) const
900 OSectionWindow* aReturn = nullptr;
902 if ( _nPos < m_aSections.size() )
903 aReturn = m_aSections[_nPos].get();
905 return aReturn;
908 namespace
910 enum SectionViewAction
912 eEndDragObj,
913 eEndAction,
914 eForceToAnotherPage,
915 eBreakAction
917 class ApplySectionViewAction
919 private:
920 SectionViewAction const m_eAction;
922 public:
923 explicit ApplySectionViewAction()
924 : m_eAction(eEndDragObj)
928 explicit ApplySectionViewAction(SectionViewAction _eAction)
929 : m_eAction(_eAction)
933 void operator() ( const OViewsWindow::TSectionsMap::value_type& _rhs )
935 OSectionView& rView( _rhs->getReportSection().getSectionView() );
936 switch ( m_eAction )
938 case eEndDragObj:
939 rView.EndDragObj();
940 break;
941 case eEndAction:
942 if ( rView.IsAction() )
943 rView.EndAction ( );
944 break;
945 case eForceToAnotherPage:
946 rView.ForceMarkedToAnotherPage();
947 break;
948 case eBreakAction:
949 if ( rView.IsAction() )
950 rView.BrkAction ( );
951 break;
952 // default:
959 void OViewsWindow::BrkAction()
961 EndDragObj_removeInvisibleObjects();
962 ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eBreakAction) );
965 void OViewsWindow::BegDragObj_createInvisibleObjectAtPosition(const tools::Rectangle& _aRect, const OSectionView& _rSection)
967 Point aNewPos(0,0);
969 for (const auto& rxSection : m_aSections)
971 OReportSection& rReportSection = rxSection->getReportSection();
972 rReportSection.getPage()->setSpecialMode();
973 OSectionView& rView = rReportSection.getSectionView();
975 if ( &rView != &_rSection )
977 SdrObject *pNewObj = new SdrUnoObj(
978 rView.getSdrModelFromSdrView(),
979 "com.sun.star.form.component.FixedText");
981 pNewObj->SetLogicRect(_aRect);
982 pNewObj->Move(Size(0, aNewPos.Y()));
983 bool bChanged = rView.GetModel()->IsChanged();
984 rReportSection.getPage()->InsertObject(pNewObj);
985 rView.GetModel()->SetChanged(bChanged);
986 m_aBegDragTempList.push_back(pNewObj);
988 rView.MarkObj( pNewObj, rView.GetSdrPageView() );
990 const long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
991 aNewPos.AdjustY( -nSectionHeight );
995 void OViewsWindow::BegDragObj(const Point& _aPnt, SdrHdl* _pHdl,const OSectionView* _pSection)
997 SAL_INFO(
998 "reportdesign", "Clickpoint X:" << _aPnt.X() << " Y:" << _aPnt.Y());
1000 m_aBegDragTempList.clear();
1002 // Calculate the absolute clickpoint in the views
1003 Point aAbsolutePnt = _aPnt;
1004 for (const auto& rxSection : m_aSections)
1006 OReportSection& rReportSection = rxSection->getReportSection();
1007 OSectionView* pView = &rReportSection.getSectionView();
1008 if (pView == _pSection)
1009 break;
1010 const long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
1011 aAbsolutePnt.AdjustY(nSectionHeight );
1013 m_aDragDelta = Point(SAL_MAX_INT32, SAL_MAX_INT32);
1014 SAL_INFO(
1015 "reportdesign",
1016 "Absolute X:" << aAbsolutePnt.X() << " Y:" << aAbsolutePnt.Y());
1018 // Create drag lines over all viewable Views
1019 // Therefore we need to identify the marked objects
1020 // and create temporary objects on all other views at the same position
1021 // relative to its occurrence.
1023 int nViewCount = 0;
1024 Point aNewObjPos(0,0);
1025 Point aLeftTop = Point(SAL_MAX_INT32, SAL_MAX_INT32);
1026 for (const auto& rxSection : m_aSections)
1028 OReportSection& rReportSection = rxSection->getReportSection();
1030 OSectionView& rView = rReportSection.getSectionView();
1032 if ( rView.AreObjectsMarked() )
1034 const size_t nCount = rView.GetMarkedObjectCount();
1035 for (size_t i=0; i < nCount; ++i)
1037 const SdrMark* pM = rView.GetSdrMarkByIndex(i);
1038 SdrObject* pObj = pM->GetMarkedSdrObj();
1039 if (::std::find(m_aBegDragTempList.begin(),m_aBegDragTempList.end(),pObj) == m_aBegDragTempList.end())
1041 tools::Rectangle aRect( pObj->GetCurrentBoundRect() );
1042 aRect.Move(0, aNewObjPos.Y());
1044 aLeftTop.setX( ::std::min( aRect.Left(), aLeftTop.X() ) );
1045 aLeftTop.setY( ::std::min( aRect.Top(), aLeftTop.Y() ) );
1047 SAL_INFO(
1048 "reportdesign",
1049 "createInvisible X:" << aRect.Left() << " Y:"
1050 << aRect.Top() << " on View #" << nViewCount);
1052 BegDragObj_createInvisibleObjectAtPosition(aRect, rView);
1056 ++nViewCount;
1057 tools::Rectangle aClipRect = rView.GetWorkArea();
1058 aClipRect.SetTop( -aNewObjPos.Y() );
1059 rView.SetWorkArea( aClipRect );
1061 const long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
1062 aNewObjPos.AdjustY(nSectionHeight );
1065 const sal_Int32 nDeltaX = std::abs(aLeftTop.X() - aAbsolutePnt.X());
1066 const sal_Int32 nDeltaY = std::abs(aLeftTop.Y() - aAbsolutePnt.Y());
1067 m_aDragDelta.setX( nDeltaX );
1068 m_aDragDelta.setY( nDeltaY );
1070 Point aNewPos = aAbsolutePnt;
1072 const short nDrgLog = static_cast<short>(PixelToLogic(Size(3,0)).Width());
1073 nViewCount = 0;
1074 for (const auto& rxSection : m_aSections)
1076 OReportSection& rReportSection = rxSection->getReportSection();
1078 SdrHdl* pHdl = _pHdl;
1079 if ( pHdl )
1081 if ( &rReportSection.getSectionView() != _pSection )
1083 const SdrHdlList& rHdlList = rReportSection.getSectionView().GetHdlList();
1084 pHdl = rHdlList.GetHdl(_pHdl->GetKind());
1087 SAL_INFO(
1088 "reportdesign",
1089 "X:" << aNewPos.X() << " Y:" << aNewPos.Y() << " on View#"
1090 << nViewCount++);
1091 rReportSection.getSectionView().BegDragObj(aNewPos, nullptr, pHdl, nDrgLog);
1093 const long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
1094 aNewPos.AdjustY( -nSectionHeight );
1099 void OViewsWindow::ForceMarkedToAnotherPage()
1101 ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eForceToAnotherPage ) );
1104 void OViewsWindow::BegMarkObj(const Point& _aPnt,const OSectionView* _pSection)
1106 bool bAdd = true;
1107 Point aNewPos = _aPnt;
1109 long nLastSectionHeight = 0;
1110 for (const auto& rxSection : m_aSections)
1112 OReportSection& rReportSection = rxSection->getReportSection();
1113 if ( &rReportSection.getSectionView() == _pSection )
1115 bAdd = false;
1116 aNewPos = _aPnt; // 2,2
1118 else if ( bAdd )
1120 const long nSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
1121 aNewPos.AdjustY(nSectionHeight );
1123 else
1125 aNewPos.AdjustY( -nLastSectionHeight );
1127 rReportSection.getSectionView().BegMarkObj ( aNewPos );
1128 nLastSectionHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
1132 OSectionView* OViewsWindow::getSectionRelativeToPosition(const OSectionView* _pSection,Point& _rPnt)
1134 OSectionView* pSection = nullptr;
1135 TSectionsMap::const_iterator aIter = m_aSections.begin();
1136 const TSectionsMap::const_iterator aEnd = m_aSections.end();
1137 aIter = std::find_if(aIter, aEnd, [&_pSection](const VclPtr<OSectionWindow>& rxSection) {
1138 return &rxSection->getReportSection().getSectionView() == _pSection; });
1139 sal_Int32 nCount = static_cast<sal_Int32>(std::distance(m_aSections.cbegin(), aIter));
1140 OSL_ENSURE(aIter != aEnd,"This can never happen!");
1141 if ( _rPnt.Y() < 0 )
1143 if ( nCount )
1144 --aIter;
1145 for (; nCount && (_rPnt.Y() < 0); --nCount)
1147 OReportSection& rReportSection = (*aIter)->getReportSection();
1148 const sal_Int32 nHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
1149 _rPnt.AdjustY(nHeight );
1150 if ( (nCount -1) > 0 && (_rPnt.Y() < 0) )
1151 --aIter;
1153 if ( nCount == 0 )
1154 pSection = &(*m_aSections.begin())->getReportSection().getSectionView();
1155 else
1156 pSection = &(*aIter)->getReportSection().getSectionView();
1158 else
1160 for (; aIter != aEnd; ++aIter)
1162 OReportSection& rReportSection = (*aIter)->getReportSection();
1163 const long nHeight = rReportSection.PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
1164 if ( (_rPnt.Y() - nHeight) < 0 )
1165 break;
1166 _rPnt.AdjustY( -nHeight );
1168 if ( aIter != aEnd )
1169 pSection = &(*aIter)->getReportSection().getSectionView();
1170 else
1171 pSection = &(*(aEnd-1))->getReportSection().getSectionView();
1174 return pSection;
1177 void OViewsWindow::EndDragObj_removeInvisibleObjects()
1179 for (const auto& rxSection : m_aSections)
1181 OReportSection& rReportSection = rxSection->getReportSection();
1182 rReportSection.getPage()->resetSpecialMode();
1186 void OViewsWindow::EndDragObj(bool _bControlKeyPressed, const OSectionView* _pSection, const Point& _aPnt)
1188 const OUString sUndoAction = RptResId(RID_STR_UNDO_CHANGEPOSITION);
1189 const UndoContext aUndoContext( getView()->getReportView()->getController().getUndoManager(), sUndoAction );
1191 Point aNewPos = _aPnt;
1192 OSectionView* pInSection = getSectionRelativeToPosition(_pSection, aNewPos);
1193 if (!_bControlKeyPressed &&
1194 _pSection && !_pSection->IsDragResize() && /* Not in resize mode */
1195 _pSection != pInSection)
1197 EndDragObj_removeInvisibleObjects();
1199 // we need to manipulate the current clickpoint, we subtract the old delta from BeginDrag
1200 aNewPos -= m_aDragDelta;
1202 uno::Sequence< beans::NamedValue > aAllreadyCopiedObjects;
1203 for (const auto& rxSection : m_aSections)
1205 OReportSection& rReportSection = rxSection->getReportSection();
1206 if ( pInSection != &rReportSection.getSectionView() )
1208 rReportSection.getSectionView().BrkAction();
1209 rReportSection.Copy(aAllreadyCopiedObjects,true);
1211 else
1212 pInSection->EndDragObj();
1215 if ( aAllreadyCopiedObjects.hasElements() )
1219 uno::Reference<report::XReportDefinition> xReportDefinition = getView()->getReportView()->getController().getReportDefinition();
1220 const sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_LEFTMARGIN);
1221 const sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(xReportDefinition,PROPERTY_RIGHTMARGIN);
1222 const sal_Int32 nPaperWidth = getStyleProperty<awt::Size>(xReportDefinition,PROPERTY_PAPERSIZE).Width;
1224 if ( aNewPos.X() < nLeftMargin )
1225 aNewPos.setX( nLeftMargin );
1226 if ( aNewPos.Y() < 0 )
1227 aNewPos.setY( 0 );
1229 Point aPrevious;
1230 for (beans::NamedValue const & namedVal : aAllreadyCopiedObjects)
1232 uno::Sequence< uno::Reference<report::XReportComponent> > aClones;
1233 namedVal.Value >>= aClones;
1234 uno::Reference<report::XReportComponent>* pColIter = aClones.getArray();
1235 const uno::Reference<report::XReportComponent>* pColEnd = pColIter + aClones.getLength();
1237 // move the cloned Components to new positions
1238 for (; pColIter != pColEnd; ++pColIter)
1240 uno::Reference< report::XReportComponent> xRC(*pColIter);
1241 aPrevious = VCLPoint(xRC->getPosition());
1242 awt::Size aSize = xRC->getSize();
1244 if ( aNewPos.X() < nLeftMargin )
1246 aNewPos.setX( nLeftMargin );
1248 else if ( (aNewPos.X() + aSize.Width) > (nPaperWidth - nRightMargin) )
1250 aNewPos.setX( nPaperWidth - nRightMargin - aSize.Width );
1252 if ( aNewPos.Y() < 0 )
1254 aNewPos.setY( 0 );
1256 if ( aNewPos.X() < 0 )
1258 aSize.Width += aNewPos.X();
1259 aNewPos.setX( 0 );
1260 xRC->setSize(aSize);
1262 xRC->setPosition(AWTPoint(aNewPos));
1263 if ( (pColIter+1) != pColEnd )
1265 // bring aNewPos to the position of the next object
1266 uno::Reference< report::XReportComponent> xRCNext(*(pColIter + 1),uno::UNO_QUERY);
1267 Point aNextPosition = VCLPoint(xRCNext->getPosition());
1268 aNewPos += aNextPosition - aPrevious;
1273 catch(uno::Exception&)
1276 pInSection->getReportSection()->Paste(aAllreadyCopiedObjects,true);
1279 else
1281 ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction() );
1282 EndDragObj_removeInvisibleObjects();
1284 m_aDragDelta = Point(SAL_MAX_INT32, SAL_MAX_INT32);
1287 void OViewsWindow::EndAction()
1289 ::std::for_each( m_aSections.begin(), m_aSections.end(), ApplySectionViewAction(eEndAction) );
1292 void OViewsWindow::MovAction(const Point& _aPnt,const OSectionView* _pSection, bool _bControlKeySet)
1294 Point aRealMousePos = _aPnt;
1295 Point aCurrentSectionPos;
1296 SAL_INFO(
1297 "reportdesign",
1298 "X:" << aRealMousePos.X() << " Y:" << aRealMousePos.Y());
1300 Point aHdlPos;
1301 SdrHdl* pHdl = _pSection->GetDragHdl();
1302 if ( pHdl )
1304 aHdlPos = pHdl->GetPos();
1307 for (const auto& rxSection : m_aSections)
1309 OReportSection& rReportSection = rxSection->getReportSection();
1310 if ( &rReportSection.getSectionView() == _pSection )
1311 break;
1312 const long nSectionHeight = rxSection->PixelToLogic(rReportSection.GetOutputSizePixel()).Height();
1313 aCurrentSectionPos.AdjustY(nSectionHeight );
1315 aRealMousePos += aCurrentSectionPos;
1317 // If control key is pressed the work area is limited to the section with the current selection.
1318 Point aPosForWorkArea(0,0);
1319 for (const auto& rxSection : m_aSections)
1321 OReportSection& rReportSection = rxSection->getReportSection();
1322 OSectionView& rView = rReportSection.getSectionView();
1323 const long nSectionHeight = rxSection->PixelToLogic(rxSection->GetOutputSizePixel()).Height();
1325 if (_bControlKeySet)
1327 tools::Rectangle aClipRect = rView.GetWorkArea();
1328 aClipRect.SetTop( aCurrentSectionPos.Y() - aPosForWorkArea.Y() );
1329 aClipRect.SetBottom( aClipRect.Top() + nSectionHeight );
1330 rView.SetWorkArea( aClipRect );
1332 else
1334 tools::Rectangle aClipRect = rView.GetWorkArea();
1335 aClipRect.SetTop( -aPosForWorkArea.Y() );
1336 rView.SetWorkArea( aClipRect );
1338 aPosForWorkArea.AdjustY(nSectionHeight );
1342 for (const auto& rxSection : m_aSections)
1344 OReportSection& rReportSection = rxSection->getReportSection();
1345 SdrHdl* pCurrentHdl = rReportSection.getSectionView().GetDragHdl();
1346 if ( pCurrentHdl && aRealMousePos.Y() > 0 )
1347 aRealMousePos = _aPnt + pCurrentHdl->GetPos() - aHdlPos;
1348 rReportSection.getSectionView().MovAction ( aRealMousePos );
1349 const long nSectionHeight = rxSection->PixelToLogic(rxSection->GetOutputSizePixel()).Height();
1350 aRealMousePos.AdjustY( -nSectionHeight );
1354 bool OViewsWindow::IsAction() const
1356 return std::any_of(m_aSections.begin(), m_aSections.end(),
1357 [](const VclPtr<OSectionWindow>& rxSection) { return rxSection->getReportSection().getSectionView().IsAction(); });
1360 bool OViewsWindow::IsDragObj() const
1362 return std::any_of(m_aSections.begin(), m_aSections.end(),
1363 [](const VclPtr<OSectionWindow>& rxSection) { return rxSection->getReportSection().getSectionView().IsAction(); });
1366 sal_uInt32 OViewsWindow::getMarkedObjectCount() const
1368 return std::accumulate(m_aSections.begin(), m_aSections.end(), sal_uInt32(0),
1369 [](const sal_uInt32 nCount, const VclPtr<OSectionWindow>& rxSection) {
1370 return nCount + static_cast<sal_uInt32>(rxSection->getReportSection().getSectionView().GetMarkedObjectCount()); });
1373 void OViewsWindow::handleKey(const vcl::KeyCode& _rCode)
1375 const sal_uInt16 nCode = _rCode.GetCode();
1376 if ( _rCode.IsMod1() )
1378 // scroll page
1379 OScrollWindowHelper* pScrollWindow = getView()->getScrollWindow();
1380 ScrollBar& rScrollBar = ( nCode == KEY_LEFT || nCode == KEY_RIGHT ) ? pScrollWindow->GetHScroll() : pScrollWindow->GetVScroll();
1381 if ( rScrollBar.IsVisible() )
1382 rScrollBar.DoScrollAction(( nCode == KEY_RIGHT || nCode == KEY_UP ) ? ScrollType::LineUp : ScrollType::LineDown );
1383 return;
1386 for (const auto& rxSection : m_aSections)
1388 OReportSection& rReportSection = rxSection->getReportSection();
1389 long nX = 0;
1390 long nY = 0;
1392 if ( nCode == KEY_UP )
1393 nY = -1;
1394 else if ( nCode == KEY_DOWN )
1395 nY = 1;
1396 else if ( nCode == KEY_LEFT )
1397 nX = -1;
1398 else if ( nCode == KEY_RIGHT )
1399 nX = 1;
1401 if ( rReportSection.getSectionView().AreObjectsMarked() )
1403 if ( _rCode.IsMod2() )
1405 // move in 1 pixel distance
1406 const Size aPixelSize = rReportSection.PixelToLogic( Size( 1, 1 ) );
1407 nX *= aPixelSize.Width();
1408 nY *= aPixelSize.Height();
1410 else
1412 // move in 1 mm distance
1413 nX *= DEFAUL_MOVE_SIZE;
1414 nY *= DEFAUL_MOVE_SIZE;
1417 OSectionView& rView = rReportSection.getSectionView();
1418 const SdrHdlList& rHdlList = rView.GetHdlList();
1419 SdrHdl* pHdl = rHdlList.GetFocusHdl();
1421 if ( pHdl == nullptr )
1423 // no handle selected
1424 if ( rView.IsMoveAllowed() )
1426 // restrict movement to work area
1427 tools::Rectangle rWorkArea = rView.GetWorkArea();
1428 rWorkArea.AdjustRight( 1 );
1430 if ( !rWorkArea.IsEmpty() )
1432 if ( rWorkArea.Top() < 0 )
1433 rWorkArea.SetTop( 0 );
1434 tools::Rectangle aMarkRect( rView.GetMarkedObjRect() );
1435 aMarkRect.Move( nX, nY );
1437 if ( !rWorkArea.IsInside( aMarkRect ) )
1439 if ( aMarkRect.Left() < rWorkArea.Left() )
1440 nX += rWorkArea.Left() - aMarkRect.Left();
1442 if ( aMarkRect.Right() > rWorkArea.Right() )
1443 nX -= aMarkRect.Right() - rWorkArea.Right();
1445 if ( aMarkRect.Top() < rWorkArea.Top() )
1446 nY += rWorkArea.Top() - aMarkRect.Top();
1448 if ( aMarkRect.Bottom() > rWorkArea.Bottom() )
1449 nY -= aMarkRect.Bottom() - rWorkArea.Bottom();
1451 bool bCheck = false;
1452 const SdrMarkList& rMarkList = rView.GetMarkedObjectList();
1453 for (size_t i = 0; !bCheck && i < rMarkList.GetMarkCount(); ++i )
1455 SdrMark* pMark = rMarkList.GetMark(i);
1456 bCheck = dynamic_cast<OUnoObject*>(pMark->GetMarkedSdrObj()) != nullptr|| dynamic_cast<OOle2Obj*>(pMark->GetMarkedSdrObj());
1460 if ( bCheck )
1462 SdrObject* pOverlapped = isOver(aMarkRect,*rReportSection.getPage(),rView);
1463 if ( pOverlapped )
1467 tools::Rectangle aOver = pOverlapped->GetLastBoundRect();
1468 Point aPos;
1469 if ( nCode == KEY_UP )
1471 aPos.setX( aMarkRect.Left() );
1472 aPos.setY( aOver.Top() - aMarkRect.getHeight() );
1473 nY += (aPos.Y() - aMarkRect.Top());
1475 else if ( nCode == KEY_DOWN )
1477 aPos.setX( aMarkRect.Left() );
1478 aPos.setY( aOver.Bottom() );
1479 nY += (aPos.Y() - aMarkRect.Top());
1481 else if ( nCode == KEY_LEFT )
1483 aPos.setX( aOver.Left() - aMarkRect.getWidth() );
1484 aPos.setY( aMarkRect.Top() );
1485 nX += (aPos.X() - aMarkRect.Left());
1487 else if ( nCode == KEY_RIGHT )
1489 aPos.setX( aOver.Right() );
1490 aPos.setY( aMarkRect.Top() );
1491 nX += (aPos.X() - aMarkRect.Left());
1494 aMarkRect.SetPos(aPos);
1495 if ( !rWorkArea.IsInside( aMarkRect ) )
1497 break;
1499 pOverlapped = isOver(aMarkRect,*rReportSection.getPage(),rView);
1501 while(pOverlapped != nullptr);
1502 if (pOverlapped != nullptr)
1503 break;
1508 if ( nX != 0 || nY != 0 )
1510 rView.MoveAllMarked( Size( nX, nY ) );
1511 rView.MakeVisible( rView.GetAllMarkedRect(), rReportSection);
1515 else // pHdl != nullptr
1517 // move the handle
1518 if (nX || nY)
1520 const Point aStartPoint( pHdl->GetPos() );
1521 const Point aEndPoint( pHdl->GetPos() + Point( nX, nY ) );
1522 const SdrDragStat& rDragStat = rView.GetDragStat();
1524 // start dragging
1525 rView.BegDragObj( aStartPoint, nullptr, pHdl, 0 );
1527 if ( rView.IsDragObj() )
1529 const bool bWasNoSnap = rDragStat.IsNoSnap();
1530 const bool bWasSnapEnabled = rView.IsSnapEnabled();
1532 // switch snapping off
1533 if ( !bWasNoSnap )
1534 const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
1535 if ( bWasSnapEnabled )
1536 rView.SetSnapEnabled( false );
1538 tools::Rectangle aNewRect;
1539 bool bCheck = false;
1540 const SdrMarkList& rMarkList = rView.GetMarkedObjectList();
1541 for (size_t i = 0; !bCheck && i < rMarkList.GetMarkCount(); ++i )
1543 SdrMark* pMark = rMarkList.GetMark(i);
1544 bCheck = dynamic_cast<OUnoObject*>(pMark->GetMarkedSdrObj()) != nullptr || dynamic_cast<OOle2Obj*>(pMark->GetMarkedSdrObj()) != nullptr;
1545 if ( bCheck )
1546 aNewRect.Union(pMark->GetMarkedSdrObj()->GetLastBoundRect());
1549 switch(pHdl->GetKind())
1551 case SdrHdlKind::Left:
1552 case SdrHdlKind::UpperLeft:
1553 case SdrHdlKind::LowerLeft:
1554 case SdrHdlKind::Upper:
1555 aNewRect.AdjustLeft(nX );
1556 aNewRect.AdjustTop(nY );
1557 break;
1558 case SdrHdlKind::UpperRight:
1559 case SdrHdlKind::Right:
1560 case SdrHdlKind::LowerRight:
1561 case SdrHdlKind::Lower:
1562 aNewRect.setWidth(aNewRect.getWidth() + nX);
1563 aNewRect.setHeight(aNewRect.getHeight() + nY);
1564 break;
1565 default:
1566 break;
1568 if ( !(bCheck && isOver(aNewRect,*rReportSection.getPage(),rView)) )
1569 rView.MovAction(aEndPoint);
1570 rView.EndDragObj();
1572 // restore snap
1573 if ( !bWasNoSnap )
1574 const_cast<SdrDragStat&>(rDragStat).SetNoSnap( bWasNoSnap );
1575 if ( bWasSnapEnabled )
1576 rView.SetSnapEnabled( bWasSnapEnabled );
1579 // make moved handle visible
1580 const tools::Rectangle aVisRect( aEndPoint - Point( DEFAUL_MOVE_SIZE, DEFAUL_MOVE_SIZE ), Size( 200, 200 ) );
1581 rView.MakeVisible( aVisRect, rReportSection);
1584 rView.AdjustMarkHdl();
1589 void OViewsWindow::stopScrollTimer()
1591 ::std::for_each(m_aSections.begin(),m_aSections.end(),
1592 [] (const TSectionsMap::value_type& sectionPtr) {
1593 sectionPtr->getReportSection().stopScrollTimer();
1597 void OViewsWindow::fillCollapsedSections(::std::vector<sal_uInt16>& _rCollapsedPositions) const
1599 sal_uInt16 i = 0;
1600 for (const auto& rxSection : m_aSections)
1602 if ( rxSection->getStartMarker().isCollapsed() )
1603 _rCollapsedPositions.push_back(i);
1604 ++i;
1608 void OViewsWindow::collapseSections(const uno::Sequence< beans::PropertyValue>& _aCollpasedSections)
1610 const beans::PropertyValue* pIter = _aCollpasedSections.getConstArray();
1611 const beans::PropertyValue* pEnd = pIter + _aCollpasedSections.getLength();
1612 for (; pIter != pEnd; ++pIter)
1614 sal_uInt16 nPos = sal_uInt16(-1);
1615 if ( (pIter->Value >>= nPos) && nPos < m_aSections.size() )
1617 m_aSections[nPos]->setCollapsed(true);
1622 void OViewsWindow::zoom(const Fraction& _aZoom)
1624 const MapMode& aMapMode = GetMapMode();
1626 Fraction aStartWidth(long(REPORT_STARTMARKER_WIDTH));
1627 if ( _aZoom < aMapMode.GetScaleX() )
1628 aStartWidth *= aMapMode.GetScaleX();
1629 else
1630 aStartWidth *= _aZoom;
1632 setZoomFactor(_aZoom,*this);
1634 for (const auto& rxSection : m_aSections)
1636 rxSection->zoom(_aZoom);
1639 Resize();
1641 Size aOut = GetOutputSizePixel();
1642 aOut.setWidth( long(aStartWidth) );
1643 aOut = PixelToLogic(aOut);
1645 tools::Rectangle aRect(PixelToLogic(Point(0,0)),aOut);
1646 Invalidate(aRect, InvalidateFlags::NoChildren);
1649 void OViewsWindow::scrollChildren(const Point& _aThumbPos)
1651 const Point aPos(PixelToLogic(_aThumbPos));
1653 MapMode aMapMode = GetMapMode();
1654 const Point aOld = aMapMode.GetOrigin();
1655 aMapMode.SetOrigin(m_pParent->GetMapMode().GetOrigin());
1657 const Point aPosY(m_pParent->PixelToLogic(_aThumbPos,aMapMode));
1659 aMapMode.SetOrigin( Point(aOld.X() , - aPosY.Y()));
1660 SetMapMode( aMapMode );
1661 Scroll(0, -( aOld.Y() + aPosY.Y()),ScrollFlags::Children);
1664 for (const auto& rxSection : m_aSections)
1666 rxSection->scrollChildren(aPos.X());
1670 void OViewsWindow::fillControlModelSelection(::std::vector< uno::Reference< uno::XInterface > >& _rSelection) const
1672 for (const auto& rxSection : m_aSections)
1674 rxSection->getReportSection().fillControlModelSelection(_rSelection);
1678 } // rptui
1681 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */