diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2020-11-18 10:12:38 +0100 |
---|---|---|
committer | Szymon Kłos <szymon.klos@collabora.com> | 2020-11-27 11:42:16 +0100 |
commit | 3000f3ee1ac63deff58fa5725a6f6c2f05aec9bb (patch) | |
tree | f658dc1a83b59519f555810b05899c1cf6621151 /vcl | |
parent | f3fc16f444f84a269df9bd2f2c3d2a47cf49d057 (diff) |
jsdialog: drag and drop support for TreeView
Change-Id: I67e2eb986b48591b7f758bbb5c1d72b6a322d4d8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106705
Tested-by: Jenkins
Reviewed-by: Szymon Kłos <szymon.klos@collabora.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/jsdialog/jsdialogbuilder.hxx | 55 | ||||
-rw-r--r-- | vcl/jsdialog/executor.cxx | 21 | ||||
-rw-r--r-- | vcl/jsdialog/jsdialogbuilder.cxx | 123 |
3 files changed, 199 insertions, 0 deletions
diff --git a/vcl/inc/jsdialog/jsdialogbuilder.hxx b/vcl/inc/jsdialog/jsdialogbuilder.hxx index 4b9e042960f4..ab7c038648d3 100644 --- a/vcl/inc/jsdialog/jsdialogbuilder.hxx +++ b/vcl/inc/jsdialog/jsdialogbuilder.hxx @@ -19,6 +19,11 @@ #include <vcl/toolkit/button.hxx> #include <vcl/toolkit/fmtfield.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 ComboBox; class VclMultiLineEdit; @@ -58,6 +63,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; @@ -128,6 +167,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, @@ -155,6 +197,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 JSDialog : public JSWidget<SalInstanceDialog, ::Dialog> @@ -309,6 +359,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 24e3eb1f14d3..13ffc1a33e06 100644 --- a/vcl/jsdialog/executor.cxx +++ b/vcl/jsdialog/executor.cxx @@ -206,6 +206,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 4fb351b5439f..58c8c64d1108 100644 --- a/vcl/jsdialog/jsdialogbuilder.cxx +++ b/vcl/jsdialog/jsdialogbuilder.cxx @@ -24,6 +24,7 @@ #include <boost/property_tree/json_parser.hpp> #include <vcl/toolkit/treelistentry.hxx> #include <vcl/jsdialog/executor.hxx> +#include <cppuhelper/supportsservice.hxx> JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr<vcl::Window> aNotifierWindow, VclPtr<vcl::Window> aContentWindow, std::string sTypeOfJSON) @@ -96,6 +97,102 @@ vcl::Window* extract_sal_widget(weld::Widget* pParent) } } +// Drag and drop + +namespace +{ +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) : SalInstanceBuilder(extract_sal_widget(pParent), rUIRoot, rUIFile) @@ -793,6 +890,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) |