summaryrefslogtreecommitdiff
path: root/svx
diff options
context:
space:
mode:
authorMarco Cecchetti <mrcekets@gmail.com>2019-03-26 13:17:08 +0100
committerMarco Cecchetti <mrcekets@gmail.com>2019-05-20 10:35:49 +0200
commit4a7a37f942b932eb14cd0c5e9e72669f3a04e6a4 (patch)
treeac8a23d703f20583a2c3ef3db1f39c08db40ed64 /svx
parente9e57c61a747f0f5859b579ff4f2bcaa53eacd79 (diff)
lok: chart: constrained dragging of pie segments
The extra information for the graphic selection is now formatted according to JSON syntax so that is easier to parse. Information for allowing the client to performa constrained dragging of a pie segment is appended when needed to the graphic selection message. A polygon approximation of the pie segment in svg format is attached too to the graphic selection message. Core now is able to handle a specific msg from the client with data about the new pie segment offset computed by the client on drag end. This information is dispatched by the chart controller to a specific method: executeDispatch_LOKPieSegmentDragging. Change-Id: I42e7742508fa3a453383bf7b95e47df169f24834 Reviewed-on: https://gerrit.libreoffice.org/70568 Reviewed-by: Marco Cecchetti <mrcekets@gmail.com> Tested-by: Marco Cecchetti <mrcekets@gmail.com>
Diffstat (limited to 'svx')
-rw-r--r--svx/source/svdraw/svdmrkv.cxx180
1 files changed, 167 insertions, 13 deletions
diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index 8a41e521d480..e95195cbd6ea 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -60,6 +60,8 @@
#include <sfx2/lokcharthelper.hxx>
#include <sfx2/viewsh.hxx>
+#include <array>
+
#include <com/sun/star/view/XSelectionSupplier.hpp>
using namespace com::sun::star;
@@ -609,6 +611,59 @@ bool SdrMarkView::ImpIsFrameHandles() const
return bFrmHdl;
}
+namespace
+{
+OUString lcl_getDragMethodServiceName( const OUString& rCID )
+{
+ OUString aRet;
+
+ sal_Int32 nIndexStart = rCID.indexOf( "DragMethod=" );
+ if( nIndexStart != -1 )
+ {
+ nIndexStart = rCID.indexOf( '=', nIndexStart );
+ if( nIndexStart != -1 )
+ {
+ nIndexStart++;
+ sal_Int32 nNextSlash = rCID.indexOf( '/', nIndexStart );
+ if( nNextSlash != -1 )
+ {
+ sal_Int32 nIndexEnd = nNextSlash;
+ sal_Int32 nNextColon = rCID.indexOf( ':', nIndexStart );
+ if( nNextColon < nNextSlash )
+ nIndexEnd = nNextColon;
+ aRet = rCID.copy(nIndexStart,nIndexEnd-nIndexStart);
+ }
+ }
+ }
+ return aRet;
+}
+
+OUString lcl_getDragParameterString( const OUString& rCID )
+{
+ OUString aRet;
+
+ sal_Int32 nIndexStart = rCID.indexOf( "DragParameter=" );
+ if( nIndexStart != -1 )
+ {
+ nIndexStart = rCID.indexOf( '=', nIndexStart );
+ if( nIndexStart != -1 )
+ {
+ nIndexStart++;
+ sal_Int32 nNextSlash = rCID.indexOf( '/', nIndexStart );
+ if( nNextSlash != -1 )
+ {
+ sal_Int32 nIndexEnd = nNextSlash;
+ sal_Int32 nNextColon = rCID.indexOf( ':', nIndexStart );
+ if( nNextColon < nNextSlash )
+ nIndexEnd = nNextColon;
+ aRet = rCID.copy(nIndexStart,nIndexEnd-nIndexStart);
+ }
+ }
+ }
+ return aRet;
+}
+} // anonymous namespace
+
void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell)
{
// remember old focus handle values to search for it again
@@ -799,11 +854,10 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell)
sSelection += OString(", ") + OString::number(nRotAngle);
- OString sProperties;
-
+ OStringBuffer aExtraInfo;
if (bWriterGraphic)
{
- sProperties = "{ WriterGraphic=true }";
+ aExtraInfo.append("{ \"isWriterGraphic\": true }");
}
else if (bIsChart)
{
@@ -817,27 +871,127 @@ void SdrMarkView::SetMarkHandles(SfxViewShell* pOtherShell)
if (aSel >>= aValue)
{
OString aObjectCID(aValue.getStr(), aValue.getLength(), osl_getThreadTextEncoding());
- sProperties += "{ ";
- const std::vector<OString> aProps{"Draggable=", "Resizable=", "Rotatable="};
+ aExtraInfo.append("{ ");
+ const std::vector<OString> aProps{"Draggable", "Resizable", "Rotatable"};
for (const auto& rProp: aProps)
{
sal_Int32 nPos = aObjectCID.indexOf(rProp);
if (nPos == -1) continue;
- nPos += rProp.getLength();
- if (sProperties.getLength() > 2)
- sProperties += ", ";
- sProperties += rProp;
- sProperties += OString::boolean(aObjectCID[nPos] == '1');
+ nPos += rProp.getLength() + 1; // '='
+ if (aExtraInfo.getLength() > 2) // != "{ "
+ aExtraInfo.append(", ");
+ aExtraInfo.append("\"is");
+ aExtraInfo.append(rProp);
+ aExtraInfo.append("\": ");
+ aExtraInfo.append(OString::boolean(aObjectCID[nPos] == '1'));
+ }
+
+ OUString sDragMethod = lcl_getDragMethodServiceName(aValue);
+ if (sDragMethod == "PieSegmentDragging")
+ {
+ // old initial offset inside the CID returned by xSelectionSupplier->getSelection()
+ // after a pie segment dragging; using SdrObject::GetName for getting a CID with the updated offset
+ aValue = pO->GetName();
+ OUString sDragParameters = lcl_getDragParameterString(aValue);
+ if (!sDragParameters.isEmpty())
+ {
+ aExtraInfo.append(", \"dragInfo\": { ");
+ aExtraInfo.append("\"dragMethod\": \"");
+ aExtraInfo.append(sDragMethod.toUtf8());
+ aExtraInfo.append("\"");
+
+ OUString sParam;
+ sal_Int32 nStartIndex = 0;
+ std::array<int, 5> aDragParameters;
+ for (auto& rParam : aDragParameters)
+ {
+ sParam = sDragParameters.getToken(0, ',', nStartIndex);
+ if (sParam.isEmpty())
+ break;
+ rParam = sParam.toInt32();
+ }
+
+ // initial offset in %
+ if (aDragParameters[0] < 0)
+ aDragParameters[0] = 0;
+ else if (aDragParameters[0] > 100)
+ aDragParameters[0] = 100;
+
+ aExtraInfo.append(", \"initialOffset\": ");
+ aExtraInfo.append(OString::number(aDragParameters[0]));
+
+ // drag direction constraint
+ Point aMinPos(aDragParameters[1], aDragParameters[2]);
+ Point aMaxPos(aDragParameters[3], aDragParameters[4]);
+ Point aDragDirection = aMaxPos - aMinPos;
+ aDragDirection = OutputDevice::LogicToLogic(aDragDirection, MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip));
+
+ aExtraInfo.append(", \"dragDirection\": [");
+ aExtraInfo.append(aDragDirection.toString());
+ aExtraInfo.append("]");
+
+ // polygon approximating the pie segment or donut segment
+ if (pO->GetObjIdentifier() == OBJ_PATHFILL)
+ {
+ const basegfx::B2DPolyPolygon aPolyPolygon(pO->TakeXorPoly());
+ if (aPolyPolygon.count() == 1)
+ {
+ const basegfx::B2DPolygon aPolygon = aPolyPolygon.getB2DPolygon(0);
+ if (sal_uInt32 nPolySize = aPolygon.count())
+ {
+ const vcl::Window* pWin = dynamic_cast<const vcl::Window*>(this->GetFirstOutputDevice());
+ const vcl::Window* pViewShellWindow = pViewShell->GetEditWindowForActiveOLEObj();
+ if (pWin && pViewShellWindow && pViewShellWindow->IsAncestorOf(*pWin))
+ {
+ // in the following code escaping sequences used inside raw literal strings
+ // are for making them understandable by the JSON parser
+
+ Point aOffsetPx = pWin->GetOffsetPixelFrom(*pViewShellWindow);
+ Point aLogicOffset = pWin->PixelToLogic(aOffsetPx);
+ OString sPolygonElem("<polygon points=\\\"");
+ for (sal_uInt32 nIndex = 0; nIndex < nPolySize; ++nIndex)
+ {
+ const basegfx::B2DPoint aB2Point = aPolygon.getB2DPoint(nIndex);
+ Point aPoint(aB2Point.getX(), aB2Point.getY());
+ aPoint.Move(aLogicOffset.getX(), aLogicOffset.getY());
+ if (nIndex > 0)
+ sPolygonElem += " ";
+ sPolygonElem += aPoint.toString();
+ }
+ sPolygonElem += R"elem(\" style=\"stroke: none; fill: rgb(114,159,207); fill-opacity: 0.8\"/>)elem";
+
+ aSelection = OutputDevice::LogicToLogic(aSelection, MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM));
+
+ OString sSVGElem(R"elem(<svg version=\"1.2\" width=\")elem");
+ sSVGElem += OString::number(aSelection.GetWidth() / 100.0);
+ sSVGElem += R"elem(mm\" height=\")elem";
+ sSVGElem += OString::number(aSelection.GetHeight() / 100.0);
+ sSVGElem += R"elem(mm\" viewBox=\")elem";
+ sSVGElem += aSelection.toString();
+ sSVGElem += R"elem(\" preserveAspectRatio=\"xMidYMid\" xmlns=\"http://www.w3.org/2000/svg\">)elem";
+
+ aExtraInfo.append(", \"svg\": \"");
+ aExtraInfo.append(sSVGElem);
+ aExtraInfo.append("\\n ");
+ aExtraInfo.append(sPolygonElem);
+ aExtraInfo.append("\\n</svg>");
+ aExtraInfo.append("\""); // svg
+ }
+ }
+ }
+ }
+ aExtraInfo.append("}"); // dragInfo
+ }
}
- sProperties += " }";
+ aExtraInfo.append(" }");
}
}
}
- if (!sProperties.isEmpty())
+ if (!aExtraInfo.isEmpty())
{
sSelection += ", ";
- sSelection += sProperties;
+ sSelection += aExtraInfo.makeStringAndClear();
}
}