cypress_test/integration_tests/desktop/writer/shape_operations_spec.js |    4 
 kit/ChildSession.cpp                                                   |   27 +
 kit/ChildSession.hpp                                                   |    1 
 loleaflet/Makefile.am                                                  |    1 
 loleaflet/css/loleaflet.css                                            |   43 
++
 loleaflet/src/layer/FormFieldButtonLayer.js                            |  154 
++++++++++
 loleaflet/src/layer/tile/TileLayer.js                                  |   14 
 loleaflet/src/map/Map.js                                               |    1 
 wsd/ClientSession.cpp                                                  |    7 
 9 files changed, 248 insertions(+), 4 deletions(-)

New commits:
commit e0a82365f32bc379aefee292eeac24b96c8e657b
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Thu May 7 15:34:37 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:09 2020 +0200

    cypress: fix shape operations test.
    
    Change-Id: Ibdca536bc8fb2a5b16d6ed085a65c25d1bc854b4

diff --git 
a/cypress_test/integration_tests/desktop/writer/shape_operations_spec.js 
b/cypress_test/integration_tests/desktop/writer/shape_operations_spec.js
index abbfe64b3..21b0a0d8c 100644
--- a/cypress_test/integration_tests/desktop/writer/shape_operations_spec.js
+++ b/cypress_test/integration_tests/desktop/writer/shape_operations_spec.js
@@ -8,8 +8,8 @@ describe('Shape operations', function() {
                helper.afterAll('shape_operations.odt', 'writer');
        });
 
-       it.skip('Insert a simple shape.', function() {
-               helper.loadTestDoc('shape_operations.odt');
+       it('Insert a simple shape.', function() {
+               helper.loadTestDoc('shape_operations.odt', 'writer');
 
                // Scroll on the up toolbar
                cy.get('#toolbar-up .w2ui-scroll-right').click();
commit 68017efb3caa801b733090f5b8085afc315ef529
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Thu May 7 15:14:13 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:09 2020 +0200

    MSForms: remove weird blue border dispalyed around the drop down button.
    
    Change-Id: Iddb696f10d9eb5364904021dd50431e11efc8dfb

diff --git a/loleaflet/css/loleaflet.css b/loleaflet/css/loleaflet.css
index b2dc2e8cb..227658acb 100644
--- a/loleaflet/css/loleaflet.css
+++ b/loleaflet/css/loleaflet.css
@@ -547,6 +547,7 @@ body {
 
 .form-field-button:hover, .form-field-button:focus {
        background: #DDDDDD;
+       outline: 0;
 }
 
 .form-field-button-image {
commit c7c690c4e805aaf5ed40b0e7f30929d26ed59327
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Thu May 7 14:21:24 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:08 2020 +0200

    MSForms: stop propagation of mouse events for the drop down button.
    
    Change-Id: Id63056f1aa39cadfc62021c5220d301f7ea26af8

diff --git a/loleaflet/src/layer/FormFieldButtonLayer.js 
b/loleaflet/src/layer/FormFieldButtonLayer.js
index 33c6b561c..0acaabce5 100644
--- a/loleaflet/src/layer/FormFieldButtonLayer.js
+++ b/loleaflet/src/layer/FormFieldButtonLayer.js
@@ -90,6 +90,10 @@ L.FormFieldButton = L.Layer.extend({
                image.src = 'images/unfold.svg';
 
                button.addEventListener('click', this._onClickDropDown);
+
+               // Stop propagation to the main document
+               button.addEventListener('mouseup', function(event) 
{event.stopPropagation();});
+               button.addEventListener('mousedown', function(event) 
{event.stopPropagation();});
        },
 
        _buildDropDownList: function(framePos, frameWidth, frameHeight) {
commit 98f4b50673f9dd2e1b56a6cb63679c5e5ac723d1
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Thu May 7 12:36:00 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:08 2020 +0200

    MSForms: do some styling of drop-down form field..
    
    Change-Id: I70d4766dcf116e31cde18f67cfea6551197657a8

diff --git a/loleaflet/css/loleaflet.css b/loleaflet/css/loleaflet.css
index 8639f504d..b2dc2e8cb 100644
--- a/loleaflet/css/loleaflet.css
+++ b/loleaflet/css/loleaflet.css
@@ -532,6 +532,7 @@ body {
        border: 1px solid;
        position: absolute;
        height: 100%;
+       border-radius: 2px;
 }
 
 .form-field-button {
@@ -541,6 +542,7 @@ body {
        height: 100%;
        box-sizing: content-box;
        padding: 0px;
+       border-radius: 2px;
 }
 
 .form-field-button:hover, .form-field-button:focus {
@@ -554,6 +556,7 @@ body {
 .drop-down-field-list {
        position: absolute;
        border: 1px solid;
+       cursor: pointer;
 }
 
 .drop-down-field-list-item {
@@ -563,3 +566,6 @@ body {
 .drop-down-field-list-item.selected {
        background: #99CCFF;
 }
+.drop-down-field-list-item:hover {
+       background: #0b87e7;
+}
commit 75dc61da7e6305a2f6b6e8e9a45e016ae1fc2e7d
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Wed May 6 13:59:03 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:08 2020 +0200

    MSForms: send item selection event to core.
    
    Change-Id: I10fceb66a4f8cd777c43411ddace3456a315b5a2

diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index e70cfde2e..ba8bdf8ee 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -301,7 +301,8 @@ bool ChildSession::_handleInput(const char *buffer, int 
length)
                tokens.equals(0, "rendershapeselection") ||
                tokens.equals(0, "removetextcontext") ||
                tokens.equals(0, "dialogevent") ||
-               tokens.equals(0, "completefunction"));
+               tokens.equals(0, "completefunction")||
+               tokens.equals(0, "formfieldevent"));
 
         if (tokens.equals(0, "clientzoom"))
         {
@@ -446,6 +447,10 @@ bool ChildSession::_handleInput(const char *buffer, int 
length)
         {
             return completeFunction(buffer, length, tokens);
         }
+        else if (tokens.equals(0, "formfieldevent"))
+        {
+            return formFieldEvent(buffer, length, tokens);
+        }
         else
         {
             assert(false && "Unknown command token.");
@@ -1426,6 +1431,23 @@ bool ChildSession::dialogEvent(const char* /*buffer*/, 
int /*length*/, const Str
     return true;
 }
 
+bool ChildSession::formFieldEvent(const char* buffer, int length, const 
StringVector& /*tokens*/)
+{
+    std::string sFirstLine = getFirstLine(buffer, length);
+    std::string sArguments = sFirstLine.substr(std::string("formfieldevent 
").size());
+
+    if (sArguments.empty())
+    {
+        sendTextFrameAndLogError("error: cmd=formfieldevent kind=syntax");
+        return false;
+    }
+
+    getLOKitDocument()->setView(_viewId);
+    getLOKitDocument()->sendFormFieldEvent(sArguments.c_str());
+
+    return true;
+}
+
 bool ChildSession::completeFunction(const char* /*buffer*/, int /*length*/, 
const StringVector& tokens)
 {
     std::string functionName;
diff --git a/kit/ChildSession.hpp b/kit/ChildSession.hpp
index fad3061aa..4c4dbb2ec 100644
--- a/kit/ChildSession.hpp
+++ b/kit/ChildSession.hpp
@@ -291,6 +291,7 @@ private:
     bool removeTextContext(const char* /*buffer*/, int /*length*/, const 
StringVector& tokens);
 
     void rememberEventsForInactiveUser(const int type, const std::string& 
payload);
+    bool formFieldEvent(const char* buffer, int length, const StringVector& 
tokens);
 
     virtual void disconnect() override;
     virtual bool _handleInput(const char* buffer, int length) override;
diff --git a/loleaflet/src/layer/FormFieldButtonLayer.js 
b/loleaflet/src/layer/FormFieldButtonLayer.js
index 4cd837ffe..33c6b561c 100644
--- a/loleaflet/src/layer/FormFieldButtonLayer.js
+++ b/loleaflet/src/layer/FormFieldButtonLayer.js
@@ -15,6 +15,7 @@ L.FormFieldButton = L.Layer.extend({
        },
 
        onAdd: function (map) {
+               this.map = map;
                this._clearButton();
                this._buildFormButton(map);
        },
@@ -102,7 +103,10 @@ L.FormFieldButton = L.Layer.extend({
                for (var i = 0; i < itemList.length; ++i) {
                        var option = L.DomUtil.create('div', 
'drop-down-field-list-item', dropDownList);
                        option.innerHTML = itemList[i];
+
                        option.addEventListener('click', 
this._onListItemSelect);
+                       option.map = this.map;
+
                        // Stop propagation to the main document
                        option.addEventListener('mouseup', function(event) 
{event.stopPropagation();});
                        option.addEventListener('mousedown', function(event) 
{event.stopPropagation();});
@@ -116,17 +120,27 @@ L.FormFieldButton = L.Layer.extend({
                this._clearButton();
        },
 
-       _onClickDropDown: function() {
+       _onClickDropDown: function(event) {
                $('.drop-down-field-list').show();
+               event.stopPropagation();
        },
 
        _onListItemSelect: function(event) {
+               $('.drop-down-field-list').hide();
                
$('.drop-down-field-list-item.selected').removeClass('selected');
                event.target.classList.add('selected');
-               // TODO: send back
-               $('.drop-down-field-list').hide();
+
                event.stopPropagation();
-               console.warn(event.target.textContent);
+
+               // Find item index
+               var index = $(event.target).index();
+
+               var message = 'formfieldevent {\"type\": \"drop-down\",' +
+                                     '\"cmd\": \"selected\",' +
+                                         '\"data\":\"' + index.toString() + 
'\"}';
+
+               // Apply selection in the document.
+               this.map._socket.sendMessage(message);
        },
 
        _clearButton: function() {
diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 6deb6808f..ded1b572c 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -728,7 +728,6 @@ L.TileLayer = L.GridLayer.extend({
                }
                else if (textMsg.startsWith('formfieldbutton:')) {
                        this._onFormFieldButtonMsg(textMsg);
-                       console.error(textMsg);
                }
        },
 
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index 956a4ba7e..41d9bbcd0 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -439,7 +439,8 @@ bool ClientSession::_handleInput(const char *buffer, int 
length)
              tokens[0] != "resizewindow" &&
              tokens[0] != "removetextcontext" &&
              tokens[0] != "dialogevent" &&
-             tokens[0] != "completefunction")
+             tokens[0] != "completefunction" &&
+             tokens[0] != "formfieldevent")
     {
         LOG_ERR("Session [" << getId() << "] got unknown command [" << 
tokens[0] << "].");
         sendTextFrameAndLogError("error: cmd=" + tokens[0] + " kind=unknown");
@@ -721,6 +722,10 @@ bool ClientSession::_handleInput(const char *buffer, int 
length)
     {
         return forwardToChild(std::string(buffer, length), docBroker);
     }
+    else if (tokens.equals(0, "formfieldevent"))
+    {
+        return forwardToChild(firstLine, docBroker);
+    }
     else
     {
         if (tokens.equals(0, "key"))
commit dc9e66f4bb3a7fc6430226e0e6dc03c506b84bd7
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Tue May 5 17:37:26 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:08 2020 +0200

    MSForms: restructure form field button rendering code.
    
    To make it more readable.
    
    Change-Id: Icfb179a5edfc65fe2dcaaebcc86c970e5d3b83b1

diff --git a/loleaflet/src/layer/FormFieldButtonLayer.js 
b/loleaflet/src/layer/FormFieldButtonLayer.js
index 14ca0f401..4cd837ffe 100644
--- a/loleaflet/src/layer/FormFieldButtonLayer.js
+++ b/loleaflet/src/layer/FormFieldButtonLayer.js
@@ -10,73 +10,103 @@ L.FormFieldButton = L.Layer.extend({
        },
 
        initialize: function (data) {
-               if (data.type === 'drop-down') {
-                       var strTwips = data.textArea.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._buttonAreaTwips = [topLeftTwips, 
bottomRightTwips];
-                       this._buttonData = data;
-               }
+               console.assert(data.type === 'drop-down');
+               this._buttonData = data;
        },
 
        onAdd: function (map) {
                this._clearButton();
-
                this._buildFormButton(map);
        },
 
        _buildFormButton: function(map) {
-               this._container = L.DomUtil.create('div', 
'form-field-button-container', this.getPane('formfieldPane'));
+               // We use a container to have the frame and the drop-down 
button the same height
+               var container = L.DomUtil.create('div', 
'form-field-button-container', this.getPane('formfieldPane'));
 
-               // Create a frame around the text area
-               this._frame = L.DomUtil.create('div', 'form-field-frame', 
this._container);
+               // Calculate button area in layer point unot
+               var buttonArea = this._calculateButtonArea(map);
+
+               // Build the frame around the text area
+               var frameData = this._buildButtonFrame(container, buttonArea);
+               var framePos = frameData[0];
+               var frameWidth = frameData[1];
+               var frameHeight = frameData[2];
+
+               // We set the shared height here.
+               container.style.height = frameHeight + 'px';
+
+               // Add a drop down button to open the list
+               this._buildDropDownButton(container, framePos, frameWidth);
+
+               // Build list of items opened by clicking on the drop down 
button
+               this._buildDropDownList(framePos, frameWidth, frameHeight);
+       },
+
+       _calculateButtonArea: function(map) {
+               // First get the data from the message in twips.
+               var strTwips = this._buttonData.textArea.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);
+               var buttonAreaTwips = [topLeftTwips, bottomRightTwips];
+
+               // Then convert to unit which can be used on the layer.
                var buttonAreaLatLng = new L.LatLngBounds(
-                               
map._docLayer._twipsToLatLng(this._buttonAreaTwips[0], this._map.getZoom()),
-                               
map._docLayer._twipsToLatLng(this._buttonAreaTwips[1], this._map.getZoom()));
+                               
map._docLayer._twipsToLatLng(buttonAreaTwips[0], this._map.getZoom()),
+                               
map._docLayer._twipsToLatLng(buttonAreaTwips[1], this._map.getZoom()));
 
                var buttonAreaLayer = new L.Bounds(
-                               
this._map.latLngToLayerPoint(buttonAreaLatLng.getNorthWest()),
-                               
this._map.latLngToLayerPoint(buttonAreaLatLng.getSouthEast()));
+                               
map.latLngToLayerPoint(buttonAreaLatLng.getNorthWest()),
+                               
map.latLngToLayerPoint(buttonAreaLatLng.getSouthEast()));
+
+               return buttonAreaLayer;
+       },
+
+       _buildButtonFrame: function(container, buttonArea) {
+               // Create a frame around the text area
+               var buttonFrame = L.DomUtil.create('div', 'form-field-frame', 
container);
 
                // Use a small padding between the text and the frame
                var extraPadding = 2;
-               var size = buttonAreaLayer.getSize();
-               this.frameWidth = size.x + 1.5 * extraPadding;
-               this.frameHeight = size.y + 1.5 * extraPadding;
-               this._frame.style.width = this.frameWidth + 'px';
-               this._container.style.height = this.frameHeight + 'px';
+               var size = buttonArea.getSize();
+               var frameWidth = size.x + 1.5 * extraPadding;
+               var frameHeight = size.y + 1.5 * extraPadding;
+               buttonFrame.style.width = frameWidth + 'px';
 
-               this.framePos = new L.Point(buttonAreaLayer.min.x - 
extraPadding, buttonAreaLayer.min.y - extraPadding);
-               L.DomUtil.setPosition(this._frame, this.framePos);
+               var framePos = new L.Point(buttonArea.min.x - extraPadding, 
buttonArea.min.y - extraPadding);
+               L.DomUtil.setPosition(buttonFrame, framePos);
 
-               // Add a drop down button to open the list
-               this._button = L.DomUtil.create('button', 'form-field-button', 
this._container);
-               var buttonPos = new L.Point(buttonAreaLayer.max.x + 
extraPadding, buttonAreaLayer.min.y - extraPadding);
-               L.DomUtil.setPosition(this._button, buttonPos);
-               this._button.style.width = this._container.style.height;
+               return [framePos, frameWidth, frameHeight];
+       },
+
+       _buildDropDownButton: function(container, framePos, frameWidth) {
+               var button = L.DomUtil.create('button', 'form-field-button', 
container);
+               var buttonPos = new L.Point(framePos.x + frameWidth, 
framePos.y);
+               L.DomUtil.setPosition(button, buttonPos);
+               button.style.width = container.style.height;
 
-               var image = L.DomUtil.create('img', 'form-field-button-image', 
this._button);
+               var image = L.DomUtil.create('img', 'form-field-button-image', 
button);
                image.src = 'images/unfold.svg';
 
-               this._button.addEventListener('click', this._onClickDropDown);
+               button.addEventListener('click', this._onClickDropDown);
+       },
 
-               // Build list of items
-               this._dropDownList = L.DomUtil.create('div', 
'drop-down-field-list', this.getPane('formfieldPane'));
+       _buildDropDownList: function(framePos, frameWidth, frameHeight) {
+               var dropDownList = L.DomUtil.create('div', 
'drop-down-field-list', this.getPane('formfieldPane'));
                $('.drop-down-field-list').hide();
-               var listPos = this.framePos;
-               L.DomUtil.setPosition(this._dropDownList, listPos);
-               this._dropDownList.style.minWidth = (this.frameWidth + 
this.frameHeight) + 'px';
+               L.DomUtil.setPosition(dropDownList, framePos);
+               dropDownList.style.minWidth = (frameWidth + frameHeight) + 'px';
 
                var itemList = this._buttonData.params.items;
                var selected = parseInt(this._buttonData.params.selected);
                for (var i = 0; i < itemList.length; ++i) {
-                       var option = L.DomUtil.create('div', 
'drop-down-field-list-item', this._dropDownList);
+                       var option = L.DomUtil.create('div', 
'drop-down-field-list-item', dropDownList);
                        option.innerHTML = itemList[i];
                        option.addEventListener('click', 
this._onListItemSelect);
                        // Stop propagation to the main document
                        option.addEventListener('mouseup', function(event) 
{event.stopPropagation();});
                        option.addEventListener('mousedown', function(event) 
{event.stopPropagation();});
+
                        if (i === selected)
                                option.classList.add('selected');
                }
@@ -101,8 +131,6 @@ L.FormFieldButton = L.Layer.extend({
 
        _clearButton: function() {
                this.getPane('formfieldPane').innerHTML = '';
-               this._frame = undefined;
-               this._button = undefined;
        }
 
 });
commit 6640ba5cef23ecf911b0058df34fbec155ab5b29
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Tue May 5 15:20:22 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:08 2020 +0200

    MSForms: use the actual item list for drop down field.
    
    Change-Id: Ib6021cf5d2a0c25bcd04f44771a33b3e3cea53fb

diff --git a/loleaflet/src/layer/FormFieldButtonLayer.js 
b/loleaflet/src/layer/FormFieldButtonLayer.js
index cfd91a605..14ca0f401 100644
--- a/loleaflet/src/layer/FormFieldButtonLayer.js
+++ b/loleaflet/src/layer/FormFieldButtonLayer.js
@@ -68,17 +68,16 @@ L.FormFieldButton = L.Layer.extend({
                L.DomUtil.setPosition(this._dropDownList, listPos);
                this._dropDownList.style.minWidth = (this.frameWidth + 
this.frameHeight) + 'px';
 
-               // TODO: use the actual list here
-               var stringList = ['text1', 'text2', 'string', 'selected_item'];
-               var selected = 'selected_item';
-               for (var i = 0; i < stringList.length; ++i) {
+               var itemList = this._buttonData.params.items;
+               var selected = parseInt(this._buttonData.params.selected);
+               for (var i = 0; i < itemList.length; ++i) {
                        var option = L.DomUtil.create('div', 
'drop-down-field-list-item', this._dropDownList);
-                       option.innerHTML = stringList[i];
+                       option.innerHTML = itemList[i];
                        option.addEventListener('click', 
this._onListItemSelect);
                        // Stop propagation to the main document
                        option.addEventListener('mouseup', function(event) 
{event.stopPropagation();});
                        option.addEventListener('mousedown', function(event) 
{event.stopPropagation();});
-                       if (stringList[i] === selected)
+                       if (i === selected)
                                option.classList.add('selected');
                }
        },
commit 3bce2d45ab344b5c7e3a20ac79ebd42620a95448
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Fri May 1 17:57:38 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:08 2020 +0200

    MSForms: build drop down list for drop-down field.
    
    Change-Id: I42a68ebf8b0201d97779f2bfc43a8dabbad9e1c0

diff --git a/loleaflet/css/loleaflet.css b/loleaflet/css/loleaflet.css
index 7f874c222..8639f504d 100644
--- a/loleaflet/css/loleaflet.css
+++ b/loleaflet/css/loleaflet.css
@@ -544,9 +544,22 @@ body {
 }
 
 .form-field-button:hover, .form-field-button:focus {
-  background: #DDDDDD;
+       background: #DDDDDD;
 }
 
 .form-field-button-image {
        margin: 3px;
 }
+
+.drop-down-field-list {
+       position: absolute;
+       border: 1px solid;
+}
+
+.drop-down-field-list-item {
+       width: 100%;
+}
+
+.drop-down-field-list-item.selected {
+       background: #99CCFF;
+}
diff --git a/loleaflet/src/layer/FormFieldButtonLayer.js 
b/loleaflet/src/layer/FormFieldButtonLayer.js
index 169f030e0..cfd91a605 100644
--- a/loleaflet/src/layer/FormFieldButtonLayer.js
+++ b/loleaflet/src/layer/FormFieldButtonLayer.js
@@ -2,7 +2,7 @@
 /*
  * L.FormFieldButton is used to interact with text based form fields.
  */
-
+/* global $ */
 L.FormFieldButton = L.Layer.extend({
 
        options: {
@@ -16,6 +16,7 @@ L.FormFieldButton = L.Layer.extend({
                        var offset = new L.Point(parseInt(strTwips[2]), 
parseInt(strTwips[3]));
                        var bottomRightTwips = topLeftTwips.add(offset);
                        this._buttonAreaTwips = [topLeftTwips, 
bottomRightTwips];
+                       this._buttonData = data;
                }
        },
 
@@ -26,8 +27,10 @@ L.FormFieldButton = L.Layer.extend({
        },
 
        _buildFormButton: function(map) {
+               this._container = L.DomUtil.create('div', 
'form-field-button-container', this.getPane('formfieldPane'));
+
                // Create a frame around the text area
-               this._frame = L.DomUtil.create('div', 'form-field-frame', 
this.getPane('formfieldPane'));
+               this._frame = L.DomUtil.create('div', 'form-field-frame', 
this._container);
                var buttonAreaLatLng = new L.LatLngBounds(
                                
map._docLayer._twipsToLatLng(this._buttonAreaTwips[0], this._map.getZoom()),
                                
map._docLayer._twipsToLatLng(this._buttonAreaTwips[1], this._map.getZoom()));
@@ -39,37 +42,68 @@ L.FormFieldButton = L.Layer.extend({
                // Use a small padding between the text and the frame
                var extraPadding = 2;
                var size = buttonAreaLayer.getSize();
-               this._frame.style.width = (size.x + 1.5 * extraPadding) + 'px';
+               this.frameWidth = size.x + 1.5 * extraPadding;
+               this.frameHeight = size.y + 1.5 * extraPadding;
+               this._frame.style.width = this.frameWidth + 'px';
+               this._container.style.height = this.frameHeight + 'px';
 
-               this.getPane('formfieldPane').style.height = (size.y + 1.5 * 
extraPadding) + 'px';
-
-               var framePos = new L.Point(buttonAreaLayer.min.x - 
extraPadding, buttonAreaLayer.min.y - extraPadding);
-               L.DomUtil.setPosition(this._frame, framePos);
+               this.framePos = new L.Point(buttonAreaLayer.min.x - 
extraPadding, buttonAreaLayer.min.y - extraPadding);
+               L.DomUtil.setPosition(this._frame, this.framePos);
 
                // Add a drop down button to open the list
-               this._button = L.DomUtil.create('button', 'form-field-button', 
this.getPane('formfieldPane'));
+               this._button = L.DomUtil.create('button', 'form-field-button', 
this._container);
                var buttonPos = new L.Point(buttonAreaLayer.max.x + 
extraPadding, buttonAreaLayer.min.y - extraPadding);
                L.DomUtil.setPosition(this._button, buttonPos);
-               this._button.style.width = 
this.getPane('formfieldPane').style.height;
+               this._button.style.width = this._container.style.height;
 
                var image = L.DomUtil.create('img', 'form-field-button-image', 
this._button);
                image.src = 'images/unfold.svg';
+
+               this._button.addEventListener('click', this._onClickDropDown);
+
+               // Build list of items
+               this._dropDownList = L.DomUtil.create('div', 
'drop-down-field-list', this.getPane('formfieldPane'));
+               $('.drop-down-field-list').hide();
+               var listPos = this.framePos;
+               L.DomUtil.setPosition(this._dropDownList, listPos);
+               this._dropDownList.style.minWidth = (this.frameWidth + 
this.frameHeight) + 'px';
+
+               // TODO: use the actual list here
+               var stringList = ['text1', 'text2', 'string', 'selected_item'];
+               var selected = 'selected_item';
+               for (var i = 0; i < stringList.length; ++i) {
+                       var option = L.DomUtil.create('div', 
'drop-down-field-list-item', this._dropDownList);
+                       option.innerHTML = stringList[i];
+                       option.addEventListener('click', 
this._onListItemSelect);
+                       // Stop propagation to the main document
+                       option.addEventListener('mouseup', function(event) 
{event.stopPropagation();});
+                       option.addEventListener('mousedown', function(event) 
{event.stopPropagation();});
+                       if (stringList[i] === selected)
+                               option.classList.add('selected');
+               }
        },
 
        onRemove: function () {
                this._clearButton();
        },
 
+       _onClickDropDown: function() {
+               $('.drop-down-field-list').show();
+       },
+
+       _onListItemSelect: function(event) {
+               
$('.drop-down-field-list-item.selected').removeClass('selected');
+               event.target.classList.add('selected');
+               // TODO: send back
+               $('.drop-down-field-list').hide();
+               event.stopPropagation();
+               console.warn(event.target.textContent);
+       },
+
        _clearButton: function() {
                this.getPane('formfieldPane').innerHTML = '';
-               if (this._frame) {
-                       L.DomUtil.remove(this._frame);
-                       this._frame = undefined;
-               }
-               if (this._button) {
-                       L.DomUtil.remove(this._button);
-                       this._button = undefined;
-               }
+               this._frame = undefined;
+               this._button = undefined;
        }
 
 });
commit 87b862a4e2fafe2c420f672af835929d588757a2
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Thu Apr 30 14:34:09 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:08 2020 +0200

    MSForms: styling form field button.
    
    Change-Id: I4bbcc16aa8afb0fa7e8e84d34e1f18086f0b8615

diff --git a/loleaflet/css/loleaflet.css b/loleaflet/css/loleaflet.css
index 834579ade..7f874c222 100644
--- a/loleaflet/css/loleaflet.css
+++ b/loleaflet/css/loleaflet.css
@@ -528,7 +528,25 @@ body {
                -o-user-select: none;
 }
 
-.drop-down-button {
-       background: #FF0000;
+.form-field-frame {
+       border: 1px solid;
        position: absolute;
+       height: 100%;
+}
+
+.form-field-button {
+       background: #FFFFFF;
+       position: absolute;
+       border: 1px solid;
+       height: 100%;
+       box-sizing: content-box;
+       padding: 0px;
+}
+
+.form-field-button:hover, .form-field-button:focus {
+  background: #DDDDDD;
+}
+
+.form-field-button-image {
+       margin: 3px;
 }
diff --git a/loleaflet/src/layer/FormFieldButtonLayer.js 
b/loleaflet/src/layer/FormFieldButtonLayer.js
index bbbb0d721..169f030e0 100644
--- a/loleaflet/src/layer/FormFieldButtonLayer.js
+++ b/loleaflet/src/layer/FormFieldButtonLayer.js
@@ -20,11 +20,14 @@ L.FormFieldButton = L.Layer.extend({
        },
 
        onAdd: function (map) {
-               if (this._button) {
-                       L.DomUtil.remove(this._button);
-               }
+               this._clearButton();
 
-               this._button = L.DomUtil.create('div', 'drop-down-button', 
this.getPane('formfieldPane'));
+               this._buildFormButton(map);
+       },
+
+       _buildFormButton: function(map) {
+               // Create a frame around the text area
+               this._frame = L.DomUtil.create('div', 'form-field-frame', 
this.getPane('formfieldPane'));
                var buttonAreaLatLng = new L.LatLngBounds(
                                
map._docLayer._twipsToLatLng(this._buttonAreaTwips[0], this._map.getZoom()),
                                
map._docLayer._twipsToLatLng(this._buttonAreaTwips[1], this._map.getZoom()));
@@ -33,17 +36,40 @@ L.FormFieldButton = L.Layer.extend({
                                
this._map.latLngToLayerPoint(buttonAreaLatLng.getNorthWest()),
                                
this._map.latLngToLayerPoint(buttonAreaLatLng.getSouthEast()));
 
+               // Use a small padding between the text and the frame
+               var extraPadding = 2;
                var size = buttonAreaLayer.getSize();
-               this._button.style.width  = size.x + 'px';
-               this._button.style.height = size.y + 'px';
+               this._frame.style.width = (size.x + 1.5 * extraPadding) + 'px';
+
+               this.getPane('formfieldPane').style.height = (size.y + 1.5 * 
extraPadding) + 'px';
+
+               var framePos = new L.Point(buttonAreaLayer.min.x - 
extraPadding, buttonAreaLayer.min.y - extraPadding);
+               L.DomUtil.setPosition(this._frame, framePos);
 
-               var pos = buttonAreaLayer.min;
-               L.DomUtil.setPosition(this._button, pos);
+               // Add a drop down button to open the list
+               this._button = L.DomUtil.create('button', 'form-field-button', 
this.getPane('formfieldPane'));
+               var buttonPos = new L.Point(buttonAreaLayer.max.x + 
extraPadding, buttonAreaLayer.min.y - extraPadding);
+               L.DomUtil.setPosition(this._button, buttonPos);
+               this._button.style.width = 
this.getPane('formfieldPane').style.height;
+
+               var image = L.DomUtil.create('img', 'form-field-button-image', 
this._button);
+               image.src = 'images/unfold.svg';
        },
 
        onRemove: function () {
-               L.DomUtil.remove(this._button);
-               this._button = undefined;
+               this._clearButton();
        },
 
+       _clearButton: function() {
+               this.getPane('formfieldPane').innerHTML = '';
+               if (this._frame) {
+                       L.DomUtil.remove(this._frame);
+                       this._frame = undefined;
+               }
+               if (this._button) {
+                       L.DomUtil.remove(this._button);
+                       this._button = undefined;
+               }
+       }
+
 });
commit d2629961e0ca99bdebcfa0e3711abe6d5cc8cbcb
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Wed Apr 29 13:36:05 2020 +0200
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Sat May 9 09:54:08 2020 +0200

    MSForms: handle formfieldbutton message.
    
    Change-Id: I17243823d9bc0074b7fd015bca23de9399e0e26c

diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index b02e7a17a..e70cfde2e 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -2568,6 +2568,9 @@ void ChildSession::loKitCallback(const int type, const 
std::string& payload)
     case LOK_CALLBACK_TAB_STOP_LIST:
         sendTextFrame("tabstoplistupdate: " + payload);
         break;
+    case LOK_CALLBACK_FORM_FIELD_BUTTON:
+        sendTextFrame("formfieldbutton: " + payload);
+        break;
 
 #if !ENABLE_DEBUG
     // we want a compilation-time failure in the debug builds; but ERR in the
diff --git a/loleaflet/Makefile.am b/loleaflet/Makefile.am
index afbde0ec7..11945badb 100644
--- a/loleaflet/Makefile.am
+++ b/loleaflet/Makefile.am
@@ -230,6 +230,7 @@ LOLEAFLET_JS =\
        src/layer/vector/Path.Transform.SVG.VML.js \
        src/layer/vector/Canvas.js \
        src/layer/vector/Path.Transform.Canvas.js \
+       src/layer/FormFieldButtonLayer.js \
        src/dom/DomEvent.js \
        src/dom/Draggable.js \
        src/map/handler/Map.Drag.js \
diff --git a/loleaflet/css/loleaflet.css b/loleaflet/css/loleaflet.css
index 40b782d95..834579ade 100644
--- a/loleaflet/css/loleaflet.css
+++ b/loleaflet/css/loleaflet.css
@@ -527,3 +527,8 @@ body {
                -webkit-user-select: none;
                -o-user-select: none;
 }
+
+.drop-down-button {
+       background: #FF0000;
+       position: absolute;
+}
diff --git a/loleaflet/src/layer/FormFieldButtonLayer.js 
b/loleaflet/src/layer/FormFieldButtonLayer.js
new file mode 100644
index 000000000..bbbb0d721
--- /dev/null
+++ b/loleaflet/src/layer/FormFieldButtonLayer.js
@@ -0,0 +1,49 @@
+/* -*- js-indent-level: 8 -*- */
+/*
+ * L.FormFieldButton is used to interact with text based form fields.
+ */
+
+L.FormFieldButton = L.Layer.extend({
+
+       options: {
+               pane: 'formfieldPane'
+       },
+
+       initialize: function (data) {
+               if (data.type === 'drop-down') {
+                       var strTwips = data.textArea.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._buttonAreaTwips = [topLeftTwips, 
bottomRightTwips];
+               }
+       },
+
+       onAdd: function (map) {
+               if (this._button) {
+                       L.DomUtil.remove(this._button);
+               }
+
+               this._button = L.DomUtil.create('div', 'drop-down-button', 
this.getPane('formfieldPane'));
+               var buttonAreaLatLng = new L.LatLngBounds(
+                               
map._docLayer._twipsToLatLng(this._buttonAreaTwips[0], this._map.getZoom()),
+                               
map._docLayer._twipsToLatLng(this._buttonAreaTwips[1], this._map.getZoom()));
+
+               var buttonAreaLayer = new L.Bounds(
+                               
this._map.latLngToLayerPoint(buttonAreaLatLng.getNorthWest()),
+                               
this._map.latLngToLayerPoint(buttonAreaLatLng.getSouthEast()));
+
+               var size = buttonAreaLayer.getSize();
+               this._button.style.width  = size.x + 'px';
+               this._button.style.height = size.y + 'px';
+
+               var pos = buttonAreaLayer.min;
+               L.DomUtil.setPosition(this._button, pos);
+       },
+
+       onRemove: function () {
+               L.DomUtil.remove(this._button);
+               this._button = undefined;
+       },
+
+});
diff --git a/loleaflet/src/layer/tile/TileLayer.js 
b/loleaflet/src/layer/tile/TileLayer.js
index 4b51906fa..6deb6808f 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -726,6 +726,10 @@ L.TileLayer = L.GridLayer.extend({
                                this._map.fire('contextchange', {context: 
message[1]});
                        }
                }
+               else if (textMsg.startsWith('formfieldbutton:')) {
+                       this._onFormFieldButtonMsg(textMsg);
+                       console.error(textMsg);
+               }
        },
 
        _onTabStopListUpdate: function (textMsg) {
@@ -3353,6 +3357,17 @@ L.TileLayer = L.GridLayer.extend({
                this._previewInvalidations = [];
        },
 
+       _onFormFieldButtonMsg: function (textMsg) {
+               textMsg = textMsg.substring('formfieldbutton:'.length + 1);
+               var json = JSON.parse(textMsg);
+               if (json.action === 'show') {
+                       this._formFieldButton = new L.FormFieldButton(json);
+                       this._map.addLayer(this._formFieldButton);
+               } else {
+                       this._map.removeLayer(this._formFieldButton);
+               }
+       },
+
        _debugGetTimeArray: function() {
                return {count: 0, ms: 0, best: Number.MAX_SAFE_INTEGER, worst: 
0, date: 0};
        },
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 982cde654..18b168a1e 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -1045,6 +1045,7 @@ L.Map = L.Evented.extend({
                this.createPane('overlayPane');
                this.createPane('markerPane');
                this.createPane('popupPane');
+               this.createPane('formfieldPane');
 
                if (!this.options.markerZoomAnimation) {
                        L.DomUtil.addClass(panes.markerPane, 
'leaflet-zoom-hide');
_______________________________________________
Libreoffice-commits mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to