/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include using ::com::sun::star::uno::Reference; using ::com::sun::star::frame::XFrame; class SfxMacroTabPage_Impl { public: SfxMacroTabPage_Impl(); OUString m_aStaticMacroLBLabel; std::unique_ptr m_xAssignPB; std::unique_ptr m_xDeletePB; std::unique_ptr m_xEventLB; std::unique_ptr m_xGroupFrame; std::unique_ptr m_xGroupLB; std::unique_ptr m_xMacroFrame; std::unique_ptr 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(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(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(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(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(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 xIter(rListBox.make_iterator()); if (rListBox.get_iter_first(*xIter)) { rListBox.set_cursor(*xIter); EnableButtons(); } } 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(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 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 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 aWidths { o3tl::narrowing(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(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 CreateSfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet) { return std::make_unique( pPage, pController, nullptr, rAttrSet ); } } std::unique_ptr 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 xPage = CreateSfxMacroTabPage(get_content_area(), this, rSet); xPage->SetFrame(rxDocumentFrame); SetTabPage(std::move(xPage)); GetTabPage()->LaunchFillGroup(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */