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

Dennis Francis (via logerrit) logerrit at kemper.freedesktop.org
Sun Jul 5 07:58:20 UTC 2020


 loleaflet/src/control/Control.ColumnHeader.js |   21 +++-
 loleaflet/src/control/Control.Header.js       |   30 ++++++
 loleaflet/src/control/Control.RowHeader.js    |   21 +++-
 loleaflet/src/control/Control.Scroll.js       |    4 
 loleaflet/src/layer/CalcGridLines.js          |   15 ++-
 loleaflet/src/layer/tile/CalcTileLayer.js     |  112 ++++++++++++++++++++------
 loleaflet/src/map/Map.js                      |    2 
 7 files changed, 160 insertions(+), 45 deletions(-)

New commits:
commit dc862d358522315c857044debf11eeceb1fc936b
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Fri May 15 08:12:03 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Sun Jul 5 09:57:59 2020 +0200

    use SheetGeometry data to draw headers/gridlines if enabled
    
    Change-Id: If146512a50c24f5fd81f6df7e0a3746f70bf21f9
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97944
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Dennis Francis <dennis.francis at collabora.com>

diff --git a/loleaflet/src/control/Control.ColumnHeader.js b/loleaflet/src/control/Control.ColumnHeader.js
index a2846f78e..254a4df41 100644
--- a/loleaflet/src/control/Control.ColumnHeader.js
+++ b/loleaflet/src/control/Control.ColumnHeader.js
@@ -193,7 +193,7 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 	},
 
 	_updateColumnHeader: function () {
-		this._map._docLayer.requestViewRowColumnData({x: this._map._getTopLeftPoint().x, y: 0, offset: {x: undefined, y: 0}});
+		this._map._docLayer.refreshViewData({x: this._map._getTopLeftPoint().x, y: 0, offset: {x: undefined, y: 0}});
 	},
 
 	drawHeaderEntry: function (entry, isOver, isHighlighted, isCurrent) {
@@ -376,8 +376,10 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 	},
 
 	viewRowColumnHeaders: function (e) {
-		if (e.data.columns && e.data.columns.length > 0) {
-			this.fillColumns(e.data.columns, e.data.columnGroups, e.converter, e.context);
+		var dataInEvent = (e.data && e.data.columns && e.data.columns.length > 0);
+		if (dataInEvent || e.updatecolumns) {
+			dataInEvent ? this.fillColumns(e.data.columns, e.data.columnGroups, e.converter, e.context) :
+				this.fillColumns(undefined, undefined, e.converter, e.context);
 			this._onUpdateCurrentColumn(e.cursor);
 			if (e.selection && e.selection.hasSelection) {
 				this._onUpdateSelection(e.selection);
@@ -389,7 +391,7 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 	},
 
 	fillColumns: function (columns, colGroups, converter, context) {
-		if (columns.length < 2)
+		if (columns && columns.length < 2)
 			return;
 
 		var canvas = this._canvas;
@@ -413,21 +415,28 @@ L.Control.ColumnHeader = L.Control.Header.extend({
 			this._lastMouseOverIndex = undefined;
 		}
 
+		var sheetGeometry = this._map._docLayer.sheetGeometry;
+		var columnsGeometry = sheetGeometry ? sheetGeometry.getColumnsGeometry() : undefined;
+
 		// create data structure for column widths
-		this._tickMap = new L.Control.Header.GapTickMap(this._map, columns);
+		this._tickMap = new L.Control.Header.GapTickMap(this._map, columns, columnsGeometry);
 		this._startOffset = this._tickMap.getStartOffset();
 
 		// setup conversion routine
 		this.converter = L.Util.bind(converter, context);
 
 		// create group array
-		this._groupLevels = parseInt(columns[0].groupLevels);
+		this._groupLevels = columns ? parseInt(columns[0].groupLevels):
+			sheetGeometry.getColumnGroupLevels();
 		this._groups = this._groupLevels ? new Array(this._groupLevels) : null;
 
 		// collect group controls data
 		if (colGroups !== undefined && this._groups) {
 			this._collectGroupsData(colGroups);
 		}
+		else if (sheetGeometry) {
+			this._collectGroupsData(sheetGeometry.getColumnGroupsDataInView());
+		}
 
 		if (this._groups) {
 			this.resize(this._computeOutlineWidth() + this._borderWidth + this._headerHeight);
diff --git a/loleaflet/src/control/Control.Header.js b/loleaflet/src/control/Control.Header.js
index 5aeac06da..3ef4bb2e0 100644
--- a/loleaflet/src/control/Control.Header.js
+++ b/loleaflet/src/control/Control.Header.js
@@ -804,7 +804,35 @@ L.Control.Header.colHeaderHeight = undefined;
  */
 L.Control.Header.GapTickMap = L.Class.extend({
 
-	initialize: function (map, ticks) {
+	initialize: function (map, ticks, dimensionGeometry) {
+
+		if (dimensionGeometry) {
+			// Until .uno:ViewRowColumnHeaders is not phased out, we need to live with
+			// GapTickMap datastructure to avoid an invasive refactoring.
+			// L.SheetGeometry and L.SheetDimension datastructures can directly provide
+			// position/size of any row/column intuitively without using unnecessary
+			// terminologies like (1-based) Gap and (0-based) Tick.
+			var dimrange = dimensionGeometry.getViewElementRange();
+			var start = Math.max(0, dimrange.start - 2);
+			var startData = dimensionGeometry.getElementData(start);
+			var startText = start ? start + 1 : 0;
+			var endText = Math.min(dimensionGeometry.getMaxIndex(), dimrange.end + 2) + 1;
+
+			this._minTickIdx = startText;
+			this._maxTickIdx = endText;
+			this._startOffset = start ? startData.startpos + startData.size : 0;
+			this._tilePixelScale = 1; // We already have everything in css px.
+
+			ticks = start ? [] : [0];
+			dimensionGeometry.forEachInRange(start,
+				this._maxTickIdx - 1, function (idx, data) {
+					ticks[idx + 1] = data.startpos + data.size;
+				});
+
+			this._ticks = ticks;
+
+			return;
+		}
 
 		var gapSize;
 		this._ticks = [];
diff --git a/loleaflet/src/control/Control.RowHeader.js b/loleaflet/src/control/Control.RowHeader.js
index afbba3c45..820f2205b 100644
--- a/loleaflet/src/control/Control.RowHeader.js
+++ b/loleaflet/src/control/Control.RowHeader.js
@@ -186,7 +186,7 @@ L.Control.RowHeader = L.Control.Header.extend({
 	},
 
 	_updateRowHeader: function () {
-		this._map._docLayer.requestViewRowColumnData({x: 0, y: this._map._getTopLeftPoint().y, offset: {x: 0, y: undefined}});
+		this._map._docLayer.refreshViewData({x: 0, y: this._map._getTopLeftPoint().y, offset: {x: 0, y: undefined}});
 	},
 
 	drawHeaderEntry: function (entry, isOver, isHighlighted, isCurrent) {
@@ -365,8 +365,10 @@ L.Control.RowHeader = L.Control.Header.extend({
 	},
 
 	viewRowColumnHeaders: function (e) {
-		if (e.data.rows && e.data.rows.length) {
-			this.fillRows(e.data.rows, e.data.rowGroups, e.converter, e.context);
+		var dataInEvent = (e.data && e.data.rows && e.data.rows.length);
+		if (dataInEvent || e.updaterows) {
+			dataInEvent ? this.fillRows(e.data.rows, e.data.rowGroups, e.converter, e.context) :
+				this.fillRows(undefined, undefined, e.converter, e.context);
 			this._onUpdateCurrentRow(e.cursor);
 			if (e.selection && e.selection.hasSelection) {
 				this._onUpdateSelection(e.selection);
@@ -378,7 +380,7 @@ L.Control.RowHeader = L.Control.Header.extend({
 	},
 
 	fillRows: function (rows, rowGroups, converter, context) {
-		if (rows.length < 2)
+		if (rows && rows.length < 2)
 			return;
 
 		var canvas = this._canvas;
@@ -394,21 +396,28 @@ L.Control.RowHeader = L.Control.Header.extend({
 			this._lastMouseOverIndex = undefined;
 		}
 
+		var sheetGeometry = this._map._docLayer.sheetGeometry;
+		var rowsGeometry = sheetGeometry ? sheetGeometry.getRowsGeometry() : undefined;
+
 		// create data structure for row heights
-		this._tickMap = new L.Control.Header.GapTickMap(this._map, rows);
+		this._tickMap = new L.Control.Header.GapTickMap(this._map, rows, rowsGeometry);
 		this._startOffset = this._tickMap.getStartOffset();
 
 		// setup conversion routine
 		this.converter = L.Util.bind(converter, context);
 
 		// create group array
-		this._groupLevels = parseInt(rows[0].groupLevels);
+		this._groupLevels = rows ? parseInt(rows[0].groupLevels) :
+			sheetGeometry.getRowGroupLevels();
 		this._groups = this._groupLevels ? new Array(this._groupLevels) : null;
 
 		// collect group controls data
 		if (rowGroups !== undefined && this._groups) {
 			this._collectGroupsData(rowGroups);
 		}
+		else if (sheetGeometry) {
+			this._collectGroupsData(sheetGeometry.getRowGroupsDataInView());
+		}
 
 		if (this._groups) {
 			this.resize(this._computeOutlineWidth() + this._borderWidth + this._headerWidth);
diff --git a/loleaflet/src/control/Control.Scroll.js b/loleaflet/src/control/Control.Scroll.js
index e3f9cf4dc..cb323e1c7 100644
--- a/loleaflet/src/control/Control.Scroll.js
+++ b/loleaflet/src/control/Control.Scroll.js
@@ -114,7 +114,7 @@ L.Control.Scroll = L.Control.extend({
 			return;
 		}
 
-		this._map._docLayer.requestViewRowColumnData({ x: newLeft, y: newTop, offset: offset});
+		this._map._docLayer.refreshViewData({ x: newLeft, y: newTop, offset: offset});
 
 		this._prevScrollY = newTop;
 		this._prevScrollX = newLeft;
@@ -267,7 +267,7 @@ L.Control.Scroll = L.Control.extend({
 			offset.y = 1;
 		}
 		if (e.updateHeaders && this._map._docLayer._docType === 'spreadsheet') {
-			this._map._docLayer.requestViewRowColumnData({x: e.x, y: e.y, offset: offset});
+			this._map._docLayer.refreshViewData({x: e.x, y: e.y, offset: offset});
 		}
 		this._map.fire('scrolloffset', offset);
 		this._ignoreScroll = null;
diff --git a/loleaflet/src/layer/CalcGridLines.js b/loleaflet/src/layer/CalcGridLines.js
index 4b4e58d3a..37492b606 100644
--- a/loleaflet/src/layer/CalcGridLines.js
+++ b/loleaflet/src/layer/CalcGridLines.js
@@ -78,8 +78,13 @@ L.CalcGridLines = L.LayerGroup.extend({
 		// into map coordinate units
 		var pixelToMapUnitRatio = this._map.options.crs.scale(this._map.getZoom());
 
-		if (ev.data.columns && ev.data.columns.length) {
-			ticks = new L.Control.Header.GapTickMap(this._map, ev.data.columns);
+		var colDataInEvent = ev.data && ev.data.columns && ev.data.columns.length;
+		var rowDataInEvent = ev.data && ev.data.rows && ev.data.rows.length;
+
+		if (colDataInEvent || ev.updatecolumns) {
+			var columnsData = colDataInEvent ? ev.data.columns : undefined;
+			var columnsGeometry = colDataInEvent ? undefined : this._map._docLayer.sheetGeometry.getColumnsGeometry();
+			ticks = new L.Control.Header.GapTickMap(this._map, columnsData, columnsGeometry);
 			this._colLines.clearLayers();
 
 			ticks.forEachTick(function(idx, pos) {
@@ -92,8 +97,10 @@ L.CalcGridLines = L.LayerGroup.extend({
 			}.bind(this));
 		}
 
-		if (ev.data.rows && ev.data.rows.length) {
-			ticks = new L.Control.Header.GapTickMap(this._map, ev.data.rows);
+		if (rowDataInEvent || ev.updaterows) {
+			var rowsData = rowDataInEvent ? ev.data.rows : undefined;
+			var rowsGeometry = rowDataInEvent ? undefined : this._map._docLayer.sheetGeometry.getRowsGeometry();
+			ticks = new L.Control.Header.GapTickMap(this._map, rowsData, rowsGeometry);
 			this._rowLines.clearLayers();
 
 			ticks.forEachTick(function(idx, pos) {
diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js
index 6ed8ae4b4..2252f2116 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -5,6 +5,10 @@
 
 /* global */
 L.CalcTileLayer = L.TileLayer.extend({
+	options: {
+		sheetGeometryDataEnabled: false
+	},
+
 	STD_EXTRA_WIDTH: 113, /* 2mm extra for optimal width,
 							  * 0.1986cm with TeX points,
 							  * 0.1993cm with PS points. */
@@ -264,13 +268,16 @@ L.CalcTileLayer = L.TileLayer.extend({
 				}
 			}
 		} else if (textMsg.startsWith('invalidateheader: column')) {
-			this.requestViewRowColumnData({x: this._map._getTopLeftPoint().x, y: 0, offset: {x: undefined, y: 0}});
+			this.refreshViewData({x: this._map._getTopLeftPoint().x, y: 0,
+				offset: {x: undefined, y: 0}}, true /* sheetGeometryChanged */);
 			this._map._socket.sendMessage('commandvalues command=.uno:ViewAnnotationsPosition');
 		} else if (textMsg.startsWith('invalidateheader: row')) {
-			this.requestViewRowColumnData({x: 0, y: this._map._getTopLeftPoint().y, offset: {x: 0, y: undefined}});
+			this.refreshViewData({x: 0, y: this._map._getTopLeftPoint().y,
+				offset: {x: 0, y: undefined}}, true /* sheetGeometryChanged */);
 			this._map._socket.sendMessage('commandvalues command=.uno:ViewAnnotationsPosition');
 		} else if (textMsg.startsWith('invalidateheader: all')) {
-			this.requestViewRowColumnData({x: this._map._getTopLeftPoint().x, y: this._map._getTopLeftPoint().y, offset: {x: undefined, y: undefined}});
+			this.refreshViewData({x: this._map._getTopLeftPoint().x, y: this._map._getTopLeftPoint().y,
+				offset: {x: undefined, y: undefined}}, true /* sheetGeometryChanged */);
 			this._map._socket.sendMessage('commandvalues command=.uno:ViewAnnotationsPosition');
 		} else {
 			L.TileLayer.prototype._onMessage.call(this, textMsg, img);
@@ -360,15 +367,17 @@ L.CalcTileLayer = L.TileLayer.extend({
 		if (part !== this._selectedPart && !this.isHiddenPart(part)) {
 			this._map.setPart(part, true);
 			this._map.fire('setpart', {selectedPart: this._selectedPart});
-			// TODO: test it!
-			this.requestViewRowColumnData();
+			this.refreshViewData(undefined, true /* sheetGeometryChanged */);
 		}
 	},
 
 	_onZoomRowColumns: function () {
 		this._sendClientZoom();
-		// TODO: test it!
-		this.requestViewRowColumnData();
+		if (this.sheetGeometry) {
+			this.sheetGeometry.setTileGeometryData(this._tileWidthTwips, this._tileHeightTwips,
+				this._tileSize, this._tilePixelScale);
+		}
+		this.refreshViewData();
 		this._map._socket.sendMessage('commandvalues command=.uno:ViewAnnotationsPosition');
 	},
 
@@ -454,8 +463,13 @@ L.CalcTileLayer = L.TileLayer.extend({
 		}
 	},
 
-	// This send .uno:ViewRowColumnHeaders command to core with the new view coordinates.
-	requestViewRowColumnData: function (coordinatesData) {
+	// This initiates a selective repainting of row/col headers and
+	// gridlines based on the settings of coordinatesData.offset. This
+	// should be called whenever the view area changes (scrolling, panning,
+	// zooming, cursor moving out of view-area etc.).  Depending on the
+	// active sheet geometry data-source, it may ask core to send current
+	// view area's data or the global data on geometry changes.
+	refreshViewData: function (coordinatesData, sheetGeometryChanged) {
 
 		// There are places that call this function with no arguments to indicate that the
 		// command arguments should be the current map area coordinates.
@@ -475,32 +489,57 @@ L.CalcTileLayer = L.TileLayer.extend({
 			topLeftPoint.y = this._map._getTopLeftPoint().y;
 		}
 
+		var updateRows = true;
+		var updateCols = true;
+
 		if (offset.x === 0) {
-			topLeftPoint.x = -1;
-			sizePx.x = 0;
+			updateCols = false;
+			if (!this.options.sheetGeometryDataEnabled) {
+				topLeftPoint.x = -1;
+				sizePx.x = 0;
+			}
 		}
 		if (offset.y === 0) {
-			topLeftPoint.y = -1;
-			sizePx.y = 0;
+			updateRows = false;
+			if (!this.options.sheetGeometryDataEnabled) {
+				topLeftPoint.y = -1;
+				sizePx.y = 0;
+			}
 		}
 
 		var pos = this._pixelsToTwips(topLeftPoint);
 		var size = this._pixelsToTwips(sizePx);
-		var payload = 'commandvalues command=.uno:ViewRowColumnHeaders?x=' + Math.round(pos.x) + '&y=' + Math.round(pos.y) +
-			'&width=' + Math.round(size.x) + '&height=' + Math.round(size.y);
 
-		if (coordinatesData.outline) {
-			payload += '&columnOutline=' + coordinatesData.outline.column + '&groupLevel=' + coordinatesData.outline.level
-				+ '&groupIndex=' + coordinatesData.outline.index + '&groupHidden=' + coordinatesData.outline.hidden;
+		if (!this.options.sheetGeometryDataEnabled) {
+			this.requestViewRowColumnData(pos, size);
+			return;
+		}
+
+		if (sheetGeometryChanged || !this.sheetGeometry) {
+			this.requestSheetGeometryData(
+				{columns: updateCols, rows: updateRows});
+			return;
 		}
 
+		this.sheetGeometry.setViewArea(pos, size);
+		this._updateHeadersGridLines(undefined, updateCols, updateRows);
+	},
+
+	// This send .uno:ViewRowColumnHeaders command to core with the new view coordinates (tile-twips).
+	requestViewRowColumnData: function (pos, size) {
+
+		var payload = 'commandvalues command=.uno:ViewRowColumnHeaders?x=' + Math.round(pos.x) + '&y=' + Math.round(pos.y) +
+			'&width=' + Math.round(size.x) + '&height=' + Math.round(size.y);
+
 		this._map._socket.sendMessage(payload);
 	},
 
 	// sends the .uno:SheetGeometryData command optionally with arguments.
-	requestSheetGeomtryData: function (flags) {
+	requestSheetGeometryData: function (flags) {
 		var unoCmd = '.uno:SheetGeometryData';
-		var haveArgs = (typeof flags == 'object' && (flags.columns === true || flags.rows === true));
+		var haveArgs = (typeof flags == 'object' &&
+			(flags.columns === true || flags.rows === true) &&
+			(flags.columns !== flags.rows));
 		var payload = 'commandvalues command=' + unoCmd;
 
 		if (haveArgs) {
@@ -533,9 +572,15 @@ L.CalcTileLayer = L.TileLayer.extend({
 		this._map._socket.sendMessage(payload);
 	},
 
-	_handleViewRowColumnHeadersMsg: function (jsonMsgObj) {
+	// Sends a notification to the row/col header and gridline controls that
+	// they need repainting.
+	// viewAreaData is the parsed .uno:ViewRowColumnHeaders JSON if that source is used.
+	// else it should be undefined.
+	_updateHeadersGridLines: function (viewAreaData, updateCols, updateRows) {
 		this._map.fire('viewrowcolumnheaders', {
-			data: jsonMsgObj,
+			data: viewAreaData,
+			updaterows: updateRows,
+			updatecolumns: updateCols,
 			cursor: this._getCursorPosSize(),
 			selection: this._getSelectionHeaderData(),
 			converter: this._twipsToPixels,
@@ -544,8 +589,17 @@ L.CalcTileLayer = L.TileLayer.extend({
 	},
 
 	_handleSheetGeometryDataMsg: function (jsonMsgObj) {
-		// TODO: use the L.SheetGeometry datastructure
-		this._map.sheetGeomData = jsonMsgObj;
+		if (!this.sheetGeometry) {
+			this.sheetGeometry = new L.SheetGeometry(jsonMsgObj,
+				this._tileWidthTwips, this._tileHeightTwips,
+				this._tileSize, this._tilePixelScale);
+		}
+
+		this.sheetGeometry.update(jsonMsgObj);
+		this.sheetGeometry.setViewArea(this._pixelsToTwips(this._map._getTopLeftPoint()),
+			this._pixelsToTwips(this._map.getSize()));
+		this._updateHeadersGridLines(undefined, true /* updateCols */,
+			true /* updateRows */);
 	},
 
 	_onCommandValuesMsg: function (textMsg) {
@@ -560,7 +614,7 @@ L.CalcTileLayer = L.TileLayer.extend({
 
 		var comment;
 		if (values.commandName === '.uno:ViewRowColumnHeaders') {
-			this._handleViewRowColumnHeadersMsg(values);
+			this._updateHeadersGridLines(values);
 
 		} else if (values.commandName === '.uno:SheetGeometryData') {
 			this._handleSheetGeometryDataMsg(values);
@@ -697,6 +751,14 @@ L.SheetGeometry = L.Class.extend({
 		return true;
 	},
 
+	getColumnsGeometry: function () {
+		return this._columns;
+	},
+
+	getRowsGeometry: function () {
+		return this._rows;
+	},
+
 	// returns an object with keys 'start' and 'end' indicating the
 	// column range in the current view area.
 	getViewColumnRange: function () {
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index dbc376765..0cd8f9282 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -324,7 +324,7 @@ L.Map = L.Evented.extend({
 		this._socket.sendMessage('commandvalues command=.uno:LanguageStatus');
 		this._socket.sendMessage('commandvalues command=.uno:ViewAnnotations');
 		if (this._docLayer._docType === 'spreadsheet') {
-			this._docLayer.requestViewRowColumnData();
+			this._docLayer.refreshViewData();
 		}
 		this._docLayer._getToolbarCommandsValues();
 	},


More information about the Libreoffice-commits mailing list