1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
19 #include <sfx2/sidebar/SidebarDockingWindow.hxx>
20 #include <sfx2/sidebar/SidebarChildWindow.hxx>
21 #include <sfx2/sidebar/SidebarController.hxx>
22 #include <sidebar/PanelDescriptor.hxx>
24 #include <comphelper/dispatchcommand.hxx>
25 #include <comphelper/processfactory.hxx>
26 #include <sfx2/lokhelper.hxx>
27 #include <sfx2/bindings.hxx>
28 #include <sfx2/dispatch.hxx>
29 #include <sfx2/viewfrm.hxx>
30 #include <svtools/acceleratorexecute.hxx>
31 #include <tools/gen.hxx>
32 #include <tools/json_writer.hxx>
33 #include <vcl/event.hxx>
34 #include <comphelper/lok.hxx>
35 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
37 #include <boost/property_tree/json_parser.hpp>
40 using namespace css::uno
;
42 namespace sfx2::sidebar
{
44 class SidebarNotifyIdle
: public Idle
46 SidebarDockingWindow
& m_rSidebarDockingWin
;
47 std::string m_LastNotificationMessage
;
48 vcl::LOKWindowId m_LastLOKWindowId
;
51 SidebarNotifyIdle(SidebarDockingWindow
&rSidebarDockingWin
) :
52 Idle("Sidebar notify"),
53 m_rSidebarDockingWin(rSidebarDockingWin
),
54 m_LastNotificationMessage(),
57 SetPriority(TaskPriority::POST_PAINT
);
60 void Invoke() override
62 auto pNotifier
= m_rSidebarDockingWin
.GetLOKNotifier();
63 auto pMobileNotifier
= SfxViewShell::Current();
64 if (!pNotifier
|| (!pMobileNotifier
&& !comphelper::LibreOfficeKit::isActive()))
69 if (pMobileNotifier
&& pMobileNotifier
->isLOKMobilePhone())
72 tools::JsonWriter aJsonWriter
;
73 m_rSidebarDockingWin
.DumpAsPropertyTree(aJsonWriter
);
74 aJsonWriter
.put("id", m_rSidebarDockingWin
.GetLOKWindowId());
75 std::unique_ptr
<char[]> data( aJsonWriter
.extractData());
76 std::string_view
message(data
.get());
77 if (message
!= m_LastNotificationMessage
)
79 m_LastNotificationMessage
= message
;
80 pMobileNotifier
->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG
, m_LastNotificationMessage
.c_str());
84 // Notify the sidebar is created, and its LOKWindowId, which
85 // is needed on mobile phones, tablets, and desktop.
86 const Point
pos(m_rSidebarDockingWin
.GetOutOffXPixel(),
87 m_rSidebarDockingWin
.GetOutOffYPixel());
88 const OString posMessage
= pos
.toString();
89 const OString sizeMessage
= m_rSidebarDockingWin
.GetSizePixel().toString();
91 const std::string message
= OString(posMessage
+ sizeMessage
).getStr();
92 const vcl::LOKWindowId lokWindowId
= m_rSidebarDockingWin
.GetLOKWindowId();
94 if (lokWindowId
!= m_LastLOKWindowId
|| message
!= m_LastNotificationMessage
)
96 m_LastLOKWindowId
= lokWindowId
;
97 m_LastNotificationMessage
= message
;
99 std::vector
<vcl::LOKPayloadItem
> aItems
;
100 aItems
.emplace_back("type", "deck");
101 aItems
.emplace_back("position", posMessage
);
102 aItems
.emplace_back("size", sizeMessage
);
103 pNotifier
->notifyWindow(lokWindowId
, "created", aItems
);
106 catch (boost::property_tree::json_parser::json_parser_error
& rError
)
108 SAL_WARN("sfx.sidebar", rError
.message());
113 SidebarDockingWindow::SidebarDockingWindow(SfxBindings
* pSfxBindings
, SidebarChildWindow
& rChildWindow
,
114 vcl::Window
* pParentWindow
, WinBits nBits
)
115 : SfxDockingWindow(pSfxBindings
, &rChildWindow
, pParentWindow
, nBits
)
116 , mpSidebarController()
117 , mbIsReadyToDrag(false)
118 , mpIdleNotify(new SidebarNotifyIdle(*this))
120 // Get the XFrame from the bindings.
121 if (pSfxBindings
==nullptr || pSfxBindings
->GetDispatcher()==nullptr)
123 OSL_ASSERT(pSfxBindings
!=nullptr);
124 OSL_ASSERT(pSfxBindings
->GetDispatcher()!=nullptr);
128 const SfxViewFrame
* pViewFrame
= pSfxBindings
->GetDispatcher()->GetFrame();
129 mpSidebarController
.set(sfx2::sidebar::SidebarController::create(this, pViewFrame
).get());
133 SidebarDockingWindow::~SidebarDockingWindow()
138 void SidebarDockingWindow::dispose()
140 if (comphelper::LibreOfficeKit::isActive())
143 Reference
<lang::XComponent
> xComponent (static_cast<XWeak
*>(mpSidebarController
.get()), UNO_QUERY
);
144 mpSidebarController
.clear();
146 xComponent
->dispose();
148 SfxDockingWindow::dispose();
151 void SidebarDockingWindow::LOKClose()
153 assert(comphelper::LibreOfficeKit::isActive());
154 if (const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
156 mpIdleNotify
->Stop();
158 pNotifier
->notifyWindow(GetLOKWindowId(), "close");
159 ReleaseLOKNotifier();
163 void SidebarDockingWindow::GetFocus()
165 if (mpSidebarController
.is())
167 mpSidebarController
->RequestOpenDeck();
168 mpSidebarController
->GetFocusManager().GrabFocus();
171 SfxDockingWindow::GetFocus();
174 bool SidebarDockingWindow::Close()
176 if (mpSidebarController
.is())
177 mpSidebarController
->SetFloatingDeckClosed(true);
179 return SfxDockingWindow::Close();
182 void SidebarDockingWindow::Resize()
184 SfxDockingWindow::Resize();
189 void SidebarDockingWindow::SyncUpdate()
191 if (mpSidebarController
.is())
192 mpSidebarController
->SyncUpdate();
195 void SidebarDockingWindow::NotifyResize()
197 if (!(comphelper::LibreOfficeKit::isActive() && mpSidebarController
.is() && SfxViewShell::Current()))
200 const vcl::ILibreOfficeKitNotifier
* pCurrentView
= SfxViewShell::Current();
201 if (GetLOKNotifier() != pCurrentView
)
203 // ViewShell not yet set, or has changed. Reset it.
204 // Note GetLOKWindowId will return a new value after resetting, so we must notify clients.
207 SetLOKNotifier(pCurrentView
);
210 mpIdleNotify
->Start();
213 SfxChildAlignment
SidebarDockingWindow::CheckAlignment (
214 SfxChildAlignment eCurrentAlignment
,
215 SfxChildAlignment eRequestedAlignment
)
217 switch (eRequestedAlignment
)
219 case SfxChildAlignment::TOP
:
220 case SfxChildAlignment::HIGHESTTOP
:
221 case SfxChildAlignment::LOWESTTOP
:
222 case SfxChildAlignment::BOTTOM
:
223 case SfxChildAlignment::LOWESTBOTTOM
:
224 case SfxChildAlignment::HIGHESTBOTTOM
:
225 return eCurrentAlignment
;
227 case SfxChildAlignment::LEFT
:
228 case SfxChildAlignment::RIGHT
:
229 case SfxChildAlignment::FIRSTLEFT
:
230 case SfxChildAlignment::LASTLEFT
:
231 case SfxChildAlignment::FIRSTRIGHT
:
232 case SfxChildAlignment::LASTRIGHT
:
233 return eRequestedAlignment
;
236 return eRequestedAlignment
;
240 bool SidebarDockingWindow::EventNotify(NotifyEvent
& rEvent
)
242 MouseNotifyEvent nType
= rEvent
.GetType();
243 if (MouseNotifyEvent::KEYINPUT
== nType
)
245 const vcl::KeyCode
& rKeyCode
= rEvent
.GetKeyEvent()->GetKeyCode();
246 switch (rKeyCode
.GetCode())
269 mpAccel
= svt::AcceleratorExecute::createAcceleratorHelper();
270 mpAccel
->init(comphelper::getProcessComponentContext(), mpSidebarController
->getXFrame());
272 const OUString
aCommand(mpAccel
->findCommand(svt::AcceleratorExecute::st_VCLKey2AWTKey(rKeyCode
)));
273 if (".uno:DesignerDialog" == aCommand
)
275 std::shared_ptr
<PanelDescriptor
> xPanelDescriptor
=
276 mpSidebarController
->GetResourceManager()->GetPanelDescriptor( "StyleListPanel" );
277 if ( xPanelDescriptor
&& mpSidebarController
->IsDeckVisible( xPanelDescriptor
->msDeckId
) )
281 if (".uno:Undo" == aCommand
|| ".uno:Redo" == aCommand
)
283 comphelper::dispatchCommand(aCommand
, {});
287 else if (MouseNotifyEvent::MOUSEBUTTONDOWN
== nType
)
289 const MouseEvent
*mEvt
= rEvent
.GetMouseEvent();
292 tools::Rectangle aGrip
= mpSidebarController
->GetDeckDragArea();
293 if ( aGrip
.IsInside( mEvt
->GetPosPixel() ) )
294 mbIsReadyToDrag
= true;
297 else if (MouseNotifyEvent::MOUSEMOVE
== nType
)
299 const MouseEvent
*mEvt
= rEvent
.GetMouseEvent();
300 tools::Rectangle aGrip
= mpSidebarController
->GetDeckDragArea();
301 if (mEvt
->IsLeft() && aGrip
.IsInside( mEvt
->GetPosPixel() ) && mbIsReadyToDrag
)
303 Point aPos
= mEvt
->GetPosPixel();
304 vcl::Window
* pWindow
= rEvent
.GetWindow();
305 if ( pWindow
!= this )
307 aPos
= pWindow
->OutputToScreenPixel( aPos
);
308 aPos
= ScreenToOutputPixel( aPos
);
310 ImplStartDocking( aPos
);
314 return SfxDockingWindow::EventNotify(rEvent
);
317 } // end of namespace sfx2::sidebar
319 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */