diff options
Diffstat (limited to 'cui/source/tabpages/macroass.cxx')
-rw-r--r-- | cui/source/tabpages/macroass.cxx | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx new file mode 100644 index 000000000..e80e471ff --- /dev/null +++ b/cui/source/tabpages/macroass.cxx @@ -0,0 +1,397 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <macroass.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <osl/diagnose.h> +#include <comphelper/string.hxx> +#include <comphelper/processfactory.hxx> +#include <svl/macitem.hxx> +#include <svx/svxids.hrc> +#include <tools/debug.hxx> +#include <vcl/idle.hxx> +#include <cfgutil.hxx> +#include <sfx2/evntconf.hxx> +#include <headertablistbox.hxx> + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::frame::XFrame; + +class SfxMacroTabPage_Impl +{ +public: + SfxMacroTabPage_Impl(); + + OUString m_aStaticMacroLBLabel; + std::unique_ptr<weld::Button> m_xAssignPB; + std::unique_ptr<weld::Button> m_xDeletePB; + std::unique_ptr<MacroEventListBox> m_xEventLB; + std::unique_ptr<weld::Widget> m_xGroupFrame; + std::unique_ptr<CuiConfigGroupListBox> m_xGroupLB; + std::unique_ptr<weld::Frame> m_xMacroFrame; + std::unique_ptr<CuiConfigFunctionListBox> m_xMacroLB; + + Idle m_aFillGroupIdle { "cui SfxMacroTabPage m_aFillGroupIdle" }; + bool m_bGotEvents; +}; + +SfxMacroTabPage_Impl::SfxMacroTabPage_Impl() + : m_bGotEvents(false) +{ +} + +static sal_uInt16 aPageRg[] = { + SID_ATTR_MACROITEM, SID_ATTR_MACROITEM, + 0 +}; + +static OUString ConvertToUIName_Impl( SvxMacro const *pMacro ) +{ + OUString aName( pMacro->GetMacName() ); + if ( pMacro->GetLanguage() != "JavaScript" ) + { + const sal_Int32 nCount = comphelper::string::getTokenCount(aName, '.'); + OUString aEntry = aName.getToken( nCount-1, '.' ); + if ( nCount > 2 ) + { + aEntry += OUString::Concat("(") + o3tl::getToken(aName, 0, '.' ) + "." + o3tl::getToken(aName, nCount-2, '.' ) + ")"; + } + return aEntry; + } + else + return aName; +} + +void SfxMacroTabPage::EnableButtons() +{ + // don't do anything as long as the eventbox is empty + weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rTreeView.get_selected_index(); + if (nSelected != -1) + { + // get bound macro + const SvxMacro* pM = aTbl.Get(static_cast<SvMacroItemId>(rTreeView.get_selected_id().toInt32())); + mpImpl->m_xDeletePB->set_sensitive(nullptr != pM); + + OUString sEventMacro = rTreeView.get_text(nSelected, 1); + + OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + mpImpl->m_xAssignPB->set_sensitive(!sScriptURI.equalsIgnoreAsciiCase(sEventMacro)); + } + else + mpImpl->m_xAssignPB->set_sensitive(false); +} + +SfxMacroTabPage::SfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rAttrSet ) + : SfxTabPage(pPage, pController, "cui/ui/eventassignpage.ui", "EventAssignPage", &rAttrSet) +{ + mpImpl.reset(new SfxMacroTabPage_Impl); + + mpImpl->m_aFillGroupIdle.SetInvokeHandler( LINK( this, SfxMacroTabPage, TimeOut_Impl ) ); + mpImpl->m_aFillGroupIdle.SetPriority( TaskPriority::HIGHEST ); + + mpImpl->m_xEventLB.reset(new MacroEventListBox(m_xBuilder->weld_tree_view("assignments"))); + mpImpl->m_xAssignPB = m_xBuilder->weld_button("assign"); + mpImpl->m_xDeletePB = m_xBuilder->weld_button("delete"); + mpImpl->m_xGroupFrame = m_xBuilder->weld_widget("groupframe"); + mpImpl->m_xGroupLB.reset(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view("libraries"))); + mpImpl->m_xMacroFrame = m_xBuilder->weld_frame("macroframe"); + mpImpl->m_aStaticMacroLBLabel = mpImpl->m_xMacroFrame->get_label(); + mpImpl->m_xMacroLB.reset(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("macros"))); + + SetFrame( rxDocumentFrame ); + + InitAndSetHandler(); + + ScriptChanged(); +} + +SfxMacroTabPage::~SfxMacroTabPage() +{ + mpImpl.reset(); +} + +void SfxMacroTabPage::AddEvent(const OUString& rEventName, SvMacroItemId nEventId) +{ + weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox(); + rTreeView.append(OUString::number(static_cast<sal_Int32>(nEventId)), rEventName); + + // if the table is valid already + SvxMacro* pM = aTbl.Get(nEventId); + if (pM) + { + OUString sNew(ConvertToUIName_Impl(pM)); + rTreeView.set_text(rTreeView.n_children() - 1, sNew, 1); + } +} + +void SfxMacroTabPage::ScriptChanged() +{ + // get new areas and their functions + mpImpl->m_xGroupFrame->show(); + mpImpl->m_xMacroFrame->show(); + + EnableButtons(); +} + +bool SfxMacroTabPage::FillItemSet( SfxItemSet* rSet ) +{ + SvxMacroItem aItem( GetWhich( aPageRg[0] ) ); + const_cast<SvxMacroTableDtor&>(aItem.GetMacroTable()) = aTbl; + + const SfxPoolItem* pItem = nullptr; + SfxItemState eState = GetItemSet().GetItemState(aItem.Which(), true, &pItem); + if (eState == SfxItemState::DEFAULT && aTbl.empty()) + { + // Don't touch the item set if there was no input and our table is empty. + return false; + } + if (SfxItemState::SET != eState || aItem != *static_cast<const SvxMacroItem*>(pItem)) + { + rSet->Put( aItem ); + return true; + } + return false; +} + +void SfxMacroTabPage::LaunchFillGroup() +{ + if (! mpImpl->m_aFillGroupIdle.IsActive() ) + mpImpl->m_aFillGroupIdle.Start(); +} + +void SfxMacroTabPage::ActivatePage( const SfxItemSet& ) +{ + LaunchFillGroup(); +} + +void SfxMacroTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + if( mpImpl->m_bGotEvents ) + return; + if( const SfxEventNamesItem* pEventsItem = aSet.GetItemIfSet( SID_EVENTCONFIG ) ) + { + mpImpl->m_bGotEvents = true; + const SfxEventNamesList& rList = pEventsItem->GetEvents(); + for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo ) + { + const SfxEventName &rOwn = rList.at(nNo); + AddEvent( rOwn.maUIName, rOwn.mnId ); + } + } +} + +void SfxMacroTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + if( SfxItemState::SET == rSet->GetItemState( GetWhich( aPageRg[0] ), true, &pItem )) + aTbl = static_cast<const SvxMacroItem*>(pItem)->GetMacroTable(); + + const SfxEventNamesItem* pEventsItem; + if( !mpImpl->m_bGotEvents && (pEventsItem = rSet->GetItemIfSet( SID_EVENTCONFIG ) ) ) + { + mpImpl->m_bGotEvents = true; + const SfxEventNamesList& rList = pEventsItem->GetEvents(); + for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo ) + { + const SfxEventName &rOwn = rList.at(nNo); + AddEvent( rOwn.maUIName, rOwn.mnId ); + } + } + + FillEvents(); + + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + std::unique_ptr<weld::TreeIter> xIter(rListBox.make_iterator()); + if (rListBox.get_iter_first(*xIter)) + rListBox.set_cursor(*xIter); +} + +bool SfxMacroTabPage::IsReadOnly() const +{ + return false; +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectEvent_Impl, weld::TreeView&, void) +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rListBox.get_selected_index(); + if (nSelected == -1) + { + DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?"); + return; + } + + ScriptChanged(); + EnableButtons(); +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectGroup_Impl, weld::TreeView&, void) +{ + mpImpl->m_xGroupLB->GroupSelected(); + const OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + OUString aLabelText; + if( !sScriptURI.isEmpty() ) + aLabelText = mpImpl->m_aStaticMacroLBLabel; + mpImpl->m_xMacroFrame->set_label( aLabelText ); + + EnableButtons(); +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectMacro_Impl, weld::TreeView&, void) +{ + EnableButtons(); +} + +IMPL_LINK(SfxMacroTabPage, AssignDeleteClickHdl_Impl, weld::Button&, rBtn, void) +{ + AssignDeleteHdl(&rBtn); +} + +IMPL_LINK(SfxMacroTabPage, AssignDeleteHdl_Impl, weld::TreeView&, rBtn, bool) +{ + AssignDeleteHdl(&rBtn); + return true; +} + +void SfxMacroTabPage::AssignDeleteHdl(const weld::Widget* pBtn) +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rListBox.get_selected_index(); + if (nSelected == -1) + { + DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?"); + return; + } + + const bool bAssEnabled = pBtn != mpImpl->m_xDeletePB.get() && mpImpl->m_xAssignPB->get_sensitive(); + + // remove from the table + SvMacroItemId nEvent = static_cast<SvMacroItemId>(rListBox.get_selected_id().toInt32()); + aTbl.Erase( nEvent ); + + OUString sScriptURI; + if( bAssEnabled ) + { + sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + if( sScriptURI.startsWith( "vnd.sun.star.script:" ) ) + { + aTbl.Insert( + nEvent, SvxMacro( sScriptURI, SVX_MACRO_LANGUAGE_SF ) ); + } + else + { + OSL_ENSURE( false, "SfxMacroTabPage::AssignDeleteHdl_Impl: this branch is *not* dead? (out of interest: tell fs, please!)" ); + aTbl.Insert( + nEvent, SvxMacro( sScriptURI, SVX_MACRO_LANGUAGE_STARBASIC ) ); + } + } + + rListBox.set_text(nSelected, sScriptURI, 1); + + EnableButtons(); +} + +IMPL_LINK( SfxMacroTabPage, TimeOut_Impl, Timer*,, void ) +{ + // FillMacroList() can take a long time -> show wait cursor and disable input + weld::Window* pDialog = GetFrameWeld(); + // perhaps the tabpage is part of a SingleTabDialog then pDialog == nullptr + std::unique_ptr<weld::WaitObject> xWait(pDialog ? new weld::WaitObject(pDialog) : nullptr); + // fill macro list + mpImpl->m_xGroupLB->Init(comphelper::getProcessComponentContext(), GetFrame(), + OUString(), false); +} + +void SfxMacroTabPage::InitAndSetHandler() +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + Link<weld::TreeView&,bool> aLnk(LINK(this, SfxMacroTabPage, AssignDeleteHdl_Impl)); + mpImpl->m_xMacroLB->connect_row_activated( aLnk); + mpImpl->m_xDeletePB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl)); + mpImpl->m_xAssignPB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl)); + rListBox.connect_row_activated(aLnk); + + rListBox.connect_changed(LINK(this, SfxMacroTabPage, SelectEvent_Impl)); + mpImpl->m_xGroupLB->connect_changed(LINK(this, SfxMacroTabPage, SelectGroup_Impl)); + mpImpl->m_xMacroLB->connect_changed(LINK(this, SfxMacroTabPage, SelectMacro_Impl)); + + std::vector<int> aWidths + { + o3tl::narrowing<int>(rListBox.get_approximate_digit_width() * 35) + }; + rListBox.set_column_fixed_widths(aWidths); + + mpImpl->m_xEventLB->show(); + + mpImpl->m_xEventLB->set_sensitive(true); + mpImpl->m_xGroupLB->set_sensitive(true); + mpImpl->m_xMacroLB->set_sensitive(true); + + mpImpl->m_xGroupLB->SetFunctionListBox(mpImpl->m_xMacroLB.get()); +} + +void SfxMacroTabPage::FillEvents() +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + + int nEntryCnt = rListBox.n_children(); + + // get events from the table and fill the EventListBox respectively + for (int n = 0 ; n < nEntryCnt; ++n) + { + OUString sOld = rListBox.get_text(n, 1); + OUString sNew; + SvMacroItemId nEventId = static_cast<SvMacroItemId>(rListBox.get_id(n).toInt32()); + if (aTbl.IsKeyValid(nEventId)) + sNew = ConvertToUIName_Impl(aTbl.Get(nEventId)); + + if (sOld == sNew) + continue; + + rListBox.set_text(n, sNew, 1); + } +} + +namespace +{ + std::unique_ptr<SfxMacroTabPage> CreateSfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet) + { + return std::make_unique<SfxMacroTabPage>( pPage, pController, nullptr, rAttrSet ); + } +} + +std::unique_ptr<SfxTabPage> SfxMacroTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return CreateSfxMacroTabPage(pPage, pController, *rAttrSet); +} + +SfxMacroAssignDlg::SfxMacroAssignDlg(weld::Widget* pParent, + const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rSet) + : SfxSingleTabDialogController(pParent, &rSet,"cui/ui/eventassigndialog.ui", + "EventAssignDialog") +{ + std::unique_ptr<SfxMacroTabPage> xPage = CreateSfxMacroTabPage(get_content_area(), this, rSet); + xPage->SetFrame(rxDocumentFrame); + SetTabPage(std::move(xPage)); + GetTabPage()->LaunchFillGroup(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |