loleaflet/build/deps.js | 4 loleaflet/dist/loleaflet.css | 12 + loleaflet/src/control/Control.Menubar.js | 2 loleaflet/src/core/LOUtil.js | 9 + loleaflet/src/layer/AnnotationManager.js | 30 ++-- loleaflet/src/layer/marker/Annotation.js | 19 ++ loleaflet/src/layer/marker/DivOverlay.js | 125 +++++++++++++++++ loleaflet/src/layer/tile/CalcTileLayer.js | 188 ++++++++++++++++++++++++++- loleaflet/src/layer/tile/ImpressTileLayer.js | 7 + loleaflet/src/layer/tile/TileLayer.js | 11 - loleaflet/src/layer/tile/WriterTileLayer.js | 33 ++++ 11 files changed, 410 insertions(+), 30 deletions(-)
New commits: commit 91666d7cd354ef31344cdd88b57d644820dcd52c Author: Henry Castro <[email protected]> Date: Fri Feb 24 15:19:48 2017 -0400 loleaflet: insert Calc comments diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js index 5d3c3c6..e1b2786 100644 --- a/loleaflet/build/deps.js +++ b/loleaflet/build/deps.js @@ -440,6 +440,10 @@ var deps = { desc: 'Annotation to put on the map.' }, + DivOverlay: { + src: ['layer/marker/DivOverlay.js'], + desc: 'Div overlay to put on the map.' + } }; if (typeof exports !== 'undefined') { diff --git a/loleaflet/dist/loleaflet.css b/loleaflet/dist/loleaflet.css index 956aaee..cebdde0 100644 --- a/loleaflet/dist/loleaflet.css +++ b/loleaflet/dist/loleaflet.css @@ -159,3 +159,15 @@ body { resize: none; background-color: #ffffc0; } + +.loleaflet-cell-annotation { + background: red; + border: 1px solid red; + pointer-events: none; +} + +.loleaflet-div-layer { + position: absolute; + left: 0; + top: 0; +} diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js index 9162512..01a4cb5 100644 --- a/loleaflet/src/control/Control.Menubar.js +++ b/loleaflet/src/control/Control.Menubar.js @@ -247,7 +247,7 @@ L.Control.Menubar = L.Control.extend({ }, {name: _('Insert'), type: 'menu', menu: [ {name: _('Image'), id: 'insertgraphic', type: 'action'}, - {name: _('Comment'), type: 'unocommand', uno: '.uno:InsertAnnotation'}, + {name: _('Comment...'), id: 'insertcomment', type: 'action'}, {type: 'separator'}, {name: _('Row'), type: 'unocommand', uno: '.uno:InsertRows'}, {name: _('Column'), type: 'unocommand', uno: '.uno:InsertColumns'}, diff --git a/loleaflet/src/core/LOUtil.js b/loleaflet/src/core/LOUtil.js index da9e323..237edbe 100644 --- a/loleaflet/src/core/LOUtil.js +++ b/loleaflet/src/core/LOUtil.js @@ -54,6 +54,13 @@ L.LOUtil = { stringToPoint: function(point) { var numbers = point.match(/\d+/g); - return L.point(numbers[0], numbers[1]); + return L.point(parseInt(numbers[0]), parseInt(numbers[1])); + }, + + stringToBounds: function(bounds) { + var numbers = bounds.match(/\d+/g); + var topLeft = L.point(parseInt(numbers[0]), parseInt(numbers[1])); + var bottomRight = topLeft.add(L.point(parseInt(numbers[2]), parseInt(numbers[3]))); + return L.bounds(topLeft, bottomRight); } }; diff --git a/loleaflet/src/layer/marker/Annotation.js b/loleaflet/src/layer/marker/Annotation.js index 6e97c9a..26299b0 100644 --- a/loleaflet/src/layer/marker/Annotation.js +++ b/loleaflet/src/layer/marker/Annotation.js @@ -68,6 +68,10 @@ L.Annotation = L.Layer.extend({ return this; }, + isEdit: function () { + return this._editNode && this._editNode.style.display !== 'none'; + }, + focus: function () { this._editText.focus(); }, @@ -106,6 +110,7 @@ L.Annotation = L.Layer.extend({ var events = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'keydown', 'keypress', 'keyup']; L.DomEvent.on(container, 'click', this._onMouseClick, this); + L.DomEvent.on(container, 'mouseleave', this._onMouseLeave, this); for (var it = 0; it < events.length; it++) { L.DomEvent.on(container, events[it], L.DomEvent.stopPropagation, this); } @@ -123,6 +128,20 @@ L.Annotation = L.Layer.extend({ this._map.fire('AnnotationClick', {annotation: this}); }, + _onMouseLeave: function (e) { + var layerPoint = this._map.mouseEventToLayerPoint(e), + latlng = this._map.layerPointToLatLng(layerPoint); + L.DomEvent.stopPropagation(e); + if (this._contextMenu || this.isEdit()) { + return; + } + this.fire('AnnotationMouseLeave', { + originalEvent: e, + latlng: latlng, + layerPoint: layerPoint + }); + }, + _onSaveClick: function (e) { L.DomEvent.stopPropagation(e); this._data.text = this._contentText.innerHTML = this._editText.value; diff --git a/loleaflet/src/layer/marker/DivOverlay.js b/loleaflet/src/layer/marker/DivOverlay.js new file mode 100644 index 0000000..c2b3623 --- /dev/null +++ b/loleaflet/src/layer/marker/DivOverlay.js @@ -0,0 +1,125 @@ +/* + * L.DivOverlay + */ + +L.DivOverlay = L.Layer.extend({ + + initialize: function (latLngBounds, options) { + this._latLngBounds = L.latLngBounds(latLngBounds); + L.setOptions(this, options); + }, + + onAdd: function (map) { + this._map = map; + if (!this._container) { + this._initLayout(); + } + map._panes.overlayPane.appendChild(this._container); + }, + + onRemove: function (map) { + map.removeLayer(this._annotation); + this.unbindAnnotation(); + map._panes.overlayPane.removeChild(this._container); + }, + + setLatLngBounds: function (latLngBounds) { + this._latLngBounds = L.latLngBounds(latLngBounds); + this.update(); + }, + + update: function () { + if (this._container) { + var topLeft = this._map.latLngToLayerPoint(this._latLngBounds.getNorthWest()); + var size = this._map.latLngToLayerPoint(this._latLngBounds.getSouthEast()).subtract(topLeft); + L.DomUtil.setPosition(this._container, topLeft); + this._container.style.width = size.x + 'px'; + this._container.style.height = size.y + 'px'; + } + if (this._annotation) { + this._annotation.setLatLng(this._latLngBounds.getNorthEast()); + } + }, + + openAnnotation: function () { + if (this._map && this._annotation && !this._map.hasLayer(this._annotation) && + !this._annotation.isEdit()) { + this._annotation.setLatLng(this._latLngBounds.getNorthEast()); + this._map.addLayer(this._annotation); + this._annotation.show(); + } + }, + + editAnnotation: function () { + if (this._map && this._annotation) { + this._annotation.setLatLng(this._latLngBounds.getNorthEast()); + this._map.addLayer(this._annotation); + this._annotation.edit(); + this._annotation.focus(); + } + }, + + closeAnnotation: function (e) { + if (this._map && this._annotation && this._map.hasLayer(this._annotation) && + !this._annotation.isEdit() && + !this._annotation.getBounds().contains(e.layerPoint)) { + this._map.removeLayer(this._annotation); + } + }, + + _onMouseLeave: function (e) { + if (this._map && this._annotation && this._map.hasLayer(this._annotation) && + !this._annotation.isEdit() && + !this._latLngBounds.contains(e.latlng)) { + this._map.removeLayer(this._annotation); + } + }, + + bindAnnotation: function (annotation) { + this._annotation = annotation; + if (!this._handlersAdded) { + this.on('mouseover', this.openAnnotation, this); + this.on('mouseout', this.closeAnnotation, this); + this._annotation.on('AnnotationMouseLeave', this._onMouseLeave, this); + this._handlersAdded = true; + } + return this; + }, + + unbindAnnotation: function () { + if (this._annotation) { + this.off('mouseover', this.openAnnotation, this); + this.off('mouseout', this.closeAnnotation, this); + this._annotation.off('AnnoationMouseLeave', this._onMouseLeave, this); + this._handlerAdded = false; + this._annotation = null; + } + return this; + }, + + _initLayout: function () { + this._container = L.DomUtil.create('div', 'loleaflet-div-layer'); + L.DomEvent.on(this._container, 'mouseover', this._fireMouseEvents, this); + L.DomEvent.on(this._container, 'mouseout', this._fireMouseEvents, this); + L.DomUtil.setOpacity(this._container, this.options.opacity); + this.update(); + }, + + _fireMouseEvents: function (e) { + var containerPoint = this._map.mouseEventToContainerPoint(e), + layerPoint = this._map.containerPointToLayerPoint(containerPoint), + latlng = this._map.layerPointToLatLng(layerPoint); + + this.fire(e.type, { + latlng: latlng, + layerPoint: layerPoint, + containerPoint: containerPoint, + originalEvent: e + }); + } +}); + +L.divOverlay = function (latLngBounds, options) { + return new L.DivOverlay(latLngBounds, options); +}; + diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js index 8bfcb6f..3b34c4a 100644 --- a/loleaflet/src/layer/tile/CalcTileLayer.js +++ b/loleaflet/src/layer/tile/CalcTileLayer.js @@ -13,11 +13,176 @@ L.CalcTileLayer = L.TileLayer.extend({ }, newAnnotation: function (comment) { + var annotation; + for (var key in this._annotations) { + if (this._cellCursor.contains(this._annotations[key]._annotation._data.cellPos)) { + annotation = this._annotations[key]; + break; + } + } + + if (annotation) { + annotation.editAnnotation(); + } else { + comment.cellPos = this._cellCursor; + this.addAnnotation(comment).editAnnotation(); + } + }, + + addAnnotation: function (comment) { + var annotation = L.divOverlay(comment.cellPos).bindAnnotation(L.annotation(L.latLng(0, 0), comment)); + annotation.mark = L.marker(comment.cellPos.getNorthEast(), { + draggable: false, + clickable:false, + keyboard: false, + icon: L.divIcon({ + iconSize: L.point(2, 2), + iconAnchor: L.point(4, 0), + className: 'loleaflet-cell-annotation' + }) + }); + this._map.addLayer(annotation); + this._map.addLayer(annotation.mark); + this._annotations[comment.id] = annotation; + return annotation; }, beforeAdd: function (map) { map._addZoomLimit(this); map.on('zoomend', this._onZoomRowColumns, this); + map.on('AnnotationCancel', this._onAnnotationCancel, this); + map.on('AnnotationSave', this._onAnnotationSave, this); + }, + + clearAnnotations: function () { + for (var key in this._annotations) { + this._map.removeLayer(this._annotations[key].mark); + this._map.removeLayer(this._annotations[key]); + } + this._annotations = {}; + }, + + onAdd: function (map) { + var that = this; + L.TileLayer.prototype.onAdd.call(this, map); + this._annotations = {}; + $.contextMenu({ + selector: '.loleaflet-annotation-content', + className: 'loleaflet-font', + items: { + modify: { + name: _('Modify'), + callback: function (key, options) { + that._onAnnotationModify.call(that, options.$trigger.get(0).annotation); + } + }, + remove: { + name: _('Remove'), + callback: function (key, options) { + that._onAnnotationRemove.call(that, options.$trigger.get(0).annotation._data.id); + } + } + }, + events: { + show: function (options) { + options.$trigger.get(0).annotation._contextMenu = true; + }, + hide: function (options) { + options.$trigger.get(0).annotation._contextMenu = false; + } + } + }); + }, + + removeAnnotation: function (id) { + var annotation = this._annotations[id]; + this._map.removeLayer(annotation.mark); + this._map.removeLayer(annotation); + delete this._annotations[id]; + }, + + _onAnnotationCancel: function (e) { + if (e.annotation._data.id === 'new') { + this.removeAnnotation(e.annotation._data.id); + } + this._map.focus(); + }, + + _onAnnotationSave: function (e) { + var comment; + if (e.annotation._data.id === 'new') { + comment = { + Text: { + type: 'string', + value: e.annotation._data.text + }, + Author: { + type: 'string', + value: e.annotation._data.author + } + }; + this._map.sendUnoCommand('.uno:InsertAnnotation', comment); + } else { + comment = { + Id: { + type: 'string', + value: e.annotation._data.id + }, + Text: { + type: 'string', + value: e.annotation._data.text + } + }; + this._map.sendUnoCommand('.uno:EditAnnotation', comment); + } + this._map.focus(); + }, + + _onAnnotationModify: function (annotation) { + annotation.edit(); + annotation.focus(); + }, + + _onAnnotationRemove: function (id) { + var comment = { + Id: { + type: 'string', + value: id + } + }; + this._map.sendUnoCommand('.uno:DeleteComment', comment); + this.removeAnnotation(id); + this._map.focus(); + }, + + _onMessage: function (textMsg, img) { + if (textMsg.startsWith('comment:')) { + var obj = JSON.parse(textMsg.substring('comment:'.length + 1)); + obj.comment.cellPos = L.LOUtil.stringToBounds(obj.comment.cellPos); + obj.comment.cellPos = L.latLngBounds(this._twipsToLatLng(obj.comment.cellPos.getBottomLeft()), + this._twipsToLatLng(obj.comment.cellPos.getTopRight())); + if (obj.comment.action === 'Add') { + var added = this._annotations['new']; + if (added) { + added._annotation._data = obj.comment; + added.setLatLngBounds(obj.comment.cellPos); + } else { + this.addAnnotation(obj.comment); + } + } else if (obj.comment.action === 'Remove') { + if (this._annotations[obj.comment.id]) { + this.removeAnnotation(obj.comment.id); + } + } else if (obj.comment.action === 'Modify') { + var modified = this._annotations[obj.comment.id]; + if (modified) { + modified._annotation._data = obj.comment; + modified.setLatLngBounds(obj.comment.cellPos); + } + } + } else { + L.TileLayer.prototype._onMessage.call(this, textMsg, img); + } }, _onInvalidateTilesMsg: function (textMsg) { @@ -221,15 +386,29 @@ L.CalcTileLayer = L.TileLayer.extend({ }, _onCommandValuesMsg: function (textMsg) { - if (textMsg.match('.uno:ViewRowColumnHeaders')) { - var data = JSON.parse(textMsg.substring(textMsg.indexOf('{'))); + var values = JSON.parse(textMsg.substring(textMsg.indexOf('{'))); + if (!values) { + return; + } + + if (values.commandName === '.uno:ViewRowColumnHeaders') { this._map.fire('viewrowcolumnheaders', { - data: data, + data: values, converter: this._twipsToPixels, context: this }); this._onUpdateCurrentHeader(); this._onUpdateSelectionHeader(); + } else if (values.comments) { + var comment; + this.clearAnnotations(); + for (var index in values.comments) { + comment = values.comments[index]; + comment.cellPos = L.LOUtil.stringToBounds(comment.cellPos); + comment.cellPos = L.latLngBounds(this._twipsToLatLng(comment.cellPos.getBottomLeft()), + this._twipsToLatLng(comment.cellPos.getTopRight())); + this.addAnnotation(comment); + } } else { L.TileLayer.prototype._onCommandValuesMsg.call(this, textMsg); commit fdd30504f825bb6111cb5cca2356996da5e88d8a Author: Henry Castro <[email protected]> Date: Fri Feb 24 15:54:10 2017 -0400 loleaflet: rework insert new annotations diff --git a/loleaflet/src/layer/AnnotationManager.js b/loleaflet/src/layer/AnnotationManager.js index 7ea8079..bb9aa2e 100644 --- a/loleaflet/src/layer/AnnotationManager.js +++ b/loleaflet/src/layer/AnnotationManager.js @@ -170,15 +170,18 @@ L.AnnotationManager = L.Class.extend({ } }, - add: function (comment) { - var annotation = L.annotation(this._map.options.maxBounds.getSouthEast(), comment).addTo(this._map).edit(); + add: function (comment, edit) { + var annotation = L.annotation(this._map.options.maxBounds.getSouthEast(), comment).addTo(this._map); this._items.push(annotation); this._items.sort(function(a, b) { return Math.abs(a._data.anchorPos.y) - Math.abs(b._data.anchorPos.y) || Math.abs(a._data.anchorPos.x) - Math.abs(b._data.anchorPos.x); }); - this.select(annotation); - annotation.focus(); + if (edit) { + annotation.edit(); + this.select(annotation); + annotation.focus(); + } }, remove: function (id) { @@ -200,14 +203,12 @@ L.AnnotationManager = L.Class.extend({ Math.abs(a._data.anchorPos.x) - Math.abs(b._data.anchorPos.x); }); added._updateContent(); - this.layout(); } else { // annotation is added by some other view - this._map.insertComment(obj.comment); - this.unselect(); + this.add(obj.comment, false); this._map.focus(); } - + this.layout(); } else if (obj.comment.action === 'Remove') { if (this.getItem(obj.comment.id)) { this.remove(obj.comment.id); @@ -288,13 +289,12 @@ L.AnnotationManager = L.Class.extend({ L.Map.include({ insertComment: function(comment) { comment = !!comment ? comment : {}; - this._docLayer._annotations.add({ - text: comment.text ? comment.text : '', - textrange: comment.textrange ? comment.textrange : '', - author: comment.author ? comment.author : this.getViewName(this._docLayer._viewId), - dateTime: comment.dateTime ? comment.dateTime : new Date().toDateString(), - id: comment.id ? comment.id : 'new', // 'new' only when added by us - anchorPos: comment.anchorPos ? comment.anchorPos : this._docLayer._latLngToTwips(this._docLayer._visibleCursor.getNorthWest()) + this._docLayer.newAnnotation({ + text: '', + textrange: '', + author: this.getViewName(this._docLayer._viewId), + dateTime: new Date().toDateString(), + id: 'new' // 'new' only when added by us }); } }); diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js index 61638b6..8bfcb6f 100644 --- a/loleaflet/src/layer/tile/CalcTileLayer.js +++ b/loleaflet/src/layer/tile/CalcTileLayer.js @@ -12,6 +12,9 @@ L.CalcTileLayer = L.TileLayer.extend({ return (twips * 127 + 36) / 72; }, + newAnnotation: function (comment) { + }, + beforeAdd: function (map) { map._addZoomLimit(this); map.on('zoomend', this._onZoomRowColumns, this); diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js b/loleaflet/src/layer/tile/ImpressTileLayer.js index 3f20f56..e384d5f 100644 --- a/loleaflet/src/layer/tile/ImpressTileLayer.js +++ b/loleaflet/src/layer/tile/ImpressTileLayer.js @@ -5,6 +5,13 @@ L.ImpressTileLayer = L.TileLayer.extend({ + newAnnotation: function (comment) { + }, + + onAdd: function (map) { + L.TileLayer.prototype.onAdd.call(this, map); + }, + _onInvalidateTilesMsg: function (textMsg) { var command = this._map._socket.parseServerCmd(textMsg); if (command.x === undefined || command.y === undefined || command.part === undefined) { diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js index f86b5bd..46acb29 100644 --- a/loleaflet/src/layer/tile/TileLayer.js +++ b/loleaflet/src/layer/tile/TileLayer.js @@ -169,10 +169,7 @@ L.TileLayer = L.GridLayer.extend({ this._levels = {}; this._tiles = {}; this._tileCache = {}; - this._annotations = L.annotationManager(map); - if (this._docType === 'text') { - this._map._socket.sendMessage('commandvalues command=.uno:ViewAnnotations'); - } + this._map._socket.sendMessage('commandvalues command=.uno:ViewAnnotations'); map._fadeAnimated = false; this._viewReset(); @@ -397,9 +394,6 @@ L.TileLayer = L.GridLayer.extend({ else if (textMsg.startsWith('graphicviewselection:')) { this._onGraphicViewSelectionMsg(textMsg); } - else if (textMsg.startsWith('comment:')) { - this._annotations.onACKComment(textMsg); - } }, toggleTileDebugMode: function() { @@ -439,9 +433,6 @@ L.TileLayer = L.GridLayer.extend({ commandValues: obj.commandValues }); } - else if (obj.comments) { - this._annotations.fill(obj.comments); - } else { this._map.fire('commandvalues', { commandName: obj.commandName, diff --git a/loleaflet/src/layer/tile/WriterTileLayer.js b/loleaflet/src/layer/tile/WriterTileLayer.js index 9a4966b..114ee76 100644 --- a/loleaflet/src/layer/tile/WriterTileLayer.js +++ b/loleaflet/src/layer/tile/WriterTileLayer.js @@ -5,6 +5,39 @@ L.WriterTileLayer = L.TileLayer.extend({ + newAnnotation: function (comment) { + if (!comment.anchorPos) { + comment.anchorPos = this._latLngToTwips(this._visibleCursor.getNorthWest()); + } + this._annotations.add(comment, true); + }, + + onAdd: function (map) { + L.TileLayer.prototype.onAdd.call(this, map); + this._annotations = L.annotationManager(map); + }, + + _onCommandValuesMsg: function (textMsg) { + var values = JSON.parse(textMsg.substring(textMsg.indexOf('{'))); + if (!values) { + return; + } + + if (values.comments) { + this._annotations.fill(values.comments); + } else { + L.TileLayer.prototype._onCommandValuesMsg.call(this, textMsg); + } + }, + + _onMessage: function (textMsg, img) { + if (textMsg.startsWith('comment:')) { + this._annotations.onACKComment(textMsg); + } else { + L.TileLayer.prototype._onMessage.call(this, textMsg, img); + } + }, + _onInvalidateTilesMsg: function (textMsg) { var command = this._map._socket.parseServerCmd(textMsg); if (command.x === undefined || command.y === undefined || command.part === undefined) { _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
