/* -*- 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 "tablehandles.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sdr::table { namespace { class OverlayTableEdge : public sdr::overlay::OverlayObject { protected: basegfx::B2DPolyPolygon maPolyPolygon; bool mbVisible; // geometry creation for OverlayObject virtual drawinglayer::primitive2d::Primitive2DContainer createOverlayObjectPrimitive2DSequence() override; public: OverlayTableEdge( const basegfx::B2DPolyPolygon& rPolyPolygon, bool bVisible ); }; } TableEdgeHdl::TableEdgeHdl( const Point& rPnt, bool bHorizontal, sal_Int32 nMin, sal_Int32 nMax, sal_Int32 nEdges ) : SdrHdl( rPnt, SdrHdlKind::User ) , mbHorizontal( bHorizontal ) , mnMin( nMin ) , mnMax( nMax ) , maEdges(nEdges) { } void TableEdgeHdl::SetEdge( sal_Int32 nEdge, sal_Int32 nStart, sal_Int32 nEnd, TableEdgeState eState ) { if( (nEdge >= 0) && (nEdge <= sal::static_int_cast(maEdges.size())) ) { maEdges[nEdge].mnStart = nStart; maEdges[nEdge].mnEnd = nEnd; maEdges[nEdge].meState = eState; } else { OSL_FAIL( "sdr::table::TableEdgeHdl::SetEdge(), invalid edge!" ); } } PointerStyle TableEdgeHdl::GetPointer() const { if( mbHorizontal ) return PointerStyle::VSplit; else return PointerStyle::HSplit; } sal_Int32 TableEdgeHdl::GetValidDragOffset( const SdrDragStat& rDrag ) const { return std::clamp( static_cast(mbHorizontal ? rDrag.GetDY() : rDrag.GetDX()), mnMin, mnMax ); } basegfx::B2DPolyPolygon TableEdgeHdl::getSpecialDragPoly(const SdrDragStat& rDrag) const { basegfx::B2DPolyPolygon aVisible; basegfx::B2DPolyPolygon aInvisible; // create and return visible and non-visible parts for drag getPolyPolygon(aVisible, aInvisible, &rDrag); aVisible.append(aInvisible); return aVisible; } void TableEdgeHdl::getPolyPolygon(basegfx::B2DPolyPolygon& rVisible, basegfx::B2DPolyPolygon& rInvisible, const SdrDragStat* pDrag) const { // changed method to create visible and invisible partial polygons in one run in // separate PolyPolygons; both kinds are used basegfx::B2DPoint aOffset(aPos.X(), aPos.Y()); rVisible.clear(); rInvisible.clear(); if( pDrag ) { basegfx::Axis2D eDragAxis = mbHorizontal ? basegfx::Axis2D::Y : basegfx::Axis2D::X; aOffset.set(eDragAxis, aOffset.get(eDragAxis) + GetValidDragOffset( *pDrag )); } basegfx::B2DPoint aStart(aOffset), aEnd(aOffset); basegfx::Axis2D eAxis = mbHorizontal ? basegfx::Axis2D::X : basegfx::Axis2D::Y; for( const TableEdge& aEdge : maEdges ) { aStart.set(eAxis, aOffset.get(eAxis) + aEdge.mnStart); aEnd.set(eAxis, aOffset.get(eAxis) + aEdge.mnEnd); basegfx::B2DPolygon aPolygon; aPolygon.append( aStart ); aPolygon.append( aEnd ); if(aEdge.meState == Visible) { rVisible.append(aPolygon); } else { rInvisible.append(aPolygon); } } } void TableEdgeHdl::CreateB2dIAObject() { GetRidOfIAObject(); if(!pHdlList || !pHdlList->GetView() || pHdlList->GetView()->areMarkHandlesHidden()) return; SdrMarkView* pView = pHdlList->GetView(); SdrPageView* pPageView = pView->GetSdrPageView(); if(!pPageView) return; basegfx::B2DPolyPolygon aVisible; basegfx::B2DPolyPolygon aInvisible; // get visible and invisible parts getPolyPolygon(aVisible, aInvisible, nullptr); if(!(aVisible.count() || aInvisible.count())) return; for(sal_uInt32 nWindow = 0; nWindow < pPageView->PageWindowCount(); nWindow++) { const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(nWindow); if(rPageWindow.GetPaintWindow().OutputToWindow()) { const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); if (xManager.is()) { if(aVisible.count()) { // create overlay object for visible parts std::unique_ptr pOverlayObject(new OverlayTableEdge(aVisible, true)); // OVERLAYMANAGER insertNewlyCreatedOverlayObjectForSdrHdl( std::move(pOverlayObject), rPageWindow.GetObjectContact(), *xManager); } if(aInvisible.count()) { // also create overlay object for invisible parts to allow // a standard HitTest using the primitives from that overlay object // (see OverlayTableEdge implementation) std::unique_ptr pOverlayObject(new OverlayTableEdge(aInvisible, false)); // OVERLAYMANAGER insertNewlyCreatedOverlayObjectForSdrHdl( std::move(pOverlayObject), rPageWindow.GetObjectContact(), *xManager); } } } } } OverlayTableEdge::OverlayTableEdge( const basegfx::B2DPolyPolygon& rPolyPolygon, bool bVisible ) : OverlayObject(COL_GRAY) , maPolyPolygon( rPolyPolygon ) , mbVisible(bVisible) { } drawinglayer::primitive2d::Primitive2DContainer OverlayTableEdge::createOverlayObjectPrimitive2DSequence() { drawinglayer::primitive2d::Primitive2DContainer aRetval; if(maPolyPolygon.count()) { // Discussed with CL. Currently i will leave the transparence out since this // a little bit expensive. We may check the look with drag polygons later const drawinglayer::primitive2d::Primitive2DReference aReference( new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D( maPolyPolygon, getBaseColor().getBColor())); if(mbVisible) { // visible, just return as sequence aRetval = drawinglayer::primitive2d::Primitive2DContainer { aReference }; } else { // embed in HiddenGeometryPrimitive2D to support HitTest of this invisible // overlay object drawinglayer::primitive2d::Primitive2DContainer aSequence { aReference }; const drawinglayer::primitive2d::Primitive2DReference aNewReference( new drawinglayer::primitive2d::HiddenGeometryPrimitive2D(std::move(aSequence))); aRetval = drawinglayer::primitive2d::Primitive2DContainer { aNewReference }; } } return aRetval; } TableBorderHdl::TableBorderHdl( const tools::Rectangle& rRect, bool bAnimate) : SdrHdl(rRect.TopLeft(), SdrHdlKind::Move), maRectangle(rRect), mbAnimate(bAnimate) { } PointerStyle TableBorderHdl::GetPointer() const { return PointerStyle::Move; } // create marker for this kind void TableBorderHdl::CreateB2dIAObject() { GetRidOfIAObject(); if (!pHdlList || !pHdlList->GetView() || pHdlList->GetView()->areMarkHandlesHidden()) return; SdrMarkView* pView = pHdlList->GetView(); SdrPageView* pPageView = pView->GetSdrPageView(); if (!pPageView) return; for(sal_uInt32 nWindow = 0; nWindow < pPageView->PageWindowCount(); nWindow++) { const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(nWindow); if (rPageWindow.GetPaintWindow().OutputToWindow()) { const rtl::Reference& xManager = rPageWindow.GetOverlayManager(); if (xManager.is()) { const basegfx::B2DRange aRange = vcl::unotools::b2DRectangleFromRectangle(maRectangle); const Color aHilightColor(SvtOptionsDrawinglayer::getHilightColor()); const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01); // make animation dependent from text edit active, because for tables // this handle is also used when text edit *is* active for it. This // interferes too much concerning repaint stuff (at least as long as // text edit is not yet on the overlay) OutputDevice& rOutDev = rPageWindow.GetPaintWindow().GetOutputDevice(); float fScaleFactor = rOutDev.GetDPIScaleFactor(); double fWidth = fScaleFactor * 6.0; std::unique_ptr pOverlayObject( new sdr::overlay::OverlayRectangle(aRange.getMinimum(), aRange.getMaximum(), aHilightColor, fTransparence, fWidth, 0.0, 0.0, mbAnimate)); // OVERLAYMANAGER insertNewlyCreatedOverlayObjectForSdrHdl( std::move(pOverlayObject), rPageWindow.GetObjectContact(), *xManager); } } } } } // end of namespace sdr::table /* vim:set shiftwidth=4 softtabstop=4 expandtab: */