[Libreoffice-commits] online.git: loleaflet/src

Marco Cecchetti (via logerrit) logerrit at kemper.freedesktop.org
Wed Apr 29 11:28:49 UTC 2020


 loleaflet/src/control/Control.LokDialog.js |  196 ++++++++++++++++++++---------
 1 file changed, 136 insertions(+), 60 deletions(-)

New commits:
commit 4c3708e076665351115b1f674519ac74a9080904
Author:     Marco Cecchetti <marco.cecchetti at collabora.com>
AuthorDate: Tue Apr 21 13:03:34 2020 +0200
Commit:     Marco Cecchetti <marco.cecchetti at 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.cecchetti at collabora.com>
    Reviewed-by: Marco Cecchetti <marco.cecchetti at 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');


More information about the Libreoffice-commits mailing list