summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-04-29 13:13:23 +0100
committerCaolán McNamara <caolanm@redhat.com>2019-05-01 15:55:55 +0200
commitf82356d9a1ce1457593a5f42728e2962561328cf (patch)
treeddac3224cc714d92cf80b5b285277c6a0a0e5e08 /vcl
parentd822953cbc1d8814ac9f9eac2107177d37103542 (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.hxx40
-rw-r--r--vcl/inc/window.h1
-rw-r--r--vcl/source/app/salvtables.cxx60
-rw-r--r--vcl/source/window/dlgctrl.cxx11
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx159
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, &gtkpos);
+
+ // 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);