diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-04-29 13:13:23 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-05-01 15:55:55 +0200 |
commit | f82356d9a1ce1457593a5f42728e2962561328cf (patch) | |
tree | ddac3224cc714d92cf80b5b285277c6a0a0e5e08 /vcl | |
parent | d822953cbc1d8814ac9f9eac2107177d37103542 (diff) |
weld ScPivotLayoutDialog
Change-Id: I821ee682bf5b65774a609227811365b94ae2063e
Reviewed-on: https://gerrit.libreoffice.org/71547
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/treeglue.hxx | 40 | ||||
-rw-r--r-- | vcl/inc/window.h | 1 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 60 | ||||
-rw-r--r-- | vcl/source/window/dlgctrl.cxx | 11 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 159 |
5 files changed, 268 insertions, 3 deletions
diff --git a/vcl/inc/treeglue.hxx b/vcl/inc/treeglue.hxx index a314c7099e2a..15b95c01546a 100644 --- a/vcl/inc/treeglue.hxx +++ b/vcl/inc/treeglue.hxx @@ -7,6 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <vcl/svimpbox.hxx> #include <vcl/svtabbx.hxx> //the default NotifyStartDrag is weird to me, and defaults to enabling all @@ -31,6 +32,8 @@ public: class LclTabListBox : public SvTabListBox { Link<SvTreeListBox*, void> m_aModelChangedHdl; + Link<SvTreeListBox*, void> m_aStartDragHdl; + Link<SvTreeListBox*, void> m_aEndDragHdl; public: LclTabListBox(vcl::Window* pParent, WinBits nWinStyle) @@ -39,12 +42,26 @@ public: } void SetModelChangedHdl(const Link<SvTreeListBox*, void>& rLink) { m_aModelChangedHdl = rLink; } + void SetStartDragHdl(const Link<SvTreeListBox*, void>& rLink) { m_aStartDragHdl = rLink; } + void SetEndDragHdl(const Link<SvTreeListBox*, void>& rLink) { m_aEndDragHdl = rLink; } virtual DragDropMode NotifyStartDrag(TransferDataContainer&, SvTreeListEntry*) override { return GetDragDropMode(); } + virtual void StartDrag(sal_Int8 nAction, const Point& rPosPixel) override + { + m_aStartDragHdl.Call(this); + SvTabListBox::StartDrag(nAction, rPosPixel); + } + + virtual void DragFinished(sal_Int8 nDropAction) override + { + m_aEndDragHdl.Call(this); + SvTabListBox::DragFinished(nDropAction); + } + virtual void ModelHasCleared() override { SvTabListBox::ModelHasCleared(); @@ -74,6 +91,29 @@ public: SvTabListBox::ModelHasRemoved(pEntry); m_aModelChangedHdl.Call(this); } + + virtual SvTreeListEntry* GetDropTarget(const Point& rPos) override + { + pTargetEntry = pImpl->GetEntry(rPos); + + // scroll + if (rPos.Y() < 12) + { + ImplShowTargetEmphasis(pTargetEntry, false); + ScrollOutputArea(+1); + } + else + { + Size aSize(pImpl->GetOutputSize()); + if (rPos.Y() > aSize.Height() - 12) + { + ImplShowTargetEmphasis(pTargetEntry, false); + ScrollOutputArea(-1); + } + } + + return pTargetEntry; + } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/inc/window.h b/vcl/inc/window.h index 74882ef77418..8e0e53b88202 100644 --- a/vcl/inc/window.h +++ b/vcl/inc/window.h @@ -244,6 +244,7 @@ public: int mnChildEventListenersIteratingCount; std::set<Link<VclWindowEvent&,void>> maChildEventListenersDeleted; Link<vcl::Window&, bool> maHelpRequestHdl; + Link<vcl::Window&, bool> maMnemonicActivateHdl; // The canvas interface for this VCL window. Is persistent after the first GetCanvas() call css::uno::WeakReference< css::rendering::XCanvas > mxCanvas; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 6babd546a238..72011c1667cf 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -245,6 +245,7 @@ protected: private: DECL_LINK(EventListener, VclWindowEvent&, void); DECL_LINK(KeyEventListener, VclWindowEvent&, bool); + DECL_LINK(MnemonicActivateHdl, vcl::Window&, bool); const bool m_bTakeOwnership; bool m_bEventListener; @@ -508,6 +509,12 @@ public: weld::Widget::connect_focus_in(rLink); } + virtual void connect_mnemonic_activate(const Link<Widget&, bool>& rLink) override + { + m_xWidget->SetMnemonicActivateHdl(LINK(this, SalInstanceWidget, MnemonicActivateHdl)); + weld::Widget::connect_mnemonic_activate(rLink); + } + virtual void connect_focus_out(const Link<Widget&, void>& rLink) override { ensure_event_listener(); @@ -599,6 +606,8 @@ public: virtual ~SalInstanceWidget() override { + if (m_aMnemonicActivateHdl.IsSet()) + m_xWidget->SetMnemonicActivateHdl(Link<vcl::Window&,bool>()); if (m_bKeyEventListener) Application::RemoveKeyListener(LINK(this, SalInstanceWidget, KeyEventListener)); if (m_bEventListener) @@ -704,6 +713,11 @@ IMPL_LINK(SalInstanceWidget, KeyEventListener, VclWindowEvent&, rEvent, bool) return HandleKeyEventListener(rEvent); } +IMPL_LINK_NOARG(SalInstanceWidget, MnemonicActivateHdl, vcl::Window&, bool) +{ + return m_aMnemonicActivateHdl.Call(*this); +} + namespace { Image createImage(const OUString& rImage) @@ -2431,6 +2445,10 @@ namespace } } +class SalInstanceTreeView; + +static SalInstanceTreeView* g_DragSource; + class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView { private: @@ -2450,6 +2468,8 @@ private: DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void); DECL_LINK(ToggleHdl, SvLBoxButtonData*, void); DECL_LINK(ModelChangedHdl, SvTreeListBox*, void); + DECL_LINK(StartDragHdl, SvTreeListBox*, void); + DECL_STATIC_LINK(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void); DECL_LINK(VisibleRangeChangedHdl, SvTreeListBox*, void); DECL_LINK(CompareHdl, const SvSortData&, sal_Int32); DECL_LINK(PopupMenuHdl, const CommandEvent&, bool); @@ -2486,6 +2506,8 @@ public: else { static_cast<LclTabListBox&>(*m_xTreeView).SetModelChangedHdl(LINK(this, SalInstanceTreeView, ModelChangedHdl)); + static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(LINK(this, SalInstanceTreeView, StartDragHdl)); + static_cast<LclTabListBox&>(*m_xTreeView).SetEndDragHdl(LINK(this, SalInstanceTreeView, FinishDragHdl)); } m_aCheckButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl)); m_aRadioButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl)); @@ -2706,6 +2728,14 @@ public: enable_notify_events(); } + virtual int get_cursor_index() const override + { + SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry(); + if (!pEntry) + return -1; + return SvTreeList::GetRelPos(pEntry); + } + virtual void set_cursor(int pos) override { if (pos == -1) @@ -3425,6 +3455,24 @@ public: return *m_xTreeView; } + virtual bool get_dest_row_at_pos(const Point &rPos, weld::TreeIter* pResult) override + { + SvTreeListEntry* pTarget = m_xTreeView->GetDropTarget(rPos); + + if (pTarget && pResult) + { + SalInstanceTreeIter& rSalIter = static_cast<SalInstanceTreeIter&>(*pResult); + rSalIter.iter = pTarget; + } + + return pTarget != nullptr; + } + + virtual TreeView* get_drag_source() const override + { + return g_DragSource; + } + virtual ~SalInstanceTreeView() override { LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); @@ -3438,6 +3486,8 @@ public: } else { + static_cast<LclTabListBox&>(*m_xTreeView).SetEndDragHdl(Link<SvTreeListBox*, void>()); + static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, void>()); static_cast<LclTabListBox&>(*m_xTreeView).SetModelChangedHdl(Link<SvTreeListBox*, void>()); } m_xTreeView->SetPopupMenuHdl(Link<const CommandEvent&, bool>()); @@ -3506,6 +3556,16 @@ IMPL_LINK_NOARG(SalInstanceTreeView, ModelChangedHdl, SvTreeListBox*, void) signal_model_changed(); } +IMPL_LINK_NOARG(SalInstanceTreeView, StartDragHdl, SvTreeListBox*, void) +{ + g_DragSource = this; +} + +IMPL_STATIC_LINK_NOARG(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void) +{ + g_DragSource = nullptr; +} + IMPL_LINK(SalInstanceTreeView, ToggleHdl, SvLBoxButtonData*, pData, void) { SvTreeListEntry* pEntry = pData->GetActEntry(); diff --git a/vcl/source/window/dlgctrl.cxx b/vcl/source/window/dlgctrl.cxx index d6e73910805d..4394513ef4eb 100644 --- a/vcl/source/window/dlgctrl.cxx +++ b/vcl/source/window/dlgctrl.cxx @@ -506,10 +506,21 @@ vcl::Window* ImplFindAccelWindow( vcl::Window* pParent, sal_uInt16& rIndex, sal_ namespace vcl { +void Window::SetMnemonicActivateHdl(const Link<vcl::Window&, bool>& rLink) +{ + if (mpWindowImpl) // may be called after dispose + { + mpWindowImpl->maMnemonicActivateHdl = rLink; + } +} + void Window::ImplControlFocus( GetFocusFlags nFlags ) { if ( nFlags & GetFocusFlags::Mnemonic ) { + if (mpWindowImpl->maMnemonicActivateHdl.Call(*this)) + return; + if ( GetType() == WindowType::RADIOBUTTON ) { if ( !static_cast<RadioButton*>(this)->IsChecked() ) diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 1893335fa645..585061667c0a 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -1269,6 +1269,18 @@ protected: m_aFocusInHdl.Call(*this); } + static gboolean signalMnemonicActivate(GtkWidget*, gboolean, gpointer widget) + { + GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget); + SolarMutexGuard aGuard; + return pThis->signal_mnemonic_activate(); + } + + bool signal_mnemonic_activate() + { + return m_aMnemonicActivateHdl.Call(*this); + } + static gboolean signalFocusOut(GtkWidget*, GdkEvent*, gpointer widget) { GtkInstanceWidget* pThis = static_cast<GtkInstanceWidget*>(widget); @@ -1304,6 +1316,7 @@ private: bool m_bFrozen; sal_uInt16 m_nLastMouseButton; gulong m_nFocusInSignalId; + gulong m_nMnemonicActivateSignalId; gulong m_nFocusOutSignalId; gulong m_nKeyPressSignalId; gulong m_nKeyReleaseSignalId; @@ -1484,6 +1497,7 @@ public: , m_bFrozen(false) , m_nLastMouseButton(0) , m_nFocusInSignalId(0) + , m_nMnemonicActivateSignalId(0) , m_nFocusOutSignalId(0) , m_nKeyPressSignalId(0) , m_nKeyReleaseSignalId(0) @@ -1865,6 +1879,12 @@ public: weld::Widget::connect_focus_in(rLink); } + virtual void connect_mnemonic_activate(const Link<Widget&, bool>& rLink) override + { + m_nMnemonicActivateSignalId = g_signal_connect(m_pWidget, "mnemonic-activate", G_CALLBACK(signalMnemonicActivate), this); + weld::Widget::connect_mnemonic_activate(rLink); + } + virtual void connect_focus_out(const Link<Widget&, void>& rLink) override { m_nFocusOutSignalId = g_signal_connect(m_pWidget, "focus-out-event", G_CALLBACK(signalFocusOut), this); @@ -1971,6 +1991,8 @@ public: g_signal_handler_disconnect(m_pWidget, m_nButtonReleaseSignalId); if (m_nFocusInSignalId) g_signal_handler_disconnect(m_pWidget, m_nFocusInSignalId); + if (m_nMnemonicActivateSignalId) + g_signal_handler_disconnect(m_pWidget, m_nMnemonicActivateSignalId); if (m_nFocusOutSignalId) g_signal_handler_disconnect(m_pWidget, m_nFocusOutSignalId); if (m_nSizeAllocateSignalId) @@ -1983,6 +2005,8 @@ public: { if (m_nFocusInSignalId) g_signal_handler_block(m_pWidget, m_nFocusInSignalId); + if (m_nMnemonicActivateSignalId) + g_signal_handler_block(m_pWidget, m_nMnemonicActivateSignalId); if (m_nFocusOutSignalId) g_signal_handler_block(m_pWidget, m_nFocusOutSignalId); if (m_nSizeAllocateSignalId) @@ -1995,6 +2019,8 @@ public: g_signal_handler_unblock(m_pWidget, m_nSizeAllocateSignalId); if (m_nFocusOutSignalId) g_signal_handler_unblock(m_pWidget, m_nFocusOutSignalId); + if (m_nMnemonicActivateSignalId) + g_signal_handler_unblock(m_pWidget, m_nMnemonicActivateSignalId); if (m_nFocusInSignalId) g_signal_handler_unblock(m_pWidget, m_nFocusInSignalId); } @@ -5854,6 +5880,10 @@ struct GtkInstanceTreeIter : public weld::TreeIter GtkTreeIter iter; }; +class GtkInstanceTreeView; + +static GtkInstanceTreeView* g_DragSource; + class GtkInstanceTreeView : public GtkInstanceContainer, public virtual weld::TreeView { private: @@ -5882,7 +5912,9 @@ private: gulong m_nVAdjustmentChangedSignalId; gulong m_nRowDeletedSignalId; gulong m_nRowInsertedSignalId; - gulong m_nPopupMenu; + gulong m_nPopupMenuSignalId; + gulong m_nDragBeginSignalId; + gulong m_nDragEndSignalId; DECL_LINK(async_signal_changed, void*, void); @@ -6168,6 +6200,17 @@ private: return default_sort_func(pModel, a, b, m_xSorter.get()); } + static void signalDragBegin(GtkWidget*, GdkDragContext*, gpointer widget) + { + GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget); + g_DragSource = pThis; + } + + static void signalDragEnd(GtkWidget*, GdkDragContext*, gpointer) + { + g_DragSource = nullptr; + } + public: GtkInstanceTreeView(GtkTreeView* pTreeView, GtkInstanceBuilder* pBuilder, bool bTakeOwnership) : GtkInstanceContainer(GTK_CONTAINER(pTreeView), pBuilder, bTakeOwnership) @@ -6181,7 +6224,9 @@ public: , m_nRowActivatedSignalId(g_signal_connect(pTreeView, "row-activated", G_CALLBACK(signalRowActivated), this)) , m_nTestExpandRowSignalId(g_signal_connect(pTreeView, "test-expand-row", G_CALLBACK(signalTestExpandRow), this)) , m_nVAdjustmentChangedSignalId(0) - , m_nPopupMenu(g_signal_connect(pTreeView, "popup-menu", G_CALLBACK(signalPopupMenu), this)) + , m_nPopupMenuSignalId(g_signal_connect(pTreeView, "popup-menu", G_CALLBACK(signalPopupMenu), this)) + , m_nDragBeginSignalId(g_signal_connect(pTreeView, "drag-begin", G_CALLBACK(signalDragBegin), this)) + , m_nDragEndSignalId(g_signal_connect(pTreeView, "drag-end", G_CALLBACK(signalDragEnd), this)) { m_pColumns = gtk_tree_view_get_columns(m_pTreeView); int nIndex(0); @@ -6962,6 +7007,23 @@ public: return path != nullptr; } + virtual int get_cursor_index() const override + { + int nRet = -1; + + GtkTreePath* path; + gtk_tree_view_get_cursor(m_pTreeView, &path, nullptr); + if (path) + { + gint depth; + gint* indices = gtk_tree_path_get_indices_with_depth(path, &depth); + nRet = indices[depth-1]; + gtk_tree_path_free(path); + } + + return nRet; + } + virtual void set_cursor(const weld::TreeIter& rIter) override { const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); @@ -7309,9 +7371,100 @@ public: weld::TreeView::connect_popup_menu(rLink); } + virtual bool get_dest_row_at_pos(const Point &rPos, weld::TreeIter* pResult) override + { + // to keep it simple we'll default to always drop before the current row + // except for the special edge cases + GtkTreeViewDropPosition pos = GTK_TREE_VIEW_DROP_BEFORE; + + // unhighlight current highlighted row + gtk_tree_view_set_drag_dest_row(m_pTreeView, nullptr, pos); + + GtkTreePath *path = nullptr; + GtkTreeViewDropPosition gtkpos = GTK_TREE_VIEW_DROP_BEFORE; + bool ret = gtk_tree_view_get_dest_row_at_pos(m_pTreeView, rPos.X(), rPos.Y(), + &path, >kpos); + + // find the last entry in the model for comparison + GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); + int nChildren = gtk_tree_model_iter_n_children(pModel, nullptr); + GtkTreePath *lastpath; + if (nChildren) + lastpath = gtk_tree_path_new_from_indices(nChildren - 1, -1); + else + lastpath = gtk_tree_path_new_from_indices(0, -1); + + if (!ret) + { + // empty space, draw an indicator at the last entry + assert(!path); + path = gtk_tree_path_copy(lastpath); + pos = GTK_TREE_VIEW_DROP_AFTER; + } + else if (gtk_tree_path_compare(path, lastpath) == 0) + { + // if we're on the last entry, see if gtk thinks + // the drop should be before or after it, and if + // its after, treat it like a drop into empty + // space, i.e. append it + if (gtkpos == GTK_TREE_VIEW_DROP_AFTER || + gtkpos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER) + { + ret = false; + pos = gtkpos; + } + } + + if (ret && pResult) + { + GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(*pResult); + gtk_tree_model_get_iter(pModel, &rGtkIter.iter, path); + } + + // highlight the row + gtk_tree_view_set_drag_dest_row(m_pTreeView, path, pos); + + assert(path); + gtk_tree_path_free(path); + gtk_tree_path_free(lastpath); + + // auto scroll if we're close to the edges + GtkAdjustment* pVAdjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(m_pTreeView)); + double fStep = gtk_adjustment_get_step_increment(pVAdjustment); + if (rPos.Y() < fStep) + { + double fValue = gtk_adjustment_get_value(pVAdjustment) - fStep; + if (fValue < 0) + fValue = 0.0; + gtk_adjustment_set_value(pVAdjustment, fValue); + } + else + { + GdkRectangle aRect; + gtk_tree_view_get_visible_rect(m_pTreeView, &aRect); + if (rPos.Y() > aRect.height - fStep) + { + double fValue = gtk_adjustment_get_value(pVAdjustment) + fStep; + double fMax = gtk_adjustment_get_upper(pVAdjustment); + if (fValue > fMax) + fValue = fMax; + gtk_adjustment_set_value(pVAdjustment, fValue); + } + } + + return ret; + } + + virtual TreeView* get_drag_source() const override + { + return g_DragSource; + } + virtual ~GtkInstanceTreeView() override { - g_signal_handler_disconnect(m_pTreeView, m_nPopupMenu); + g_signal_handler_disconnect(m_pTreeView, m_nDragEndSignalId); + g_signal_handler_disconnect(m_pTreeView, m_nDragBeginSignalId); + g_signal_handler_disconnect(m_pTreeView, m_nPopupMenuSignalId); GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); g_signal_handler_disconnect(pModel, m_nRowDeletedSignalId); g_signal_handler_disconnect(pModel, m_nRowInsertedSignalId); |