kit/ChildSession.cpp | 33 ++++++++++++++ kit/ChildSession.hpp | 1 loleaflet/css/partsPreviewControl.css | 6 ++ loleaflet/src/control/Control.PartsPreview.js | 61 ++++++++++++++++++++++++++ wsd/ClientSession.cpp | 18 +++++++ wsd/protocol.txt | 4 + 6 files changed, 122 insertions(+), 1 deletion(-)
New commits: commit 2eab5cea763d037ed7d11f0ba88b8299edc592ff Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> AuthorDate: Mon Sep 17 07:17:31 2018 -0400 Commit: Ashod Nakashian <ashnak...@gmail.com> CommitDate: Sat Aug 17 04:33:04 2019 +0200 wsd: leaflet: support reordering of slides via drag-and-drop Change-Id: I1b471ba07dd0a1016a0759de729171ae968262cb Reviewed-on: https://gerrit.libreoffice.org/69635 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/71099 diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp index fc41597e5..be169fc6f 100644 --- a/kit/ChildSession.cpp +++ b/kit/ChildSession.cpp @@ -232,6 +232,10 @@ bool ChildSession::_handleInput(const char *buffer, int length) { return selectClientPart(buffer, length, tokens); } + else if (tokens[0] == "moveselectedclientparts") + { + return moveSelectedClientParts(buffer, length, tokens); + } else if (tokens[0] == "setpage") { return setPage(buffer, length, tokens); @@ -1964,6 +1968,35 @@ bool ChildSession::selectClientPart(const char* /*buffer*/, int /*length*/, cons return true; } +bool ChildSession::moveSelectedClientParts(const char* /*buffer*/, int /*length*/, const std::vector<std::string>& tokens) +{ + int nPosition; + if (tokens.size() < 2 || + !getTokenInteger(tokens[1], "position", nPosition)) + { + sendTextFrame("error: cmd=moveselectedclientparts kind=invalid"); + return false; + } + + getLOKitDocument()->setView(_viewId); + + if (getLOKitDocument()->getDocumentType() != LOK_DOCTYPE_TEXT) + { + getLOKitDocument()->moveSelectedParts(nPosition, false); // Move, don't duplicate. + + // Get the status to recreate the previews and correctly order parts. + const std::string status = LOKitHelper::documentStatus(getLOKitDocument()->get()); + if (!status.empty()) + return sendTextFrame("statusupdate: " + status); + } + else + { + LOG_WRN("ChildSession::moveSelectedClientParts[" << getName() << "]: error moving parts on text documents."); + } + + return true; // Non-fatal to fail. +} + bool ChildSession::setPage(const char* /*buffer*/, int /*length*/, const std::vector<std::string>& tokens) { int page; diff --git a/kit/ChildSession.hpp b/kit/ChildSession.hpp index cc5ff6a15..1d2cd3fdd 100644 --- a/kit/ChildSession.hpp +++ b/kit/ChildSession.hpp @@ -269,6 +269,7 @@ private: bool saveAs(const char* buffer, int length, const std::vector<std::string>& tokens); bool setClientPart(const char* buffer, int length, const std::vector<std::string>& tokens); bool selectClientPart(const char* buffer, int length, const std::vector<std::string>& tokens); + bool moveSelectedClientParts(const char* buffer, int length, const std::vector<std::string>& tokens); bool setPage(const char* buffer, int length, const std::vector<std::string>& tokens); bool sendWindowCommand(const char* buffer, int length, const std::vector<std::string>& tokens); bool signDocumentContent(const char* buffer, int length, const std::vector<std::string>& tokens); diff --git a/loleaflet/css/partsPreviewControl.css b/loleaflet/css/partsPreviewControl.css index 438b137d3..66e47c9bb 100644 --- a/loleaflet/css/partsPreviewControl.css +++ b/loleaflet/css/partsPreviewControl.css @@ -20,7 +20,7 @@ .preview-img { /* In draw docs, the width of previews are small, but we want a min of 180px to align it with document's left edge */ - min-width: 180px; + min-width: 180px; vertical-align: middle; max-width: 184px; cursor: pointer; @@ -30,3 +30,7 @@ .preview-img-selected { border-color: #000000; } + +.preview-img-dropsite { + border-bottom: 2px solid red; +} diff --git a/loleaflet/src/control/Control.PartsPreview.js b/loleaflet/src/control/Control.PartsPreview.js index 3ebe4baaa..8f0629957 100644 --- a/loleaflet/src/control/Control.PartsPreview.js +++ b/loleaflet/src/control/Control.PartsPreview.js @@ -85,6 +85,7 @@ L.Control.PartsPreview = L.Control.extend({ _createPreview: function (i, hashCode, bottomBound) { var frame = L.DomUtil.create('div', 'preview-frame', this._scrollContainer); + this._addDnDHandlers(frame); L.DomUtil.create('span', 'preview-helper', frame); var imgClassName = 'preview-img'; @@ -209,6 +210,7 @@ L.Control.PartsPreview = L.Control.extend({ for (it = 0; it < parts; it++) { if (this._previewTiles[it].hash !== e.partNames[it]) { this._previewTiles[it].hash = e.partNames[it]; + this._map.getPreview(it, it, 180, 180, {autoUpdate: this.options.autoUpdate}); } } } @@ -276,7 +278,66 @@ L.Control.PartsPreview = L.Control.extend({ } } } + }, + + _addDnDHandlers: function (elem) { + if (elem) { + elem.setAttribute('draggable', true); + elem.addEventListener('dragstart', this._handleDragStart, false); + elem.addEventListener('dragenter', this._handleDragEnter, false) + elem.addEventListener('dragover', this._handleDragOver, false); + elem.addEventListener('dragleave', this._handleDragLeave, false); + elem.addEventListener('drop', this._handleDrop, false); + elem.addEventListener('dragend', this._handleDragEnd, false); + elem.partsPreview = this; + } + }, + + _handleDragStart: function (e) { + // By default we move when dragging, but can + // support duplication with ctrl in the future. + e.dataTransfer.effectAllowed = 'move'; + }, + + _handleDragOver: function (e) { + if (e.preventDefault) { + e.preventDefault(); + } + + // By default we move when dragging, but can + // support duplication with ctrl in the future. + e.dataTransfer.dropEffect = 'move'; + + this.classList.add('preview-img-dropsite'); + return false; + }, + + _handleDragEnter: function () { + }, + + _handleDragLeave: function () { + this.classList.remove('preview-img-dropsite'); + }, + + _handleDrop: function (e) { + if (e.stopPropagation) { + e.stopPropagation(); + } + + var part = $('#slide-sorter .mCSB_container .preview-frame').index(e.target.parentNode); + if (part !== null) { + var partId = parseInt(part); + this.partsPreview._map._socket.sendMessage('moveselectedclientparts position=' + partId); + } + + this.classList.remove('preview-img-dropsite'); + return false; + }, + + _handleDragEnd: function () { + this.classList.remove('preview-img-dropsite'); } + }); L.control.partsPreview = function (options) { diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index f10f08724..5dbcaa7d0 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -402,6 +402,7 @@ bool ClientSession::_handleInput(const char *buffer, int length) tokens[0] != "selecttext" && tokens[0] != "setclientpart" && tokens[0] != "selectclientpart" && + tokens[0] != "moveselectedclientparts" && tokens[0] != "setpage" && tokens[0] != "status" && tokens[0] != "statusupdate" && @@ -580,6 +581,23 @@ bool ClientSession::_handleInput(const char *buffer, int length) } } } + else if (tokens[0] == "moveselectedclientparts") + { + if(!_isTextDocument) + { + int nPosition; + if (tokens.size() != 2 || + !getTokenInteger(tokens[1], "position", nPosition)) + { + sendTextFrame("error: cmd=moveselectedclientparts kind=syntax"); + return false; + } + else + { + return forwardToChild(std::string(buffer, length), docBroker); + } + } + } else if (tokens[0] == "clientzoom") { int tilePixelWidth, tilePixelHeight, tileTwipWidth, tileTwipHeight; diff --git a/wsd/protocol.txt b/wsd/protocol.txt index a1bdb39cb..bf11deafd 100644 --- a/wsd/protocol.txt +++ b/wsd/protocol.txt @@ -144,6 +144,10 @@ selectclientpart part=<partNumber> Informs the server that the client changed the selection state of <partNumber>. +moveselectedclientparts position=<positionNumber> + + Moves the selected parts to a new position. + setpage page=<pageNumber> Valid only for text documents. _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits