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 <macroass.hxx>
21 #include <o3tl/safeint.hxx>
22 #include <o3tl/string_view.hxx>
23 #include <osl/diagnose.h>
24 #include <comphelper/string.hxx>
25 #include <comphelper/processfactory.hxx>
26 #include <svl/macitem.hxx>
27 #include <svx/svxids.hrc>
28 #include <tools/debug.hxx>
29 #include <vcl/idle.hxx>
30 #include <cfgutil.hxx>
31 #include <sfx2/evntconf.hxx>
32 #include <headertablistbox.hxx>
34 using ::com::sun::star::uno::Reference
;
35 using ::com::sun::star::frame::XFrame
;
37 class SfxMacroTabPage_Impl
40 SfxMacroTabPage_Impl();
42 OUString m_aStaticMacroLBLabel
;
43 std::unique_ptr
<weld::Button
> m_xAssignPB
;
44 std::unique_ptr
<weld::Button
> m_xDeletePB
;
45 std::unique_ptr
<MacroEventListBox
> m_xEventLB
;
46 std::unique_ptr
<weld::Widget
> m_xGroupFrame
;
47 std::unique_ptr
<CuiConfigGroupListBox
> m_xGroupLB
;
48 std::unique_ptr
<weld::Frame
> m_xMacroFrame
;
49 std::unique_ptr
<CuiConfigFunctionListBox
> m_xMacroLB
;
51 Idle m_aFillGroupIdle
{ "cui SfxMacroTabPage m_aFillGroupIdle" };
55 SfxMacroTabPage_Impl::SfxMacroTabPage_Impl()
60 static sal_uInt16 aPageRg
[] = {
61 SID_ATTR_MACROITEM
, SID_ATTR_MACROITEM
,
65 static OUString
ConvertToUIName_Impl( SvxMacro
const *pMacro
)
67 OUString
aName( pMacro
->GetMacName() );
68 if ( pMacro
->GetLanguage() != "JavaScript" )
70 const sal_Int32 nCount
= comphelper::string::getTokenCount(aName
, '.');
71 OUString aEntry
= aName
.getToken( nCount
-1, '.' );
74 aEntry
+= OUString::Concat("(") + o3tl::getToken(aName
, 0, '.' ) + "." + o3tl::getToken(aName
, nCount
-2, '.' ) + ")";
82 void SfxMacroTabPage::EnableButtons()
84 // don't do anything as long as the eventbox is empty
85 weld::TreeView
& rTreeView
= mpImpl
->m_xEventLB
->GetListBox();
86 int nSelected
= rTreeView
.get_selected_index();
90 const SvxMacro
* pM
= aTbl
.Get(static_cast<SvMacroItemId
>(rTreeView
.get_selected_id().toInt32()));
91 mpImpl
->m_xDeletePB
->set_sensitive(nullptr != pM
);
93 OUString sEventMacro
= rTreeView
.get_text(nSelected
, 1);
95 OUString sScriptURI
= mpImpl
->m_xMacroLB
->GetSelectedScriptURI();
96 mpImpl
->m_xAssignPB
->set_sensitive(!sScriptURI
.equalsIgnoreAsciiCase(sEventMacro
));
99 mpImpl
->m_xAssignPB
->set_sensitive(false);
102 SfxMacroTabPage::SfxMacroTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const Reference
< XFrame
>& rxDocumentFrame
, const SfxItemSet
& rAttrSet
)
103 : SfxTabPage(pPage
, pController
, u
"cui/ui/eventassignpage.ui"_ustr
, u
"EventAssignPage"_ustr
, &rAttrSet
)
105 mpImpl
.reset(new SfxMacroTabPage_Impl
);
107 mpImpl
->m_aFillGroupIdle
.SetInvokeHandler( LINK( this, SfxMacroTabPage
, TimeOut_Impl
) );
108 mpImpl
->m_aFillGroupIdle
.SetPriority( TaskPriority::HIGHEST
);
110 mpImpl
->m_xEventLB
.reset(new MacroEventListBox(m_xBuilder
->weld_tree_view(u
"assignments"_ustr
)));
111 mpImpl
->m_xAssignPB
= m_xBuilder
->weld_button(u
"assign"_ustr
);
112 mpImpl
->m_xDeletePB
= m_xBuilder
->weld_button(u
"delete"_ustr
);
113 mpImpl
->m_xGroupFrame
= m_xBuilder
->weld_widget(u
"groupframe"_ustr
);
114 mpImpl
->m_xGroupLB
.reset(new CuiConfigGroupListBox(m_xBuilder
->weld_tree_view(u
"libraries"_ustr
)));
115 mpImpl
->m_xMacroFrame
= m_xBuilder
->weld_frame(u
"macroframe"_ustr
);
116 mpImpl
->m_aStaticMacroLBLabel
= mpImpl
->m_xMacroFrame
->get_label();
117 mpImpl
->m_xMacroLB
.reset(new CuiConfigFunctionListBox(m_xBuilder
->weld_tree_view(u
"macros"_ustr
)));
119 SetFrame( rxDocumentFrame
);
126 SfxMacroTabPage::~SfxMacroTabPage()
131 void SfxMacroTabPage::AddEvent(const OUString
& rEventName
, SvMacroItemId nEventId
)
133 weld::TreeView
& rTreeView
= mpImpl
->m_xEventLB
->GetListBox();
134 rTreeView
.append(OUString::number(static_cast<sal_Int32
>(nEventId
)), rEventName
);
136 // if the table is valid already
137 SvxMacro
* pM
= aTbl
.Get(nEventId
);
140 OUString
sNew(ConvertToUIName_Impl(pM
));
141 rTreeView
.set_text(rTreeView
.n_children() - 1, sNew
, 1);
145 void SfxMacroTabPage::ScriptChanged()
147 // get new areas and their functions
148 mpImpl
->m_xGroupFrame
->show();
149 mpImpl
->m_xMacroFrame
->show();
154 bool SfxMacroTabPage::FillItemSet( SfxItemSet
* rSet
)
156 SvxMacroItem
aItem( GetWhich( aPageRg
[0] ) );
157 const_cast<SvxMacroTableDtor
&>(aItem
.GetMacroTable()) = aTbl
;
159 const SfxPoolItem
* pItem
= nullptr;
160 SfxItemState eState
= GetItemSet().GetItemState(aItem
.Which(), true, &pItem
);
161 if (eState
== SfxItemState::DEFAULT
&& aTbl
.empty())
163 // Don't touch the item set if there was no input and our table is empty.
166 if (SfxItemState::SET
!= eState
|| aItem
!= *static_cast<const SvxMacroItem
*>(pItem
))
174 void SfxMacroTabPage::LaunchFillGroup()
176 if (! mpImpl
->m_aFillGroupIdle
.IsActive() )
177 mpImpl
->m_aFillGroupIdle
.Start();
180 void SfxMacroTabPage::ActivatePage( const SfxItemSet
& )
185 void SfxMacroTabPage::PageCreated(const SfxAllItemSet
& aSet
)
187 if( mpImpl
->m_bGotEvents
)
189 if( const SfxEventNamesItem
* pEventsItem
= aSet
.GetItemIfSet( SID_EVENTCONFIG
) )
191 mpImpl
->m_bGotEvents
= true;
192 const SfxEventNamesList
& rList
= pEventsItem
->GetEvents();
193 for ( size_t nNo
= 0, nCnt
= rList
.size(); nNo
< nCnt
; ++nNo
)
195 const SfxEventName
&rOwn
= rList
.at(nNo
);
196 AddEvent( rOwn
.maUIName
, rOwn
.mnId
);
201 void SfxMacroTabPage::Reset( const SfxItemSet
* rSet
)
203 const SfxPoolItem
* pItem
;
204 if( SfxItemState::SET
== rSet
->GetItemState( GetWhich( aPageRg
[0] ), true, &pItem
))
205 aTbl
= static_cast<const SvxMacroItem
*>(pItem
)->GetMacroTable();
207 const SfxEventNamesItem
* pEventsItem
;
208 if( !mpImpl
->m_bGotEvents
&& (pEventsItem
= rSet
->GetItemIfSet( SID_EVENTCONFIG
) ) )
210 mpImpl
->m_bGotEvents
= true;
211 const SfxEventNamesList
& rList
= pEventsItem
->GetEvents();
212 for ( size_t nNo
= 0, nCnt
= rList
.size(); nNo
< nCnt
; ++nNo
)
214 const SfxEventName
&rOwn
= rList
.at(nNo
);
215 AddEvent( rOwn
.maUIName
, rOwn
.mnId
);
221 weld::TreeView
& rListBox
= mpImpl
->m_xEventLB
->GetListBox();
222 std::unique_ptr
<weld::TreeIter
> xIter(rListBox
.make_iterator());
223 if (rListBox
.get_iter_first(*xIter
))
225 rListBox
.set_cursor(*xIter
);
230 bool SfxMacroTabPage::IsReadOnly() const
235 IMPL_LINK_NOARG(SfxMacroTabPage
, SelectEvent_Impl
, weld::TreeView
&, void)
237 weld::TreeView
& rListBox
= mpImpl
->m_xEventLB
->GetListBox();
238 int nSelected
= rListBox
.get_selected_index();
241 DBG_ASSERT(nSelected
!= -1, "Where does the empty entry come from?");
249 IMPL_LINK_NOARG(SfxMacroTabPage
, SelectGroup_Impl
, weld::TreeView
&, void)
251 mpImpl
->m_xGroupLB
->GroupSelected();
252 const OUString sScriptURI
= mpImpl
->m_xMacroLB
->GetSelectedScriptURI();
254 if( !sScriptURI
.isEmpty() )
255 aLabelText
= mpImpl
->m_aStaticMacroLBLabel
;
256 mpImpl
->m_xMacroFrame
->set_label( aLabelText
);
261 IMPL_LINK_NOARG(SfxMacroTabPage
, SelectMacro_Impl
, weld::TreeView
&, void)
266 IMPL_LINK(SfxMacroTabPage
, AssignDeleteClickHdl_Impl
, weld::Button
&, rBtn
, void)
268 AssignDeleteHdl(&rBtn
);
271 IMPL_LINK(SfxMacroTabPage
, AssignDeleteHdl_Impl
, weld::TreeView
&, rBtn
, bool)
273 AssignDeleteHdl(&rBtn
);
277 void SfxMacroTabPage::AssignDeleteHdl(const weld::Widget
* pBtn
)
279 weld::TreeView
& rListBox
= mpImpl
->m_xEventLB
->GetListBox();
280 int nSelected
= rListBox
.get_selected_index();
283 DBG_ASSERT(nSelected
!= -1, "Where does the empty entry come from?");
287 const bool bAssEnabled
= pBtn
!= mpImpl
->m_xDeletePB
.get() && mpImpl
->m_xAssignPB
->get_sensitive();
289 // remove from the table
290 SvMacroItemId nEvent
= static_cast<SvMacroItemId
>(rListBox
.get_selected_id().toInt32());
291 aTbl
.Erase( nEvent
);
296 sScriptURI
= mpImpl
->m_xMacroLB
->GetSelectedScriptURI();
297 if( sScriptURI
.startsWith( "vnd.sun.star.script:" ) )
300 nEvent
, SvxMacro( sScriptURI
, SVX_MACRO_LANGUAGE_SF
) );
304 OSL_ENSURE( false, "SfxMacroTabPage::AssignDeleteHdl_Impl: this branch is *not* dead? (out of interest: tell fs, please!)" );
306 nEvent
, SvxMacro( sScriptURI
, SVX_MACRO_LANGUAGE_STARBASIC
) );
310 rListBox
.set_text(nSelected
, sScriptURI
, 1);
315 IMPL_LINK( SfxMacroTabPage
, TimeOut_Impl
, Timer
*,, void )
317 // FillMacroList() can take a long time -> show wait cursor and disable input
318 weld::Window
* pDialog
= GetFrameWeld();
319 // perhaps the tabpage is part of a SingleTabDialog then pDialog == nullptr
320 std::unique_ptr
<weld::WaitObject
> xWait(pDialog
? new weld::WaitObject(pDialog
) : nullptr);
322 mpImpl
->m_xGroupLB
->Init(comphelper::getProcessComponentContext(), GetFrame(),
326 void SfxMacroTabPage::InitAndSetHandler()
328 weld::TreeView
& rListBox
= mpImpl
->m_xEventLB
->GetListBox();
329 Link
<weld::TreeView
&,bool> aLnk(LINK(this, SfxMacroTabPage
, AssignDeleteHdl_Impl
));
330 mpImpl
->m_xMacroLB
->connect_row_activated( aLnk
);
331 mpImpl
->m_xDeletePB
->connect_clicked(LINK(this, SfxMacroTabPage
, AssignDeleteClickHdl_Impl
));
332 mpImpl
->m_xAssignPB
->connect_clicked(LINK(this, SfxMacroTabPage
, AssignDeleteClickHdl_Impl
));
333 rListBox
.connect_row_activated(aLnk
);
335 rListBox
.connect_changed(LINK(this, SfxMacroTabPage
, SelectEvent_Impl
));
336 mpImpl
->m_xGroupLB
->connect_changed(LINK(this, SfxMacroTabPage
, SelectGroup_Impl
));
337 mpImpl
->m_xMacroLB
->connect_changed(LINK(this, SfxMacroTabPage
, SelectMacro_Impl
));
339 std::vector
<int> aWidths
341 o3tl::narrowing
<int>(rListBox
.get_approximate_digit_width() * 35)
343 rListBox
.set_column_fixed_widths(aWidths
);
345 mpImpl
->m_xEventLB
->show();
347 mpImpl
->m_xEventLB
->set_sensitive(true);
348 mpImpl
->m_xGroupLB
->set_sensitive(true);
349 mpImpl
->m_xMacroLB
->set_sensitive(true);
351 mpImpl
->m_xGroupLB
->SetFunctionListBox(mpImpl
->m_xMacroLB
.get());
354 void SfxMacroTabPage::FillEvents()
356 weld::TreeView
& rListBox
= mpImpl
->m_xEventLB
->GetListBox();
358 int nEntryCnt
= rListBox
.n_children();
360 // get events from the table and fill the EventListBox respectively
361 for (int n
= 0 ; n
< nEntryCnt
; ++n
)
363 OUString sOld
= rListBox
.get_text(n
, 1);
365 SvMacroItemId nEventId
= static_cast<SvMacroItemId
>(rListBox
.get_id(n
).toInt32());
366 if (aTbl
.IsKeyValid(nEventId
))
367 sNew
= ConvertToUIName_Impl(aTbl
.Get(nEventId
));
372 rListBox
.set_text(n
, sNew
, 1);
378 std::unique_ptr
<SfxMacroTabPage
> CreateSfxMacroTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rAttrSet
)
380 return std::make_unique
<SfxMacroTabPage
>( pPage
, pController
, nullptr, rAttrSet
);
384 std::unique_ptr
<SfxTabPage
> SfxMacroTabPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rAttrSet
)
386 return CreateSfxMacroTabPage(pPage
, pController
, *rAttrSet
);
389 SfxMacroAssignDlg::SfxMacroAssignDlg(weld::Widget
* pParent
,
390 const Reference
< XFrame
>& rxDocumentFrame
, const SfxItemSet
& rSet
)
391 : SfxSingleTabDialogController(pParent
, &rSet
,u
"cui/ui/eventassigndialog.ui"_ustr
,
392 u
"EventAssignDialog"_ustr
)
394 std::unique_ptr
<SfxMacroTabPage
> xPage
= CreateSfxMacroTabPage(get_content_area(), this, rSet
);
395 xPage
->SetFrame(rxDocumentFrame
);
396 SetTabPage(std::move(xPage
));
397 GetTabPage()->LaunchFillGroup();
400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */