Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / docshell / macromgr.cxx
blob8c64ee7308a5c1116231b5d3025679766bf46888
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 "macromgr.hxx"
21 #include "document.hxx"
23 #include "basic/basmgr.hxx"
24 #include "cppuhelper/implbase1.hxx"
25 #include "sfx2/objsh.hxx"
26 #include "formulacell.hxx"
27 #include <com/sun/star/container/XContainer.hpp>
29 #include <list>
31 using namespace ::com::sun::star;
32 using ::com::sun::star::uno::RuntimeException;
33 using ::com::sun::star::uno::Reference;
34 using ::boost::unordered_map;
35 using ::std::list;
36 using ::std::for_each;
37 using ::std::pair;
39 // ============================================================================
41 /**
42 * A simple container to keep track of cells that depend on basic modules
43 * changes. We don't check for duplicates at insertion time; instead, we
44 * remove duplicates at query time.
46 class ScUserMacroDepTracker
48 public:
49 void addCell(const OUString& rModuleName, ScFormulaCell* pCell)
51 ModuleCellMap::iterator itr = maCells.find(rModuleName);
52 if (itr == maCells.end())
54 pair<ModuleCellMap::iterator, bool> r = maCells.insert(
55 ModuleCellMap::value_type(rModuleName, list<ScFormulaCell*>()));
57 if (!r.second)
58 // insertion failed.
59 return;
61 itr = r.first;
63 itr->second.push_back(pCell);
66 void removeCell(ScFormulaCell* pCell)
68 ModuleCellMap::iterator itr = maCells.begin(), itrEnd = maCells.end();
69 for (; itr != itrEnd; ++itr)
70 itr->second.remove(pCell);
73 void getCellsByModule(const OUString& rModuleName, list<ScFormulaCell*>& rCells)
75 ModuleCellMap::iterator itr = maCells.find(rModuleName);
76 if (itr == maCells.end())
77 return;
79 list<ScFormulaCell*>& rCellList = itr->second;
81 // Remove duplicates.
82 rCellList.sort();
83 rCellList.unique();
84 // exception safe copy
85 list<ScFormulaCell*> temp(rCellList);
86 rCells.swap(temp);
89 private:
90 typedef boost::unordered_map<OUString, list<ScFormulaCell*>, OUStringHash> ModuleCellMap;
91 ModuleCellMap maCells;
95 // ============================================================================
97 ScMacroManager::ScMacroManager(ScDocument* pDoc) :
98 mpDepTracker(new ScUserMacroDepTracker),
99 mpDoc(pDoc)
103 ScMacroManager::~ScMacroManager()
107 typedef ::cppu::WeakImplHelper1< ::com::sun::star::container::XContainerListener > ContainerListenerHelper;
109 class VBAProjectListener : public ContainerListenerHelper
111 ScMacroManager* mpMacroMgr;
112 public:
113 VBAProjectListener( ScMacroManager* pMacroMgr ) : mpMacroMgr( pMacroMgr ) {}
114 // XEventListener
115 virtual void SAL_CALL disposing( const lang::EventObject& /*Source*/ ) throw(RuntimeException) {}
117 // XContainerListener
118 virtual void SAL_CALL elementInserted( const container::ContainerEvent& /*Event*/ ) throw(RuntimeException){}
119 virtual void SAL_CALL elementReplaced( const container::ContainerEvent& Event ) throw(RuntimeException)
121 OUString sModuleName;
122 Event.Accessor >>= sModuleName;
123 OSL_TRACE("VBAProjectListener::elementReplaced(%s)", OUStringToOString( sModuleName, RTL_TEXTENCODING_UTF8 ).getStr() );
124 mpMacroMgr->InitUserFuncData();
125 mpMacroMgr->BroadcastModuleUpdate(sModuleName);
127 virtual void SAL_CALL elementRemoved( const container::ContainerEvent& /*Event*/ ) throw(RuntimeException){}
131 void ScMacroManager::InitUserFuncData()
133 // Clear boost::unordered_map
134 mhFuncToVolatile.clear();
135 OUString sProjectName("Standard");
137 Reference< container::XContainer > xModuleContainer;
138 SfxObjectShell* pShell = mpDoc->GetDocumentShell();
139 if (pShell && !pShell->GetBasicManager()->GetName().isEmpty())
141 sProjectName = pShell->GetBasicManager()->GetName();
145 Reference< script::XLibraryContainer > xLibraries( pShell->GetBasicContainer(), uno::UNO_QUERY_THROW );
146 xModuleContainer.set( xLibraries->getByName( sProjectName ), uno::UNO_QUERY_THROW );
148 if ( xModuleContainer.is() )
150 // remove old listener ( if there was one )
151 if ( mxContainerListener.is() )
152 xModuleContainer->removeContainerListener( mxContainerListener );
153 // Create listener
154 mxContainerListener = new VBAProjectListener( this );
155 xModuleContainer->addContainerListener( mxContainerListener );
158 catch( uno::Exception& )
163 void ScMacroManager::SetUserFuncVolatile( const OUString& sName, bool isVolatile )
165 mhFuncToVolatile[ sName ] = isVolatile;
168 bool ScMacroManager::GetUserFuncVolatile( const OUString& sName )
170 NameBoolMap::iterator it = mhFuncToVolatile.find( sName );
171 if ( it == mhFuncToVolatile.end() )
172 return false;
173 return it->second;
176 void ScMacroManager::AddDependentCell(const OUString& aModuleName, ScFormulaCell* pCell)
178 mpDepTracker->addCell(aModuleName, pCell);
181 void ScMacroManager::RemoveDependentCell(ScFormulaCell* pCell)
183 mpDepTracker->removeCell(pCell);
186 void ScMacroManager::BroadcastModuleUpdate(const OUString& aModuleName)
188 list<ScFormulaCell*> aCells;
189 mpDepTracker->getCellsByModule(aModuleName, aCells);
190 list<ScFormulaCell*>::iterator itr = aCells.begin(), itrEnd = aCells.end();
191 for (; itr != itrEnd; ++itr)
193 ScFormulaCell* pCell = *itr;
194 mpDoc->PutInFormulaTree(pCell); // for F9 recalc
196 // for recalc on cell value change. If the cell is not volatile, the
197 // cell stops listening right away after it gets re-interpreted.
198 mpDoc->StartListeningArea(BCA_LISTEN_ALWAYS, pCell);
202 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */