loleaflet/Makefile                                    |    2 
 loleaflet/README                                      |   22 
 loleaflet/build/deps.js                               |   19 
 loleaflet/debug/document/document_simple_example.html |   21 
 loleaflet/spec/loleaflet/loleafletSpec.js             |   23 
 loleaflet/spec/tilebench/TileBenchSpec.js             |   30 
 loleaflet/src/control/Buttons.js                      |    4 
 loleaflet/src/control/Control.Parts.js                |    6 
 loleaflet/src/control/Control.PartsPreview.js         |    8 
 loleaflet/src/control/Control.Search.js               |    2 
 loleaflet/src/control/Control.Tabs.js                 |    4 
 loleaflet/src/control/Parts.js                        |   56 +
 loleaflet/src/control/Permission.js                   |    4 
 loleaflet/src/control/Search.js                       |    4 
 loleaflet/src/core/Socket.js                          |  204 +++++
 loleaflet/src/layer/Layer.js                          |    5 
 loleaflet/src/layer/tile/CalcTileLayer.js             |  126 +++
 loleaflet/src/layer/tile/GridLayer.js                 |   90 --
 loleaflet/src/layer/tile/ImpressTileLayer.js          |  156 ++++
 loleaflet/src/layer/tile/TileLayer.js                 |  685 ++++++------------
 loleaflet/src/layer/tile/WriterTileLayer.js           |  158 ++++
 loleaflet/src/map/Map.js                              |   40 -
 loleaflet/src/map/handler/Map.DoubleClickZoom.js      |    2 
 loleaflet/src/map/handler/Map.Mouse.js                |    4 
 loolwsd/LOOLWSD.cpp                                   |   11 
 loolwsd/configure.ac                                  |    2 
 26 files changed, 1051 insertions(+), 637 deletions(-)

New commits:
commit c60b89b9a87a31a687cd4a5d4e5f811628e52435
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Mon Sep 7 15:56:47 2015 +0300

    loolwsd: copy /etc/hosts when running the server

diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 2f86e50..8e76a80 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -869,6 +869,11 @@ void LOOLWSD::desktopMain()
     {
         resolv.copyTo(Path(jail, "/etc").toString());
     }
+    File hosts("/etc/hosts");
+    if (hosts.exists())
+    {
+        hosts.copyTo(Path(jail, "/etc").toString());
+    }
 #ifdef __linux
     // Create the urandom and random devices
     File(Path(jail, "/dev")).createDirectory();
commit e1d2db5cec5eda60b37e5511a3b72b740b9f9125
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Mon Sep 7 11:45:36 2015 +0300

    loleaflet: bump version after tarball

diff --git a/loleaflet/Makefile b/loleaflet/Makefile
index 2d2ea05..e21333b 100644
--- a/loleaflet/Makefile
+++ b/loleaflet/Makefile
@@ -3,7 +3,7 @@
 # ("micro") part: Between releases odd, even for releases (no other
 # changes inbetween).
 
-VERSION=1.1.38
+VERSION=1.1.39
 
 # Version number of the bundled 'draw' thing
 DRAW_VERSION=0.2.4
commit 2e660ebfd0689e523d48c6534c25ea11092c7e07
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Mon Sep 7 11:45:23 2015 +0300

    lolealfet: bump version beforetarball

diff --git a/loleaflet/Makefile b/loleaflet/Makefile
index aa5021a..2d2ea05 100644
--- a/loleaflet/Makefile
+++ b/loleaflet/Makefile
@@ -3,7 +3,7 @@
 # ("micro") part: Between releases odd, even for releases (no other
 # changes inbetween).
 
-VERSION=1.1.37
+VERSION=1.1.38
 
 # Version number of the bundled 'draw' thing
 DRAW_VERSION=0.2.4
commit 2d4b34ef1e7edd3205466ad4b989b9b0d9119f23
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Mon Sep 7 11:38:49 2015 +0300

    lolealfet: don't prefetch if map is undefined
    
    This happens when the map is removed and some hooks still remain

diff --git a/loleaflet/src/layer/tile/GridLayer.js 
b/loleaflet/src/layer/tile/GridLayer.js
index 95469d5..844736a 100644
--- a/loleaflet/src/layer/tile/GridLayer.js
+++ b/loleaflet/src/layer/tile/GridLayer.js
@@ -897,6 +897,9 @@ L.GridLayer = L.Layer.extend({
        },
 
        _resetPreFetching: function (resetBorder) {
+               if (!this._map) {
+                       return;
+               }
                clearInterval(this._tilesPreFetcher);
                clearTimeout(this._preFetchIdle);
                if (resetBorder) {
commit 428357fee1a5365c44f426f58606c0db2662be1c
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Mon Sep 7 11:38:34 2015 +0300

    loleaflet: We don't have styles yet

diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 4e2846f..57852d7 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -52,7 +52,6 @@ L.Socket = {
                }
                this.socket.send(msg);
                this.socket.send('status');
-               this.socket.send('styles');
                for (var i = 0; i < this._msgQueue.length; i++) {
                        this.socket.send(this._msgQueue[i].msg);
                        L.Log.log(this._msgQueue[i].msg, 
this._msgQueue[i].coords);
commit feb629081905ecd4258167c8efe38577a4a53f46
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Thu Sep 3 10:33:20 2015 +0300

    loleaflet: hide selection when switching thorugh cached parts

diff --git a/loleaflet/src/control/Parts.js b/loleaflet/src/control/Parts.js
index 040d909..55d4c9b 100644
--- a/loleaflet/src/control/Parts.js
+++ b/loleaflet/src/control/Parts.js
@@ -31,9 +31,9 @@ L.Map.include({
                        docType: docLayer._docType
                });
                L.Socket.sendMessage('setclientpart part=' + 
docLayer._selectedPart);
+               docLayer._clearSelections();
                docLayer._update();
                docLayer._pruneTiles();
-               docLayer._clearSelections();
                docLayer._prevSelectedPartNeedsUpdate = true;
                if (docLayer._invalidatePreview) {
                        docLayer._invalidatePreview();
diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js 
b/loleaflet/src/layer/tile/CalcTileLayer.js
index 7550ddb..d405e2d 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -91,7 +91,6 @@ L.CalcTileLayer = L.TileLayer.extend({
                if (part !== this._selectedPart) {
                        this._selectedPart = part;
                        this._update();
-                       this._clearSelections();
                        this._map.fire('setpart', {selectedPart: 
this._selectedPart});
                }
        },
diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js 
b/loleaflet/src/layer/tile/ImpressTileLayer.js
index 2acc5c3..1717cf3 100644
--- a/loleaflet/src/layer/tile/ImpressTileLayer.js
+++ b/loleaflet/src/layer/tile/ImpressTileLayer.js
@@ -97,7 +97,6 @@ L.ImpressTileLayer = L.TileLayer.extend({
                if (part !== this._selectedPart) {
                        this._selectedPart = part;
                        this._update();
-                       this._clearSelections();
                        this._map.fire('setpart', {selectedPart: 
this._selectedPart});
                }
        },
diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 8e89c1e..010d3f3 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -105,7 +105,6 @@ L.TileLayer = L.GridLayer.extend({
                map._fadeAnimated = false;
                this._viewReset();
                map.on('drag resize zoomend', this._updateScrollOffset, this);
-               map.on('clearselection', this._clearSelections, this);
                map.on('copy', this._onCopy, this);
                map.on('zoomend', this._onUpdateCursor, this);
                map.on('dragstart', this._onDragStart, this);
@@ -300,7 +299,7 @@ L.TileLayer = L.GridLayer.extend({
 
        _onTextSelectionMsg: function (textMsg) {
                var strTwips = textMsg.match(/\d+/g);
-               this._clearSelections();
+               this._selections.clearLayers();
                if (strTwips != null) {
                        var rectangles = [];
                        var selectionCenter = new L.Point(0, 0);
@@ -437,7 +436,16 @@ L.TileLayer = L.GridLayer.extend({
        },
 
        _clearSelections: function () {
+               // hide the cursor
+               this._isCursorOverlayVisible = false;
+               this._onUpdateCursor();
+               // hide the text selection
                this._selections.clearLayers();
+               // hide the selection handles
+               this._onUpdateTextSelection();
+               // hide the graphic selection
+               this._graphicSelection = null;
+               this._onUpdateGraphicSelection();
        },
 
        _postMouseEvent: function(type, x, y, count) {
@@ -533,7 +541,7 @@ L.TileLayer = L.GridLayer.extend({
 
        // Update group layer selection handler.
        _onUpdateGraphicSelection: function () {
-               if (!this._isEmptyRectangle(this._graphicSelection)) {
+               if (this._graphicSelection && 
!this._isEmptyRectangle(this._graphicSelection)) {
                        if (this._graphicMarker) {
                                this._graphicMarker.off('editstart editend', 
this._onGraphicEdit, this);
                                this._map.removeLayer(this._graphicMarker);
commit 59bf3c169d5f4acffea207576782718741132b74
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Thu Sep 3 09:49:55 2015 +0300

    loleaflet: don't handle mouse events before the doc is loaded

diff --git a/loleaflet/src/map/handler/Map.Mouse.js 
b/loleaflet/src/map/handler/Map.Mouse.js
index 9049084..a5f58f1 100644
--- a/loleaflet/src/map/handler/Map.Mouse.js
+++ b/loleaflet/src/map/handler/Map.Mouse.js
@@ -25,6 +25,10 @@ L.Map.Mouse = L.Handler.extend({
 
        _onMouseEvent: function (e) {
                var docLayer = this._map._docLayer;
+               if (!docLayer) {
+                       // document not yet loaded
+                       return;
+               }
                if (docLayer._graphicMarker && 
docLayer._graphicMarker.isDragged) {
                        return;
                }
commit 25cc20693edc7ed7287dd938fd719af65664f5af
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Thu Sep 3 09:34:16 2015 +0300

    loleaflet: don't prefetch in tilebench

diff --git a/loleaflet/spec/tilebench/TileBenchSpec.js 
b/loleaflet/spec/tilebench/TileBenchSpec.js
index 926a100..7fb85de 100644
--- a/loleaflet/spec/tilebench/TileBenchSpec.js
+++ b/loleaflet/spec/tilebench/TileBenchSpec.js
@@ -49,6 +49,7 @@ describe('TileBench', function () {
                        map.on('statusindicator', L.bind(function (e) {
                                if (e.statusType === 'alltilesloaded') {
                                        map.fire('requestloksession');
+                                       map._docLayer._preFetchTiles = function 
() {};
                                        done();
                                }
                        }, done));
commit 5d9ea2eb14f5b1eded96f542a33c24dd70deec9e
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 20:00:42 2015 +0300

    loleaflet: moved img decoding in L.Socket
    
    This gives a better tile loading time by 10ms

diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 781c25b..4e2846f 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -84,6 +84,15 @@ L.Socket = {
                                textMsg = String.fromCharCode.apply(null, 
imgBytes);
                        }
                }
+               else {
+                       var data = imgBytes.subarray(index + 1);
+                       // read the tile data
+                       var strBytes = '';
+                       for (var i = 0; i < data.length; i++) {
+                               strBytes += String.fromCharCode(data[i]);
+                       }
+                       var img = 'data:image/png;base64,' + 
window.btoa(strBytes);
+               }
 
                if (textMsg.startsWith('status:') && !this._map._docLayer) {
                        // first status message, we need to create the document 
layer
@@ -112,7 +121,7 @@ L.Socket = {
                        this._map.addLayer(docLayer);
                }
                if (this._map._docLayer) {
-                       this._map._docLayer._onMessage(textMsg, imgBytes, 
index);
+                       this._map._docLayer._onMessage(textMsg, img);
                }
        },
 
diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 12af0b8..8e89c1e 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -174,7 +174,7 @@ L.TileLayer = L.GridLayer.extend({
                return tile;
        },
 
-       _onMessage: function (textMsg, imgBytes, index) {
+       _onMessage: function (textMsg, img) {
                if (textMsg.startsWith('cursorvisible:')) {
                        this._onCursorVisibleMsg(textMsg);
                }
@@ -221,7 +221,7 @@ L.TileLayer = L.GridLayer.extend({
                        this._onTextSelectionStartMsg(textMsg);
                }
                else if (textMsg.startsWith('tile:')) {
-                       this._onTileMsg(textMsg, imgBytes, index);
+                       this._onTileMsg(textMsg, img);
                }
        },
 
@@ -378,22 +378,13 @@ L.TileLayer = L.GridLayer.extend({
                }
        },
 
-       _onTileMsg: function (textMsg, imgBytes, index) {
+       _onTileMsg: function (textMsg, img) {
                var command = L.Socket.parseServerCmd(textMsg);
                var coords = this._twipsToCoords(command);
                coords.z = command.zoom;
                coords.part = command.part;
-               var data = imgBytes.subarray(index + 1);
-
-               // read the tile data
-               var strBytes = '';
-               for (var i = 0; i < data.length; i++) {
-                       strBytes += String.fromCharCode(data[i]);
-               }
-
                var key = this._tileCoordsToKey(coords);
                var tile = this._tiles[key];
-               var img = 'data:image/png;base64,' + window.btoa(strBytes);
                if (command.id !== undefined) {
                        this._map.fire('tilepreview', {
                                tile: img,
commit ce5b5f9fb56d1c88b94affaa17b722bf6be9a5ae
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 19:50:24 2015 +0300

    loleaflet: fixed typo and removed return value

diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index b9bf086..781c25b 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -17,7 +17,6 @@ L.Socket = {
                this.socket.onopen = L.bind(this._onOpen, this);
                this.socket.onmessage = L.bind(this._onMessage, this);
                this.socket.binaryType = 'arraybuffer';
-               return this.socket;
        },
 
        close: function () {
@@ -29,7 +28,7 @@ L.Socket = {
        sendMessage: function (msg, coords) {
                var socketState = this.socket.readyState;
                if (socketState === 2 || socketState === 3) {
-                       this._socket = this.connect(this._map);
+                       this.connect(this._map);
                        this._msgQueue.push({msg: msg, coords: coords});
                }
 
commit a416bf27e7d0727f690dbdb6bbbd0cb0d0bfecf5
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 18:16:59 2015 +0300

    loleaflet: sometimes the graphic marker is not created
    
    It was reported to me but I couldn't reproduce. I suspect some invalid
    coordinates

diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index fffba11..12af0b8 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -548,6 +548,10 @@ L.TileLayer = L.GridLayer.extend({
                                this._map.removeLayer(this._graphicMarker);
                        }
                        this._graphicMarker = 
L.rectangle(this._graphicSelection, {fill: false});
+                       if (!this._graphicMarker) {
+                               this._map.fire('error', {msg: 'Graphic marker 
initialization'});
+                               return;
+                       }
                        this._graphicMarker.editing.enable();
                        this._graphicMarker.on('editstart editend', 
this._onGraphicEdit, this);
                        this._map.addLayer(this._graphicMarker);
commit f9633c967dbadba64c16f99ad9a307b154ebf941
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 18:09:08 2015 +0300

    loleaflet: updated the tests to reflect the new map initialization
    
    Conflicts:
        loleaflet/spec/loadtest/LoadTestSpec.js
        loleaflet/spec/tilebench/TileBenchSpec.js

diff --git a/loleaflet/spec/loleaflet/loleafletSpec.js 
b/loleaflet/spec/loleaflet/loleafletSpec.js
index 2d0edf5..fd16985 100644
--- a/loleaflet/spec/loleaflet/loleafletSpec.js
+++ b/loleaflet/spec/loleaflet/loleafletSpec.js
@@ -15,34 +15,11 @@ describe('TileBench', function () {
        before(function () {
                // initialize the map and load the document
                map = L.map('map', {
-                       center: [0, 0],
-                       zoom: 10,
-                       minZoom: 1,
-                       maxZoom: 20,
                        server: 'ws://localhost:9980',
-                       doubleClickZoom: false
-               });
-
-               var docLayer = new L.TileLayer('', {
                        doc: 'file:///home/mihai/Desktop/test_docs/eval.odt',
-                       useSocket : true,
                        edit: false,
                        readOnly: false
                });
-
-               docLayer.sendMessage = L.bind(function (msg, coords) {
-                       var now = Date.now();
-                       if (msg.startsWith('tile')) {
-                               msg += ' timestamp=' + now;
-                       }
-                       L.Log.log(msg, L.OUTGOING, coords, now);
-                       this._map.socket.send(msg);
-               }, docLayer);
-
-               // don't pre-fetch tiles
-               docLayer._preFetchTiles = L.Util.falseFn;
-
-               map.addLayer(docLayer);
        });
 
        afterEach(function () {
diff --git a/loleaflet/spec/tilebench/TileBenchSpec.js 
b/loleaflet/spec/tilebench/TileBenchSpec.js
index a31a0b6..926a100 100644
--- a/loleaflet/spec/tilebench/TileBenchSpec.js
+++ b/loleaflet/spec/tilebench/TileBenchSpec.js
@@ -16,36 +16,23 @@ describe('TileBench', function () {
        before(function () {
                // initialize the map and load the document
                map = L.map('map', {
-                       center: [0, 0],
-                       zoom: 10,
-                       minZoom: 1,
-                       maxZoom: 20,
                        server: 'ws://localhost:9980',
-                       doubleClickZoom: false
-               });
-
-               var docLayer = new L.TileLayer('', {
                        doc: 'file:///home/mihai/Desktop/test_docs/eval.odt',
-                       useSocket : true,
                        edit: false,
                        readOnly: false
                });
 
                // add a timestamp to tile messages so we can identify
                // the response
-               docLayer.sendMessage = L.bind(function (msg, coords) {
+               L.Socket.sendMessage = L.bind(function (msg, coords) {
                        var now = Date.now();
                        if (msg.startsWith('tile')) {
                                msg += ' timestamp=' + now;
                        }
                        L.Log.log(msg, L.OUTGOING, coords, now);
-                       this._map.socket.send(msg);
-               }, docLayer);
-
-               // don't pre-fetch tiles
-               docLayer._preFetchTiles = L.Util.falseFn;
+                       this.socket.send(msg);
+               }, L.Socket);
 
-               map.addLayer(docLayer);
                map.addControl(L.control.scroll());
        });
 
@@ -54,16 +41,14 @@ describe('TileBench', function () {
        });
 
        after(function () {
-               map.socket.onclose = undefined;
-               map.socket.onerror = undefined;
-               map.socket.close();
+               map.remove();
        });
 
        describe('Benchmarking', function () {
                it('Load all new tiles', function (done) {
                        map.on('statusindicator', L.bind(function (e) {
                                if (e.statusType === 'alltilesloaded') {
-                                       loadCount += 1;
+                                       map.fire('requestloksession');
                                        done();
                                }
                        }, done));
@@ -92,7 +77,7 @@ describe('TileBench', function () {
                                var y = Math.floor(docLayer._docHeightTwips / 
docLayer._tileHeightTwips);
                                var coords = new L.Point(x, y);
                                coords.z = map.getZoom();
-                               coords.part = docLayer._currentPart;
+                               coords.part = docLayer._selectedPart;
                                var key = docLayer._tileCoordsToKey(coords);
                                if (docLayer._tiles[key]) {
                                        // the tile is already here, the whole 
document is loaded
@@ -104,7 +89,7 @@ describe('TileBench', function () {
 
                        for (var i = 0; i < keyInput.length; i++) {
                                setTimeout(L.bind(function () {
-                                       
map._docLayer.sendMessage(keyInput[this][1]);
+                                       L.Socket.sendMessage(keyInput[this][1]);
                                }, i), keyInput[i][0]);
                        }
                });
commit e2cecbc2076042e029107f3f4c2f4100b55ce83c
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 17:23:33 2015 +0300

    loleaflet: autoupdate previews from the preview control

diff --git a/loleaflet/src/control/Control.PartsPreview.js 
b/loleaflet/src/control/Control.PartsPreview.js
index 1bec8a4..4112d01 100644
--- a/loleaflet/src/control/Control.PartsPreview.js
+++ b/loleaflet/src/control/Control.PartsPreview.js
@@ -3,6 +3,10 @@
  */
 
 L.Control.PartsPreview = L.Control.extend({
+       options: {
+               autoUpdate: true
+       },
+
        onAdd: function (map) {
                this._previewInitialized = false;
                this._previewTiles = {};
@@ -42,7 +46,7 @@ L.Control.PartsPreview = L.Control.extend({
                                        .on(img, 'click', L.DomEvent.stop)
                                        .on(img, 'click', this._setPart, this)
                                        .on(img, 'click', this._refocusOnMap, 
this);
-                               this._map.getPartPreview(i, i, 180, 180);
+                               this._map.getPartPreview(i, i, 180, 180, 
{autoUpdate: this.options.autoUpdate});
                        }
                        this._previewInitialized = true;
                }
@@ -57,7 +61,7 @@ L.Control.PartsPreview = L.Control.extend({
 
        _updatePart: function (e) {
                if (e.docType === 'presentation') {
-                       this._map.getPartPreview(e.part, e.part, 180, 180);
+                       this._map.getPartPreview(e.part, e.part, 180, 180, 
{autoUpdate: this.options.autoUpdate});
                }
        },
 
commit e2a67ba62da7dc3fde89259d6e06c19dbd3c86c7
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 17:21:35 2015 +0300

    loleaflet: impress preview invalidation

diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js 
b/loleaflet/src/layer/tile/ImpressTileLayer.js
index 2a437ef..2acc5c3 100644
--- a/loleaflet/src/layer/tile/ImpressTileLayer.js
+++ b/loleaflet/src/layer/tile/ImpressTileLayer.js
@@ -86,6 +86,10 @@ L.ImpressTileLayer = L.TileLayer.extend({
                        this._lastValidPart = command.part;
                        this._map.fire('updatepart', {part: command.part, 
docType: this._docType});
                }
+
+               // 1s after the last invalidation, update the preview
+               clearTimeout(this._previewInvalidator);
+               this._previewInvalidator = 
setTimeout(L.bind(this._invalidatePreview, this), 1000);
        },
 
        _onSetPartMsg: function (textMsg) {
@@ -124,6 +128,30 @@ L.ImpressTileLayer = L.TileLayer.extend({
                                this._preFetchPart = this._selectedPart;
                                this._preFetchBorder = null;
                        }
-        }
+               }
+       },
+
+       _invalidatePreview: function () {
+               if (this._map._docPreviews) {
+                       // invalidate part previews
+                       for (var key in this._map._docPreviews) {
+                               var preview = this._map._docPreviews[key];
+                               if (preview.part === this._selectedPart ||
+                                       (preview.part === 
this._prevSelectedPart && this._prevSelectedPartNeedsUpdate)) {
+                                       // if the current part needs its 
preview updated OR
+                                       // the part has been changed and we 
need to update the previous part preview
+                                       if (preview.part === 
this._prevSelectedPart) {
+                                               
this._prevSelectedPartNeedsUpdate = false;
+                                       }
+                                       if (preview.autoUpdate) {
+                                               
this._map.getPartPreview(preview.id, preview.part, preview.maxWidth, 
preview.maxHeight,
+                                                               {autoUpdate: 
true});
+                                       }
+                                       else {
+                                               
this._map.fire('invalidatepreview', {id: preview.id});
+                                       }
+                               }
+                       }
+               }
        }
 });
commit f8fc4559469045ceb501ed023b713c1f6c069a64
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 17:21:19 2015 +0300

    loleaflet: writer preview invalidation

diff --git a/loleaflet/src/layer/tile/WriterTileLayer.js 
b/loleaflet/src/layer/tile/WriterTileLayer.js
index 68260a1..fe85e9d 100644
--- a/loleaflet/src/layer/tile/WriterTileLayer.js
+++ b/loleaflet/src/layer/tile/WriterTileLayer.js
@@ -79,6 +79,13 @@ L.WriterTileLayer = L.TileLayer.extend({
                                delete this._tileCache[key];
                        }
                }
+               if (!this._previewInvalidations) {
+                       this._previewInvalidations = [];
+               }
+               this._previewInvalidations.push(invalidBounds);
+               // 1s after the last invalidation, update the preview
+               clearTimeout(this._previewInvalidator);
+               this._previewInvalidator = 
setTimeout(L.bind(this._invalidatePreview, this), 1000);
        },
 
        _onSetPartMsg: function (textMsg) {
@@ -111,5 +118,41 @@ L.WriterTileLayer = L.TileLayer.extend({
                        this._resetPreFetching(true);
                        this._update();
                }
+       },
+
+       _invalidatePreview: function () {
+               // invalidate writer page previews
+               if (this._map._docPreviews && this._previewInvalidations) {
+                       var toInvalidate = {};
+                       for (var i = 0; i < this._previewInvalidations.length; 
i++) {
+                               var invalidBounds = 
this._previewInvalidations[i];
+                               var invalidPixBounds = new L.Bounds(
+                                               
invalidBounds.min.divideBy(this.options.tileWidthTwips).multiplyBy(this._tileSize),
+                                               
invalidBounds.max.divideBy(this.options.tileWidthTwips).multiplyBy(this._tileSize));
+
+                               for (var key in this._map._docPreviews) {
+                                       // find preview tiles that need to be 
updated and add them in a set
+                                       var preview = 
this._map._docPreviews[key];
+                                       var bounds = new L.Bounds(new 
L.Point(preview.x, preview.y),
+                                                                               
          new L.Point(preview.x + preview.width, preview.y + preview.height));
+                                       if 
(invalidPixBounds.intersects(bounds)) {
+                                               toInvalidate[key] = true;
+                                       }
+                               }
+
+                               for (key in toInvalidate) {
+                                       // update invalid preview tiles
+                                       preview = this._map._docPreviews[key];
+                                       if (preview.autoUpdate) {
+                                               
this._map.getDocPreview(preview.id, preview.maxWidth, preview.maxHeight,
+                                                               preview.x, 
preview.y, preview.width, preview.height, {autoUpdate: true});
+                                       }
+                                       else {
+                                               
this._map.fire('invalidatepreview', {id: preview.id});
+                                       }
+                               }
+                       }
+               }
+               this._previewInvalidations = [];
        }
 });
commit 9b84f3787c9f097423a1955ee59d8b3dcbffc530
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 17:12:02 2015 +0300

    loleaflet: option for automatically updating the previews

diff --git a/loleaflet/README b/loleaflet/README
index 5ce2b41..672dc0f 100644
--- a/loleaflet/README
+++ b/loleaflet/README
@@ -89,10 +89,11 @@ Buttons like Bold, Italic, Strike through etc.
 Parts (like slides in presentation, or sheets in spreadsheets):
     - API:
         map.setPart('next' | 'prev' | partNumber)
-        map.getPartPreview(id, part, maxWidth, maxHeight) where:
+        map.getPartPreview(id, part, maxWidth, maxHeight, [options]) where:
             + id = the ID of the request so that the response can be identified
             + maxWidth / maxHeight are the desired dimensions of the preview, 
a smaller
               image might be returned in order to keep the original ratio of 
the document
+            + options = {autoUpdate: true} - automatically updates the previews
         map.getNumberOfParts()
         map.getCurrentPartNumber()
     - events:
@@ -101,6 +102,8 @@ Parts (like slides in presentation, or sheets in 
spreadsheets):
             + e.parts == the number of parts that the document has
             + e.docType == 'text' | 'spreadsheet' | 'presentation' | 'drawing' 
| 'other'
             + [e.partNames] if present, part names (e.g. sheet names)
+        map.on('invalidatepreview', function (e) {})
+            + e.id = the preview's id
 
 Statusindicator (when the document is loading):
     - events
@@ -160,17 +163,20 @@ Writer pages:
         map.goToPage(page)
         map.getNumberOfPages()
         map.getCurrentPageNumber()
-        map.getDocPreview(id, maxWidth, maxHeight, x, y, width, height)
+        map.getDocPreview(id, maxWidth, maxHeight, x, y, width, height, 
[options])
             + id = the ID of the request so that the response can be identified
             + maxWidth / maxHeight are the desired dimensions of the preview, 
a smaller
               image might be returned in order to keep the original ratio of 
the document
             + x/y = starting position, where to get the preview from
+            + options = {autoUpdate: true} - automatically updates the previews
 
     - events
         map.on('pagenumberchanged', function (e) {}) where:
             + e.currentPage = the page on which the cursor lies
             + e.pages = number of pages
             + e.docType = document type, should be 'text'
+        map.on('invalidatepreview', function (e) {})
+            + e.id = the preview's id
 
 Error:
     - events
diff --git a/loleaflet/src/control/Parts.js b/loleaflet/src/control/Parts.js
index 08e1c89..040d909 100644
--- a/loleaflet/src/control/Parts.js
+++ b/loleaflet/src/control/Parts.js
@@ -4,6 +4,7 @@
 L.Map.include({
        setPart: function (part) {
                var docLayer = this._docLayer;
+               docLayer._prevSelectedPart = docLayer._selectedPart;
                if (part === 'prev') {
                        if (docLayer._selectedPart > 0) {
                                docLayer._selectedPart -= 1;
@@ -33,9 +34,19 @@ L.Map.include({
                docLayer._update();
                docLayer._pruneTiles();
                docLayer._clearSelections();
+               docLayer._prevSelectedPartNeedsUpdate = true;
+               if (docLayer._invalidatePreview) {
+                       docLayer._invalidatePreview();
+               }
        },
 
-       getPartPreview: function (id, part, maxWidth, maxHeight) {
+       getPartPreview: function (id, part, maxWidth, maxHeight, options) {
+               if (!this._docPreviews) {
+                       this._docPreviews = {};
+               }
+               var autoUpdate = options ? options.autoUpdate : false;
+               this._docPreviews[id] = {id: id, part: part, maxWidth: 
maxWidth, maxHeight: maxHeight, autoUpdate: autoUpdate};
+
                var docLayer = this._docLayer;
                var docRatio = docLayer._docWidthTwips / 
docLayer._docHeightTwips;
                var imgRatio = maxWidth / maxHeight;
@@ -56,7 +67,14 @@ L.Map.include({
                                                        'id=' + id);
        },
 
-       getDocPreview: function (id, maxWidth, maxHeight, x, y, width, height) {
+       getDocPreview: function (id, maxWidth, maxHeight, x, y, width, height, 
options) {
+               if (!this._docPreviews) {
+                       this._docPreviews = {};
+               }
+               var autoUpdate = options ? options.autoUpdate : false;
+               this._docPreviews[id] = {id: id, maxWidth: maxWidth, maxHeight: 
maxHeight, x: x, y: y,
+                       width: width, height: height, autoUpdate: autoUpdate};
+
                var docLayer = this._docLayer;
                var docRatio = width / height;
                var imgRatio = maxWidth / maxHeight;
@@ -83,6 +101,12 @@ L.Map.include({
                                                        'id=' + id);
        },
 
+       removePreviewUpdate: function (id) {
+               if (this._docPreviews && this._docPreviews[id]) {
+                       this._docPreviews[id].autoUpdate = false;
+               }
+       },
+
        goToPage: function (page) {
                var docLayer = this._docLayer;
                if (page === 'prev') {
commit dcabc24a03af1ae2a31020e8ff268040a623d861
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 15:14:00 2015 +0300

    loleaflet: setPart msg is now handled separately

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js 
b/loleaflet/src/layer/tile/CalcTileLayer.js
index 4a0d1fb..7550ddb 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -86,6 +86,16 @@ L.CalcTileLayer = L.TileLayer.extend({
                }
        },
 
+       _onSetPartMsg: function (textMsg) {
+               var part = parseInt(textMsg.match(/\d+/g)[0]);
+               if (part !== this._selectedPart) {
+                       this._selectedPart = part;
+                       this._update();
+                       this._clearSelections();
+                       this._map.fire('setpart', {selectedPart: 
this._selectedPart});
+               }
+       },
+
        _onStatusMsg: function (textMsg) {
                var command = L.Socket.parseServerCmd(textMsg);
                if (command.width && command.height && this._documentInfo !== 
textMsg) {
@@ -106,6 +116,7 @@ L.CalcTileLayer = L.TileLayer.extend({
                                docType: this._docType,
                                partNames: partNames
                        });
+                       this._resetPreFetching(true);
                        this._update();
                        if (this._preFetchPart !== this._selectedPart) {
                                this._preFetchPart = this._selectedPart;
diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js 
b/loleaflet/src/layer/tile/ImpressTileLayer.js
index d9eddf1..2a437ef 100644
--- a/loleaflet/src/layer/tile/ImpressTileLayer.js
+++ b/loleaflet/src/layer/tile/ImpressTileLayer.js
@@ -88,31 +88,42 @@ L.ImpressTileLayer = L.TileLayer.extend({
                }
        },
 
+       _onSetPartMsg: function (textMsg) {
+               var part = parseInt(textMsg.match(/\d+/g)[0]);
+               if (part !== this._selectedPart) {
+                       this._selectedPart = part;
+                       this._update();
+                       this._clearSelections();
+                       this._map.fire('setpart', {selectedPart: 
this._selectedPart});
+               }
+       },
+
        _onStatusMsg: function (textMsg) {
                var command = L.Socket.parseServerCmd(textMsg);
                if (command.width && command.height && this._documentInfo !== 
textMsg) {
                        this._docWidthTwips = command.width;
-            this._docHeightTwips = command.height;
-            this._docType = command.type;
-            this._updateMaxBounds(true);
-            this._documentInfo = textMsg;
-            this._parts = command.parts;
-            this._selectedPart = command.selectedPart;
-            L.Socket.sendMessage('setclientpart part=' + this._selectedPart);
-            var partNames = textMsg.match(/[^\r\n]+/g);
-            // only get the last matches
-            partNames = partNames.slice(partNames.length - this._parts);
-            this._map.fire('updateparts', {
-                selectedPart: this._selectedPart,
-                parts: this._parts,
-                docType: this._docType,
-                partNames: partNames
-            });
-            this._update();
-            if (this._preFetchPart !== this._selectedPart) {
-                this._preFetchPart = this._selectedPart;
-                this._preFetchBorder = null;
-            }
+                       this._docHeightTwips = command.height;
+                       this._docType = command.type;
+                       this._updateMaxBounds(true);
+                       this._documentInfo = textMsg;
+                       this._parts = command.parts;
+                       this._selectedPart = command.selectedPart;
+                       L.Socket.sendMessage('setclientpart part=' + 
this._selectedPart);
+                       var partNames = textMsg.match(/[^\r\n]+/g);
+                       // only get the last matches
+                       partNames = partNames.slice(partNames.length - 
this._parts);
+                       this._map.fire('updateparts', {
+                               selectedPart: this._selectedPart,
+                               parts: this._parts,
+                               docType: this._docType,
+                               partNames: partNames
+                       });
+                       this._resetPreFetching(true);
+                       this._update();
+                       if (this._preFetchPart !== this._selectedPart) {
+                               this._preFetchPart = this._selectedPart;
+                               this._preFetchBorder = null;
+                       }
         }
        }
 });
diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index dbd40bf..fffba11 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -271,24 +271,6 @@ L.TileLayer = L.GridLayer.extend({
                this._map.fire('search', {originalPhrase: originalPhrase, 
count: 0});
        },
 
-       _onSetPartMsg: function (textMsg) {
-               var part = parseInt(textMsg.match(/\d+/g)[0]);
-               if (part !== this._selectedPart && this._docType !== 'text') {
-                       this._selectedPart = part;
-                       this._update();
-                       this._clearSelections();
-                       this._map.fire('setpart', {selectedPart: 
this._selectedPart});
-               }
-               else if (this._docType === 'text') {
-                       this._currentPage = part;
-                       this._map.fire('pagenumberchanged', {
-                               currentPage: part,
-                               pages: this._pages,
-                               docType: this._docType
-                       });
-               }
-       },
-
        _onStateChangedMsg: function (textMsg) {
                var unoMsg = textMsg.substr(14);
                var unoCmd = unoMsg.match('.uno:(.*)=')[1];
diff --git a/loleaflet/src/layer/tile/WriterTileLayer.js 
b/loleaflet/src/layer/tile/WriterTileLayer.js
index 178c8e6..68260a1 100644
--- a/loleaflet/src/layer/tile/WriterTileLayer.js
+++ b/loleaflet/src/layer/tile/WriterTileLayer.js
@@ -81,9 +81,18 @@ L.WriterTileLayer = L.TileLayer.extend({
                }
        },
 
+       _onSetPartMsg: function (textMsg) {
+               var part = parseInt(textMsg.match(/\d+/g)[0]);
+               this._currentPage = part;
+               this._map.fire('pagenumberchanged', {
+                       currentPage: part,
+                       pages: this._pages,
+                       docType: this._docType
+               });
+       },
+
        _onStatusMsg: function (textMsg) {
                var command = L.Socket.parseServerCmd(textMsg);
-               console.log(textMsg);
                if (command.width && command.height && this._documentInfo !== 
textMsg) {
                        this._docWidthTwips = command.width;
                        this._docHeightTwips = command.height;
@@ -99,6 +108,7 @@ L.WriterTileLayer = L.TileLayer.extend({
                                pages: this._pages,
                                docType: this._docType
                        });
+                       this._resetPreFetching(true);
                        this._update();
                }
        }
commit 6bef2d4bbb3f8cbcbeaf9691809f68772c549b21
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 14:28:02 2015 +0300

    loleaflet: the status msg is handled now separately

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js 
b/loleaflet/src/layer/tile/CalcTileLayer.js
index 687d03a..4a0d1fb 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -84,5 +84,33 @@ L.CalcTileLayer = L.TileLayer.extend({
                                delete this._tileCache[key];
                        }
                }
+       },
+
+       _onStatusMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               if (command.width && command.height && this._documentInfo !== 
textMsg) {
+                       this._docWidthTwips = command.width;
+                       this._docHeightTwips = command.height;
+                       this._docType = command.type;
+                       this._updateMaxBounds(true);
+                       this._documentInfo = textMsg;
+                       this._parts = command.parts;
+                       this._selectedPart = command.selectedPart;
+                       L.Socket.sendMessage('setclientpart part=' + 
this._selectedPart);
+                       var partNames = textMsg.match(/[^\r\n]+/g);
+                       // only get the last matches
+                       partNames = partNames.slice(partNames.length - 
this._parts);
+                       this._map.fire('updateparts', {
+                               selectedPart: this._selectedPart,
+                               parts: this._parts,
+                               docType: this._docType,
+                               partNames: partNames
+                       });
+                       this._update();
+                       if (this._preFetchPart !== this._selectedPart) {
+                               this._preFetchPart = this._selectedPart;
+                               this._preFetchBorder = null;
+                       }
+               }
        }
 });
diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js 
b/loleaflet/src/layer/tile/ImpressTileLayer.js
index ba2f765..d9eddf1 100644
--- a/loleaflet/src/layer/tile/ImpressTileLayer.js
+++ b/loleaflet/src/layer/tile/ImpressTileLayer.js
@@ -86,5 +86,33 @@ L.ImpressTileLayer = L.TileLayer.extend({
                        this._lastValidPart = command.part;
                        this._map.fire('updatepart', {part: command.part, 
docType: this._docType});
                }
+       },
+
+       _onStatusMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               if (command.width && command.height && this._documentInfo !== 
textMsg) {
+                       this._docWidthTwips = command.width;
+            this._docHeightTwips = command.height;
+            this._docType = command.type;
+            this._updateMaxBounds(true);
+            this._documentInfo = textMsg;
+            this._parts = command.parts;
+            this._selectedPart = command.selectedPart;
+            L.Socket.sendMessage('setclientpart part=' + this._selectedPart);
+            var partNames = textMsg.match(/[^\r\n]+/g);
+            // only get the last matches
+            partNames = partNames.slice(partNames.length - this._parts);
+            this._map.fire('updateparts', {
+                selectedPart: this._selectedPart,
+                parts: this._parts,
+                docType: this._docType,
+                partNames: partNames
+            });
+            this._update();
+            if (this._preFetchPart !== this._selectedPart) {
+                this._preFetchPart = this._selectedPart;
+                this._preFetchBorder = null;
+            }
+        }
        }
 });
diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 6b30a3a..dbd40bf 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -298,47 +298,6 @@ L.TileLayer = L.GridLayer.extend({
                }
        },
 
-       _onStatusMsg: function (textMsg) {
-               var command = L.Socket.parseServerCmd(textMsg);
-               if (command.width && command.height && this._documentInfo !== 
textMsg) {
-                       this._docWidthTwips = command.width;
-                       this._docHeightTwips = command.height;
-                       this._docType = command.type;
-                       this._updateMaxBounds(true);
-                       this._documentInfo = textMsg;
-                       this._parts = command.parts;
-                       this._selectedPart = command.selectedPart;
-                       if (this._docType === 'text') {
-                               this._selectedPart = 0;
-                               this._parts = 1;
-                               this._currentPage = command.selectedPart;
-                               this._pages = command.parts;
-                               this._map.fire('pagenumberchanged', {
-                                       currentPage: this._currentPage,
-                                       pages: this._pages,
-                                       docType: this._docType
-                               });
-                       }
-                       else {
-                               L.Socket.sendMessage('setclientpart part=' + 
this._selectedPart);
-                               var partNames = textMsg.match(/[^\r\n]+/g);
-                               // only get the last matches
-                               partNames = partNames.slice(partNames.length - 
this._parts);
-                               this._map.fire('updateparts', {
-                                       selectedPart: this._selectedPart,
-                                       parts: this._parts,
-                                       docType: this._docType,
-                                       partNames: partNames
-                               });
-                       }
-                       this._update();
-                       if (this._preFetchPart !== this._selectedPart) {
-                               this._preFetchPart = this._selectedPart;
-                               this._preFetchBorder = null;
-                       }
-               }
-       },
-
        _onStatusIndicatorMsg: function (textMsg) {
                if (textMsg.startsWith('statusindicatorstart:')) {
                        this._map.fire('statusindicator', {statusType : 
'start'});
diff --git a/loleaflet/src/layer/tile/WriterTileLayer.js 
b/loleaflet/src/layer/tile/WriterTileLayer.js
index e2dde74..178c8e6 100644
--- a/loleaflet/src/layer/tile/WriterTileLayer.js
+++ b/loleaflet/src/layer/tile/WriterTileLayer.js
@@ -79,5 +79,27 @@ L.WriterTileLayer = L.TileLayer.extend({
                                delete this._tileCache[key];
                        }
                }
+       },
+
+       _onStatusMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               console.log(textMsg);
+               if (command.width && command.height && this._documentInfo !== 
textMsg) {
+                       this._docWidthTwips = command.width;
+                       this._docHeightTwips = command.height;
+                       this._docType = command.type;
+                       this._updateMaxBounds(true);
+                       this._documentInfo = textMsg;
+                       this._selectedPart = 0;
+                       this._parts = 1;
+                       this._currentPage = command.selectedPart;
+                       this._pages = command.parts;
+                       this._map.fire('pagenumberchanged', {
+                               currentPage: this._currentPage,
+                               pages: this._pages,
+                               docType: this._docType
+                       });
+                       this._update();
+               }
        }
 });
commit 6e7260f899a107b7886556fb0b0ef1825f60adc4
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 14:27:29 2015 +0300

    loleaflet: fixed typo

diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js
index 08959c2..8b7348c 100644
--- a/loleaflet/build/deps.js
+++ b/loleaflet/build/deps.js
@@ -63,7 +63,7 @@ var deps = {
                deps: ['TileLayer']
        },
 
-       WriterTileLayer: {
+       CalcTileLayer: {
                src: ['layer/tile/CalcTileLayer.js'],
                desc: 'Calc tile layer.',
                deps: ['TileLayer']
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index b25cf1c..b9bf086 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -90,13 +90,13 @@ L.Socket = {
                        // first status message, we need to create the document 
layer
                        var command = this.parseServerCmd(textMsg);
                        var docLayer = null;
-                       if (command.style === 'text') {
+                       if (command.type === 'text') {
                                docLayer = new L.WriterTileLayer('', {
                                        edit: this._map.options.edit,
                                        readOnly: this._map.options.readOnly
                                });
                        }
-                       else if (command.style === 'spreadsheet') {
+                       else if (command.type === 'spreadsheet') {
                                docLayer = new L.CalcTileLayer('', {
                                        edit: this._map.options.edit,
                                        readOnly: this._map.options.readOnly
commit 00dcd25e60544b83579472a98c7124d6ef03845f
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 13:57:34 2015 +0300

    loleaflet: tile invalidation is now handled in the 3 components

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js 
b/loleaflet/src/layer/tile/CalcTileLayer.js
index 1a1795a..687d03a 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -3,4 +3,86 @@
  */
 
 L.CalcTileLayer = L.TileLayer.extend({
+
+       _onInvalidateTilesMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               if (command.x === undefined || command.y === undefined || 
command.part === undefined) {
+                       var strTwips = textMsg.match(/\d+/g);
+                       command.x = parseInt(strTwips[0]);
+                       command.y = parseInt(strTwips[1]);
+                       command.width = parseInt(strTwips[2]);
+                       command.height = parseInt(strTwips[3]);
+                       command.part = this._currentPart;
+               }
+               if (this._docType === 'text') {
+                       command.part = 0;
+               }
+               var topLeftTwips = new L.Point(command.x, command.y);
+               var offset = new L.Point(command.width, command.height);
+               var bottomRightTwips = topLeftTwips.add(offset);
+               var invalidBounds = new L.Bounds(topLeftTwips, 
bottomRightTwips);
+               var visibleTopLeft = 
this._latLngToTwips(this._map.getBounds().getNorthWest());
+               var visibleBottomRight = 
this._latLngToTwips(this._map.getBounds().getSouthEast());
+               var visibleArea = new L.Bounds(visibleTopLeft, 
visibleBottomRight);
+               var toRequest = [];
+
+               for (var key in this._tiles) {
+                       var coords = this._tiles[key].coords;
+                       var tileTopLeft = this._coordsToTwips(coords);
+                       var tileBottomRight = new L.Point(this._tileWidthTwips, 
this._tileHeightTwips);
+                       var bounds = new L.Bounds(tileTopLeft, 
tileTopLeft.add(tileBottomRight));
+                       if (invalidBounds.intersects(bounds) && coords.part === 
command.part) {
+                               if (this._tiles[key]._invalidCount) {
+                                       this._tiles[key]._invalidCount += 1;
+                               }
+                               else {
+                                       this._tiles[key]._invalidCount = 1;
+                               }
+                               if (visibleArea.intersects(bounds)) {
+                                       var msg = 'tile ' +
+                                                       'part=' + coords.part + 
' ' +
+                                                       'width=' + 
this._tileSize + ' ' +
+                                                       'height=' + 
this._tileSize + ' ' +
+                                                       'tileposx=' + 
tileTopLeft.x + ' '    +
+                                                       'tileposy=' + 
tileTopLeft.y + ' ' +
+                                                       'tilewidth=' + 
this._tileWidthTwips + ' ' +
+                                                       'tileheight=' + 
this._tileHeightTwips;
+                                       toRequest.push({msg: msg, key: key, 
coords: coords});
+                               }
+                               else {
+                                       // tile outside of the visible area, 
just remove it
+                                       this._preFetchBorder = null;
+                                       this._removeTile(key);
+                               }
+                       }
+               }
+
+               // Sort tiles so that we request those closer to the cursor 
first
+               var cursorPos = 
this._map.project(this._visibleCursor.getNorthWest());
+               cursorPos = cursorPos.divideBy(this._tileSize);
+               toRequest.sort(function(x, y) {return 
x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);});
+               for (var i = 0; i < toRequest.length; i++) {
+                       L.Socket.sendMessage(toRequest[i].msg, 
toRequest[i].key);
+               }
+
+               for (key in this._tileCache) {
+                       // compute the rectangle that each tile covers in the 
document based
+                       // on the zoom level
+                       coords = this._keyToTileCoords(key);
+                       if (coords.part !== command.part) {
+                               continue;
+                       }
+                       var scale = this._map.getZoomScale(coords.z);
+                       topLeftTwips = new L.Point(
+                                       this.options.tileWidthTwips / scale * 
coords.x,
+                                       this.options.tileHeightTwips / scale * 
coords.y);
+                       bottomRightTwips = topLeftTwips.add(new L.Point(
+                                       this.options.tileWidthTwips / scale,
+                                       this.options.tileHeightTwips / scale));
+                       bounds = new L.Bounds(topLeftTwips, bottomRightTwips);
+                       if (invalidBounds.intersects(bounds)) {
+                               delete this._tileCache[key];
+                       }
+               }
+       }
 });
diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js 
b/loleaflet/src/layer/tile/ImpressTileLayer.js
index a2d1fbf..ba2f765 100644
--- a/loleaflet/src/layer/tile/ImpressTileLayer.js
+++ b/loleaflet/src/layer/tile/ImpressTileLayer.js
@@ -2,6 +2,89 @@
  * Impress tile layer is used to display a presentation document
  */
 
-
 L.ImpressTileLayer = L.TileLayer.extend({
+
+       _onInvalidateTilesMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               if (command.x === undefined || command.y === undefined || 
command.part === undefined) {
+                       var strTwips = textMsg.match(/\d+/g);
+                       command.x = parseInt(strTwips[0]);
+                       command.y = parseInt(strTwips[1]);
+                       command.width = parseInt(strTwips[2]);
+                       command.height = parseInt(strTwips[3]);
+                       command.part = this._currentPart;
+               }
+               var topLeftTwips = new L.Point(command.x, command.y);
+               var offset = new L.Point(command.width, command.height);
+               var bottomRightTwips = topLeftTwips.add(offset);
+               var invalidBounds = new L.Bounds(topLeftTwips, 
bottomRightTwips);
+               var visibleTopLeft = 
this._latLngToTwips(this._map.getBounds().getNorthWest());
+               var visibleBottomRight = 
this._latLngToTwips(this._map.getBounds().getSouthEast());
+               var visibleArea = new L.Bounds(visibleTopLeft, 
visibleBottomRight);
+               var toRequest = [];
+
+               for (var key in this._tiles) {
+                       var coords = this._tiles[key].coords;
+                       var tileTopLeft = this._coordsToTwips(coords);
+                       var tileBottomRight = new L.Point(this._tileWidthTwips, 
this._tileHeightTwips);
+                       var bounds = new L.Bounds(tileTopLeft, 
tileTopLeft.add(tileBottomRight));
+                       if (invalidBounds.intersects(bounds) && coords.part === 
command.part) {
+                               if (this._tiles[key]._invalidCount) {
+                                       this._tiles[key]._invalidCount += 1;
+                               }
+                               else {
+                                       this._tiles[key]._invalidCount = 1;
+                               }
+                               if (visibleArea.intersects(bounds)) {
+                                       var msg = 'tile ' +
+                                                       'part=' + coords.part + 
' ' +
+                                                       'width=' + 
this._tileSize + ' ' +
+                                                       'height=' + 
this._tileSize + ' ' +
+                                                       'tileposx=' + 
tileTopLeft.x + ' '    +
+                                                       'tileposy=' + 
tileTopLeft.y + ' ' +
+                                                       'tilewidth=' + 
this._tileWidthTwips + ' ' +
+                                                       'tileheight=' + 
this._tileHeightTwips;
+                                       toRequest.push({msg: msg, key: key, 
coords: coords});
+                               }
+                               else {
+                                       // tile outside of the visible area, 
just remove it
+                                       this._preFetchBorder = null;
+                                       this._removeTile(key);
+                               }
+                       }
+               }
+
+               // Sort tiles so that we request those closer to the cursor 
first
+               var cursorPos = 
this._map.project(this._visibleCursor.getNorthWest());
+               cursorPos = cursorPos.divideBy(this._tileSize);
+               toRequest.sort(function(x, y) {return 
x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);});
+               for (var i = 0; i < toRequest.length; i++) {
+                       L.Socket.sendMessage(toRequest[i].msg, 
toRequest[i].key);
+               }
+
+               for (key in this._tileCache) {
+                       // compute the rectangle that each tile covers in the 
document based
+                       // on the zoom level
+                       coords = this._keyToTileCoords(key);
+                       if (coords.part !== command.part) {
+                               continue;
+                       }
+                       var scale = this._map.getZoomScale(coords.z);
+                       topLeftTwips = new L.Point(
+                                       this.options.tileWidthTwips / scale * 
coords.x,
+                                       this.options.tileHeightTwips / scale * 
coords.y);
+                       bottomRightTwips = topLeftTwips.add(new L.Point(
+                                       this.options.tileWidthTwips / scale,
+                                       this.options.tileHeightTwips / scale));
+                       bounds = new L.Bounds(topLeftTwips, bottomRightTwips);
+                       if (invalidBounds.intersects(bounds)) {
+                               delete this._tileCache[key];
+                       }
+               }
+               if (command.part === this._currentPart &&
+                       command.part !== this._lastValidPart) {
+                       this._lastValidPart = command.part;
+                       this._map.fire('updatepart', {part: command.part, 
docType: this._docType});
+               }
+       }
 });
diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 9f9176b..6b30a3a 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -266,94 +266,6 @@ L.TileLayer = L.GridLayer.extend({
                this._onUpdateCursor();
        },
 
-       _onInvalidateTilesMsg: function (textMsg) {
-               var command = L.Socket.parseServerCmd(textMsg);
-               if (command.x === undefined || command.y === undefined || 
command.part === undefined) {
-                       var strTwips = textMsg.match(/\d+/g);
-                       command.x = parseInt(strTwips[0]);
-                       command.y = parseInt(strTwips[1]);
-                       command.width = parseInt(strTwips[2]);
-                       command.height = parseInt(strTwips[3]);
-                       command.part = this._selectedPart;
-               }
-               if (this._docType === 'text') {
-                       command.part = 0;
-               }
-               var topLeftTwips = new L.Point(command.x, command.y);
-               var offset = new L.Point(command.width, command.height);
-               var bottomRightTwips = topLeftTwips.add(offset);
-               var invalidBounds = new L.Bounds(topLeftTwips, 
bottomRightTwips);
-               var visibleTopLeft = 
this._latLngToTwips(this._map.getBounds().getNorthWest());
-               var visibleBottomRight = 
this._latLngToTwips(this._map.getBounds().getSouthEast());
-               var visibleArea = new L.Bounds(visibleTopLeft, 
visibleBottomRight);
-               var toRequest = [];
-
-               for (var key in this._tiles) {
-                       var coords = this._tiles[key].coords;
-                       var tileTopLeft = this._coordsToTwips(coords);
-                       var tileBottomRight = new L.Point(this._tileWidthTwips, 
this._tileHeightTwips);
-                       var bounds = new L.Bounds(tileTopLeft, 
tileTopLeft.add(tileBottomRight));
-                       if (invalidBounds.intersects(bounds) && coords.part === 
command.part) {
-                               if (this._tiles[key]._invalidCount) {
-                                       this._tiles[key]._invalidCount += 1;
-                               }
-                               else {
-                                       this._tiles[key]._invalidCount = 1;
-                               }
-                               if (visibleArea.intersects(bounds)) {
-                                       var msg = 'tile ' +
-                                                       'part=' + coords.part + 
' ' +
-                                                       'width=' + 
this._tileSize + ' ' +
-                                                       'height=' + 
this._tileSize + ' ' +
-                                                       'tileposx=' + 
tileTopLeft.x + ' '    +
-                                                       'tileposy=' + 
tileTopLeft.y + ' ' +
-                                                       'tilewidth=' + 
this._tileWidthTwips + ' ' +
-                                                       'tileheight=' + 
this._tileHeightTwips;
-                                       toRequest.push({msg: msg, key: key, 
coords: coords});
-                               }
-                               else {
-                                       // tile outside of the visible area, 
just remove it
-                                       this._preFetchBorder = null;
-                                       this._removeTile(key);
-                               }
-                       }
-               }
-
-               // Sort tiles so that we request those closer to the cursor 
first
-               var cursorPos = 
this._map.project(this._visibleCursor.getNorthWest());
-               cursorPos = cursorPos.divideBy(this._tileSize);
-               toRequest.sort(function(x, y) {return 
x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);});
-               for (var i = 0; i < toRequest.length; i++) {
-                       L.Socket.sendMessage(toRequest[i].msg, 
toRequest[i].key);
-               }
-
-               for (key in this._tileCache) {
-                       // compute the rectangle that each tile covers in the 
document based
-                       // on the zoom level
-                       coords = this._keyToTileCoords(key);
-                       if (coords.part !== command.part) {
-                               continue;
-                       }
-                       var scale = this._map.getZoomScale(coords.z);
-                       topLeftTwips = new L.Point(
-                                       this.options.tileWidthTwips / scale * 
coords.x,
-                                       this.options.tileHeightTwips / scale * 
coords.y);
-                       bottomRightTwips = topLeftTwips.add(new L.Point(
-                                       this.options.tileWidthTwips / scale,
-                                       this.options.tileHeightTwips / scale));
-                       bounds = new L.Bounds(topLeftTwips, bottomRightTwips);
-                       if (invalidBounds.intersects(bounds)) {
-                               delete this._tileCache[key];
-                       }
-               }
-               if (command.part === this._selectedPart &&
-                       command.part !== this._lastValidPart) {
-                       this._lastValidPart = command.part;
-                       this._map.fire('updatepart', {part: command.part, 
docType: this._docType});
-               }
-
-       },
-
        _onSearchNotFoundMsg: function (textMsg) {
                var originalPhrase = textMsg.substring(16);
                this._map.fire('search', {originalPhrase: originalPhrase, 
count: 0});
diff --git a/loleaflet/src/layer/tile/WriterTileLayer.js 
b/loleaflet/src/layer/tile/WriterTileLayer.js
index 6eb0258..e2dde74 100644
--- a/loleaflet/src/layer/tile/WriterTileLayer.js
+++ b/loleaflet/src/layer/tile/WriterTileLayer.js
@@ -3,4 +3,81 @@
  */
 
 L.WriterTileLayer = L.TileLayer.extend({
+
+       _onInvalidateTilesMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               if (command.x === undefined || command.y === undefined || 
command.part === undefined) {
+                       var strTwips = textMsg.match(/\d+/g);
+                       command.x = parseInt(strTwips[0]);
+                       command.y = parseInt(strTwips[1]);
+                       command.width = parseInt(strTwips[2]);
+                       command.height = parseInt(strTwips[3]);
+                       command.part = this._currentPart;
+               }
+               command.part = 0;
+               var topLeftTwips = new L.Point(command.x, command.y);
+               var offset = new L.Point(command.width, command.height);
+               var bottomRightTwips = topLeftTwips.add(offset);
+               var invalidBounds = new L.Bounds(topLeftTwips, 
bottomRightTwips);
+               var visibleTopLeft = 
this._latLngToTwips(this._map.getBounds().getNorthWest());
+               var visibleBottomRight = 
this._latLngToTwips(this._map.getBounds().getSouthEast());
+               var visibleArea = new L.Bounds(visibleTopLeft, 
visibleBottomRight);
+               var toRequest = [];
+
+               for (var key in this._tiles) {
+                       var coords = this._tiles[key].coords;
+                       var tileTopLeft = this._coordsToTwips(coords);
+                       var tileBottomRight = new L.Point(this._tileWidthTwips, 
this._tileHeightTwips);
+                       var bounds = new L.Bounds(tileTopLeft, 
tileTopLeft.add(tileBottomRight));
+                       if (invalidBounds.intersects(bounds) && coords.part === 
command.part) {
+                               if (this._tiles[key]._invalidCount) {
+                                       this._tiles[key]._invalidCount += 1;
+                               }
+                               else {
+                                       this._tiles[key]._invalidCount = 1;
+                               }
+                               if (visibleArea.intersects(bounds)) {
+                                       var msg = 'tile ' +
+                                                       'part=' + coords.part + 
' ' +
+                                                       'width=' + 
this._tileSize + ' ' +
+                                                       'height=' + 
this._tileSize + ' ' +
+                                                       'tileposx=' + 
tileTopLeft.x + ' '    +
+                                                       'tileposy=' + 
tileTopLeft.y + ' ' +
+                                                       'tilewidth=' + 
this._tileWidthTwips + ' ' +
+                                                       'tileheight=' + 
this._tileHeightTwips;
+                                       toRequest.push({msg: msg, key: key, 
coords: coords});
+                               }
+                               else {
+                                       // tile outside of the visible area, 
just remove it
+                                       this._preFetchBorder = null;
+                                       this._removeTile(key);
+                               }
+                       }
+               }
+
+               // Sort tiles so that we request those closer to the cursor 
first
+               var cursorPos = 
this._map.project(this._visibleCursor.getNorthWest());
+               cursorPos = cursorPos.divideBy(this._tileSize);
+               toRequest.sort(function(x, y) {return 
x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);});
+               for (var i = 0; i < toRequest.length; i++) {
+                       L.Socket.sendMessage(toRequest[i].msg, 
toRequest[i].key);
+               }
+
+               for (key in this._tileCache) {
+                       // compute the rectangle that each tile covers in the 
document based
+                       // on the zoom level
+                       coords = this._keyToTileCoords(key);
+                       var scale = this._map.getZoomScale(coords.z);
+                       topLeftTwips = new L.Point(
+                                       this.options.tileWidthTwips / scale * 
coords.x,
+                                       this.options.tileHeightTwips / scale * 
coords.y);
+                       bottomRightTwips = topLeftTwips.add(new L.Point(
+                                       this.options.tileWidthTwips / scale,
+                                       this.options.tileHeightTwips / scale));
+                       bounds = new L.Bounds(topLeftTwips, bottomRightTwips);
+                       if (invalidBounds.intersects(bounds)) {
+                               delete this._tileCache[key];
+                       }
+               }
+       }
 });
commit 6e74a351ba05765a7c2934c133915f8991cb2697
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 12:28:37 2015 +0300

    loleaflet: renamed 'currentPart' to 'selectedPart'

diff --git a/loleaflet/src/control/Control.Parts.js 
b/loleaflet/src/control/Control.Parts.js
index 9fc0b16..4a24e78 100644
--- a/loleaflet/src/control/Control.Parts.js
+++ b/loleaflet/src/control/Control.Parts.js
@@ -62,17 +62,17 @@ L.Control.Parts = L.Control.extend({
        _updateDisabled: function (e) {
                var className = 'leaflet-disabled';
                var parts = e.parts;
-               var currentPart = e.currentPart;
+               var selectedPart = e.selectedPart;
                var docType = e.docType;
                if (docType === 'text') {
                        return;
                }
-               if (currentPart === 0) {
+               if (selectedPart === 0) {
                        L.DomUtil.addClass(this._prevPartButton, className);
                } else {
                        L.DomUtil.removeClass(this._prevPartButton, className);
                }
-               if (currentPart === parts - 1) {
+               if (selectedPart === parts - 1) {
                        L.DomUtil.addClass(this._nextPartButton, className);
                } else {
                        L.DomUtil.removeClass(this._nextPartButton, className);
diff --git a/loleaflet/src/control/Control.Tabs.js 
b/loleaflet/src/control/Control.Tabs.js
index cce0de9..b5ce57d 100644
--- a/loleaflet/src/control/Control.Tabs.js
+++ b/loleaflet/src/control/Control.Tabs.js
@@ -15,7 +15,7 @@ L.Control.Tabs = L.Control.extend({
 
        _updateDisabled: function (e) {
                var parts = e.parts;
-               var currentPart = e.currentPart;
+               var selectedPart = e.selectedPart;
                var docType = e.docType;
                var partNames = e.partNames;
                if (docType === 'text') {
@@ -47,7 +47,7 @@ L.Control.Tabs = L.Control.extend({
                        for (var key in this._spreadsheetTabs) {
                                var part =  parseInt(key.match(/\d+/g)[0]);
                                
L.DomUtil.removeClass(this._spreadsheetTabs[key], 'selected');
-                               if (part === currentPart) {
+                               if (part === selectedPart) {
                                        
L.DomUtil.addClass(this._spreadsheetTabs[key], 'selected');
                                }
                        }
diff --git a/loleaflet/src/control/Parts.js b/loleaflet/src/control/Parts.js
index 7089cfb..08e1c89 100644
--- a/loleaflet/src/control/Parts.js
+++ b/loleaflet/src/control/Parts.js
@@ -5,17 +5,17 @@ L.Map.include({
        setPart: function (part) {
                var docLayer = this._docLayer;
                if (part === 'prev') {
-                       if (docLayer._currentPart > 0) {
-                               docLayer._currentPart -= 1;
+                       if (docLayer._selectedPart > 0) {
+                               docLayer._selectedPart -= 1;
                        }
                }
                else if (part === 'next') {
-                       if (docLayer._currentPart < docLayer._parts - 1) {
-                               docLayer._currentPart += 1;
+                       if (docLayer._selectedPart < docLayer._parts - 1) {
+                               docLayer._selectedPart += 1;
                        }
                }
                else if (typeof (part) === 'number' && part >= 0 && part < 
docLayer._parts) {
-                       docLayer._currentPart = part;
+                       docLayer._selectedPart = part;
                }
                else {
                        return;
@@ -25,11 +25,11 @@ L.Map.include({
                        L.Socket.sendMessage('resetselection');
                }
                this.fire('updateparts', {
-                       currentPart: docLayer._currentPart,
+                       selectedPart: docLayer._selectedPart,
                        parts: docLayer._parts,
                        docType: docLayer._docType
                });
-               L.Socket.sendMessage('setclientpart part=' + 
docLayer._currentPart);
+               L.Socket.sendMessage('setclientpart part=' + 
docLayer._selectedPart);
                docLayer._update();
                docLayer._pruneTiles();
                docLayer._clearSelections();
@@ -114,7 +114,7 @@ L.Map.include({
        },
 
        getCurrentPartNumber: function () {
-               return this._docLayer._currentPart;
+               return this._docLayer._selectedPart;
        },
 
        getDocSize: function () {
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 5e49874..b25cf1c 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -160,7 +160,7 @@ L.Socket = {
                                command.parts = 
parseInt(tokens[i].substring(6));
                        }
                        else if (tokens[i].substring(0, 8) === 'current=') {
-                               command.currentPart = 
parseInt(tokens[i].substring(8));
+                               command.selectedPart = 
parseInt(tokens[i].substring(8));
                        }
                        else if (tokens[i].substring(0, 3) === 'id=') {
                                // remove newline characters
diff --git a/loleaflet/src/layer/tile/GridLayer.js 
b/loleaflet/src/layer/tile/GridLayer.js
index d46eeec..95469d5 100644
--- a/loleaflet/src/layer/tile/GridLayer.js
+++ b/loleaflet/src/layer/tile/GridLayer.js
@@ -466,7 +466,7 @@ L.GridLayer = L.Layer.extend({
 
                for (var key in this._tiles) {
                        if (this._keyToTileCoords(key).z !== zoom ||
-                                       this._keyToTileCoords(key).part !== 
this._currentPart) {
+                                       this._keyToTileCoords(key).part !== 
this._selectedPart) {
                                this._tiles[key].current = false;
                        }
                }
@@ -478,7 +478,7 @@ L.GridLayer = L.Layer.extend({
                        for (var i = tileRange.min.x; i <= tileRange.max.x; 
i++) {
                                var coords = new L.Point(i, j);
                                coords.z = zoom;
-                               coords.part = this._currentPart;
+                               coords.part = this._selectedPart;
 
                                if (!this._isValidTile(coords)) { continue; }
 
@@ -615,7 +615,7 @@ L.GridLayer = L.Layer.extend({
                var tilePos = this._getTilePos(coords),
                        key = this._tileCoordsToKey(coords);
 
-               if (coords.part === this._currentPart) {
+               if (coords.part === this._selectedPart) {
                        var tile = this.createTile(this._wrapCoords(coords), 
L.bind(this._tileReady, this, coords));
 
                        this._initTile(tile);
@@ -656,7 +656,7 @@ L.GridLayer = L.Layer.extend({
                                        'tileposy=' + twips.y + ' ' +
                                        'tilewidth=' + this._tileWidthTwips + ' 
' +
                                        'tileheight=' + this._tileHeightTwips;
-                       if (coords.part !== this._currentPart) {
+                       if (coords.part !== this._selectedPart) {
                                msg += ' prefetch=true';
                        }
                        L.Socket.sendMessage(msg, key);
@@ -766,7 +766,7 @@ L.GridLayer = L.Layer.extend({
                }
 
                if (!this._preFetchBorder) {
-                       if (this._currentPart !== this._preFetchPart) {
+                       if (this._selectedPart !== this._preFetchPart) {
                                // all tiles from the new part have to be 
pre-fetched
                                var tileBorder = this._preFetchBorder = new 
L.Bounds(new L.Point(0, 0), new L.Point(0, 0));
                        }
@@ -851,36 +851,36 @@ L.GridLayer = L.Layer.extend({
                                        tileBorder.max.x * this._tileWidthTwips 
< this._docWidthTwips ||
                                         tileBorder.max.y * 
this._tileHeightTwips < this._docHeightTwips) &&
                                        this.options.preFetchOtherParts) {
-                               var diff = this._preFetchPart - 
this._currentPart;
-                               if (diff === 0 && this._currentPart < 
this._parts - 1) {
+                               var diff = this._preFetchPart - 
this._selectedPart;
+                               if (diff === 0 && this._selectedPart < 
this._parts - 1) {
                                        this._preFetchPart += 1;
                                        this._preFetchBorder = null;
                                }
-                               else if (diff === 0 && this._currentPart > 0) {
+                               else if (diff === 0 && this._selectedPart > 0) {
                                        this._preFetchPart -= 1;
                                        this._preFetchBorder = null;
                                }
                                else if (diff > 0) {
-                                       if (this._currentPart - diff >= 0) {
+                                       if (this._selectedPart - diff >= 0) {
                                                // lower part number
-                                               this._preFetchPart = 
this._currentPart - diff;
+                                               this._preFetchPart = 
this._selectedPart - diff;
                                                this._preFetchBorder = null;
                                        }
-                                       else if (this._currentPart + diff + 1 < 
this._parts) {
+                                       else if (this._selectedPart + diff + 1 
< this._parts) {
                                                // higher part number
-                                               this._preFetchPart = 
this._currentPart + diff + 1;
+                                               this._preFetchPart = 
this._selectedPart + diff + 1;
                                                this._preFetchBorder = null;
                                        }
                                }
                                else if (diff < 0) {
-                                       if (this._currentPart - diff + 1 < 
this._parts) {
+                                       if (this._selectedPart - diff + 1 < 
this._parts) {
                                                // higher part number
-                                               this._preFetchPart = 
this._currentPart - diff + 1;
+                                               this._preFetchPart = 
this._selectedPart - diff + 1;
                                                this._preFetchBorder = null;
                                        }
-                                       else if (this._currentPart + diff - 1 
>= 0) {
+                                       else if (this._selectedPart + diff - 1 
>= 0) {
                                                // lower part number
-                                               this._preFetchPart = 
this._currentPart + diff - 1;
+                                               this._preFetchPart = 
this._selectedPart + diff - 1;
                                                this._preFetchBorder = null;
                                        }
                                }
@@ -904,7 +904,7 @@ L.GridLayer = L.Layer.extend({
                }
                var interval = 750;
                var idleTime = 5000;
-               this._preFetchPart = this._currentPart;
+               this._preFetchPart = this._selectedPart;
                this._preFetchIdle = setTimeout(L.bind(function () {
                        this._tilesPreFetcher = 
setInterval(L.bind(this._preFetchTiles, this), interval);
                }, this), idleTime);
diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 06927ab..9f9176b 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -274,7 +274,7 @@ L.TileLayer = L.GridLayer.extend({
                        command.y = parseInt(strTwips[1]);
                        command.width = parseInt(strTwips[2]);
                        command.height = parseInt(strTwips[3]);
-                       command.part = this._currentPart;
+                       command.part = this._selectedPart;
                }
                if (this._docType === 'text') {
                        command.part = 0;
@@ -346,7 +346,7 @@ L.TileLayer = L.GridLayer.extend({
                                delete this._tileCache[key];
                        }
                }
-               if (command.part === this._currentPart &&
+               if (command.part === this._selectedPart &&
                        command.part !== this._lastValidPart) {
                        this._lastValidPart = command.part;
                        this._map.fire('updatepart', {part: command.part, 
docType: this._docType});
@@ -361,11 +361,11 @@ L.TileLayer = L.GridLayer.extend({
 
        _onSetPartMsg: function (textMsg) {
                var part = parseInt(textMsg.match(/\d+/g)[0]);
-               if (part !== this._currentPart && this._docType !== 'text') {
-                       this._currentPart = part;
+               if (part !== this._selectedPart && this._docType !== 'text') {
+                       this._selectedPart = part;
                        this._update();
                        this._clearSelections();
-                       this._map.fire('setpart', {currentPart: 
this._currentPart});
+                       this._map.fire('setpart', {selectedPart: 
this._selectedPart});
                }
                else if (this._docType === 'text') {
                        this._currentPage = part;
@@ -395,11 +395,11 @@ L.TileLayer = L.GridLayer.extend({
                        this._updateMaxBounds(true);
                        this._documentInfo = textMsg;
                        this._parts = command.parts;
-                       this._currentPart = command.currentPart;
+                       this._selectedPart = command.selectedPart;
                        if (this._docType === 'text') {
-                               this._currentPart = 0;
+                               this._selectedPart = 0;
                                this._parts = 1;
-                               this._currentPage = command.currentPart;
+                               this._currentPage = command.selectedPart;
                                this._pages = command.parts;
                                this._map.fire('pagenumberchanged', {
                                        currentPage: this._currentPage,
@@ -408,20 +408,20 @@ L.TileLayer = L.GridLayer.extend({
                                });
                        }
                        else {
-                               L.Socket.sendMessage('setclientpart part=' + 
this._currentPart);
+                               L.Socket.sendMessage('setclientpart part=' + 
this._selectedPart);
                                var partNames = textMsg.match(/[^\r\n]+/g);
                                // only get the last matches
                                partNames = partNames.slice(partNames.length - 
this._parts);
                                this._map.fire('updateparts', {
-                                       currentPart: this._currentPart,
+                                       selectedPart: this._selectedPart,
                                        parts: this._parts,
                                        docType: this._docType,
                                        partNames: partNames
                                });
                        }
                        this._update();
-                       if (this._preFetchPart !== this._currentPart) {
-                               this._preFetchPart = this._currentPart;
+                       if (this._preFetchPart !== this._selectedPart) {
+                               this._preFetchPart = this._selectedPart;
                                this._preFetchBorder = null;
                        }
                }
commit 5d35d050e0391fa4450862fdc7b338cf2de7978a
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 12:04:13 2015 +0300

    loleaflet: alphabetically ordered the server commands

diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 36f0156..06927ab 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -178,21 +178,24 @@ L.TileLayer = L.GridLayer.extend({
                if (textMsg.startsWith('cursorvisible:')) {
                        this._onCursorVisibleMsg(textMsg);
                }
-               else if (textMsg.startsWith('invalidatecursor:')) {
-                       this._onInvalidateCursorMsg(textMsg);
-               }
-               else if (textMsg.startsWith('textselectionstart:')) {
-                       this._onTextSelectionStartMsg(textMsg);
-               }
-               else if (textMsg.startsWith('textselectionend:')) {
-                       this._onTextSelectionEndMsg(textMsg);
+               else if (textMsg.startsWith('error:')) {
+                       this._onErrorMsg(textMsg);
                }
                else if (textMsg.startsWith('graphicselection:')) {
                        this._onGraphicSelectionMsg(textMsg);
                }
+               else if (textMsg.startsWith('invalidatecursor:')) {
+                       this._onInvalidateCursorMsg(textMsg);
+               }
                else if (textMsg.startsWith('invalidatetiles:') && 
!textMsg.match('EMPTY')) {
                        this._onInvalidateTilesMsg(textMsg);
                }
+               else if (textMsg.startsWith('searchnotfound:')) {
+                       this._onSearchNotFoundMsg(textMsg);
+               }
+               else if (textMsg.startsWith('setpart:')) {
+                       this._onSetPartMsg(textMsg);
+               }
                else if (textMsg.startsWith('statechanged:')) {
                        this._onStateChangedMsg(textMsg);
                }
@@ -202,8 +205,8 @@ L.TileLayer = L.GridLayer.extend({
                else if (textMsg.startsWith('statusindicator')) {
                        this._onStatusIndicatorMsg(textMsg);
                }
-               else if (textMsg.startsWith('tile:')) {
-                       this._onTileMsg(textMsg, imgBytes, index);
+               else if (textMsg.startsWith('styles:')) {
+                       this._onStylesMsg(textMsg);
                }
                else if (textMsg.startsWith('textselection:')) {
                        this._onTextSelectionMsg(textMsg);
@@ -211,17 +214,14 @@ L.TileLayer = L.GridLayer.extend({
                else if (textMsg.startsWith('textselectioncontent:')) {
                        this._onTextSelectionContentMsg(textMsg);
                }
-               else if (textMsg.startsWith('setpart:')) {
-                       this._onSetPartMsg(textMsg);
-               }
-               else if (textMsg.startsWith('searchnotfound:')) {
-                       this._onSearchNotFoundMsg(textMsg);
+               else if (textMsg.startsWith('textselectionend:')) {
+                       this._onTextSelectionEndMsg(textMsg);
                }
-               else if (textMsg.startsWith('styles:')) {
-                       this._onStylesMsg(textMsg);
+               else if (textMsg.startsWith('textselectionstart:')) {
+                       this._onTextSelectionStartMsg(textMsg);
                }
-               else if (textMsg.startsWith('error:')) {
-                       this._onErrorMsg(textMsg);
+               else if (textMsg.startsWith('tile:')) {
+                       this._onTileMsg(textMsg, imgBytes, index);
                }
        },
 
commit c921432ad02f299234c974644d38a6cc5dddbae3
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 11:59:38 2015 +0300

    loleaflet: modularized the onMessage method
    
    Conflicts:
        loleaflet/src/layer/tile/TileLayer.js

diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 1f60b48..36f0156 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -176,198 +176,259 @@ L.TileLayer = L.GridLayer.extend({
 
        _onMessage: function (textMsg, imgBytes, index) {
                if (textMsg.startsWith('cursorvisible:')) {
-                       var command = textMsg.match('cursorvisible: true');
-                       this._isCursorVisible = command ? true : false;
-                       this._isCursorOverlayVisible = true;
-                       this._onUpdateCursor();
+                       this._onCursorVisibleMsg(textMsg);
                }
                else if (textMsg.startsWith('invalidatecursor:')) {
-                       var strTwips = textMsg.match(/\d+/g);
-                       var topLeftTwips = new L.Point(parseInt(strTwips[0]), 
parseInt(strTwips[1]));
-                       var offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
-                       var bottomRightTwips = topLeftTwips.add(offset);
-                       this._visibleCursor = new L.LatLngBounds(
-                                                       
this._twipsToLatLng(topLeftTwips, this._map.getZoom()),
-                                                       
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
-                       this._isCursorOverlayVisible = true;
-                       this._onUpdateCursor();
+                       this._onInvalidateCursorMsg(textMsg);
                }
                else if (textMsg.startsWith('textselectionstart:')) {
-                       strTwips = textMsg.match(/\d+/g);
-                       if (strTwips != null) {
-                               topLeftTwips = new 
L.Point(parseInt(strTwips[0]), parseInt(strTwips[1]));
-                               offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
-                               bottomRightTwips = topLeftTwips.add(offset);
-                               this._textSelectionStart = new L.LatLngBounds(
-                                                       
this._twipsToLatLng(topLeftTwips, this._map.getZoom()),
-                                                       
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
-                       }
-                       else {
-                               this._textSelectionStart = new 
L.LatLngBounds(new L.LatLng(0, 0), new L.LatLng(0, 0));
-                       }
+                       this._onTextSelectionStartMsg(textMsg);
                }
                else if (textMsg.startsWith('textselectionend:')) {
-                       strTwips = textMsg.match(/\d+/g);
-                       if (strTwips != null) {
-                               topLeftTwips = new 
L.Point(parseInt(strTwips[0]), parseInt(strTwips[1]));
-                               offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
-                               bottomRightTwips = topLeftTwips.add(offset);
-                               this._textSelectionEnd = new L.LatLngBounds(
-                                                       
this._twipsToLatLng(topLeftTwips, this._map.getZoom()),
-                                                       
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
-                       }
-                       else {
-                               this._textSelectionEnd = new L.LatLngBounds(new 
L.LatLng(0, 0), new L.LatLng(0, 0));
-                       }
+                       this._onTextSelectionEndMsg(textMsg);
                }
                else if (textMsg.startsWith('graphicselection:')) {
-                       if (textMsg.match('EMPTY')) {
-                               this._graphicSelection = new L.LatLngBounds(new 
L.LatLng(0, 0), new L.LatLng(0, 0));
-                       }
-                       else {
-                               strTwips = textMsg.match(/\d+/g);
-                               topLeftTwips = new 
L.Point(parseInt(strTwips[0]), parseInt(strTwips[1]));
-                               offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
-                               bottomRightTwips = topLeftTwips.add(offset);
-                               this._graphicSelection = new L.LatLngBounds(
-                                                               
this._twipsToLatLng(topLeftTwips, this._map.getZoom()),
-                                                               
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
-                       }
-
-                       this._onUpdateGraphicSelection();
+                       this._onGraphicSelectionMsg(textMsg);
                }
                else if (textMsg.startsWith('invalidatetiles:') && 
!textMsg.match('EMPTY')) {
-                       command = L.Socket.parseServerCmd(textMsg);
-                       if (command.x === undefined || command.y === undefined 
|| command.part === undefined) {
-                               strTwips = textMsg.match(/\d+/g);
-                               command.x = parseInt(strTwips[0]);
-                               command.y = parseInt(strTwips[1]);
-                               command.width = parseInt(strTwips[2]);
-                               command.height = parseInt(strTwips[3]);
-                               command.part = this._currentPart;
-                       }
-                       if (this._docType === 'text') {
-                               command.part = 0;
-                       }
-                       topLeftTwips = new L.Point(command.x, command.y);
-                       offset = new L.Point(command.width, command.height);
-                       bottomRightTwips = topLeftTwips.add(offset);
-                       var invalidBounds = new L.Bounds(topLeftTwips, 
bottomRightTwips);
-                       var visibleTopLeft = 
this._latLngToTwips(this._map.getBounds().getNorthWest());
-                       var visibleBottomRight = 
this._latLngToTwips(this._map.getBounds().getSouthEast());
-                       var visibleArea = new L.Bounds(visibleTopLeft, 
visibleBottomRight);
-                       var toRequest = [];
-
-                       for (var key in this._tiles) {
-                               var coords = this._tiles[key].coords;
-                               var tileTopLeft = this._coordsToTwips(coords);
-                               var tileBottomRight = new 
L.Point(this._tileWidthTwips, this._tileHeightTwips);
-                               var bounds = new L.Bounds(tileTopLeft, 
tileTopLeft.add(tileBottomRight));
-                               if (invalidBounds.intersects(bounds) && 
coords.part === command.part) {
-                                       if (this._tiles[key]._invalidCount) {
-                                               this._tiles[key]._invalidCount 
+= 1;
-                                       }
-                                       else {
-                                               this._tiles[key]._invalidCount 
= 1;
-                                       }
-                                       if (visibleArea.intersects(bounds)) {
-                                               var msg = 'tile ' +
-                                                               'part=' + 
coords.part + ' ' +
-                                                               'width=' + 
this._tileSize + ' ' +
-                                                               'height=' + 
this._tileSize + ' ' +
-                                                               'tileposx=' + 
tileTopLeft.x + ' '    +
-                                                               'tileposy=' + 
tileTopLeft.y + ' ' +
-                                                               'tilewidth=' + 
this._tileWidthTwips + ' ' +
-                                                               'tileheight=' + 
this._tileHeightTwips;
-                                               toRequest.push({msg: msg, key: 
key, coords: coords});
-                                       }
-                                       else {
-                                               // tile outside of the visible 
area, just remove it
-                                               this._preFetchBorder = null;
-                                               this._removeTile(key);
-                                       }
-                               }
-                       }
-                       var cursorPos = 
this._map.project(this._visibleCursor.getNorthWest());
-                       cursorPos = cursorPos.divideBy(this._tileSize);
-                       toRequest.sort(function(x, y) {return 
x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);});
-                       for (var i = 0; i < toRequest.length; i++) {
-                               L.Socket.sendMessage(toRequest[i].msg, 
toRequest[i].key);
-                       }
-                       for (key in this._tileCache) {
-                               // compute the rectangle that each tile covers 
in the document based
-                               // on the zoom level
-                               coords = this._keyToTileCoords(key);
-                               if (coords.part !== command.part) {
-                                       continue;
-                               }
-                               var scale = this._map.getZoomScale(coords.z);
-                               topLeftTwips = new L.Point(
-                                               this.options.tileWidthTwips / 
scale * coords.x,
-                                               this.options.tileHeightTwips / 
scale * coords.y);
-                               bottomRightTwips = topLeftTwips.add(new L.Point(
-                                               this.options.tileWidthTwips / 
scale,
-                                               this.options.tileHeightTwips / 
scale));
-                               bounds = new L.Bounds(topLeftTwips, 
bottomRightTwips);
-                               if (invalidBounds.intersects(bounds)) {
-                                       delete this._tileCache[key];
-                               }
-                       }
-                       if (command.part === this._currentPart &&
-                               command.part !== this._lastValidPart) {
-                               this._lastValidPart = command.part;
-                               this._map.fire('updatepart', {part: 
command.part, docType: this._docType});
-                       }
+                       this._onInvalidateTilesMsg(textMsg);
                }
                else if (textMsg.startsWith('statechanged:')) {
-                       var unoMsg = textMsg.substr(14);
-                       var unoCmd = unoMsg.match('.uno:(.*)=')[1];
-                       var state = unoMsg.match('.*=(.*)')[1];
-                       if (unoCmd && state) {
-                               this._map.fire('commandstatechanged', {unoCmd : 
unoCmd, state : state});
-                       }
+                       this._onStateChangedMsg(textMsg);
                }
                else if (textMsg.startsWith('status:')) {
-                       command = L.Socket.parseServerCmd(textMsg);
-                       if (command.width && command.height && 
this._documentInfo !== textMsg) {
-                               this._docWidthTwips = command.width;
-                               this._docHeightTwips = command.height;
-                               this._docType = command.type;
-                               this._updateMaxBounds(true);
-                               this._documentInfo = textMsg;
-                               this._parts = command.parts;
-                               this._currentPart = command.currentPart;
-                               if (this._docType === 'text') {
-                                       this._currentPart = 0;
-                                       this._parts = 1;
-                                       this._currentPage = command.currentPart;
-                                       this._pages = command.parts;
-                                       this._map.fire('pagenumberchanged', {
-                                               currentPage: this._currentPage,
-                                               pages: this._pages,
-                                               docType: this._docType
-                                       });
+                       this._onStatusMsg(textMsg);
+               }
+               else if (textMsg.startsWith('statusindicator')) {
+                       this._onStatusIndicatorMsg(textMsg);
+               }
+               else if (textMsg.startsWith('tile:')) {
+                       this._onTileMsg(textMsg, imgBytes, index);
+               }
+               else if (textMsg.startsWith('textselection:')) {
+                       this._onTextSelectionMsg(textMsg);
+               }
+               else if (textMsg.startsWith('textselectioncontent:')) {
+                       this._onTextSelectionContentMsg(textMsg);
+               }
+               else if (textMsg.startsWith('setpart:')) {
+                       this._onSetPartMsg(textMsg);
+               }
+               else if (textMsg.startsWith('searchnotfound:')) {
+                       this._onSearchNotFoundMsg(textMsg);
+               }
+               else if (textMsg.startsWith('styles:')) {
+                       this._onStylesMsg(textMsg);
+               }
+               else if (textMsg.startsWith('error:')) {
+                       this._onErrorMsg(textMsg);
+               }
+       },
+
+       _onCursorVisibleMsg: function(textMsg) {
+               var command = textMsg.match('cursorvisible: true');
+               this._isCursorVisible = command ? true : false;
+               this._isCursorOverlayVisible = true;
+               this._onUpdateCursor();
+       },
+
+       _onErrorMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               this._map.fire('error', {cmd: command.errorCmd, kind: 
command.errorKind});
+       },
+
+       _onGraphicSelectionMsg: function (textMsg) {
+               if (textMsg.match('EMPTY')) {
+                       this._graphicSelection = new L.LatLngBounds(new 
L.LatLng(0, 0), new L.LatLng(0, 0));
+               }
+               else {
+                       var strTwips = textMsg.match(/\d+/g);
+                       var topLeftTwips = new L.Point(parseInt(strTwips[0]), 
parseInt(strTwips[1]));
+                       var offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
+                       var bottomRightTwips = topLeftTwips.add(offset);
+                       this._graphicSelection = new L.LatLngBounds(
+                                                       
this._twipsToLatLng(topLeftTwips, this._map.getZoom()),
+                                                       
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
+               }
+
+               this._onUpdateGraphicSelection();
+       },
+
+       _onInvalidateCursorMsg: function (textMsg) {
+               var strTwips = textMsg.match(/\d+/g);
+               var topLeftTwips = new L.Point(parseInt(strTwips[0]), 
parseInt(strTwips[1]));
+               var offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
+               var bottomRightTwips = topLeftTwips.add(offset);
+               this._visibleCursor = new L.LatLngBounds(
+                                               
this._twipsToLatLng(topLeftTwips, this._map.getZoom()),
+                                               
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
+               this._isCursorOverlayVisible = true;
+               this._onUpdateCursor();
+       },
+
+       _onInvalidateTilesMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               if (command.x === undefined || command.y === undefined || 
command.part === undefined) {
+                       var strTwips = textMsg.match(/\d+/g);
+                       command.x = parseInt(strTwips[0]);
+                       command.y = parseInt(strTwips[1]);
+                       command.width = parseInt(strTwips[2]);
+                       command.height = parseInt(strTwips[3]);
+                       command.part = this._currentPart;
+               }
+               if (this._docType === 'text') {
+                       command.part = 0;
+               }
+               var topLeftTwips = new L.Point(command.x, command.y);
+               var offset = new L.Point(command.width, command.height);
+               var bottomRightTwips = topLeftTwips.add(offset);
+               var invalidBounds = new L.Bounds(topLeftTwips, 
bottomRightTwips);
+               var visibleTopLeft = 
this._latLngToTwips(this._map.getBounds().getNorthWest());
+               var visibleBottomRight = 
this._latLngToTwips(this._map.getBounds().getSouthEast());
+               var visibleArea = new L.Bounds(visibleTopLeft, 
visibleBottomRight);
+               var toRequest = [];
+
+               for (var key in this._tiles) {
+                       var coords = this._tiles[key].coords;
+                       var tileTopLeft = this._coordsToTwips(coords);
+                       var tileBottomRight = new L.Point(this._tileWidthTwips, 
this._tileHeightTwips);
+                       var bounds = new L.Bounds(tileTopLeft, 
tileTopLeft.add(tileBottomRight));
+                       if (invalidBounds.intersects(bounds) && coords.part === 
command.part) {
+                               if (this._tiles[key]._invalidCount) {
+                                       this._tiles[key]._invalidCount += 1;
                                }
                                else {
-                                       L.Socket.sendMessage('setclientpart 
part=' + this._currentPart);
-                                       var partNames = 
textMsg.match(/[^\r\n]+/g);
-                                       // only get the last matches
-                                       partNames = 
partNames.slice(partNames.length - this._parts);
-                                       this._map.fire('updateparts', {
-                                               currentPart: this._currentPart,
-                                               parts: this._parts,
-                                               docType: this._docType,
-                                               partNames: partNames
-                                       });
+                                       this._tiles[key]._invalidCount = 1;
+                               }
+                               if (visibleArea.intersects(bounds)) {
+                                       var msg = 'tile ' +
+                                                       'part=' + coords.part + 
' ' +
+                                                       'width=' + 
this._tileSize + ' ' +
+                                                       'height=' + 
this._tileSize + ' ' +
+                                                       'tileposx=' + 
tileTopLeft.x + ' '    +
+                                                       'tileposy=' + 
tileTopLeft.y + ' ' +
+                                                       'tilewidth=' + 
this._tileWidthTwips + ' ' +
+                                                       'tileheight=' + 
this._tileHeightTwips;
+                                       toRequest.push({msg: msg, key: key, 
coords: coords});
                                }
-                               this._update();
-                               if (this._preFetchPart !== this._currentPart) {
-                                       this._preFetchPart = this._currentPart;
+                               else {
+                                       // tile outside of the visible area, 
just remove it
                                        this._preFetchBorder = null;
+                                       this._removeTile(key);
                                }
                        }
                }
-               else if (textMsg.startsWith('statusindicatorstart:')) {
+
+               // Sort tiles so that we request those closer to the cursor 
first
+               var cursorPos = 
this._map.project(this._visibleCursor.getNorthWest());
+               cursorPos = cursorPos.divideBy(this._tileSize);
+               toRequest.sort(function(x, y) {return 
x.coords.distanceTo(cursorPos) - y.coords.distanceTo(cursorPos);});
+               for (var i = 0; i < toRequest.length; i++) {
+                       L.Socket.sendMessage(toRequest[i].msg, 
toRequest[i].key);
+               }
+
+               for (key in this._tileCache) {
+                       // compute the rectangle that each tile covers in the 
document based
+                       // on the zoom level
+                       coords = this._keyToTileCoords(key);
+                       if (coords.part !== command.part) {
+                               continue;
+                       }
+                       var scale = this._map.getZoomScale(coords.z);
+                       topLeftTwips = new L.Point(
+                                       this.options.tileWidthTwips / scale * 
coords.x,
+                                       this.options.tileHeightTwips / scale * 
coords.y);
+                       bottomRightTwips = topLeftTwips.add(new L.Point(
+                                       this.options.tileWidthTwips / scale,
+                                       this.options.tileHeightTwips / scale));
+                       bounds = new L.Bounds(topLeftTwips, bottomRightTwips);
+                       if (invalidBounds.intersects(bounds)) {
+                               delete this._tileCache[key];
+                       }
+               }
+               if (command.part === this._currentPart &&
+                       command.part !== this._lastValidPart) {
+                       this._lastValidPart = command.part;
+                       this._map.fire('updatepart', {part: command.part, 
docType: this._docType});
+               }
+
+       },
+
+       _onSearchNotFoundMsg: function (textMsg) {
+               var originalPhrase = textMsg.substring(16);
+               this._map.fire('search', {originalPhrase: originalPhrase, 
count: 0});
+       },
+
+       _onSetPartMsg: function (textMsg) {
+               var part = parseInt(textMsg.match(/\d+/g)[0]);
+               if (part !== this._currentPart && this._docType !== 'text') {
+                       this._currentPart = part;
+                       this._update();
+                       this._clearSelections();
+                       this._map.fire('setpart', {currentPart: 
this._currentPart});
+               }
+               else if (this._docType === 'text') {
+                       this._currentPage = part;
+                       this._map.fire('pagenumberchanged', {
+                               currentPage: part,
+                               pages: this._pages,
+                               docType: this._docType
+                       });
+               }
+       },
+
+       _onStateChangedMsg: function (textMsg) {
+               var unoMsg = textMsg.substr(14);
+               var unoCmd = unoMsg.match('.uno:(.*)=')[1];
+               var state = unoMsg.match('.*=(.*)')[1];
+               if (unoCmd && state) {
+                       this._map.fire('commandstatechanged', {unoCmd : unoCmd, 
state : state});
+               }
+       },
+
+       _onStatusMsg: function (textMsg) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               if (command.width && command.height && this._documentInfo !== 
textMsg) {
+                       this._docWidthTwips = command.width;
+                       this._docHeightTwips = command.height;
+                       this._docType = command.type;
+                       this._updateMaxBounds(true);
+                       this._documentInfo = textMsg;
+                       this._parts = command.parts;
+                       this._currentPart = command.currentPart;
+                       if (this._docType === 'text') {
+                               this._currentPart = 0;
+                               this._parts = 1;
+                               this._currentPage = command.currentPart;
+                               this._pages = command.parts;
+                               this._map.fire('pagenumberchanged', {
+                                       currentPage: this._currentPage,
+                                       pages: this._pages,
+                                       docType: this._docType
+                               });
+                       }
+                       else {
+                               L.Socket.sendMessage('setclientpart part=' + 
this._currentPart);
+                               var partNames = textMsg.match(/[^\r\n]+/g);
+                               // only get the last matches
+                               partNames = partNames.slice(partNames.length - 
this._parts);
+                               this._map.fire('updateparts', {
+                                       currentPart: this._currentPart,
+                                       parts: this._parts,
+                                       docType: this._docType,
+                                       partNames: partNames
+                               });
+                       }
+                       this._update();
+                       if (this._preFetchPart !== this._currentPart) {
+                               this._preFetchPart = this._currentPart;
+                               this._preFetchBorder = null;
+                       }
+               }
+       },
+
+       _onStatusIndicatorMsg: function (textMsg) {
+               if (textMsg.startsWith('statusindicatorstart:')) {
                        this._map.fire('statusindicator', {statusType : 
'start'});
                }
                else if (textMsg.startsWith('statusindicatorsetvalue:')) {
@@ -377,123 +438,136 @@ L.TileLayer = L.GridLayer.extend({
                else if (textMsg.startsWith('statusindicatorfinish:')) {
                        this._map.fire('statusindicator', {statusType : 
'finish'});
                }
-               else if (textMsg.startsWith('tile:')) {
-                       command = L.Socket.parseServerCmd(textMsg);
-                       coords = this._twipsToCoords(command);
-                       coords.z = command.zoom;
-                       coords.part = command.part;
-                       var data = imgBytes.subarray(index + 1);
-
-                       // read the tile data
-                       var strBytes = '';
-                       for (i = 0; i < data.length; i++) {
-                               strBytes += String.fromCharCode(data[i]);
-                       }
+       },
 
-                       key = this._tileCoordsToKey(coords);
-                       var tile = this._tiles[key];
-                       var img = 'data:image/png;base64,' + 
window.btoa(strBytes);
-                       if (command.id !== undefined) {
-                               this._map.fire('tilepreview', {
-                                       tile: img,
-                                       id: command.id,
-                                       width: command.width,
-                                       height: command.height,
-                                       part: command.part,
-                                       docType: this._docType
-                               });
+       _onStylesMsg: function (textMsg) {
+               this._docStyles = JSON.parse(textMsg.substring(8));
+               this._map.fire('updatestyles', {styles: this._docStyles});
+       },
+
+       _onTextSelectionMsg: function (textMsg) {
+               var strTwips = textMsg.match(/\d+/g);
+               this._clearSelections();
+               if (strTwips != null) {
+                       var rectangles = [];
+                       var selectionCenter = new L.Point(0, 0);
+                       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]);
+                               selectionCenter = 
selectionCenter.add(topLeftTwips);
+                               selectionCenter = 
selectionCenter.add(offset.divideBy(2));
                        }
-                       else if (tile) {
-                               if (this._tiles[key]._invalidCount > 0) {
-                                       this._tiles[key]._invalidCount -= 1;
-                               }
-                               if (!tile.loaded) {
-                                       this._emptyTilesCount -= 1;
-                                       if (this._emptyTilesCount === 0) {
-                                               
this._map.fire('statusindicator', {statusType: 'alltilesloaded'});
-                                       }
-                               }
-                               tile.el.src = img;
+                       // average of all rectangles' centers
+                       selectionCenter = 
selectionCenter.divideBy(strTwips.length / 4);
+                       selectionCenter = this._twipsToLatLng(selectionCenter);
+                       if (!this._map.getBounds().contains(selectionCenter)) {
+                               var center = this._map.project(selectionCenter);
+                               center = 
center.subtract(this._map.getSize().divideBy(2));
+                               center.x = Math.round(center.x < 0 ? 0 : 
center.x);
+                               center.y = Math.round(center.y < 0 ? 0 : 
center.y);
+                               this._map.fire('scrollto', {x: center.x, y: 
center.y});
                        }
-                       else if (command.preFetch === 'true') {
-                               this._emptyTilesCount -= 1;
-                               this._tileCache[key] = img;
+
+                       var polygons = 
L.PolyUtil.rectanglesToPolygons(rectangles, this);
+                       for (i = 0; i < polygons.length; i++) {
+                               var selection = new L.Polygon(polygons[i], {
+                                       pointerEvents: 'none',
+                                       fillColor: '#43ACE8',
+                                       fillOpacity: 0.25,
+                                       weight: 2,
+                                       opacity: 0.25});
+                               this._selections.addLayer(selection);
+                       }
+                       if (this._selectionContentRequest) {
+                               clearTimeout(this._selectionContentRequest);
                        }
-                       L.Log.log(textMsg, L.INCOMING, key);
+                       this._selectionContentRequest = 
setTimeout(L.bind(function () {
+                               L.Socket.sendMessage('gettextselection 
mimetype=text/plain;charset=utf-8');}, this), 100);
                }
-               else if (textMsg.startsWith('textselection:')) {
-                       strTwips = textMsg.match(/\d+/g);
-                       this._clearSelections();
-                       if (strTwips != null) {
-                               var rectangles = [];
-                               var selectionCenter = new L.Point(0, 0);
-                               for (i = 0; i < strTwips.length; i += 4) {
-                                       topLeftTwips = new 
L.Point(parseInt(strTwips[i]), parseInt(strTwips[i + 1]));
-                                       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));
-                                       bottomRightTwips = 
topLeftTwips.add(offset);
-                                       rectangles.push([bottomLeftTwips, 
bottomRightTwips, topLeftTwips, topRightTwips]);
-                                       selectionCenter = 
selectionCenter.add(topLeftTwips);
-                                       selectionCenter = 
selectionCenter.add(offset.divideBy(2));
-                               }
-                               // average of all rectangles' centers
-                               selectionCenter = 
selectionCenter.divideBy(strTwips.length / 4);
-                               selectionCenter = 
this._twipsToLatLng(selectionCenter);
-                               if 
(!this._map.getBounds().contains(selectionCenter)) {
-                                       var center = 
this._map.project(selectionCenter);
-                                       center = 
center.subtract(this._map.getSize().divideBy(2));
-                                       center.x = center.x < 0 ? 0 : center.x;
-                                       center.y = center.y < 0 ? 0 : center.y;
-                                       this._map.fire('scrollto', {x: 
center.x, y: center.y});
-                               }
+               this._onUpdateTextSelection();
+       },
 
-                               var polygons = 
L.PolyUtil.rectanglesToPolygons(rectangles, this);
-                               for (i = 0; i < polygons.length; i++) {
-                                       var selection = new 
L.Polygon(polygons[i], {
-                                               pointerEvents: 'none',
-                                               fillColor: '#43ACE8',
-                                               fillOpacity: 0.25,
-                                               weight: 2,
-                                               opacity: 0.25});
-                                       this._selections.addLayer(selection);
-                               }
-                               if (this._selectionContentRequest) {
-                                       
clearTimeout(this._selectionContentRequest);
-                               }
-                               this._selectionContentRequest = 
setTimeout(L.bind(function () {
-                                       L.Socket.sendMessage('gettextselection 
mimetype=text/plain;charset=utf-8');}, this), 100);
-                       }
-                       this._onUpdateTextSelection();
+       _onTextSelectionContentMsg: function (textMsg) {
+               this._selectionTextContent = textMsg.substr(22);
+       },
+
+       _onTextSelectionEndMsg: function (textMsg) {
+               var strTwips = textMsg.match(/\d+/g);
+               if (strTwips != null) {
+                       var topLeftTwips = new L.Point(parseInt(strTwips[0]), 
parseInt(strTwips[1]));
+                       var offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
+                       var bottomRightTwips = topLeftTwips.add(offset);
+                       this._textSelectionEnd = new L.LatLngBounds(
+                                               
this._twipsToLatLng(topLeftTwips, this._map.getZoom()),
+                                               
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
                }
-               else if (textMsg.startsWith('textselectioncontent:')) {
-                       this._selectionTextContent = textMsg.substr(22);
+               else {
+                       this._textSelectionEnd = new L.LatLngBounds(new 
L.LatLng(0, 0), new L.LatLng(0, 0));
                }
-               else if (textMsg.startsWith('setpart:')) {
-                       var part = parseInt(textMsg.match(/\d+/g)[0]);
-                       if (part !== this._currentPart && this._docType !== 
'text') {
-                               this._currentPart = part;
-                               this._update();
-                               this._clearSelections();
-                               this._map.fire('setpart', {currentPart: 
this._currentPart});
+       },
+
+       _onTextSelectionStartMsg: function (textMsg) {
+               var strTwips = textMsg.match(/\d+/g);
+               if (strTwips != null) {
+                       var topLeftTwips = new L.Point(parseInt(strTwips[0]), 
parseInt(strTwips[1]));
+                       var offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
+                       var bottomRightTwips = topLeftTwips.add(offset);
+                       this._textSelectionStart = new L.LatLngBounds(
+                                               
this._twipsToLatLng(topLeftTwips, this._map.getZoom()),
+                                               
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
+               }
+               else {
+                       this._textSelectionStart = new L.LatLngBounds(new 
L.LatLng(0, 0), new L.LatLng(0, 0));
+               }
+       },
+
+       _onTileMsg: function (textMsg, imgBytes, index) {
+               var command = L.Socket.parseServerCmd(textMsg);
+               var coords = this._twipsToCoords(command);
+               coords.z = command.zoom;
+               coords.part = command.part;
+               var data = imgBytes.subarray(index + 1);
+
+               // read the tile data
+               var strBytes = '';
+               for (var i = 0; i < data.length; i++) {
+                       strBytes += String.fromCharCode(data[i]);
+               }
+
+               var key = this._tileCoordsToKey(coords);
+               var tile = this._tiles[key];
+               var img = 'data:image/png;base64,' + window.btoa(strBytes);
+               if (command.id !== undefined) {
+                       this._map.fire('tilepreview', {
+                               tile: img,
+                               id: command.id,
+                               width: command.width,
+                               height: command.height,
+                               part: command.part,
+                               docType: this._docType
+                       });
+               }
+               else if (tile) {
+                       if (this._tiles[key]._invalidCount > 0) {
+                               this._tiles[key]._invalidCount -= 1;
                        }
-                       else if (this._docType === 'text') {
-                               this._currentPage = part;
-                               this._map.fire('pagenumberchanged', {
-                                       currentPage: part,
-                                       pages: this._pages,
-                                       docType: this._docType
-                               });
+                       if (!tile.loaded) {
+                               this._emptyTilesCount -= 1;
+                               if (this._emptyTilesCount === 0) {
+                                       this._map.fire('statusindicator', 
{statusType: 'alltilesloaded'});
+                               }
                        }
+                       tile.el.src = img;
                }
-               else if (textMsg.startsWith('searchnotfound:')) {
-                       var originalPhrase = textMsg.substring(16);
-                       this._map.fire('search', {originalPhrase: 
originalPhrase, count: 0});
-               }
-               else if (textMsg.startsWith('error:')) {
-                       command = L.Socket.parseServerCmd(textMsg);
-                       this._map.fire('error', {cmd: command.errorCmd, kind: 
command.errorKind});
+               else if (command.preFetch === 'true') {
+                       this._tileCache[key] = img;
                }
+               L.Log.log(textMsg, L.INCOMING, key);
+
        },
 
        _tileOnLoad: function (done, tile) {
@@ -542,8 +616,6 @@ L.TileLayer = L.GridLayer.extend({
                                ' x=' + x + ' y=' + y);
        },
 
-
-
        // Is rRectangle empty?
        _isEmptyRectangle: function (aBounds) {
                return aBounds.getSouthWest().equals(new L.LatLng(0, 0)) && 
aBounds.getNorthEast().equals(new L.LatLng(0, 0));
commit 837d92f33dcafb0664c1ae57b8ca3d39f6d552f8
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Wed Sep 2 10:47:19 2015 +0300

    loleaflet: first splitting of TileLayer into 3 components

diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js
index 5fe8271..08959c2 100644
--- a/loleaflet/build/deps.js
+++ b/loleaflet/build/deps.js
@@ -51,6 +51,24 @@ var deps = {
                deps: ['TileLayer']
        },
 
+       WriterTileLayer: {
+               src: ['layer/tile/WriterTileLayer.js'],
+               desc: 'Writer tile layer.',
+               deps: ['TileLayer']
+       },
+
+       ImpressTileLayer: {
+               src: ['layer/tile/ImpressTileLayer.js'],
+               desc: 'Impress tile layer.',
+               deps: ['TileLayer']
+       },
+
+       WriterTileLayer: {
+               src: ['layer/tile/CalcTileLayer.js'],
+               desc: 'Calc tile layer.',
+               deps: ['TileLayer']
+       },
+
        ImageOverlay: {
                src: ['layer/ImageOverlay.js'],
                desc: 'Used to display an image over a particular rectangular 
area of the map.'
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 78cb922..5e49874 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -89,13 +89,32 @@ L.Socket = {
                if (textMsg.startsWith('status:') && !this._map._docLayer) {
                        // first status message, we need to create the document 
layer
                        var command = this.parseServerCmd(textMsg);
-                       this._map._docLayer = new L.TileLayer('', {
-                               edit: this._map.options.edit,
-                               readOnly: this._map.options.readOnly
-                       });
-                       this._map.addLayer(this._map._docLayer);
+                       var docLayer = null;
+                       if (command.style === 'text') {
+                               docLayer = new L.WriterTileLayer('', {
+                                       edit: this._map.options.edit,
+                                       readOnly: this._map.options.readOnly
+                               });
+                       }
+                       else if (command.style === 'spreadsheet') {
+                               docLayer = new L.CalcTileLayer('', {
+                                       edit: this._map.options.edit,
+                                       readOnly: this._map.options.readOnly
+                               });
+                       }
+                       else {
+                               docLayer = new L.ImpressTileLayer('', {
+                                       edit: this._map.options.edit,
+                                       readOnly: this._map.options.readOnly
+                               });
+                       }
+
+                       this._map._docLayer = docLayer;
+                       this._map.addLayer(docLayer);
+               }
+               if (this._map._docLayer) {
+                       this._map._docLayer._onMessage(textMsg, imgBytes, 
index);
                }
-               this._map._docLayer._onMessage(textMsg, imgBytes, index);
        },
 
        _onSocketError: function () {
diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js 
b/loleaflet/src/layer/tile/CalcTileLayer.js
new file mode 100644
index 0000000..1a1795a
--- /dev/null
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -0,0 +1,6 @@
+/*
+ * Calc tile layer is used to display a spreadsheet document
+ */
+
+L.CalcTileLayer = L.TileLayer.extend({
+});
diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js 
b/loleaflet/src/layer/tile/ImpressTileLayer.js
new file mode 100644
index 0000000..a2d1fbf
--- /dev/null
+++ b/loleaflet/src/layer/tile/ImpressTileLayer.js
@@ -0,0 +1,7 @@
+/*
+ * Impress tile layer is used to display a presentation document
+ */
+
+
+L.ImpressTileLayer = L.TileLayer.extend({
+});
diff --git a/loleaflet/src/layer/tile/WriterTileLayer.js 
b/loleaflet/src/layer/tile/WriterTileLayer.js
new file mode 100644
index 0000000..6eb0258
--- /dev/null
+++ b/loleaflet/src/layer/tile/WriterTileLayer.js
@@ -0,0 +1,6 @@
+/*
+ * Writer tile layer is used to display a text document
+ */
+
+L.WriterTileLayer = L.TileLayer.extend({
+});
commit a98137a6d5df5eb652f45e41d83a860a5f654f8a
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Tue Sep 1 18:15:43 2015 +0300

    loleaflet: README update

diff --git a/loleaflet/README b/loleaflet/README
index 0ce0f70..5ce2b41 100644
--- a/loleaflet/README
+++ b/loleaflet/README
@@ -193,15 +193,11 @@ Implementation details
 
 Loading a document:
     The map should have the following options:
-        - center at [0, 0] this will try to place the [0, 0] point in the 
middle of the
-          map, but it will be moved in the top left corner when the maxBounds 
are set
-        - zoom = defautl zoom value, zooming in and out will refer to this 
value
         - server address
-
-    The layer (actual document) should have the following options:
-        - doc = path to the document that will be loaded
-        - useSocket = tells the map the tiles will be received from a websocket
-          connection. If this parameter is false, an image will be loaded in 
each tile
+        - doc - path to the document that will be loaded
+        - edit = the initial permission
+        - readOnly - whether the document is read only
+        - [timestamp] - optionally provided for remote documents
 
 How zooming works:
     The zoom level goes from 1 to 20 (those limits can be changed) and the 
initial
commit affb12ceb5a1cb78106a994c72cbf57f69e7c92c
Author: Mihai Varga <mihai.va...@collabora.com>
Date:   Tue Sep 1 17:53:44 2015 +0300

    loleaflet: moved the socket init/communication to core/Socket.js
    
    The socket is now available through the L.Socket object which now also

... etc. - the rest is truncated
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to