nss: upgrade to release 3.73
[LibreOffice.git] / svtools / source / control / toolbarmenu.cxx
blobb376490fa4fd919c6a2024840393a9b81236c801
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <comphelper/processfactory.hxx>
22 #include <osl/diagnose.h>
24 #include <vcl/taskpanelist.hxx>
25 #include <vcl/settings.hxx>
26 #include <vcl/commandevent.hxx>
27 #include <vcl/event.hxx>
28 #include <vcl/svapp.hxx>
30 #include <svtools/framestatuslistener.hxx>
31 #include <svtools/valueset.hxx>
32 #include <svtools/toolbarmenu.hxx>
34 using namespace ::com::sun::star::uno;
35 using namespace ::com::sun::star::lang;
36 using namespace ::com::sun::star::frame;
37 using namespace ::com::sun::star::accessibility;
39 namespace {
41 vcl::Window* GetTopMostParentSystemWindow( vcl::Window* pWindow )
43 OSL_ASSERT( pWindow );
44 if ( pWindow )
46 // ->manually search topmost system window
47 // required because their might be another system window between this and the top window
48 pWindow = pWindow->GetParent();
49 SystemWindow* pTopMostSysWin = nullptr;
50 while ( pWindow )
52 if ( pWindow->IsSystemWindow() )
53 pTopMostSysWin = static_cast<SystemWindow*>(pWindow);
54 pWindow = pWindow->GetParent();
56 pWindow = pTopMostSysWin;
57 OSL_ASSERT( pWindow );
58 return pWindow;
61 return nullptr;
64 class ToolbarPopupStatusListener : public svt::FrameStatusListener
66 public:
67 ToolbarPopupStatusListener( const css::uno::Reference< css::frame::XFrame >& xFrame,
68 WeldToolbarPopup& rToolbarPopup );
70 virtual void SAL_CALL dispose() override;
71 virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
73 WeldToolbarPopup* mpPopup;
77 ToolbarPopupStatusListener::ToolbarPopupStatusListener(
78 const css::uno::Reference< css::frame::XFrame >& xFrame,
79 WeldToolbarPopup& rToolbarPopup )
80 : svt::FrameStatusListener( ::comphelper::getProcessComponentContext(), xFrame )
81 , mpPopup( &rToolbarPopup )
86 void SAL_CALL ToolbarPopupStatusListener::dispose()
88 mpPopup = nullptr;
89 svt::FrameStatusListener::dispose();
93 void SAL_CALL ToolbarPopupStatusListener::statusChanged( const css::frame::FeatureStateEvent& Event )
95 if( mpPopup )
96 mpPopup->statusChanged( Event );
101 void WeldToolbarPopup::AddStatusListener(const OUString& rCommandURL)
103 if (!m_xStatusListener.is())
104 m_xStatusListener.set(new ToolbarPopupStatusListener(m_xFrame, *this));
106 m_xStatusListener->addStatusListener(rCommandURL);
109 void WeldToolbarPopup::statusChanged(const css::frame::FeatureStateEvent& /*Event*/)
113 void InterimToolbarPopup::EndPopupMode()
115 GetDockingManager()->EndPopupMode(this);
118 WeldToolbarPopup::WeldToolbarPopup(const css::uno::Reference<css::frame::XFrame>& rFrame,
119 weld::Widget* pParent, const OUString& rUIFile,
120 const OString& rId)
121 : m_xBuilder(Application::CreateBuilder(pParent, rUIFile))
122 , m_xTopLevel(m_xBuilder->weld_container(rId))
123 , m_xContainer(m_xBuilder->weld_container("container"))
124 , m_xFrame(rFrame)
126 m_xTopLevel->connect_focus_in(LINK(this, WeldToolbarPopup, FocusHdl));
129 WeldToolbarPopup::~WeldToolbarPopup()
131 if (m_xStatusListener.is())
132 m_xStatusListener->dispose();
135 IMPL_LINK_NOARG(WeldToolbarPopup, FocusHdl, weld::Widget&, void)
137 GrabFocus();
140 ToolbarPopupContainer::ToolbarPopupContainer(weld::Widget* pParent)
141 : m_xBuilder(Application::CreateBuilder(pParent, "svx/ui/toolbarpopover.ui"))
142 , m_xTopLevel(m_xBuilder->weld_container("ToolbarPopover"))
143 , m_xContainer(m_xBuilder->weld_container("container"))
145 m_xTopLevel->connect_focus_in(LINK(this, ToolbarPopupContainer, FocusHdl));
148 void ToolbarPopupContainer::setPopover(std::unique_ptr<WeldToolbarPopup> xPopup)
150 m_xPopup = std::move(xPopup);
151 // move the WeldToolbarPopup contents into this toolbar so on-demand contents can appear inside a preexisting gtk popover
152 // because the arrow for the popover is only enabled if there's a popover set
153 m_xPopup->getTopLevel()->move(m_xPopup->getContainer(), m_xContainer.get());
154 m_xPopup->GrabFocus();
157 void ToolbarPopupContainer::unsetPopover()
159 if (!m_xPopup)
160 return;
161 m_xContainer->move(m_xPopup->getContainer(), m_xPopup->getTopLevel());
162 m_xPopup.reset();
165 ToolbarPopupContainer::~ToolbarPopupContainer()
167 unsetPopover();
170 IMPL_LINK_NOARG(ToolbarPopupContainer, FocusHdl, weld::Widget&, void)
172 if (m_xPopup)
173 m_xPopup->GrabFocus();
176 InterimToolbarPopup::InterimToolbarPopup(const css::uno::Reference<css::frame::XFrame>& rFrame, vcl::Window* pParent,
177 std::unique_ptr<WeldToolbarPopup> xPopup, bool bTearable)
178 : DockingWindow(pParent,
179 !bTearable ? OString("InterimDockParent") : OString("InterimTearableParent"),
180 !bTearable ? OUString("svx/ui/interimdockparent.ui") : OUString("svx/ui/interimtearableparent.ui"),
181 rFrame)
182 , m_xBox(get("box"))
183 , m_xFrame(rFrame)
184 , m_xBuilder(Application::CreateInterimBuilder(m_xBox.get(), "svx/ui/interimparent.ui", false))
185 , m_xContainer(m_xBuilder->weld_container("container"))
186 , m_xPopup(std::move(xPopup))
188 vcl::Window* pWindow = GetTopMostParentSystemWindow(this);
189 if (pWindow)
190 static_cast<SystemWindow*>(pWindow)->GetTaskPaneList()->AddWindow(this);
192 // move the WeldToolbarPopup contents into this interim toolbar so welded contents can appear as a dropdown in an unwelded toolbar
193 m_xPopup->getTopLevel()->move(m_xPopup->getContainer(), m_xContainer.get());
196 void InterimToolbarPopup::GetFocus()
198 DockingWindow::GetFocus();
199 if (!m_xPopup)
200 return;
201 m_xPopup->GrabFocus();
204 void InterimToolbarPopup::dispose()
206 vcl::Window* pWindow = GetTopMostParentSystemWindow(this);
207 if (pWindow)
208 static_cast<SystemWindow*>(pWindow)->GetTaskPaneList()->RemoveWindow(this);
210 // if we have focus when disposed, pick the document window as destination
211 // for focus rather than let it go to an arbitrary windows
212 if (HasFocus())
214 if (auto xWindow = m_xFrame->getContainerWindow())
215 xWindow->setFocus();
217 // move the contents back where it belongs
218 m_xContainer->move(m_xPopup->getContainer(), m_xPopup->getTopLevel());
219 m_xPopup.reset();
220 m_xContainer.reset();
221 m_xBuilder.reset();
222 m_xBox.clear();
223 m_xFrame.clear();
224 DockingWindow::dispose();
227 InterimToolbarPopup::~InterimToolbarPopup()
229 disposeOnce();
232 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */