Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "macroass.hxx"
21 :
22 : #include <basic/basmgr.hxx>
23 : #include <comphelper/string.hxx>
24 : #include <dialmgr.hxx>
25 : #include <svl/macitem.hxx>
26 : #include <svx/dialogs.hrc>
27 : #include <svtools/svmedit.hxx>
28 : #include <vcl/idle.hxx>
29 : #include "cfgutil.hxx"
30 : #include <sfx2/app.hxx>
31 : #include <sfx2/evntconf.hxx>
32 : #include <sfx2/objsh.hxx>
33 : #include "cuires.hrc"
34 : #include <vcl/fixed.hxx>
35 : #include "headertablistbox.hxx"
36 : #include "svtools/svlbitm.hxx"
37 : #include "svtools/treelistentry.hxx"
38 :
39 : using ::com::sun::star::uno::Reference;
40 : using ::com::sun::star::frame::XFrame;
41 :
42 0 : class _SfxMacroTabPage_Impl
43 : {
44 : public:
45 : _SfxMacroTabPage_Impl();
46 :
47 : OUString maStaticMacroLBLabel;
48 : VclPtr<PushButton> pAssignPB;
49 : VclPtr<PushButton> pDeletePB;
50 : OUString sStrEvent;
51 : OUString sAssignedMacro;
52 : VclPtr<MacroEventListBox> pEventLB;
53 : VclPtr<VclFrame> pGroupFrame;
54 : VclPtr<SfxConfigGroupListBox> pGroupLB;
55 : VclPtr<VclFrame> pMacroFrame;
56 : VclPtr<SfxConfigFunctionListBox> pMacroLB;
57 :
58 : bool bReadOnly;
59 : Idle maFillGroupIdle;
60 : bool bGotEvents;
61 : bool m_bDummyActivated; ///< has this tab page already been activated
62 : };
63 :
64 0 : _SfxMacroTabPage_Impl::_SfxMacroTabPage_Impl()
65 : : pAssignPB(NULL)
66 : , pDeletePB(NULL)
67 : , pEventLB(NULL)
68 : , pGroupFrame(NULL)
69 : , pGroupLB(NULL)
70 : , pMacroFrame(NULL)
71 : , pMacroLB(NULL)
72 : , bReadOnly(false)
73 : , bGotEvents(false)
74 0 : , m_bDummyActivated(false)
75 : {
76 0 : }
77 :
78 : static sal_uInt16 aPageRg[] = {
79 : SID_ATTR_MACROITEM, SID_ATTR_MACROITEM,
80 : 0
81 : };
82 :
83 : // attention, this array is indexed directly (0, 1, ...) in the code
84 : static long nTabs[] =
85 : {
86 : 2, // Number of Tabs
87 : 0, 90
88 : };
89 :
90 : // IDs for items in HeaderBar of EventLB
91 : #define ITEMID_EVENT 1
92 : #define ITMEID_ASSMACRO 2
93 :
94 :
95 : #define LB_MACROS_ITEMPOS 2
96 :
97 0 : OUString ConvertToUIName_Impl( SvxMacro *pMacro )
98 : {
99 0 : OUString aName( pMacro->GetMacName() );
100 0 : OUString aEntry;
101 0 : if ( pMacro->GetLanguage() != "JavaScript" )
102 : {
103 0 : sal_uInt16 nCount = comphelper::string::getTokenCount(aName, '.');
104 0 : aEntry = aName.getToken( nCount-1, '.' );
105 0 : if ( nCount > 2 )
106 : {
107 0 : aEntry += "(";
108 0 : aEntry += aName.getToken( 0, '.' );
109 0 : aEntry += ".";
110 0 : aEntry += aName.getToken( nCount-2, '.' );
111 0 : aEntry += ")";
112 : }
113 0 : return aEntry;
114 : }
115 : else
116 0 : return aName;
117 : }
118 :
119 0 : void _SfxMacroTabPage::EnableButtons()
120 : {
121 : // don't do anything as long as the eventbox is empty
122 0 : const SvTreeListEntry* pE = mpImpl->pEventLB->GetListBox().FirstSelected();
123 0 : if ( pE )
124 : {
125 : // get bound macro
126 0 : const SvxMacro* pM = aTbl.Get( (sal_uInt16)reinterpret_cast<sal_uLong>(pE->GetUserData()) );
127 0 : mpImpl->pDeletePB->Enable( 0 != pM && !mpImpl->bReadOnly );
128 :
129 0 : OUString sEventMacro = static_cast<const SvLBoxString*>(pE->GetItem( LB_MACROS_ITEMPOS ))->GetText();
130 :
131 0 : OUString sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI();
132 0 : mpImpl->pAssignPB->Enable( !mpImpl->bReadOnly && !sScriptURI.equalsIgnoreAsciiCase( sEventMacro ) );
133 : }
134 : else
135 0 : mpImpl->pAssignPB->Enable( false );
136 0 : }
137 :
138 0 : _SfxMacroTabPage::_SfxMacroTabPage(vcl::Window* pParent, const SfxItemSet& rAttrSet)
139 0 : : SfxTabPage(pParent, "EventAssignPage", "cui/ui/eventassignpage.ui", &rAttrSet)
140 : {
141 0 : mpImpl = new _SfxMacroTabPage_Impl;
142 0 : }
143 :
144 0 : _SfxMacroTabPage::~_SfxMacroTabPage()
145 : {
146 0 : disposeOnce();
147 0 : }
148 :
149 0 : void _SfxMacroTabPage::dispose()
150 : {
151 0 : DELETEZ( mpImpl );
152 0 : SfxTabPage::dispose();
153 0 : }
154 :
155 0 : void _SfxMacroTabPage::AddEvent( const OUString & rEventName, sal_uInt16 nEventId )
156 : {
157 0 : OUString sTmp( rEventName );
158 0 : sTmp += "\t";
159 :
160 : // if the table is valid already
161 0 : SvxMacro* pM = aTbl.Get( nEventId );
162 0 : if( pM )
163 : {
164 0 : OUString sNew( ConvertToUIName_Impl( pM ) );
165 0 : sTmp += sNew;
166 : }
167 :
168 0 : SvTreeListEntry* pE = mpImpl->pEventLB->GetListBox().InsertEntry( sTmp );
169 0 : pE->SetUserData( reinterpret_cast< void* >( sal::static_int_cast< sal_IntPtr >( nEventId )) );
170 0 : }
171 :
172 0 : void _SfxMacroTabPage::ScriptChanged()
173 : {
174 : // get new areas and their functions
175 0 : mpImpl->pGroupFrame->Show();
176 0 : mpImpl->pMacroFrame->Show();
177 :
178 0 : EnableButtons();
179 0 : }
180 :
181 0 : bool _SfxMacroTabPage::FillItemSet( SfxItemSet* rSet )
182 : {
183 0 : SvxMacroItem aItem( GetWhich( aPageRg[0] ) );
184 0 : ((SvxMacroTableDtor&)aItem.GetMacroTable()) = aTbl;
185 :
186 : const SfxPoolItem* pItem;
187 0 : if( SfxItemState::SET != GetItemSet().GetItemState( aItem.Which(), true, &pItem )
188 0 : || aItem != *static_cast<const SvxMacroItem*>(pItem) )
189 : {
190 0 : rSet->Put( aItem );
191 0 : return true;
192 : }
193 0 : return false;
194 : }
195 :
196 0 : void _SfxMacroTabPage::LaunchFillGroup()
197 : {
198 0 : if (!mpImpl->maFillGroupIdle.GetIdleHdl().IsSet())
199 : {
200 0 : mpImpl->maFillGroupIdle.SetIdleHdl( LINK( this, _SfxMacroTabPage, TimeOut_Impl ) );
201 0 : mpImpl->maFillGroupIdle.SetPriority( SchedulerPriority::HIGHEST );
202 0 : mpImpl->maFillGroupIdle.Start();
203 : }
204 0 : }
205 :
206 0 : void _SfxMacroTabPage::ActivatePage( const SfxItemSet& )
207 : {
208 : // fdo#57553 lazily init script providers, because it is annoying if done
209 : // on dialog open (SfxTabDialog::Start_Impl activates all tab pages once!)
210 0 : if (!mpImpl->m_bDummyActivated)
211 : {
212 0 : mpImpl->m_bDummyActivated = true;
213 0 : return;
214 : }
215 0 : LaunchFillGroup();
216 : }
217 :
218 0 : void _SfxMacroTabPage::PageCreated(const SfxAllItemSet& aSet)
219 : {
220 : const SfxPoolItem* pEventsItem;
221 0 : if( !mpImpl->bGotEvents && SfxItemState::SET == aSet.GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) )
222 : {
223 0 : mpImpl->bGotEvents = true;
224 0 : const SfxEventNamesList& rList = static_cast<const SfxEventNamesItem*>(pEventsItem)->GetEvents();
225 0 : for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo )
226 : {
227 0 : const SfxEventName *pOwn = rList.at(nNo);
228 0 : AddEvent( pOwn->maUIName, pOwn->mnId );
229 : }
230 : }
231 0 : }
232 :
233 0 : void _SfxMacroTabPage::Reset( const SfxItemSet* rSet )
234 : {
235 : const SfxPoolItem* pItem;
236 0 : if( SfxItemState::SET == rSet->GetItemState( GetWhich( aPageRg[0] ), true, &pItem ))
237 0 : aTbl = static_cast<const SvxMacroItem*>(pItem)->GetMacroTable();
238 :
239 : const SfxPoolItem* pEventsItem;
240 0 : if( !mpImpl->bGotEvents && SfxItemState::SET == rSet->GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) )
241 : {
242 0 : mpImpl->bGotEvents = true;
243 0 : const SfxEventNamesList& rList = static_cast<const SfxEventNamesItem*>(pEventsItem)->GetEvents();
244 0 : for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo )
245 : {
246 0 : const SfxEventName *pOwn = rList.at(nNo);
247 0 : AddEvent( pOwn->maUIName, pOwn->mnId );
248 : }
249 : }
250 :
251 0 : FillEvents();
252 :
253 0 : SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
254 0 : SvTreeListEntry* pE = rListBox.GetEntry( 0 );
255 0 : if( pE )
256 0 : rListBox.SetCurEntry( pE );
257 0 : }
258 :
259 0 : bool _SfxMacroTabPage::IsReadOnly() const
260 : {
261 0 : return mpImpl->bReadOnly;
262 : }
263 :
264 0 : IMPL_LINK( _SfxMacroTabPage, SelectEvent_Impl, SvTabListBox*, )
265 : {
266 0 : SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
267 0 : SvTreeListEntry* pE = rListBox.FirstSelected();
268 : sal_uLong nPos;
269 0 : if( !pE || LISTBOX_ENTRY_NOTFOUND ==
270 0 : ( nPos = rListBox.GetModel()->GetAbsPos( pE ) ) )
271 : {
272 : DBG_ASSERT( pE, "wo kommt der leere Eintrag her?" );
273 0 : return 0;
274 : }
275 :
276 0 : ScriptChanged();
277 0 : EnableButtons();
278 0 : return 0;
279 : }
280 :
281 0 : IMPL_LINK( _SfxMacroTabPage, SelectGroup_Impl, ListBox*, )
282 : {
283 0 : mpImpl->pGroupLB->GroupSelected();
284 0 : const OUString sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI();
285 0 : OUString aLabelText;
286 0 : if( !sScriptURI.isEmpty() )
287 0 : aLabelText = mpImpl->maStaticMacroLBLabel;
288 0 : mpImpl->pMacroFrame->set_label( aLabelText );
289 :
290 0 : EnableButtons();
291 0 : return 0;
292 : }
293 :
294 0 : IMPL_LINK( _SfxMacroTabPage, SelectMacro_Impl, ListBox*, )
295 : {
296 0 : EnableButtons();
297 0 : return 0;
298 : }
299 :
300 0 : IMPL_LINK( _SfxMacroTabPage, AssignDeleteHdl_Impl, PushButton*, pBtn )
301 : {
302 0 : SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
303 0 : SvTreeListEntry* pE = rListBox.FirstSelected();
304 : sal_uLong nPos;
305 0 : if( !pE || LISTBOX_ENTRY_NOTFOUND ==
306 0 : ( nPos = rListBox.GetModel()->GetAbsPos( pE ) ) )
307 : {
308 : DBG_ASSERT( pE, "wo kommt der leere Eintrag her?" );
309 0 : return 0;
310 : }
311 :
312 0 : const bool bAssEnabled = pBtn != mpImpl->pDeletePB && mpImpl->pAssignPB->IsEnabled();
313 :
314 : // remove from the table
315 0 : sal_uInt16 nEvent = (sal_uInt16)reinterpret_cast<sal_uLong>(pE->GetUserData());
316 0 : aTbl.Erase( nEvent );
317 :
318 0 : OUString sScriptURI;
319 0 : if( bAssEnabled )
320 : {
321 0 : sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI();
322 0 : if( sScriptURI.startsWith( "vnd.sun.star.script:" ) )
323 : {
324 : aTbl.Insert(
325 0 : nEvent, SvxMacro( sScriptURI, OUString( SVX_MACRO_LANGUAGE_SF ) ) );
326 : }
327 : else
328 : {
329 : OSL_ENSURE( false, "_SfxMacroTabPage::AssignDeleteHdl_Impl: this branch is *not* dead? (out of interest: tell fs, please!)" );
330 : aTbl.Insert(
331 0 : nEvent, SvxMacro( sScriptURI, OUString( SVX_MACRO_LANGUAGE_STARBASIC ) ) );
332 : }
333 : }
334 :
335 0 : mpImpl->pEventLB->SetUpdateMode( false );
336 0 : pE->ReplaceItem( new SvLBoxString( pE, 0, sScriptURI ), LB_MACROS_ITEMPOS );
337 0 : rListBox.GetModel()->InvalidateEntry( pE );
338 0 : rListBox.Select( pE );
339 0 : rListBox.MakeVisible( pE );
340 0 : rListBox.SetUpdateMode( true );
341 :
342 0 : EnableButtons();
343 0 : return 0;
344 : }
345 :
346 0 : IMPL_LINK_TYPED( _SfxMacroTabPage, TimeOut_Impl, Idle*,, void )
347 : {
348 : // FillMacroList() can take a long time -> show wait cursor and disable input
349 0 : SfxTabDialog* pTabDlg = GetTabDialog();
350 : // perhaps the tabpage is part of a SingleTabDialog then pTabDlg == NULL
351 0 : if ( pTabDlg )
352 : {
353 0 : pTabDlg->EnterWait();
354 0 : pTabDlg->EnableInput( false );
355 : }
356 0 : FillMacroList();
357 0 : if ( pTabDlg )
358 : {
359 0 : pTabDlg->EnableInput( true );
360 0 : pTabDlg->LeaveWait();
361 : }
362 0 : }
363 :
364 0 : void _SfxMacroTabPage::InitAndSetHandler()
365 : {
366 0 : SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
367 0 : HeaderBar& rHeaderBar = mpImpl->pEventLB->GetHeaderBar();
368 0 : Link<> aLnk(LINK(this, _SfxMacroTabPage, AssignDeleteHdl_Impl ));
369 0 : mpImpl->pMacroLB->SetDoubleClickHdl( aLnk );
370 0 : mpImpl->pDeletePB->SetClickHdl( aLnk );
371 0 : mpImpl->pAssignPB->SetClickHdl( aLnk );
372 0 : rListBox.SetDoubleClickHdl( aLnk );
373 :
374 0 : rListBox.SetSelectHdl( LINK( this, _SfxMacroTabPage, SelectEvent_Impl ));
375 0 : mpImpl->pGroupLB->SetSelectHdl( LINK( this, _SfxMacroTabPage, SelectGroup_Impl ));
376 0 : mpImpl->pMacroLB->SetSelectHdl( LINK( this, _SfxMacroTabPage, SelectMacro_Impl ));
377 :
378 0 : rListBox.SetSelectionMode( SINGLE_SELECTION );
379 0 : rListBox.SetTabs( &nTabs[0], MAP_APPFONT );
380 0 : Size aSize( nTabs[ 2 ], 0 );
381 0 : rHeaderBar.InsertItem( ITEMID_EVENT, mpImpl->sStrEvent, LogicToPixel( aSize, MapMode( MAP_APPFONT ) ).Width() );
382 0 : aSize.Width() = 1764; // don't know what, so 42^2 is best to use...
383 0 : rHeaderBar.InsertItem( ITMEID_ASSMACRO, mpImpl->sAssignedMacro, LogicToPixel( aSize, MapMode( MAP_APPFONT ) ).Width() );
384 0 : rListBox.SetSpaceBetweenEntries( 0 );
385 :
386 0 : mpImpl->pEventLB->Show();
387 0 : mpImpl->pEventLB->ConnectElements();
388 :
389 0 : mpImpl->pEventLB->Enable( true );
390 0 : mpImpl->pGroupLB->Enable( true );
391 0 : mpImpl->pMacroLB->Enable( true );
392 :
393 0 : mpImpl->pGroupLB->SetFunctionListBox( mpImpl->pMacroLB );
394 :
395 0 : }
396 :
397 0 : void _SfxMacroTabPage::FillMacroList()
398 : {
399 : mpImpl->pGroupLB->Init(
400 : ::com::sun::star::uno::Reference<
401 : ::com::sun::star::uno::XComponentContext >(),
402 : GetFrame(),
403 0 : OUString(), false);
404 0 : }
405 :
406 0 : void _SfxMacroTabPage::FillEvents()
407 : {
408 0 : SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox();
409 :
410 0 : sal_uLong nEntryCnt = rListBox.GetEntryCount();
411 :
412 : // get events from the table and fill the EventListBox respectively
413 0 : for( sal_uLong n = 0 ; n < nEntryCnt ; ++n )
414 : {
415 0 : SvTreeListEntry* pE = rListBox.GetEntry( n );
416 0 : if( pE )
417 : {
418 0 : SvLBoxString* pLItem = static_cast<SvLBoxString*>( pE->GetItem( LB_MACROS_ITEMPOS ) );
419 : DBG_ASSERT( pLItem && SV_ITEM_ID_LBOXSTRING == pLItem->GetType(), "_SfxMacroTabPage::FillEvents(): no LBoxString" );
420 :
421 0 : OUString sOld( pLItem->GetText() );
422 0 : OUString sNew;
423 0 : sal_uInt16 nEventId = ( sal_uInt16 ) reinterpret_cast<sal_uLong>( pE->GetUserData() );
424 0 : if( aTbl.IsKeyValid( nEventId ) )
425 0 : sNew = ConvertToUIName_Impl( aTbl.Get( nEventId ) );
426 :
427 0 : if( sOld != sNew )
428 : {
429 0 : pE->ReplaceItem( new SvLBoxString( pE, 0, sNew ), LB_MACROS_ITEMPOS );
430 0 : rListBox.GetModel()->InvalidateEntry( pE );
431 0 : }
432 : }
433 : }
434 0 : }
435 :
436 0 : SfxMacroTabPage::SfxMacroTabPage(vcl::Window* pParent, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rSet )
437 0 : : _SfxMacroTabPage( pParent, rSet )
438 : {
439 0 : mpImpl->sStrEvent = get<FixedText>("eventft")->GetText();
440 0 : mpImpl->sAssignedMacro = get<FixedText>("assignft")->GetText();
441 0 : get(mpImpl->pEventLB , "assignments");
442 0 : get(mpImpl->pAssignPB, "assign");
443 0 : get(mpImpl->pDeletePB, "delete");
444 0 : get(mpImpl->pGroupFrame, "groupframe");
445 0 : get(mpImpl->pGroupLB, "libraries");
446 0 : get(mpImpl->pMacroFrame, "macroframe");
447 0 : mpImpl->maStaticMacroLBLabel = mpImpl->pMacroFrame->get_label();
448 0 : get(mpImpl->pMacroLB, "macros");
449 :
450 0 : SetFrame( rxDocumentFrame );
451 :
452 0 : InitAndSetHandler();
453 :
454 0 : ScriptChanged();
455 0 : }
456 :
457 : namespace
458 : {
459 0 : VclPtr<SfxMacroTabPage> CreateSfxMacroTabPage( vcl::Window* pParent, const SfxItemSet& rAttrSet )
460 : {
461 0 : return VclPtr<SfxMacroTabPage>::Create( pParent, nullptr, rAttrSet );
462 : }
463 : }
464 :
465 0 : VclPtr<SfxTabPage> SfxMacroTabPage::Create( vcl::Window* pParent, const SfxItemSet* rAttrSet )
466 : {
467 0 : return CreateSfxMacroTabPage(pParent, *rAttrSet);
468 : }
469 :
470 0 : SfxMacroAssignDlg::SfxMacroAssignDlg(vcl::Window* pParent,
471 : const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rSet)
472 : : SfxSingleTabDialog(pParent, rSet, "EventAssignDialog",
473 0 : "cui/ui/eventassigndialog.ui")
474 : {
475 0 : SfxMacroTabPage* pPage = CreateSfxMacroTabPage(get_content_area(), rSet);
476 0 : pPage->SetFrame( rxDocumentFrame );
477 0 : SetTabPage( pPage );
478 0 : pPage->LaunchFillGroup();
479 0 : }
480 :
481 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|