[Libreoffice-commits] core.git: include/LibreOfficeKit libreofficekit/source sw/qa sw/source

Miklos Vajna vmiklos at collabora.co.uk
Fri Jul 22 15:13:36 UTC 2016


 include/LibreOfficeKit/LibreOfficeKitEnums.h   |   16 ++++++
 libreofficekit/source/gtk/lokdocview.cxx       |   59 +++++++++++++++++++++++++
 sw/qa/extras/tiledrendering/tiledrendering.cxx |   49 ++++++++++++++++++++
 sw/source/core/frmedt/feshview.cxx             |    7 ++
 sw/source/uibase/uiview/viewdraw.cxx           |    9 +++
 5 files changed, 139 insertions(+), 1 deletion(-)

New commits:
commit 897189cfc6b3f6f3a9a0148b060ea25e5f8d9eaa
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Jul 22 16:39:47 2016 +0200

    sw: add new LOK_CALLBACK_VIEW_LOCK callback
    
    When we're after SdrBeginTextEdit(), but before SdrEndTextEdit(), and
    have multiple views, then only the active view paints the edited text,
    the other views look like the shape has no text at all.
    
    Add a new callback that exposes the position and size of the rectangle
    where the shape text will be painted after text edit ended, so clients
    can draw some kind of locking indicator there. This way the rendered
    result can differ in the "shape has no text" and the "shape text is
    edited in an other view" cases.
    
    Change-Id: I6096479a8a05c2547d15222e6d997b848af02945
    Reviewed-on: https://gerrit.libreoffice.org/27441
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 63abda8..651e9bc 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -390,6 +390,22 @@ typedef enum
      */
     LOK_CALLBACK_VIEW_CURSOR_VISIBLE,
 
+    /**
+     * The size and/or the position of a lock rectangle in one of the other
+     * views has changed.
+     *
+     * The payload format:
+     *
+     * {
+     *     "viewId": "..."
+     *     "rectangle": "..."
+     * }
+     *
+     * - viewId is a value returned earlier by lok::Document::createView()
+     * - rectangle uses the format of LOK_CALLBACK_INVALIDATE_TILES.
+     */
+    LOK_CALLBACK_VIEW_LOCK,
+
 }
 LibreOfficeKitCallbackType;
 
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index d5a1dd3..f604b58 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -190,6 +190,10 @@ struct LOKDocViewPrivateImpl
     /// Event source ID for handleTimeout() of this widget.
     guint m_nTimeoutId;
 
+    /// Rectangles of view locks. The current view can only see
+    /// them, can't modify them. Key is the view id.
+    std::map<int, ViewRectangle> m_aViewLockRectangles;
+
     LOKDocViewPrivateImpl()
         : m_aLOPath(nullptr),
         m_pUserProfileURL(nullptr),
@@ -415,6 +419,8 @@ callbackTypeToString (int nType)
         return "LOK_CALLBACK_UNO_COMMAND_RESULT";
     case LOK_CALLBACK_ERROR:
         return "LOK_CALLBACK_ERROR";
+    case LOK_CALLBACK_VIEW_LOCK:
+        return "LOK_CALLBACK_VIEW_LOCK";
     }
     g_assert(false);
     return nullptr;
@@ -1314,6 +1320,25 @@ callback (gpointer pData)
         gtk_widget_queue_draw(GTK_WIDGET(pDocView));
         break;
     }
+    case LOK_CALLBACK_VIEW_LOCK:
+    {
+        std::stringstream aStream(pCallback->m_aPayload);
+        boost::property_tree::ptree aTree;
+        boost::property_tree::read_json(aStream, aTree);
+        int nViewId = aTree.get<int>("viewId");
+        int nPart = aTree.get<int>("part");
+        const std::string& rRectangle = aTree.get<std::string>("rectangle");
+        if (rRectangle != "EMPTY")
+            priv->m_aViewLockRectangles[nViewId] = ViewRectangle(nPart, payloadToRectangle(pDocView, rRectangle.c_str()));
+        else
+        {
+            auto it = priv->m_aViewLockRectangles.find(nViewId);
+            if (it != priv->m_aViewLockRectangles.end())
+                priv->m_aViewLockRectangles.erase(it);
+        }
+        gtk_widget_queue_draw(GTK_WIDGET(pDocView));
+        break;
+    }
     default:
         g_assert(false);
         break;
@@ -1746,6 +1771,40 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo)
         cairo_stroke(pCairo);
     }
 
+    // View locks: they are colored.
+    for (auto& rPair : priv->m_aViewLockRectangles)
+    {
+        const ViewRectangle& rRectangle = rPair.second;
+        if (rRectangle.m_nPart != priv->m_nPartId)
+            continue;
+
+        // Draw a rectangle.
+        const GdkRGBA& rDark = getDarkColor(rPair.first);
+        cairo_set_source_rgb(pCairo, rDark.red, rDark.green, rDark.blue);
+        cairo_rectangle(pCairo,
+                        twipToPixel(rRectangle.m_aRectangle.x, priv->m_fZoom),
+                        twipToPixel(rRectangle.m_aRectangle.y, priv->m_fZoom),
+                        twipToPixel(rRectangle.m_aRectangle.width, priv->m_fZoom),
+                        twipToPixel(rRectangle.m_aRectangle.height, priv->m_fZoom));
+        cairo_set_line_width(pCairo, 2.0);
+        cairo_stroke(pCairo);
+
+        // Cross it.
+        cairo_move_to(pCairo,
+                      twipToPixel(rRectangle.m_aRectangle.x, priv->m_fZoom),
+                      twipToPixel(rRectangle.m_aRectangle.y, priv->m_fZoom));
+        cairo_line_to(pCairo,
+                      twipToPixel(rRectangle.m_aRectangle.x + rRectangle.m_aRectangle.width, priv->m_fZoom),
+                      twipToPixel(rRectangle.m_aRectangle.y + rRectangle.m_aRectangle.height, priv->m_fZoom));
+        cairo_move_to(pCairo,
+                      twipToPixel(rRectangle.m_aRectangle.x, priv->m_fZoom),
+                      twipToPixel(rRectangle.m_aRectangle.y + rRectangle.m_aRectangle.height, priv->m_fZoom));
+        cairo_line_to(pCairo,
+                      twipToPixel(rRectangle.m_aRectangle.x + rRectangle.m_aRectangle.width, priv->m_fZoom),
+                      twipToPixel(rRectangle.m_aRectangle.y, priv->m_fZoom));
+        cairo_stroke(pCairo);
+    }
+
     return FALSE;
 }
 
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index b4ccff4..c20fe73 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -25,6 +25,7 @@
 #include <drawdoc.hxx>
 #include <ndtxt.hxx>
 #include <wrtsh.hxx>
+#include <view.hxx>
 #include <sfx2/viewsh.hxx>
 #include <sfx2/lokhelper.hxx>
 
@@ -55,6 +56,7 @@ public:
     void testMissingInvalidation();
     void testViewCursorVisibility();
     void testViewCursorCleanup();
+    void testViewLock();
 
     CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
     CPPUNIT_TEST(testRegisterCallback);
@@ -77,6 +79,7 @@ public:
     CPPUNIT_TEST(testMissingInvalidation);
     CPPUNIT_TEST(testViewCursorVisibility);
     CPPUNIT_TEST(testViewCursorCleanup);
+    CPPUNIT_TEST(testViewLock);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -559,6 +562,7 @@ public:
     bool m_bTilesInvalidated;
     bool m_bViewCursorVisible;
     bool m_bGraphicViewSelection;
+    bool m_bViewLock;
 
     ViewCallback()
         : m_bOwnCursorInvalidated(false),
@@ -567,7 +571,8 @@ public:
           m_bViewSelectionSet(false),
           m_bTilesInvalidated(false),
           m_bViewCursorVisible(false),
-          m_bGraphicViewSelection(false)
+          m_bGraphicViewSelection(false),
+          m_bViewLock(false)
     {
     }
 
@@ -618,6 +623,14 @@ public:
             m_bGraphicViewSelection = aTree.get_child("selection").get_value<std::string>() != "EMPTY";
         }
         break;
+        case LOK_CALLBACK_VIEW_LOCK:
+        {
+            std::stringstream aStream(pPayload);
+            boost::property_tree::ptree aTree;
+            boost::property_tree::read_json(aStream, aTree);
+            m_bViewLock = aTree.get_child("rectangle").get_value<std::string>() != "EMPTY";
+        }
+        break;
         }
     }
 };
@@ -772,6 +785,40 @@ void SwTiledRenderingTest::testViewCursorCleanup()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void SwTiledRenderingTest::testViewLock()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    // Load a document that has a shape and create two views.
+    SwXTextDocument* pXTextDocument = createDoc("shape.fodt");
+    ViewCallback aView1;
+    SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1);
+    SfxLokHelper::createView();
+    pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+    ViewCallback aView2;
+    SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2);
+
+    // Begin text edit in the second view and assert that the first gets a lock
+    // notification.
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+    SdrObject* pObject = pPage->GetObj(0);
+    SdrView* pView = pWrtShell->GetDrawView();
+    aView1.m_bViewLock = false;
+    pWrtShell->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell->GetWin());
+    CPPUNIT_ASSERT(aView1.m_bViewLock);
+
+    // End text edit in the second view, and assert that the lock is removed in
+    // the first view.
+    pWrtShell->EndTextEdit();
+    CPPUNIT_ASSERT(!aView1.m_bViewLock);
+
+    mxComponent->dispose();
+    mxComponent.clear();
+
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx
index 894fa01..5e4b92c 100644
--- a/sw/source/core/frmedt/feshview.cxx
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -82,6 +82,9 @@
 #include <sortedobjs.hxx>
 #include <HandleAnchorNodeChg.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
+#include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <calbck.hxx>
 
 #include <com/sun/star/embed/EmbedMisc.hpp>
@@ -1054,6 +1057,10 @@ void SwFEShell::EndTextEdit()
     }
     else
         pView->SdrEndTextEdit();
+
+    if (comphelper::LibreOfficeKit::isActive())
+        SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_LOCK, "rectangle", "EMPTY");
+
     EndAllAction();
 }
 
diff --git a/sw/source/uibase/uiview/viewdraw.cxx b/sw/source/uibase/uiview/viewdraw.cxx
index d5dcb93..011afcb 100644
--- a/sw/source/uibase/uiview/viewdraw.cxx
+++ b/sw/source/uibase/uiview/viewdraw.cxx
@@ -68,6 +68,9 @@
 #include <svx/svdpagv.hxx>
 #include <svx/extrusionbar.hxx>
 #include <vcl/svapp.hxx>
+#include <comphelper/lok.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
 
 using namespace ::com::sun::star;
 
@@ -573,6 +576,12 @@ bool SwView::BeginTextEdit(SdrObject* pObj, SdrPageView* pPV, vcl::Window* pWin,
         if (pView)
         {
             pView->SetSelection(aNewSelection);
+
+            if (comphelper::LibreOfficeKit::isActive())
+            {
+                OString sRect = pView->GetOutputArea().toString();
+                SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_LOCK, "rectangle", sRect);
+            }
         }
     }
 


More information about the Libreoffice-commits mailing list