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.fran...@collabora.com>
AuthorDate: Fri May 15 08:12:03 2020 +0530
Commit:     Dennis Francis <dennis.fran...@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 <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Dennis Francis <dennis.fran...@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();
        },
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to