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 <svtools/toolbarmenu.hxx>
26 #include <svx/dialmgr.hxx>
27 #include <lboxctrl.hxx>
28 #include <tools/urlobj.hxx>
30 #include <svx/strings.hrc>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/propertyvalue.hxx>
35 #include <com/sun/star/util/URLTransformer.hpp>
36 #include <com/sun/star/frame/XDispatchProvider.hpp>
39 using namespace ::com::sun::star::uno
;
40 using namespace ::com::sun::star::beans
;
41 using namespace ::com::sun::star::util
;
42 using namespace ::com::sun::star::frame
;
44 class SvxPopupWindowListBox final
: public WeldToolbarPopup
46 rtl::Reference
<SvxUndoRedoControl
> m_xControl
;
47 std::unique_ptr
<weld::TreeView
> m_xListBox
;
48 std::unique_ptr
<weld::TreeIter
> m_xScratchIter
;
52 void UpdateRow(int nRow
);
54 DECL_LINK(KeyInputHdl
, const KeyEvent
&, bool);
55 DECL_LINK(ActivateHdl
, weld::TreeView
&, bool);
56 DECL_LINK(MouseMoveHdl
, const MouseEvent
&, bool);
57 DECL_LINK(MousePressHdl
, const MouseEvent
&, bool);
58 DECL_LINK(MouseReleaseHdl
, const MouseEvent
&, bool);
61 SvxPopupWindowListBox(SvxUndoRedoControl
* pControl
, weld::Widget
* pParent
,
62 const std::vector
<OUString
>& rUndoRedoList
);
64 virtual void GrabFocus() override
66 m_xListBox
->grab_focus();
70 SvxPopupWindowListBox::SvxPopupWindowListBox(SvxUndoRedoControl
* pControl
, weld::Widget
* pParent
,
71 const std::vector
<OUString
>& rUndoRedoList
)
72 : WeldToolbarPopup(pControl
->getFrameInterface(), pParent
, u
"svx/ui/floatingundoredo.ui"_ustr
, u
"FloatingUndoRedo"_ustr
)
73 , m_xControl(pControl
)
74 , m_xListBox(m_xBuilder
->weld_tree_view(u
"treeview"_ustr
))
75 , m_xScratchIter(m_xListBox
->make_iterator())
78 m_xListBox
->set_selection_mode(SelectionMode::Multiple
);
80 for (const OUString
& s
: rUndoRedoList
)
81 m_xListBox
->append_text(s
);
82 if (!rUndoRedoList
.empty())
84 m_xListBox
->set_cursor(0);
85 m_xListBox
->select(0);
91 m_xListBox
->set_size_request(m_xListBox
->get_approximate_digit_width() * 25,
92 m_xListBox
->get_height_rows(m_nVisRows
) + 2);
94 m_xListBox
->connect_row_activated(LINK(this, SvxPopupWindowListBox
, ActivateHdl
));
95 m_xListBox
->connect_mouse_move(LINK(this, SvxPopupWindowListBox
, MouseMoveHdl
));
96 m_xListBox
->connect_mouse_press(LINK(this, SvxPopupWindowListBox
, MousePressHdl
));
97 m_xListBox
->connect_mouse_release(LINK(this, SvxPopupWindowListBox
, MouseReleaseHdl
));
98 m_xListBox
->connect_key_press(LINK(this, SvxPopupWindowListBox
, KeyInputHdl
));
101 void SvxUndoRedoControl::SetInfo( sal_Int32 nCount
)
105 pId
= getCommandURL() == ".uno:Undo" ? RID_SVXSTR_NUM_UNDO_ACTION
: RID_SVXSTR_NUM_REDO_ACTION
;
107 pId
= getCommandURL() == ".uno:Undo" ? RID_SVXSTR_NUM_UNDO_ACTIONS
: RID_SVXSTR_NUM_REDO_ACTIONS
;
108 OUString aActionStr
= SvxResId(pId
);
109 OUString aText
= aActionStr
.replaceAll("$(ARG1)", OUString::number(nCount
));
113 void SvxPopupWindowListBox::UpdateRow(int nRow
)
115 int nOldSelectedRows
= m_nSelectedRows
;
116 while (m_nSelectedRows
< nRow
+ 1)
118 m_xListBox
->select(m_nSelectedRows
++);
120 while (m_nSelectedRows
- 1 > nRow
)
122 m_xListBox
->unselect(--m_nSelectedRows
);
124 if (nOldSelectedRows
!= m_nSelectedRows
)
125 m_xControl
->SetInfo(m_nSelectedRows
);
128 IMPL_LINK(SvxPopupWindowListBox
, MouseMoveHdl
, const MouseEvent
&, rMEvt
, bool)
130 if (m_xListBox
->get_dest_row_at_pos(rMEvt
.GetPosPixel(), m_xScratchIter
.get(), false))
131 UpdateRow(m_xListBox
->get_iter_index_in_parent(*m_xScratchIter
));
135 IMPL_LINK(SvxPopupWindowListBox
, MousePressHdl
, const MouseEvent
&, rMEvt
, bool)
137 if (m_xListBox
->get_dest_row_at_pos(rMEvt
.GetPosPixel(), m_xScratchIter
.get(), false))
139 UpdateRow(m_xListBox
->get_iter_index_in_parent(*m_xScratchIter
));
140 ActivateHdl(*m_xListBox
);
145 IMPL_LINK(SvxPopupWindowListBox
, MouseReleaseHdl
, const MouseEvent
&, rMEvt
, bool)
147 if (m_xListBox
->get_dest_row_at_pos(rMEvt
.GetPosPixel(), m_xScratchIter
.get(), false))
148 UpdateRow(m_xListBox
->get_iter_index_in_parent(*m_xScratchIter
));
152 IMPL_LINK(SvxPopupWindowListBox
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
154 const vcl::KeyCode
& rKCode
= rKEvt
.GetKeyCode();
155 if (rKCode
.GetModifier()) // only with no modifiers held
158 sal_uInt16 nCode
= rKCode
.GetCode();
160 if (nCode
== KEY_UP
|| nCode
== KEY_PAGEUP
||
161 nCode
== KEY_DOWN
|| nCode
== KEY_PAGEDOWN
)
163 sal_Int32 nIndex
= m_nSelectedRows
- 1;
164 sal_Int32 nOrigIndex
= nIndex
;
165 sal_Int32 nCount
= m_xListBox
->n_children();
169 else if (nCode
== KEY_DOWN
)
171 else if (nCode
== KEY_PAGEUP
)
172 nIndex
-= m_nVisRows
;
173 else if (nCode
== KEY_PAGEDOWN
)
174 nIndex
+= m_nVisRows
;
178 if (nIndex
>= nCount
)
181 if (nIndex
!= nOrigIndex
)
183 m_xListBox
->scroll_to_row(nIndex
);
184 if (nIndex
> nOrigIndex
)
186 for (int i
= nOrigIndex
+ 1; i
<= nIndex
; ++i
)
191 for (int i
= nOrigIndex
- 1; i
>= nIndex
; --i
)
201 IMPL_LINK_NOARG(SvxPopupWindowListBox
, ActivateHdl
, weld::TreeView
&, bool)
203 m_xControl
->Do(m_nSelectedRows
);
204 m_xControl
->EndPopupMode();
208 void SvxUndoRedoControl::Do(sal_Int16 nCount
)
210 Reference
< XDispatchProvider
> xDispatchProvider( m_xFrame
, UNO_QUERY
);
211 if ( !xDispatchProvider
.is() )
214 css::util::URL aTargetURL
;
215 Reference
< XURLTransformer
> xTrans( URLTransformer::create(::comphelper::getProcessComponentContext()) );
216 aTargetURL
.Complete
= m_aCommandURL
;
217 xTrans
->parseStrict( aTargetURL
);
219 Reference
< XDispatch
> xDispatch
= xDispatchProvider
->queryDispatch( aTargetURL
, OUString(), 0 );
220 if ( xDispatch
.is() )
222 INetURLObject
aObj( m_aCommandURL
);
223 Sequence
< PropertyValue
> aArgs
{ comphelper::makePropertyValue(aObj
.GetURLPath(), nCount
) };
224 xDispatch
->dispatch(aTargetURL
, aArgs
);
228 SvxUndoRedoControl::SvxUndoRedoControl(const css::uno::Reference
<css::uno::XComponentContext
>& rContext
)
229 : PopupWindowController(rContext
, nullptr, OUString())
233 void SvxUndoRedoControl::initialize( const css::uno::Sequence
< css::uno::Any
>& rArguments
)
235 PopupWindowController::initialize(rArguments
);
237 ToolBox
* pToolBox
= nullptr;
239 if (!getToolboxId(nId
, &pToolBox
) && !m_pToolbar
)
242 if (getModuleName() != "com.sun.star.script.BasicIDE")
245 aDefaultTooltip
= m_pToolbar
->get_item_tooltip_text(m_aCommandURL
);
248 pToolBox
->SetItemBits(nId
, ToolBoxItemBits::DROPDOWN
| pToolBox
->GetItemBits(nId
));
249 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( u
".uno:GetUndoStrings"_ustr
);
305 updateStatus( u
".uno:GetRedoStrings"_ustr
);
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( u
".uno:GetUndoStrings"_ustr
);
315 updateStatus( u
".uno:GetRedoStrings"_ustr
);
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 u
"com.sun.star.comp.svx.UndoRedoToolBoxControl"_ustr
;
334 css::uno::Sequence
<OUString
> SvxUndoRedoControl::getSupportedServiceNames()
336 return { u
"com.sun.star.frame.ToolbarController"_ustr
};
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: */