loleaflet/src/control/Control.LokDialog.js | 196 ++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 60 deletions(-)
New commits: commit 4c3708e076665351115b1f674519ac74a9080904 Author: Marco Cecchetti <marco.cecche...@collabora.com> AuthorDate: Tue Apr 21 13:03:34 2020 +0200 Commit: Marco Cecchetti <marco.cecche...@collabora.com> CommitDate: Wed Apr 29 13:28:31 2020 +0200 leaflet: calc: formula bar: improve selection handling This patch provides some improvements for the single input line case: - start selection handle is visible only if the current visible line is the first selected line - end selection handle is visible only if the current visible line is the last selected line - by dragging the selection handles is possible to switch to previous/next line Change-Id: I168163306420d57d7d074682f7a8c3303a79da82 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92123 Tested-by: Marco Cecchetti <marco.cecche...@collabora.com> Reviewed-by: Marco Cecchetti <marco.cecche...@collabora.com> diff --git a/loleaflet/src/control/Control.LokDialog.js b/loleaflet/src/control/Control.LokDialog.js index 0c76b1d13..42e3fdbc8 100644 --- a/loleaflet/src/control/Control.LokDialog.js +++ b/loleaflet/src/control/Control.LokDialog.js @@ -381,6 +381,7 @@ L.Control.LokDialog = L.Control.extend({ } else if (e.action === 'text_selection') { if (this._isOpen(e.id)) { var rectangles = []; + var startHandleVisible, endHandleVisible; if (e.rectangles) { var dataList = e.rectangles.match(/\d+/g); if (dataList != null) { @@ -394,7 +395,14 @@ L.Control.LokDialog = L.Control.extend({ } } } - this._updateTextSelection(e.id, rectangles); + + if (e.startHandleVisible) { + startHandleVisible = e.startHandleVisible === 'true'; + } + if (e.endHandleVisible) { + endHandleVisible = e.endHandleVisible === 'true'; + } + this._updateTextSelection(e.id, rectangles, startHandleVisible, endHandleVisible); } } else if (e.action === 'title_changed') { if (e.title && this._dialogs[parseInt(e.id)]) { @@ -455,18 +463,26 @@ L.Control.LokDialog = L.Control.extend({ L.DomUtil.addClass(cursor, 'blinking-cursor'); }, - _updateTextSelection: function(dlgId, rectangles) { + _updateTextSelection: function(dlgId, rectangles, startHandleVisible, endHandleVisible) { var strId = this._toIntId(dlgId); var selections = this._dialogs[strId].textSelection.rectangles; L.DomUtil.empty(selections); var handles = this._dialogs[strId].textSelection.handles; - var startHandle = this._dialogs[strId].textSelection.startHandle; - var endHandle = this._dialogs[strId].textSelection.endHandle; + var startHandle, endHandle; + if (startHandleVisible) { + startHandle = this._dialogs[strId].textSelection.startHandle; + } else if (handles.start) { + L.DomUtil.remove(handles.start); + handles.start = null; + } + if (endHandleVisible) { + endHandle = this._dialogs[strId].textSelection.endHandle; + } else if (handles.end) { + L.DomUtil.remove(handles.end); + handles.end = null; + } if (!rectangles || rectangles.length < 1) { - if (!startHandle.isDragged && !endHandle.isDragged) { - L.DomUtil.empty(handles); - } return; } @@ -480,34 +496,43 @@ L.Control.LokDialog = L.Control.extend({ L.DomUtil.setStyle(container, 'top', rect.y + 'px'); } - var startRect = rectangles[0]; - var endRect = rectangles[rectangles.length - 1]; - if (startRect.width < 1 || endRect.width < 1) - return; - startRect = {x: startRect.x, y: startRect.y, width: 1, height: startRect.height}; - endRect = {x: endRect.x + endRect.width - 1, y: endRect.y, width: 1, height: endRect.height}; - var startPos = L.point(startRect.x, startRect.y + startRect.height); - startPos = startPos.subtract(L.point(0, 2)); - startHandle.lastPos = startPos; - startHandle.rowHeight = startRect.height; - var endPos = L.point(endRect.x, endRect.y + endRect.height); - endPos = endPos.subtract(L.point(0, 2)); - endHandle.lastPos = endPos; - endHandle.rowHeight = endRect.height; - - if (!startHandle.isDragged) { - if (!handles.children || !handles.children[0]) - handles.appendChild(startHandle); - //console.log('lokdialog: _updateTextSelection: startPos: x: ' + startPos.x + ', y: ' + startPos.y); + var startPos; + if (startHandle) { + var startRect = rectangles[0]; + if (startRect.width < 1) + return; + startRect = {x: startRect.x, y: startRect.y, width: 1, height: startRect.height}; + startPos = L.point(startRect.x, startRect.y + startRect.height); + startPos = startPos.subtract(L.point(0, 2)); + startHandle.lastPos = startPos; + startHandle.rowHeight = startRect.height; + } + + var endPos; + if (endHandle) { + var endRect = rectangles[rectangles.length - 1]; + if (endRect.width < 1) + return; + endRect = {x: endRect.x + endRect.width - 1, y: endRect.y, width: 1, height: endRect.height}; + endPos = L.point(endRect.x, endRect.y + endRect.height); + endPos = endPos.subtract(L.point(0, 2)); + endHandle.lastPos = endPos; + endHandle.rowHeight = endRect.height; + } + + if (startHandle && handles.draggingStopped) { + if (!handles.start) + handles.start = handles.appendChild(startHandle); + // console.log('lokdialog: _updateTextSelection: startPos: x: ' + startPos.x + ', y: ' + startPos.y); startHandle.pos = startPos; L.DomUtil.setStyle(startHandle, 'left', startPos.x + 'px'); L.DomUtil.setStyle(startHandle, 'top', startPos.y + 'px'); } - if (!endHandle.isDragged) { - if (!handles.children || !handles.children[1]) - handles.appendChild(endHandle); - //console.log('lokdialog: _updateTextSelection: endPos: x: ' + endPos.x + ', y: ' + endPos.y); + if (endHandle && handles.draggingStopped) { + if (!handles.end) + handles.end = handles.appendChild(endHandle); + // console.log('lokdialog: _updateTextSelection: endPos: x: ' + endPos.x + ', y: ' + endPos.y); endHandle.pos = endPos; L.DomUtil.setStyle(endHandle, 'left', endPos.x + 'px'); L.DomUtil.setStyle(endHandle, 'top', endPos.y + 'px'); @@ -521,9 +546,24 @@ L.Control.LokDialog = L.Control.extend({ e.target.isDragged = true; e.target.dragStartPos = mousePos; + // single input line: check if after moving to a new line the handles have swapped position + if (handles.scrollDir !== 0 && handles.start && handles.end) { + var startDX = Math.abs(handles.beforeScrollingPosX - handles.start.pos.x); + var endDX = Math.abs(handles.beforeScrollingPosX - handles.end.pos.x); + if (handles.scrollDir === -1 && handles.lastDraggedHandle === 'end' && startDX < endDX) { + handles.lastDraggedHandle = 'start'; + } else if (handles.scrollDir === 1 && handles.lastDraggedHandle === 'start' && endDX < startDX) { + handles.lastDraggedHandle = 'end'; + } + } + + handles.scrollDir = 0; + handles.beforeScrollingPosX = 0; + handles.draggingStopped = false; if (!handles.lastDraggedHandle) handles.lastDraggedHandle = 'end'; var swap = handles.lastDraggedHandle !== e.target.type; + // check if we need to notify the lok core of swapping the mark/cursor roles if (swap) { handles.lastDraggedHandle = e.target.type; var pos = e.target.pos; @@ -534,68 +574,94 @@ L.Control.LokDialog = L.Control.extend({ _onSelectionHandleDrag: function (e) { var handles = this._calcInputBar.textSelection.handles; - var startHandle = handles.children[0]; - var endHandle = handles.children[1]; - var dragEnd = e.type === 'mouseup' || e.type === 'mouseout' || e.type === 'panend'; + var startHandle = handles.start; + var endHandle = handles.end; + + var dragEnd = e.type === 'mouseup' || e.type === 'panend'; + // when stopDragging is true we do not update the text selection + // further even if the dragging action is not over + var stopDragging = dragEnd || e.type === 'mouseout'; - if ((!startHandle || !startHandle.isDragged) && (!endHandle || !endHandle.isDragged) && dragEnd) { - var code = 0; + // single input line: dragging with no text selected -> move to previous/next line + var keyCode = 0; + if (dragEnd && (!startHandle || !startHandle.isDragged) && (!endHandle || !endHandle.isDragged)) { if (e.deltaX > 30 || e.deltaY > 20) - code = 1025; // ArrowUp + keyCode = 1025; // ArrowUp else if (e.deltaX < -30 || e.deltaY < -20) - code = 1024; // ArrowDown - if (code) { - this._map._docLayer.postKeyboardEvent('input', 0, code); + keyCode = 1024; // ArrowDown + if (keyCode) { + this._map._docLayer.postKeyboardEvent('input', 0, keyCode); this._map._textInput._emptyArea(); - this._map._docLayer.postKeyboardEvent('up', 0, code); + this._map._docLayer.postKeyboardEvent('up', 0, keyCode); } - } - - if (!endHandle || !startHandle) return; + } var draggedHandle; - if (startHandle.isDragged) + if (startHandle && startHandle.isDragged) draggedHandle = startHandle; - else if (endHandle.isDragged) + else if (endHandle && endHandle.isDragged) draggedHandle = endHandle; if (!draggedHandle) return; - if (dragEnd) draggedHandle.isDragged = false; + if (handles.draggingStopped) + return; + if (stopDragging) + handles.draggingStopped = true; + var mousePos = L.DomEvent.getMousePosition(e.pointers ? e.srcEvent : e, handles); var pos = draggedHandle.pos.add(mousePos.subtract(draggedHandle.dragStartPos)); - var maxX = parseInt(handles.style.width) - 5; - var maxY = parseInt(handles.style.height) - 5; - if (pos.x < handles.offsetX) - pos.x = dragEnd ? draggedHandle.lastPos.x : handles.offsetX; - else if (mousePos.x > maxX) - pos.x = dragEnd ? draggedHandle.lastPos.x : maxX; - if (pos.y < handles.offsetY) - pos.y = dragEnd ? draggedHandle.lastPos.y : handles.offsetY; - else if (mousePos.y > maxY) - pos.y = dragEnd ? draggedHandle.lastPos.y : maxY; + // try to avoid unpleasant small vertical bouncing when dragging the handle horizontally if (Math.abs(pos.y - draggedHandle.lastPos.y) < 6) { pos.y = draggedHandle.lastPos.y; } - if (draggedHandle.type === 'end') { + // try to avoid to swap the handles position when they are both visible + if (startHandle && draggedHandle.type === 'end') { if (startHandle.pos.y - pos.y > 2) pos.y = draggedHandle.lastPos.y; if (startHandle.pos.y - pos.y > -2 && pos.x - startHandle.pos.x < 2) pos = draggedHandle.lastPos; } - if (draggedHandle.type === 'start') { + if (endHandle && draggedHandle.type === 'start') { if (pos.y - endHandle.pos.y > 2) pos.y = draggedHandle.lastPos.y; if (pos.y - endHandle.pos.y > -endHandle.rowHeight && endHandle.pos.x - pos.x < 2) pos = draggedHandle.lastPos; } + var dragAreaWidth = parseInt(handles.style.width); + var dragAreaHeight = parseInt(handles.style.height); + var maxX = dragAreaWidth - 5; + var maxY = dragAreaHeight - 5; + + // handle cases where the handle is dragged out of the input area + if (pos.x < handles.offsetX) + pos.x = stopDragging ? draggedHandle.lastPos.x : handles.offsetX; + else if (pos.x > maxX) + pos.x = stopDragging ? draggedHandle.lastPos.x : maxX; + + if (pos.y < handles.offsetY) { + handles.scrollDir = -1; + keyCode = 5121; // Shift + ArrowUp + pos.y = stopDragging ? draggedHandle.lastPos.y : handles.offsetY; + } + else if (pos.y > maxY) { + if (pos.y > dragAreaHeight - 1 || e.type === 'mouseout') { // on desktop mouseout works better + handles.scrollDir = 1; + keyCode = 5120; // Shift + ArrowDown + } + pos.y = stopDragging ? draggedHandle.lastPos.y : maxY; + } + + if (keyCode) + handles.draggingStopped = true; + var handlePos = pos; - if (dragEnd) { + if (stopDragging) { handlePos = draggedHandle.lastPos; draggedHandle.pos = pos; } @@ -604,6 +670,14 @@ L.Control.LokDialog = L.Control.extend({ L.DomUtil.setStyle(draggedHandle, 'top', handlePos.y + 'px'); this._map._socket.sendMessage('windowselecttext id=' + draggedHandle.dialogId + ' swap=false x=' + pos.x + ' y=' + pos.y); + + // check if we need to move to previous/next line + if (keyCode) { + handles.beforeScrollingPosX = pos.x; + this._map._docLayer.postKeyboardEvent('input', 0, keyCode); + this._map._textInput._emptyArea(); + this._map._docLayer.postKeyboardEvent('up', 0, keyCode); + } }, focus: function(dlgId, acceptInput) { @@ -840,7 +914,9 @@ L.Control.LokDialog = L.Control.extend({ L.DomUtil.setStyle(handles, 'position', 'absolute'); L.DomUtil.setStyle(handles, 'background', 'transparent'); this._setCanvasWidthHeight(handles, width, height); - handles.offsetX = window.mode.isMobile() ? 0 : 48; // 48 with sigma and equal buttons + handles.draggingStopped = true; + handles.scrollDir = 0; + handles.offsetX = window.mode.isMobile() ? 0 : 48; // 48 with sigma and equal buttons handles.offsetY = 0; var startHandle = document.createElement('div'); L.DomUtil.addClass(startHandle, 'leaflet-selection-marker-start'); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits