diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-04-09 11:23:48 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-04-10 21:23:21 +0200 |
commit | 3d648f76ac90fe8e28691313d0d4e78a8278e511 (patch) | |
tree | f3e0de959d8ddff61a9ff4af79e481bec25aa29d /vcl | |
parent | 47500ab25b9c5bbeeb6fde3866bdd924948fd88a (diff) |
weld ScCorrelationDialog
this is first of the calc dialogs with a range selector, so some temp
scaffolding is required during interim case of both welded/unwelded
in existence
Change-Id: I5480179092da7b56864cef066af781b35f735ebc
Reviewed-on: https://gerrit.libreoffice.org/70474
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/source/app/salvtables.cxx | 94 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 109 |
2 files changed, 203 insertions, 0 deletions
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 0926dac611fb..74716b18aa35 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -1016,15 +1016,48 @@ IMPL_LINK_NOARG(SalInstanceWindow, HelpHdl, vcl::Window&, bool) return false; } +typedef std::set<VclPtr<vcl::Window> > winset; + +namespace +{ + void hideUnless(const vcl::Window *pTop, const winset& rVisibleWidgets, + std::vector<VclPtr<vcl::Window> > &rWasVisibleWidgets) + { + for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild; + pChild = pChild->GetWindow(GetWindowType::Next)) + { + if (!pChild->IsVisible()) + continue; + if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end()) + { + rWasVisibleWidgets.emplace_back(pChild); + pChild->Hide(); + } + else if (isContainerWindow(pChild)) + { + hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets); + } + } + } +} + class SalInstanceDialog : public SalInstanceWindow, public virtual weld::Dialog { private: VclPtr<::Dialog> m_xDialog; + // for calc ref dialog that shrink to range selection widgets and resize back + VclPtr<vcl::Window> m_xRefEdit; + std::vector<VclPtr<vcl::Window> > m_aHiddenWidgets; // vector of hidden Controls + long m_nOldEditWidthReq; // Original width request of the input field + sal_Int32 m_nOldBorderWidth; // border width for expanded dialog + public: SalInstanceDialog(::Dialog* pDialog, SalInstanceBuilder* pBuilder, bool bTakeOwnership) : SalInstanceWindow(pDialog, pBuilder, bTakeOwnership) , m_xDialog(pDialog) + , m_nOldEditWidthReq(0) + , m_nOldBorderWidth(0) { } @@ -1044,6 +1077,67 @@ public: return m_xDialog->StartExecuteAsync(aCtx); } + virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) override + { + SalInstanceWidget* pVclEdit = dynamic_cast<SalInstanceWidget*>(pEdit); + SalInstanceWidget* pVclButton = dynamic_cast<SalInstanceWidget*>(pButton); + + vcl::Window* pRefEdit = pVclEdit->getWidget(); + vcl::Window* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr; + + auto nOldEditWidth = pRefEdit->GetSizePixel().Width(); + m_nOldEditWidthReq = pRefEdit->get_width_request(); + + //We want just pRefBtn and pRefEdit to be shown + //mark widgets we want to be visible, starting with pRefEdit + //and all its direct parents. + winset aVisibleWidgets; + vcl::Window *pContentArea = m_xDialog->get_content_area(); + for (vcl::Window *pCandidate = pRefEdit; + pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible()); + pCandidate = pCandidate->GetWindow(GetWindowType::RealParent)) + { + aVisibleWidgets.insert(pCandidate); + } + //same again with pRefBtn, except stop if there's a + //shared parent in the existing widgets + for (vcl::Window *pCandidate = pRefBtn; + pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible()); + pCandidate = pCandidate->GetWindow(GetWindowType::RealParent)) + { + if (aVisibleWidgets.insert(pCandidate).second) + break; + } + + //hide everything except the aVisibleWidgets + hideUnless(pContentArea, aVisibleWidgets, m_aHiddenWidgets); + + pRefEdit->set_width_request(nOldEditWidth); + m_nOldBorderWidth = m_xDialog->get_border_width(); + m_xDialog->set_border_width(0); + if (vcl::Window *pActionArea = m_xDialog->get_action_area()) + pActionArea->Hide(); + m_xDialog->setOptimalLayoutSize(); + m_xRefEdit = pRefEdit; + } + + virtual void undo_collapse() override + { + // All others: Show(); + for (VclPtr<vcl::Window> const & pWindow : m_aHiddenWidgets) + { + pWindow->Show(); + } + m_aHiddenWidgets.clear(); + + m_xRefEdit->set_width_request(m_nOldEditWidthReq); + m_xRefEdit.clear(); + m_xDialog->set_border_width(m_nOldBorderWidth); + if (vcl::Window *pActionArea = m_xDialog->get_action_area()) + pActionArea->Show(); + m_xDialog->setOptimalLayoutSize(); + } + virtual void SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>& rLink) override { m_xDialog->SetInstallLOKNotifierHdl(rLink); diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 7f294bae8c21..f7d138f5f538 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -2761,6 +2761,34 @@ struct DialogRunner } }; +typedef std::set<GtkWidget*> winset; + +namespace +{ + void hideUnless(GtkContainer *pTop, const winset& rVisibleWidgets, + std::vector<GtkWidget*> &rWasVisibleWidgets) + { + GList* pChildren = gtk_container_get_children(pTop); + for (GList* pEntry = g_list_first(pChildren); pEntry; pEntry = g_list_next(pEntry)) + { + GtkWidget* pChild = static_cast<GtkWidget*>(pEntry->data); + if (!gtk_widget_get_visible(pChild)) + continue; + if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end()) + { + g_object_ref(pChild); + rWasVisibleWidgets.emplace_back(pChild); + gtk_widget_hide(pChild); + } + else if (GTK_IS_CONTAINER(pChild)) + { + hideUnless(GTK_CONTAINER(pChild), rVisibleWidgets, rWasVisibleWidgets); + } + } + g_list_free(pChildren); + } +} + class GtkInstanceDialog : public GtkInstanceWindow, public virtual weld::Dialog { private: @@ -2773,6 +2801,13 @@ private: gulong m_nCloseSignalId; gulong m_nResponseSignalId; + // for calc ref dialog that shrink to range selection widgets and resize back + GtkWidget* m_pRefEdit; + std::vector<GtkWidget*> m_aHiddenWidgets; // vector of hidden Controls + int m_nOldEditWidth; // Original width of the input field + int m_nOldEditWidthReq; // Original width request of the input field + int m_nOldBorderWidth; // border width for expanded dialog + static void signalClose(GtkWidget*, gpointer widget) { GtkInstanceDialog* pThis = static_cast<GtkInstanceDialog*>(widget); @@ -2828,6 +2863,10 @@ public: , m_aDialogRun(pDialog) , m_nCloseSignalId(g_signal_connect(m_pDialog, "close", G_CALLBACK(signalClose), this)) , m_nResponseSignalId(0) + , m_pRefEdit(nullptr) + , m_nOldEditWidth(0) + , m_nOldEditWidthReq(0) + , m_nOldBorderWidth(0) { } @@ -2948,6 +2987,69 @@ public: return new GtkInstanceContainer(GTK_CONTAINER(gtk_dialog_get_content_area(m_pDialog)), m_pBuilder, false); } + virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) override + { + GtkInstanceWidget* pVclEdit = dynamic_cast<GtkInstanceWidget*>(pEdit); + GtkInstanceWidget* pVclButton = dynamic_cast<GtkInstanceWidget*>(pButton); + + GtkWidget* pRefEdit = pVclEdit->getWidget(); + GtkWidget* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr; + + m_nOldEditWidth = gtk_widget_get_allocated_width(pRefEdit); + + gtk_widget_get_size_request(pRefEdit, &m_nOldEditWidthReq, nullptr); + + //We want just pRefBtn and pRefEdit to be shown + //mark widgets we want to be visible, starting with pRefEdit + //and all its direct parents. + winset aVisibleWidgets; + GtkWidget *pContentArea = gtk_dialog_get_content_area(m_pDialog); + for (GtkWidget *pCandidate = pRefEdit; + pCandidate && pCandidate != pContentArea && gtk_widget_get_visible(pCandidate); + pCandidate = gtk_widget_get_parent(pCandidate)) + { + aVisibleWidgets.insert(pCandidate); + } + //same again with pRefBtn, except stop if there's a + //shared parent in the existing widgets + for (GtkWidget *pCandidate = pRefBtn; + pCandidate && pCandidate != pContentArea && gtk_widget_get_visible(pCandidate); + pCandidate = gtk_widget_get_parent(pCandidate)) + { + if (aVisibleWidgets.insert(pCandidate).second) + break; + } + + //hide everything except the aVisibleWidgets + hideUnless(GTK_CONTAINER(pContentArea), aVisibleWidgets, m_aHiddenWidgets); + + gtk_widget_set_size_request(pRefEdit, m_nOldEditWidth, -1); + m_nOldBorderWidth = gtk_container_get_border_width(GTK_CONTAINER(m_pDialog)); + gtk_container_set_border_width(GTK_CONTAINER(m_pDialog), 0); + if (GtkWidget* pActionArea = gtk_dialog_get_action_area(m_pDialog)) + gtk_widget_hide(pActionArea); + resize_to_request(); + m_pRefEdit = pRefEdit; + } + + virtual void undo_collapse() override + { + // All others: Show(); + for (GtkWidget* pWindow : m_aHiddenWidgets) + { + gtk_widget_show(pWindow); + g_object_unref(pWindow); + } + m_aHiddenWidgets.clear(); + + gtk_widget_set_size_request(m_pRefEdit, m_nOldEditWidthReq, -1); + m_pRefEdit = nullptr; + gtk_container_set_border_width(GTK_CONTAINER(m_pDialog), m_nOldBorderWidth); + if (GtkWidget* pActionArea = gtk_dialog_get_action_area(m_pDialog)) + gtk_widget_show(pActionArea); + resize_to_request(); + } + virtual void SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>&) override { //not implemented for the gtk variant @@ -2955,6 +3057,13 @@ public: virtual ~GtkInstanceDialog() override { + if (!m_aHiddenWidgets.empty()) + { + for (GtkWidget* pWindow : m_aHiddenWidgets) + g_object_unref(pWindow); + m_aHiddenWidgets.clear(); + } + g_signal_handler_disconnect(m_pDialog, m_nCloseSignalId); if (m_nResponseSignalId) g_signal_handler_disconnect(m_pDialog, m_nResponseSignalId); |