Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2008 by Sun Microsystems, Inc.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "macromgr.hxx"
30 : : #include "document.hxx"
31 : :
32 : : #include "basic/basmgr.hxx"
33 : : #include "cppuhelper/implbase1.hxx"
34 : : #include "sfx2/objsh.hxx"
35 : : #include "cell.hxx"
36 : : #include <com/sun/star/container/XContainer.hpp>
37 : :
38 : : #include <list>
39 : :
40 : : using namespace ::com::sun::star;
41 : : using ::com::sun::star::uno::RuntimeException;
42 : : using ::com::sun::star::uno::Reference;
43 : : using ::rtl::OUString;
44 : : using ::rtl::OUStringHash;
45 : : using ::boost::unordered_map;
46 : : using ::std::list;
47 : : using ::std::for_each;
48 : : using ::std::pair;
49 : :
50 : : // ============================================================================
51 : :
52 : : /**
53 : : * A simple container to keep track of cells that depend on basic modules
54 : : * changes. We don't check for duplicates at insertion time; instead, we
55 : : * remove duplicates at query time.
56 : : */
57 [ + - ]: 6 : class ScUserMacroDepTracker
58 : : {
59 : : public:
60 : 0 : void addCell(const OUString& rModuleName, ScFormulaCell* pCell)
61 : : {
62 [ # # ]: 0 : ModuleCellMap::iterator itr = maCells.find(rModuleName);
63 [ # # ][ # # ]: 0 : if (itr == maCells.end())
64 : : {
65 : : pair<ModuleCellMap::iterator, bool> r = maCells.insert(
66 [ # # ][ # # ]: 0 : ModuleCellMap::value_type(rModuleName, list<ScFormulaCell*>()));
67 : :
68 [ # # ]: 0 : if (!r.second)
69 : : // insertion failed.
70 : 0 : return;
71 : :
72 : 0 : itr = r.first;
73 : : }
74 [ # # ][ # # ]: 0 : itr->second.push_back(pCell);
75 : : }
76 : :
77 : 3 : void removeCell(ScFormulaCell* pCell)
78 : : {
79 [ + - ][ + - ]: 3 : ModuleCellMap::iterator itr = maCells.begin(), itrEnd = maCells.end();
80 [ - + ]: 3 : for (; itr != itrEnd; ++itr)
81 [ # # ][ # # ]: 0 : itr->second.remove(pCell);
82 : 3 : }
83 : :
84 : 0 : void getCellsByModule(const OUString& rModuleName, list<ScFormulaCell*>& rCells)
85 : : {
86 [ # # ]: 0 : ModuleCellMap::iterator itr = maCells.find(rModuleName);
87 [ # # ][ # # ]: 0 : if (itr == maCells.end())
88 : 0 : return;
89 : :
90 [ # # ]: 0 : list<ScFormulaCell*>& rCellList = itr->second;
91 : :
92 : : // Remove duplicates.
93 [ # # ]: 0 : rCellList.sort();
94 [ # # ]: 0 : rCellList.unique();
95 : : // exception safe copy
96 [ # # ]: 0 : list<ScFormulaCell*> temp(rCellList);
97 [ # # ]: 0 : rCells.swap(temp);
98 : : }
99 : :
100 : : private:
101 : : typedef boost::unordered_map<OUString, list<ScFormulaCell*>, OUStringHash> ModuleCellMap;
102 : : ModuleCellMap maCells;
103 : : };
104 : :
105 : :
106 : : // ============================================================================
107 : :
108 : 3 : ScMacroManager::ScMacroManager(ScDocument* pDoc) :
109 [ + - ]: 3 : mpDepTracker(new ScUserMacroDepTracker),
110 [ + - ][ + - ]: 6 : mpDoc(pDoc)
111 : : {
112 : 3 : }
113 : :
114 [ + - ]: 3 : ScMacroManager::~ScMacroManager()
115 : : {
116 : 3 : }
117 : :
118 : : typedef ::cppu::WeakImplHelper1< ::com::sun::star::container::XContainerListener > ContainerListenerHelper;
119 : :
120 [ # # ]: 0 : class VBAProjectListener : public ContainerListenerHelper
121 : : {
122 : : ScMacroManager* mpMacroMgr;
123 : : public:
124 : 0 : VBAProjectListener( ScMacroManager* pMacroMgr ) : mpMacroMgr( pMacroMgr ) {}
125 : : // XEventListener
126 : 0 : virtual void SAL_CALL disposing( const lang::EventObject& /*Source*/ ) throw(RuntimeException) {}
127 : :
128 : : // XContainerListener
129 : 0 : virtual void SAL_CALL elementInserted( const container::ContainerEvent& /*Event*/ ) throw(RuntimeException){}
130 : 0 : virtual void SAL_CALL elementReplaced( const container::ContainerEvent& Event ) throw(RuntimeException)
131 : : {
132 : 0 : rtl::OUString sModuleName;
133 : 0 : Event.Accessor >>= sModuleName;
134 : : OSL_TRACE("VBAProjectListener::elementReplaced(%s)", rtl::OUStringToOString( sModuleName, RTL_TEXTENCODING_UTF8 ).getStr() );
135 [ # # ]: 0 : mpMacroMgr->InitUserFuncData();
136 [ # # ]: 0 : mpMacroMgr->BroadcastModuleUpdate(sModuleName);
137 : 0 : }
138 : 0 : virtual void SAL_CALL elementRemoved( const container::ContainerEvent& /*Event*/ ) throw(RuntimeException){}
139 : :
140 : : };
141 : :
142 : 0 : void ScMacroManager::InitUserFuncData()
143 : : {
144 : : // Clear boost::unordered_map
145 [ # # ]: 0 : mhFuncToVolatile.clear();
146 [ # # ]: 0 : String sProjectName( RTL_CONSTASCII_USTRINGPARAM("Standard") );
147 : :
148 : 0 : Reference< container::XContainer > xModuleContainer;
149 : 0 : SfxObjectShell* pShell = mpDoc->GetDocumentShell();
150 [ # # ][ # # ]: 0 : if ( pShell && pShell->GetBasicManager()->GetName().Len() > 0 )
[ # # ][ # # ]
[ # # ]
[ # # # # ]
[ # # ]
151 [ # # ][ # # ]: 0 : sProjectName = pShell->GetBasicManager()->GetName();
[ # # ][ # # ]
152 : : try
153 : : {
154 [ # # ][ # # ]: 0 : Reference< script::XLibraryContainer > xLibraries( pShell->GetBasicContainer(), uno::UNO_QUERY_THROW );
155 [ # # ][ # # ]: 0 : xModuleContainer.set( xLibraries->getByName( sProjectName ), uno::UNO_QUERY_THROW );
[ # # ][ # # ]
156 : :
157 [ # # ]: 0 : if ( xModuleContainer.is() )
158 : : {
159 : : // remove old listener ( if there was one )
160 [ # # ]: 0 : if ( mxContainerListener.is() )
161 [ # # ][ # # ]: 0 : xModuleContainer->removeContainerListener( mxContainerListener );
162 : : // Create listener
163 [ # # ][ # # ]: 0 : mxContainerListener = new VBAProjectListener( this );
[ # # ]
164 [ # # ][ # # ]: 0 : xModuleContainer->addContainerListener( mxContainerListener );
165 [ # # ]: 0 : }
166 : : }
167 [ # # ]: 0 : catch( uno::Exception& )
168 : : {
169 [ # # ]: 0 : }
170 : 0 : }
171 : :
172 : 0 : void ScMacroManager::SetUserFuncVolatile( const OUString& sName, bool isVolatile )
173 : : {
174 : 0 : mhFuncToVolatile[ sName ] = isVolatile;
175 : 0 : }
176 : :
177 : 0 : bool ScMacroManager::GetUserFuncVolatile( const OUString& sName )
178 : : {
179 [ # # ]: 0 : NameBoolMap::iterator it = mhFuncToVolatile.find( sName );
180 [ # # ][ # # ]: 0 : if ( it == mhFuncToVolatile.end() )
181 : 0 : return false;
182 [ # # ]: 0 : return it->second;
183 : : }
184 : :
185 : 0 : void ScMacroManager::AddDependentCell(const OUString& aModuleName, ScFormulaCell* pCell)
186 : : {
187 : 0 : mpDepTracker->addCell(aModuleName, pCell);
188 : 0 : }
189 : :
190 : 3 : void ScMacroManager::RemoveDependentCell(ScFormulaCell* pCell)
191 : : {
192 : 3 : mpDepTracker->removeCell(pCell);
193 : 3 : }
194 : :
195 : 0 : void ScMacroManager::BroadcastModuleUpdate(const OUString& aModuleName)
196 : : {
197 [ # # ]: 0 : list<ScFormulaCell*> aCells;
198 [ # # ]: 0 : mpDepTracker->getCellsByModule(aModuleName, aCells);
199 : 0 : list<ScFormulaCell*>::iterator itr = aCells.begin(), itrEnd = aCells.end();
200 [ # # ][ # # ]: 0 : for (; itr != itrEnd; ++itr)
[ # # ]
201 : : {
202 [ # # ]: 0 : ScFormulaCell* pCell = *itr;
203 [ # # ]: 0 : mpDoc->PutInFormulaTree(pCell); // for F9 recalc
204 : :
205 : : // for recalc on cell value change. If the cell is not volatile, the
206 : : // cell stops listening right away after it gets re-interpreted.
207 [ # # ]: 0 : mpDoc->StartListeningArea(BCA_LISTEN_ALWAYS, pCell);
208 : 0 : }
209 : 0 : }
210 : :
211 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|