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 .
20 #include <sal/config.h>
22 #include <sal/types.h>
23 #include <vcl/event.hxx>
24 #include <vcl/toolbox.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <svtools/toolbarmenu.hxx>
27 #include <svx/dialmgr.hxx>
28 #include <lboxctrl.hxx>
29 #include <tools/urlobj.hxx>
31 #include <svx/strings.hrc>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/propertyvalue.hxx>
36 #include <com/sun/star/util/URLTransformer.hpp>
37 #include <com/sun/star/frame/XDispatchProvider.hpp>
40 using namespace ::com::sun::star::uno
;
41 using namespace ::com::sun::star::beans
;
42 using namespace ::com::sun::star::util
;
43 using namespace ::com::sun::star::frame
;
45 class SvxPopupWindowListBox final
: public WeldToolbarPopup
47 rtl::Reference
<SvxUndoRedoControl
> m_xControl
;
48 std::unique_ptr
<weld::TreeView
> m_xListBox
;
49 std::unique_ptr
<weld::TreeIter
> m_xScratchIter
;
53 void UpdateRow(int nRow
);
55 DECL_LINK(KeyInputHdl
, const KeyEvent
&, bool);
56 DECL_LINK(ActivateHdl
, weld::TreeView
&, bool);
57 DECL_LINK(MouseMoveHdl
, const MouseEvent
&, bool);
58 DECL_LINK(MousePressHdl
, const MouseEvent
&, bool);
59 DECL_LINK(MouseReleaseHdl
, const MouseEvent
&, bool);
62 SvxPopupWindowListBox(SvxUndoRedoControl
* pControl
, weld::Widget
* pParent
,
63 const std::vector
<OUString
>& rUndoRedoList
);
65 virtual void GrabFocus() override
67 m_xListBox
->grab_focus();
71 SvxPopupWindowListBox::SvxPopupWindowListBox(SvxUndoRedoControl
* pControl
, weld::Widget
* pParent
,
72 const std::vector
<OUString
>& rUndoRedoList
)
73 : WeldToolbarPopup(pControl
->getFrameInterface(), pParent
, "svx/ui/floatingundoredo.ui", "FloatingUndoRedo")
74 , m_xControl(pControl
)
75 , m_xListBox(m_xBuilder
->weld_tree_view("treeview"))
76 , m_xScratchIter(m_xListBox
->make_iterator())
79 m_xListBox
->set_selection_mode(SelectionMode::Multiple
);
81 for (const OUString
& s
: rUndoRedoList
)
82 m_xListBox
->append_text(s
);
83 if (!rUndoRedoList
.empty())
85 m_xListBox
->set_cursor(0);
86 m_xListBox
->select(0);
92 m_xListBox
->set_size_request(m_xListBox
->get_approximate_digit_width() * 25,
93 m_xListBox
->get_height_rows(m_nVisRows
) + 2);
95 m_xListBox
->connect_row_activated(LINK(this, SvxPopupWindowListBox
, ActivateHdl
));
96 m_xListBox
->connect_mouse_move(LINK(this, SvxPopupWindowListBox
, MouseMoveHdl
));
97 m_xListBox
->connect_mouse_press(LINK(this, SvxPopupWindowListBox
, MousePressHdl
));
98 m_xListBox
->connect_mouse_release(LINK(this, SvxPopupWindowListBox
, MouseReleaseHdl
));
99 m_xListBox
->connect_key_press(LINK(this, SvxPopupWindowListBox
, KeyInputHdl
));
102 void SvxUndoRedoControl::SetInfo( sal_Int32 nCount
)
106 pId
= getCommandURL() == ".uno:Undo" ? RID_SVXSTR_NUM_UNDO_ACTION
: RID_SVXSTR_NUM_REDO_ACTION
;
108 pId
= getCommandURL() == ".uno:Undo" ? RID_SVXSTR_NUM_UNDO_ACTIONS
: RID_SVXSTR_NUM_REDO_ACTIONS
;
109 OUString aActionStr
= SvxResId(pId
);
110 OUString aText
= aActionStr
.replaceAll("$(ARG1)", OUString::number(nCount
));
114 void SvxPopupWindowListBox::UpdateRow(int nRow
)
116 int nOldSelectedRows
= m_nSelectedRows
;
117 while (m_nSelectedRows
< nRow
+ 1)
119 m_xListBox
->select(m_nSelectedRows
++);
121 while (m_nSelectedRows
- 1 > nRow
)
123 m_xListBox
->unselect(--m_nSelectedRows
);
125 if (nOldSelectedRows
!= m_nSelectedRows
)
126 m_xControl
->SetInfo(m_nSelectedRows
);
129 IMPL_LINK(SvxPopupWindowListBox
, MouseMoveHdl
, const MouseEvent
&, rMEvt
, bool)
131 if (m_xListBox
->get_dest_row_at_pos(rMEvt
.GetPosPixel(), m_xScratchIter
.get(), false))
132 UpdateRow(m_xListBox
->get_iter_index_in_parent(*m_xScratchIter
));
136 IMPL_LINK(SvxPopupWindowListBox
, MousePressHdl
, const MouseEvent
&, rMEvt
, bool)
138 if (m_xListBox
->get_dest_row_at_pos(rMEvt
.GetPosPixel(), m_xScratchIter
.get(), false))
140 UpdateRow(m_xListBox
->get_iter_index_in_parent(*m_xScratchIter
));
141 ActivateHdl(*m_xListBox
);
146 IMPL_LINK(SvxPopupWindowListBox
, MouseReleaseHdl
, const MouseEvent
&, rMEvt
, bool)
148 if (m_xListBox
->get_dest_row_at_pos(rMEvt
.GetPosPixel(), m_xScratchIter
.get(), false))
149 UpdateRow(m_xListBox
->get_iter_index_in_parent(*m_xScratchIter
));
153 IMPL_LINK(SvxPopupWindowListBox
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
155 const vcl::KeyCode
& rKCode
= rKEvt
.GetKeyCode();
156 if (rKCode
.GetModifier()) // only with no modifiers held
159 sal_uInt16 nCode
= rKCode
.GetCode();
161 if (nCode
== KEY_UP
|| nCode
== KEY_PAGEUP
||
162 nCode
== KEY_DOWN
|| nCode
== KEY_PAGEDOWN
)
164 sal_Int32 nIndex
= m_nSelectedRows
- 1;
165 sal_Int32 nOrigIndex
= nIndex
;
166 sal_Int32 nCount
= m_xListBox
->n_children();
170 else if (nCode
== KEY_DOWN
)
172 else if (nCode
== KEY_PAGEUP
)
173 nIndex
-= m_nVisRows
;
174 else if (nCode
== KEY_PAGEDOWN
)
175 nIndex
+= m_nVisRows
;
179 if (nIndex
>= nCount
)
182 if (nIndex
!= nOrigIndex
)
184 m_xListBox
->scroll_to_row(nIndex
);
185 if (nIndex
> nOrigIndex
)
187 for (int i
= nOrigIndex
+ 1; i
<= nIndex
; ++i
)
192 for (int i
= nOrigIndex
- 1; i
>= nIndex
; --i
)
202 IMPL_LINK_NOARG(SvxPopupWindowListBox
, ActivateHdl
, weld::TreeView
&, bool)
204 m_xControl
->Do(m_nSelectedRows
);
205 m_xControl
->EndPopupMode();
209 void SvxUndoRedoControl::Do(sal_Int16 nCount
)
211 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
212 if ( !xDispatchProvider
.is() )
215 css::util::URL aTargetURL
;
216 Reference
< XURLTransformer
> xTrans( URLTransformer::create(::comphelper::getProcessComponentContext()) );
217 aTargetURL
.Complete
= m_aCommandURL
;
218 xTrans
->parseStrict( aTargetURL
);
220 Reference
< XDispatch
> xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
221 if ( xDispatch
.is() )
223 INetURLObject
aObj( m_aCommandURL
);
224 Sequence
< PropertyValue
> aArgs
{ comphelper::makePropertyValue(aObj
.GetURLPath(), nCount
) };
225 xDispatch
->dispatch(aTargetURL
, aArgs
);
229 SvxUndoRedoControl::SvxUndoRedoControl(const css::uno::Reference
<css::uno::XComponentContext
>& rContext
)
230 : PopupWindowController(rContext
, nullptr, OUString())
234 void SvxUndoRedoControl::initialize( const css::uno::Sequence
< css::uno::Any
>& rArguments
)
236 PopupWindowController::initialize(rArguments
);
238 ToolBox
* pToolBox
= nullptr;
240 if (!getToolboxId(nId
, &pToolBox
) && !m_pToolbar
)
243 if (getModuleName() != "com.sun.star.script.BasicIDE")
246 pToolBox
->SetItemBits(nId
, ToolBoxItemBits::DROPDOWN
| pToolBox
->GetItemBits(nId
));
248 aDefaultTooltip
= m_pToolbar
->get_item_tooltip_text(m_aCommandURL
);
250 aDefaultTooltip
= pToolBox
->GetQuickHelpText(nId
);
254 SvxUndoRedoControl::~SvxUndoRedoControl()
258 void SvxUndoRedoControl::SetText(const OUString
& rText
)
260 mxInterimPopover
->SetText(rText
);
264 void SAL_CALL
SvxUndoRedoControl::statusChanged(const css::frame::FeatureStateEvent
& rEvent
)
266 if (rEvent
.FeatureURL
.Main
== ".uno:GetUndoStrings" || rEvent
.FeatureURL
.Main
== ".uno:GetRedoStrings")
268 css::uno::Sequence
<OUString
> aStrings
;
269 rEvent
.State
>>= aStrings
;
270 aUndoRedoList
= comphelper::sequenceToContainer
<std::vector
<OUString
>>(aStrings
);
274 PopupWindowController::statusChanged(rEvent
);
276 ToolBox
* pToolBox
= nullptr;
278 if (!getToolboxId(nId
, &pToolBox
) && !m_pToolbar
)
281 if (!rEvent
.IsEnabled
)
284 m_pToolbar
->set_item_tooltip_text(m_aCommandURL
, aDefaultTooltip
);
286 pToolBox
->SetQuickHelpText(nId
, aDefaultTooltip
);
290 OUString aQuickHelpText
;
291 if (rEvent
.State
>>= aQuickHelpText
)
294 m_pToolbar
->set_item_tooltip_text(m_aCommandURL
, aQuickHelpText
);
296 pToolBox
->SetQuickHelpText(nId
, aQuickHelpText
);
300 std::unique_ptr
<WeldToolbarPopup
> SvxUndoRedoControl::weldPopupWindow()
302 if ( m_aCommandURL
== ".uno:Undo" )
303 updateStatus( ".uno:GetUndoStrings");
305 updateStatus( ".uno:GetRedoStrings");
307 return std::make_unique
<SvxPopupWindowListBox
>(this, m_pToolbar
, aUndoRedoList
);
310 VclPtr
<vcl::Window
> SvxUndoRedoControl::createVclPopupWindow( vcl::Window
* pParent
)
312 if ( m_aCommandURL
== ".uno:Undo" )
313 updateStatus( ".uno:GetUndoStrings");
315 updateStatus( ".uno:GetRedoStrings");
317 auto xPopupWin
= std::make_unique
<SvxPopupWindowListBox
>(this, pParent
->GetFrameWeld(), aUndoRedoList
);
319 mxInterimPopover
= VclPtr
<InterimToolbarPopup
>::Create(getFrameInterface(), pParent
,
320 std::move(xPopupWin
));
322 SetInfo(1); // count of selected rows
324 mxInterimPopover
->Show();
326 return mxInterimPopover
;
329 OUString
SvxUndoRedoControl::getImplementationName()
331 return "com.sun.star.comp.svx.UndoRedoToolBoxControl";
334 css::uno::Sequence
<OUString
> SvxUndoRedoControl::getSupportedServiceNames()
336 return { "com.sun.star.frame.ToolbarController" };
339 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
340 com_sun_star_comp_svx_UndoRedoToolBoxControl_get_implementation(
341 css::uno::XComponentContext
* rContext
,
342 css::uno::Sequence
<css::uno::Any
> const & )
344 return cppu::acquire(new SvxUndoRedoControl(rContext
));
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */