[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - vcl/inc vcl/jsdialog

Szymon KÅ‚os (via logerrit) logerrit at kemper.freedesktop.org
Tue Dec 1 11:18:32 UTC 2020


 vcl/inc/jsdialog/jsdialogbuilder.hxx |   55 ++++++++++++++++
 vcl/jsdialog/executor.cxx            |   21 ++++++
 vcl/jsdialog/jsdialogbuilder.cxx     |  119 +++++++++++++++++++++++++++++++++++
 3 files changed, 195 insertions(+)

New commits:
commit 3dc572e07671107f6aa4a627660ab9c403d54dc9
Author:     Szymon Kłos <szymon.klos at collabora.com>
AuthorDate: Wed Nov 18 10:12:38 2020 +0100
Commit:     Szymon Kłos <szymon.klos at collabora.com>
CommitDate: Tue Dec 1 12:17:56 2020 +0100

    jsdialog:  drag and drop support for TreeView
    
    Change-Id: I67e2eb986b48591b7f758bbb5c1d72b6a322d4d8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106928
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>

diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx
index 3d7b6c62c24e..b6ee02c4ff04 100644
--- a/vcl/inc/jsdialog/jsdialogbuilder.hxx
+++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx
@@ -21,6 +21,11 @@
 #include <vcl/fmtfield.hxx>
 #include <vcl/svtabbx.hxx>
 
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <cppuhelper/compbase.hxx>
+
 class ToolBox;
 class SfxViewShell;
 class VclMultiLineEdit;
@@ -59,6 +64,40 @@ public:
     void notifyDialogState(bool bForce = false);
 };
 
+class JSDropTarget final
+    : public cppu::WeakComponentImplHelper<css::datatransfer::dnd::XDropTarget,
+                                           css::lang::XInitialization, css::lang::XServiceInfo>
+{
+    osl::Mutex m_aMutex;
+    std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> m_aListeners;
+
+public:
+    JSDropTarget();
+
+    // XInitialization
+    virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArgs) override;
+
+    // XDropTarget
+    virtual void SAL_CALL addDropTargetListener(
+        const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>&) override;
+    virtual void SAL_CALL removeDropTargetListener(
+        const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>&) override;
+    virtual sal_Bool SAL_CALL isActive() override;
+    virtual void SAL_CALL setActive(sal_Bool active) override;
+    virtual sal_Int8 SAL_CALL getDefaultActions() override;
+    virtual void SAL_CALL setDefaultActions(sal_Int8 actions) override;
+
+    OUString SAL_CALL getImplementationName() override;
+
+    sal_Bool SAL_CALL supportsService(OUString const& ServiceName) override;
+
+    css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+    void fire_drop(const css::datatransfer::dnd::DropTargetDropEvent& dtde);
+
+    void fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent& dtde);
+};
+
 class JSInstanceBuilder : public SalInstanceBuilder
 {
     sal_uInt64 m_nWindowId;
@@ -141,6 +180,9 @@ private:
 template <class BaseInstanceClass, class VclClass>
 class JSWidget : public BaseInstanceClass, public JSDialogSender
 {
+protected:
+    rtl::Reference<JSDropTarget> m_xDropTarget;
+
 public:
     JSWidget(VclPtr<vcl::Window> aNotifierWindow, VclPtr<vcl::Window> aContentWindow,
              VclClass* pObject, SalInstanceBuilder* pBuilder, bool bTakeOwnership,
@@ -168,6 +210,14 @@ public:
         BaseInstanceClass::set_sensitive(sensitive);
         notifyDialogState();
     }
+
+    virtual css::uno::Reference<css::datatransfer::dnd::XDropTarget> get_drop_target() override
+    {
+        if (!m_xDropTarget)
+            m_xDropTarget.set(new JSDropTarget);
+
+        return m_xDropTarget.get();
+    }
 };
 
 class VCL_DLLPUBLIC JSDialog : public JSWidget<SalInstanceDialog, ::Dialog>
@@ -323,6 +373,11 @@ public:
     using SalInstanceTreeView::select;
     /// pos is used differently here, it defines how many steps of iterator we need to perform to take entry
     virtual void select(int pos) override;
+
+    virtual weld::TreeView* get_drag_source() const override;
+
+    void drag_start();
+    void drag_end();
 };
 
 class JSExpander : public JSWidget<SalInstanceExpander, ::VclExpander>
diff --git a/vcl/jsdialog/executor.cxx b/vcl/jsdialog/executor.cxx
index 8e1ec3cf8f7b..b4613db68fe9 100644
--- a/vcl/jsdialog/executor.cxx
+++ b/vcl/jsdialog/executor.cxx
@@ -205,6 +205,27 @@ bool ExecuteAction(sal_uInt64 nWindowId, const OString& rWidget, StringMap& rDat
 
                     pTreeView->select(nRow);
                     LOKTrigger::trigger_row_activated(*pTreeView);
+                    return true;
+                }
+                else if (sAction == "dragstart")
+                {
+                    OString nRowString
+                        = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
+                    int nRow = std::atoi(nRowString.getStr());
+
+                    pTreeView->select(nRow);
+
+                    JSTreeView* pJSTreeView = dynamic_cast<JSTreeView*>(pTreeView);
+                    if (pJSTreeView)
+                        pJSTreeView->drag_start();
+                    return true;
+                }
+                else if (sAction == "dragend")
+                {
+                    JSTreeView* pJSTreeView = dynamic_cast<JSTreeView*>(pTreeView);
+                    if (pJSTreeView)
+                        pJSTreeView->drag_end();
+                    return true;
                 }
             }
         }
diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx
index f02d469dc701..05903cef6f49 100644
--- a/vcl/jsdialog/jsdialogbuilder.cxx
+++ b/vcl/jsdialog/jsdialogbuilder.cxx
@@ -16,6 +16,7 @@
 #include <vcl/toolbox.hxx>
 #include <vcl/vclmedit.hxx>
 #include <vcl/treelistentry.hxx>
+#include <cppuhelper/supportsservice.hxx>
 
 using namespace weld;
 
@@ -89,6 +90,98 @@ void JSDialogSender::notifyDialogState(bool bForce)
     mpIdleNotify->Start();
 }
 
+// Drag and drop
+
+class JSDropTargetDropContext
+    : public cppu::WeakImplHelper<css::datatransfer::dnd::XDropTargetDropContext>
+{
+public:
+    JSDropTargetDropContext() {}
+
+    // XDropTargetDropContext
+    virtual void SAL_CALL acceptDrop(sal_Int8 /*dragOperation*/) override {}
+
+    virtual void SAL_CALL rejectDrop() override {}
+
+    virtual void SAL_CALL dropComplete(sal_Bool /*bSuccess*/) override {}
+};
+
+static JSTreeView* g_DragSource;
+
+JSDropTarget::JSDropTarget()
+    : WeakComponentImplHelper(m_aMutex)
+{
+}
+
+void JSDropTarget::initialize(const css::uno::Sequence<css::uno::Any>& /*rArgs*/) {}
+
+void JSDropTarget::addDropTargetListener(
+    const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>& xListener)
+{
+    ::osl::Guard<::osl::Mutex> aGuard(m_aMutex);
+
+    m_aListeners.push_back(xListener);
+}
+
+void JSDropTarget::removeDropTargetListener(
+    const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>& xListener)
+{
+    ::osl::Guard<::osl::Mutex> aGuard(m_aMutex);
+
+    m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), xListener),
+                       m_aListeners.end());
+}
+
+sal_Bool JSDropTarget::isActive() { return false; }
+
+void JSDropTarget::setActive(sal_Bool /*active*/) {}
+
+sal_Int8 JSDropTarget::getDefaultActions() { return 0; }
+
+void JSDropTarget::setDefaultActions(sal_Int8 /*actions*/) {}
+
+OUString JSDropTarget::getImplementationName()
+{
+    return "com.sun.star.datatransfer.dnd.JSDropTarget";
+}
+
+sal_Bool JSDropTarget::supportsService(OUString const& ServiceName)
+{
+    return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> JSDropTarget::getSupportedServiceNames()
+{
+    css::uno::Sequence<OUString> aRet{ "com.sun.star.datatransfer.dnd.JSDropTarget" };
+    return aRet;
+}
+
+void JSDropTarget::fire_drop(const css::datatransfer::dnd::DropTargetDropEvent& dtde)
+{
+    osl::ClearableGuard<osl::Mutex> aGuard(m_aMutex);
+    std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners(
+        m_aListeners);
+    aGuard.clear();
+
+    for (auto const& listener : aListeners)
+    {
+        listener->drop(dtde);
+    }
+}
+
+void JSDropTarget::fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent& dtde)
+{
+    osl::ClearableGuard<::osl::Mutex> aGuard(m_aMutex);
+    std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> aListeners(
+        m_aListeners);
+    aGuard.clear();
+
+    for (auto const& listener : aListeners)
+    {
+        listener->dragEnter(dtde);
+    }
+}
+
 // used for dialogs
 JSInstanceBuilder::JSInstanceBuilder(weld::Widget* pParent, const OUString& rUIRoot,
                                      const OUString& rUIFile)
@@ -806,6 +899,32 @@ void JSTreeView::select(int pos)
     enable_notify_events();
 }
 
+weld::TreeView* JSTreeView::get_drag_source() const { return g_DragSource; }
+
+void JSTreeView::drag_start() { g_DragSource = this; }
+
+void JSTreeView::drag_end()
+{
+    css::datatransfer::dnd::XDropTarget* xDropTarget = m_xDropTarget.get();
+    if (xDropTarget)
+    {
+        css::datatransfer::dnd::DropTargetDropEvent aEvent;
+        aEvent.Source = xDropTarget;
+        aEvent.Context = new JSDropTargetDropContext();
+        // dummy values
+        aEvent.LocationX = 50;
+        aEvent.LocationY = 50;
+        aEvent.DropAction = css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT;
+        aEvent.SourceActions = css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT;
+
+        m_xDropTarget->fire_drop(aEvent);
+
+        notifyDialogState();
+    }
+
+    g_DragSource = nullptr;
+}
+
 JSExpander::JSExpander(VclPtr<vcl::Window> aNotifierWindow, VclPtr<vcl::Window> aContentWindow,
                        ::VclExpander* pExpander, SalInstanceBuilder* pBuilder, bool bTakeOwnership,
                        std::string sTypeOfJSON)


More information about the Libreoffice-commits mailing list