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

Marco Cecchetti marco.cecchetti at collabora.com
Sun Jan 24 11:33:24 PST 2016


 loleaflet/src/control/Parts.js         |    1 
 loleaflet/src/control/Search.js        |    8 ++++
 loleaflet/src/dom/DomEvent.js          |   15 ++++++--
 loleaflet/src/dom/Draggable.js         |    9 ++++
 loleaflet/src/layer/tile/TileLayer.js  |   61 ++++++++++++++++++++++++++++++++-
 loleaflet/src/map/Map.js               |   28 ++++++++++++++-
 loleaflet/src/map/handler/Map.Mouse.js |   36 ++++++++++++++++++-
 7 files changed, 152 insertions(+), 6 deletions(-)

New commits:
commit a698d6a2d11cbc1190519793eaad3cde75526ca8
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Sun Jan 24 14:56:51 2016 +0100

    loleaflet - fix for multi-line text selection issues
    
    Steps for reproducing the problem:
    1) try to select some multi-line text
    2) still holding the mouse button pressed move the mouse pointer
    outside the browser window
    3) release the mouse button
    4) move the cursor back over the map.
    
    Expected result: the selection should not change any more after the
    mouse button has been released.
    Real result: the selection changes when you move the mouse.
    
    The same happens when you move the mouse pointer out of the tiles
    covering, even if we are still inside the html document element area
    where the map is embedded.
    
    A similar issue occurs in view only mode when you drag the document: in
    this case the problem occurs only when you move the mouse pointer out of
    the tiles covering, but still inside the html document element area
    where the map is embedded.
    
    The behaviour described above is due to the fact that the map container
    receives mouse events only when the mouse pointer is over the map.
    The implemented fix checks for mouseout events which occur between a
    tile element and a non-tile element (such as the the resize-detector
    iframe, the scroll-bar container, the selection cursor marker). When
    such an event occurs handlers for mousemove and mouseup events are
    attached to the HTML document element and to the resize-detector iframe.
    In the same way when a mouseover event occurs between a tile element and
    a non-tile element such handlers are removed.
    
    It was needed to attach handlers to the resize-detector iframe too since
    the HTML document element seems to not be able to receive mouse events
    that occur inside the iframe area.
    
    A side effect of this fix is that now the text selection goes on
    changing as far as the mouse button is not released even when the mouse
    pointer is moved out of the tiles covering.
    
    Since for an iframe the coordinates embedded in a mouse event are
    relative to the iframe area, it was needed to implement a workaround in
    order to avoid sudden changes in the current selection or in the
    document position when the mouse pointer moves out of the map.

diff --git a/loleaflet/src/dom/DomEvent.js b/loleaflet/src/dom/DomEvent.js
index a83a5ac..d1f9141 100644
--- a/loleaflet/src/dom/DomEvent.js
+++ b/loleaflet/src/dom/DomEvent.js
@@ -180,11 +180,20 @@ L.DomEvent = {
 			return new L.Point(e.clientX, e.clientY);
 		}
 
-		var rect = container.getBoundingClientRect();
+		var rect = container.getBoundingClientRect(), // constant object
+			left = rect.left,
+			top = rect.top;
+
+		// iframe mouse coordinates are relative to the frame area
+		// `target`: body element of the iframe; `currentTarget`: content window of the iframe
+		if (e.currentTarget && e.currentTarget.frameElement
+			&& L.DomUtil.hasClass(e.currentTarget.frameElement, 'resize-detector')) {
+			left = top = 0;
+		}
 
 		return new L.Point(
-			e.clientX - rect.left - container.clientLeft,
-			e.clientY - rect.top - container.clientTop);
+			e.clientX - left - container.clientLeft,
+			e.clientY - top - container.clientTop);
 	},
 
 	getWheelDelta: function (e) {
diff --git a/loleaflet/src/dom/Draggable.js b/loleaflet/src/dom/Draggable.js
index 3eaafa7..4e7280d 100644
--- a/loleaflet/src/dom/Draggable.js
+++ b/loleaflet/src/dom/Draggable.js
@@ -90,6 +90,15 @@ L.Draggable = L.Evented.extend({
 		    offset = newPoint.subtract(this._startPoint);
 
 		if (this._map) {
+			// needed in order to avoid a jump when the document is dragged and the mouse pointer move
+			// from over the map into the html document element area which is not covered by tiles
+			// (resize-detector iframe)
+			if (e.currentTarget && e.currentTarget.frameElement
+				&& L.DomUtil.hasClass(e.currentTarget.frameElement, 'resize-detector')) {
+				var rect = this._map._container.getBoundingClientRect(),
+					correction = new L.Point(rect.left, rect.top);
+				offset = offset.add(correction);
+			}
 			if (this._map.getDocSize().x < this._map.getSize().x) {
 				// don't pan horizontaly when the document fits in the viewing
 				// area horizontally (docWidth < viewAreaWidth)
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index a2f9e06..87dd60f 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -595,6 +595,8 @@ L.Map = L.Evented.extend({
 
 		this._targets = {};
 
+		this._mouseOut = false;
+
 		var onOff = remove ? 'off' : 'on';
 
 		L.DomEvent[onOff](this._container, 'click dblclick mousedown mouseup ' +
@@ -613,6 +615,17 @@ L.Map = L.Evented.extend({
 		        function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container);
 	},
 
+	_isMouseEnteringLeaving: function (e) {
+		var target = e.target || e.srcElement,
+			related = e.relatedTarget;
+
+		if (!target) { return false; }
+
+		return (L.DomUtil.hasClass(target, 'leaflet-tile')
+			&& !(related && (L.DomUtil.hasClass(related, 'leaflet-tile')
+				|| L.DomUtil.hasClass(related, 'leaflet-cursor'))));
+	},
+
 	_handleDOMEvent: function (e) {
 		if (!this._loaded || L.DomEvent._skipped(e)) { return; }
 
@@ -621,8 +634,21 @@ L.Map = L.Evented.extend({
 			//type = e.type === 'keypress' && e.keyCode === 13 ? 'click' : e.type;
 			type = e.type;
 
+		// we need to keep track if we have entered/left the map
+		this._mouseEnteringLeaving = false;
+		// mouse leaving the map ?
+		if (!target && !this._mouseOut && type === 'mouseout') {
+			this._mouseEnteringLeaving = this._isMouseEnteringLeaving(e);
+			this._mouseOut = this._mouseEnteringLeaving; // event type == mouseout
+		}
+		// mouse entering the map ?
+		if (!target && this._mouseOut && type === 'mouseover') {
+			this._mouseEnteringLeaving = this._isMouseEnteringLeaving(e);
+			this._mouseOut = !this._mouseEnteringLeaving; // event type == mouseover
+		}
+
 		// special case for map mouseover/mouseout events so that they're actually mouseenter/mouseleave
-		if (!target && (type === 'mouseover' || type === 'mouseout') &&
+		if (!target && !this._mouseEnteringLeaving && (type === 'mouseover' || type === 'mouseout') &&
 				!L.DomEvent._checkMouse(this._container, e)) { return; }
 
 		// prevents outline when clicking on keyboard-focusable element
diff --git a/loleaflet/src/map/handler/Map.Mouse.js b/loleaflet/src/map/handler/Map.Mouse.js
index 440298d..28919d6 100644
--- a/loleaflet/src/map/handler/Map.Mouse.js
+++ b/loleaflet/src/map/handler/Map.Mouse.js
@@ -90,7 +90,15 @@ L.Map.Mouse = L.Handler.extend({
 		buttons |= e.originalEvent.button === this.JSButtons.middle ? this.LOButtons.middle : 0;
 		buttons |= e.originalEvent.button === this.JSButtons.right ? this.LOButtons.right : 0;
 
-		if (e.type === 'mousedown') {
+		var mouseEnteringLeavingMap = this._map._mouseEnteringLeaving;
+
+		if (mouseEnteringLeavingMap && e.type === 'mouseover' && this._mouseDown) {
+			L.DomEvent.off(document, 'mousemove', this._onMouseMoveOutside, this);
+			L.DomEvent.off(document, 'mouseup', this._onMouseUpOutside, this);
+			L.DomEvent.off(this._map._resizeDetector.contentWindow, 'mousemove', this._onMouseMoveOutside, this);
+			L.DomEvent.off(this._map._resizeDetector.contentWindow, 'mouseup', this._onMouseUpOutside, this);
+		}
+		else if (e.type === 'mousedown') {
 			docLayer._resetPreFetching();
 			this._mouseDown = true;
 			if (this._holdMouseEvent) {
@@ -211,6 +219,12 @@ L.Map.Mouse = L.Handler.extend({
 			docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, count, buttons, modifier);
 			docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, count, buttons, modifier);
 		}
+		else if (mouseEnteringLeavingMap && e.type === 'mouseout' && this._mouseDown) {
+			L.DomEvent.on(this._map._resizeDetector.contentWindow, 'mousemove', this._onMouseMoveOutside, this);
+			L.DomEvent.on(this._map._resizeDetector.contentWindow, 'mouseup', this._onMouseUpOutside, this);
+			L.DomEvent.on(document, 'mousemove', this._onMouseMoveOutside, this);
+			L.DomEvent.on(document, 'mouseup', this._onMouseUpOutside, this);
+		}
 	},
 
 	_executeMouseEvents: function () {
@@ -219,6 +233,26 @@ L.Map.Mouse = L.Handler.extend({
 			this._mouseEventsQueue[i]();
 		}
 		this._mouseEventsQueue = [];
+	},
+
+	_onMouseMoveOutside: function (e) {
+		this._map._handleDOMEvent(e);
+		if (this._map.dragging.enabled()) {
+			this._map.dragging._draggable._onMove(e);
+		}
+	},
+
+	_onMouseUpOutside: function (e) {
+		this._mouseDown = false;
+		L.DomEvent.off(document, 'mousemove', this._onMouseMoveOutside, this);
+		L.DomEvent.off(document, 'mouseup', this._onMouseUpOutside, this);
+		L.DomEvent.off(this._map._resizeDetector.contentWindow, 'mousemove', this._onMouseMoveOutside, this);
+		L.DomEvent.off(this._map._resizeDetector.contentWindow, 'mouseup', this._onMouseUpOutside, this);
+
+		this._map._handleDOMEvent(e);
+		if (this._map.dragging.enabled()) {
+			this._map.dragging._draggable._onUp(e);
+		}
 	}
 });
 
commit 47aeaa62e0120df9927f554d0c8db7dc7e079f6b
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Thu Jan 21 10:54:24 2016 +0100

    text doc - search - normal search does not discard highlighting
    
    Improved search behavior for text documents:now when a normal search is
    performed with the same search string utilized by a previous searchAll
    action, search results highlighting is not removed.

diff --git a/loleaflet/src/control/Search.js b/loleaflet/src/control/Search.js
index 136f97b..5528a08 100644
--- a/loleaflet/src/control/Search.js
+++ b/loleaflet/src/control/Search.js
@@ -6,27 +6,9 @@ L.Map.include({
 		if (all === undefined) {
 			all = 0;
 		}
-
-		// check if there is a cached searchAll result for this phrase
-		// if there is update index for next/prev iteration
-		if (this._docLayer._searchResults && text === this._docLayer._searchTerm) {
-			if (backward) {
-				if (this._docLayer._searchIndex > 0) {
-					this._docLayer._searchIndex--;
-				}
-				else {
-					this._docLayer._searchIndex = this._docLayer._searchResults.length - 1;
-				}
-			} else {
-				if (this._docLayer._searchIndex < this._docLayer._searchResults.length - 1) {
-					this._docLayer._searchIndex++;
-				}
-				else {
-					this._docLayer._searchIndex = 0;
-				}
-			}
-			this.setPart(this._docLayer._searchResults[this._docLayer._searchIndex].part);
-			return;
+		if (this._docLayer._searchResults && text !== this._docLayer._searchTerm)
+		{
+			this._docLayer._clearSearchResults();
 		}
 
 		var searchCmd = {
@@ -61,6 +43,9 @@ L.Map.include({
 	},
 
 	searchAll: function (text, backward) {
+		if (this._docLayer._searchResults && text === this._docLayer._searchTerm) {
+			return;
+		}
 		this.search(text, backward, 1);
 	},
 
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index e0d1d77..22d8306 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -503,7 +503,6 @@ L.TileLayer = L.GridLayer.extend({
 	},
 
 	_onSearchResultSelection: function (textMsg) {
-		this._clearSearchResults();
 		textMsg = textMsg.substring(23);
 		var obj = JSON.parse(textMsg);
 		var originalPhrase = obj.searchString;
@@ -518,22 +517,19 @@ L.TileLayer = L.GridLayer.extend({
 		}
 		// do not cache search results if there is only one result.
 		// this way regular searches works fine
-		if (this._docType === 'presentation' && count > 1)
+		if (count > 1)
 		{
-			this._map._socket.sendMessage('resetselection');
+			this._clearSearchResults();
 			this._searchResults = results;
-			this._searchTerm = originalPhrase;
-			this._searchIndex = 0;
-
 			this._map.setPart(results[0].part); // go to first result.
 		}
+		this._searchTerm = originalPhrase;
 		this._map.fire('search', {originalPhrase: originalPhrase, count: count, results: results});
 	},
 
 	_clearSearchResults: function() {
 		this._searchResults = null;
 		this._searchTerm = null;
-		this._searchIndex = null;
 		this._searchResultsLayer.clearLayers();
 	},
 
@@ -542,12 +538,12 @@ L.TileLayer = L.GridLayer.extend({
 			return;
 		}
 		this._searchResultsLayer.clearLayers();
-		for (var k=0; k < this._searchResults.length; k++)
+		for (var k = 0; k < this._searchResults.length; k++)
 		{
 			var result = this._searchResults[k];
 			if (result.part === this._selectedPart)
 			{
-				var _fillColor = (k === this._searchIndex) ? '#43ACE8' : '#CCCCCC';
+				var _fillColor = '#CCCCCC';
 				var strTwips = result.twipsRectangles.match(/\d+/g);
 				var rectangles = [];
 				for (var i = 0; i < strTwips.length; i += 4) {
commit b281819ab1fc0bad18c67c2bf4db9fbba0c6f354
Author: Ozcan Esen <ozcan.esen at collabora.com>
Date:   Thu Jan 14 22:11:12 2016 +0200

    loleaflet: new searchAll for presentation
    
    does not affect regular searches since it caches results only if
    (this._docType === 'presentation' && count > 1) and clears cache on
    mousedown
    
    Change-Id: I5569424df6e463da0c63166eef36842fa7d32f0e

diff --git a/loleaflet/src/control/Parts.js b/loleaflet/src/control/Parts.js
index 189f2d5..46d5f07 100644
--- a/loleaflet/src/control/Parts.js
+++ b/loleaflet/src/control/Parts.js
@@ -41,6 +41,7 @@ L.Map.include({
 		if (docLayer._docType === 'spreadsheet') {
 			this._socket.sendMessage('commandvalues command=.uno:ViewRowColumnHeaders');
 		}
+		docLayer._drawSearchResuls();
 	},
 
 	getPreview: function (id, index, maxWidth, maxHeight, options) {
diff --git a/loleaflet/src/control/Search.js b/loleaflet/src/control/Search.js
index bf14a13..136f97b 100644
--- a/loleaflet/src/control/Search.js
+++ b/loleaflet/src/control/Search.js
@@ -7,6 +7,28 @@ L.Map.include({
 			all = 0;
 		}
 
+		// check if there is a cached searchAll result for this phrase
+		// if there is update index for next/prev iteration
+		if (this._docLayer._searchResults && text === this._docLayer._searchTerm) {
+			if (backward) {
+				if (this._docLayer._searchIndex > 0) {
+					this._docLayer._searchIndex--;
+				}
+				else {
+					this._docLayer._searchIndex = this._docLayer._searchResults.length - 1;
+				}
+			} else {
+				if (this._docLayer._searchIndex < this._docLayer._searchResults.length - 1) {
+					this._docLayer._searchIndex++;
+				}
+				else {
+					this._docLayer._searchIndex = 0;
+				}
+			}
+			this.setPart(this._docLayer._searchResults[this._docLayer._searchIndex].part);
+			return;
+		}
+
 		var searchCmd = {
 			'SearchItem.SearchString': {
 				'type': 'string'
@@ -43,6 +65,7 @@ L.Map.include({
 	},
 
 	resetSelection: function () {
+		this._docLayer._clearSearchResults();
 		this._socket.sendMessage('resetselection');
 	}
 });
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 55e7004..e0d1d77 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -132,6 +132,9 @@ L.TileLayer = L.GridLayer.extend({
 		this._selections = new L.LayerGroup();
 		map.addLayer(this._selections);
 
+		this._searchResultsLayer = new L.LayerGroup();
+		map.addLayer(this._searchResultsLayer);
+
 		this._levels = {};
 		this._tiles = {};
 		this._tileCache = {};
@@ -494,11 +497,13 @@ L.TileLayer = L.GridLayer.extend({
 	},
 
 	_onSearchNotFoundMsg: function (textMsg) {
+		this._clearSearchResults();
 		var originalPhrase = textMsg.substring(16);
 		this._map.fire('search', {originalPhrase: originalPhrase, count: 0});
 	},
 
 	_onSearchResultSelection: function (textMsg) {
+		this._clearSearchResults();
 		textMsg = textMsg.substring(23);
 		var obj = JSON.parse(textMsg);
 		var originalPhrase = obj.searchString;
@@ -507,12 +512,66 @@ L.TileLayer = L.GridLayer.extend({
 		for (var i = 0; i < obj.searchResultSelection.length; i++) {
 			results.push({
 				part: parseInt(obj.searchResultSelection[i].part),
-				rectangles: this._twipsRectanglesToPixelBounds(obj.searchResultSelection[i].rectangles)
+				rectangles: this._twipsRectanglesToPixelBounds(obj.searchResultSelection[i].rectangles),
+				twipsRectangles: obj.searchResultSelection[i].rectangles
 			});
 		}
+		// do not cache search results if there is only one result.
+		// this way regular searches works fine
+		if (this._docType === 'presentation' && count > 1)
+		{
+			this._map._socket.sendMessage('resetselection');
+			this._searchResults = results;
+			this._searchTerm = originalPhrase;
+			this._searchIndex = 0;
+
+			this._map.setPart(results[0].part); // go to first result.
+		}
 		this._map.fire('search', {originalPhrase: originalPhrase, count: count, results: results});
 	},
 
+	_clearSearchResults: function() {
+		this._searchResults = null;
+		this._searchTerm = null;
+		this._searchIndex = null;
+		this._searchResultsLayer.clearLayers();
+	},
+
+	_drawSearchResuls: function() {
+		if (!this._searchResults) {
+			return;
+		}
+		this._searchResultsLayer.clearLayers();
+		for (var k=0; k < this._searchResults.length; k++)
+		{
+			var result = this._searchResults[k];
+			if (result.part === this._selectedPart)
+			{
+				var _fillColor = (k === this._searchIndex) ? '#43ACE8' : '#CCCCCC';
+				var strTwips = result.twipsRectangles.match(/\d+/g);
+				var rectangles = [];
+				for (var i = 0; i < strTwips.length; i += 4) {
+					var topLeftTwips = new L.Point(parseInt(strTwips[i]), parseInt(strTwips[i + 1]));
+					var offset = new L.Point(parseInt(strTwips[i + 2]), parseInt(strTwips[i + 3]));
+					var topRightTwips = topLeftTwips.add(new L.Point(offset.x, 0));
+					var bottomLeftTwips = topLeftTwips.add(new L.Point(0, offset.y));
+					var bottomRightTwips = topLeftTwips.add(offset);
+					rectangles.push([bottomLeftTwips, bottomRightTwips, topLeftTwips, topRightTwips]);
+				}
+				var polygons = L.PolyUtil.rectanglesToPolygons(rectangles, this);
+				for (var j = 0; j < polygons.length; j++) {
+					var selection = new L.Polygon(polygons[j], {
+						pointerEvents: 'none',
+						fillColor: _fillColor,
+						fillOpacity: 0.25,
+						weight: 2,
+						opacity: 0.25});
+					this._searchResultsLayer.addLayer(selection);
+				}
+			}
+		}
+	},
+
 	_onStateChangedMsg: function (textMsg) {
 		var unoMsg = textMsg.substr(14).split('=');
 		var commandName = '',
@@ -707,6 +766,10 @@ L.TileLayer = L.GridLayer.extend({
 		this._map._socket.sendMessage('mouse type=' + type +
 				' x=' + x + ' y=' + y + ' count=' + count +
 				' buttons=' + buttons + ' modifier=' + modifier);
+
+		if (type === 'buttondown') {
+			this._clearSearchResults();
+		}
 	},
 
 	_postKeyboardEvent: function(type, charcode, keycode) {


More information about the Libreoffice-commits mailing list