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
10 #include <memory>
11 #include <com/sun/star/embed/Aspects.hpp>
12 #include <com/sun/star/embed/XEmbeddedObject.hpp>
13 #include <com/sun/star/awt/Size.hpp>
14 #include <com/sun/star/chart/ChartDataRowSource.hpp>
15 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
16 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
17
18 #include <tools/gen.hxx>
19 #include <svx/svdoole2.hxx>
20 #include <svx/svdpage.hxx>
21 #include <svx/svdundo.hxx>
22 #include <unotools/moduleoptions.hxx>
23 #include <comphelper/propertysequence.hxx>
24 #include <comphelper/classids.hxx>
25 #include <toolkit/helper/vclunohelper.hxx>
26 #include <tools/globname.hxx>
27 #include <svtools/embedhlp.hxx>
28 #include <comphelper/sequence.hxx>
29 #include <vcl/svapp.hxx>
30
31 #include <TablePivotChart.hxx>
32 #include <TablePivotCharts.hxx>
33 #include <PivotTableDataProvider.hxx>
34 #include <ChartTools.hxx>
35
36 #include <miscuno.hxx>
37 #include <docsh.hxx>
38 #include <drwlayer.hxx>
39
40 using namespace css;
41
42 namespace sc
43 {
44
45 SC_SIMPLE_SERVICE_INFO(TablePivotCharts, "TablePivotCharts", "com.sun.star.table.TablePivotCharts")
46
TablePivotCharts(ScDocShell * pDocShell,SCTAB nTab)47 TablePivotCharts::TablePivotCharts(ScDocShell* pDocShell, SCTAB nTab)
48 : m_pDocShell(pDocShell)
49 , m_nTab(nTab)
50 {
51 m_pDocShell->GetDocument().AddUnoObject(*this);
52 }
53
~TablePivotCharts()54 TablePivotCharts::~TablePivotCharts()
55 {
56 SolarMutexGuard aGuard;
57
58 if (m_pDocShell)
59 m_pDocShell->GetDocument().RemoveUnoObject(*this);
60 }
61
Notify(SfxBroadcaster &,const SfxHint & rHint)62 void TablePivotCharts::Notify(SfxBroadcaster& /*rBroadcaster*/, const SfxHint& rHint)
63 {
64 if (rHint.GetId() == SfxHintId::Dying)
65 m_pDocShell = nullptr;
66 }
67
68 // XTablePivotCharts
addNewByName(OUString const & rName,const awt::Rectangle & aRect,OUString const & rDataPilotName)69 void SAL_CALL TablePivotCharts::addNewByName(OUString const & rName,
70 const awt::Rectangle& aRect,
71 OUString const & rDataPilotName)
72 {
73 SolarMutexGuard aGuard;
74
75 if (!m_pDocShell)
76 return;
77
78 ScDocument& rDoc = m_pDocShell->GetDocument();
79 ScDrawLayer* pModel = m_pDocShell->MakeDrawLayer();
80 SdrPage* pPage = pModel->GetPage(sal_uInt16(m_nTab));
81 if (!pPage)
82 return;
83
84 // chart can't be inserted if any ole object with that name exists on any table
85 // (empty string: generate valid name)
86
87 OUString aName = rName;
88 SCTAB nDummy;
89 if (!aName.isEmpty() && pModel->GetNamedObject(aName, OBJ_OLE2, nDummy))
90 {
91 // object exists - only RuntimeException is specified
92 throw uno::RuntimeException();
93 }
94
95 uno::Reference<embed::XEmbeddedObject> xObject;
96
97 if (SvtModuleOptions().IsChart())
98 xObject = m_pDocShell->GetEmbeddedObjectContainer().CreateEmbeddedObject(SvGlobalName(SO3_SCH_CLASSID).GetByteSequence(), aName);
99
100 if (!xObject.is())
101 return;
102
103 Point aRectPos(aRect.X, aRect.Y);
104 bool bLayoutRTL = rDoc.IsLayoutRTL(m_nTab);
105 if ((aRectPos.X() < 0 && !bLayoutRTL) || (aRectPos.X() > 0 && bLayoutRTL))
106 aRectPos.setX( 0 );
107
108 if (aRectPos.Y() < 0)
109 aRectPos.setY( 0 );
110
111 Size aRectSize(aRect.Width, aRect.Height);
112 if (aRectSize.Width() <= 0)
113 aRectSize.setWidth( 5000 ); // default size
114
115 if (aRectSize.Height() <= 0)
116 aRectSize.setHeight( 5000 );
117
118 ::tools::Rectangle aInsRect(aRectPos, aRectSize);
119
120 sal_Int64 nAspect(embed::Aspects::MSOLE_CONTENT);
121 MapUnit aMapUnit(VCLUnoHelper::UnoEmbed2VCLMapUnit(xObject->getMapUnit(nAspect)));
122 Size aSize(aInsRect.GetSize());
123 aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(aMapUnit));
124 awt::Size aAwtSize;
125 aAwtSize.Width = aSize.Width();
126 aAwtSize.Height = aSize.Height();
127
128 rtl::Reference<sc::PivotTableDataProvider> pPivotTableDataProvider(new sc::PivotTableDataProvider(rDoc));
129 pPivotTableDataProvider->setPivotTableName(rDataPilotName);
130
131 uno::Reference<chart2::data::XDataProvider> xDataProvider(pPivotTableDataProvider);
132
133 uno::Reference<chart2::data::XDataReceiver> xReceiver;
134
135 if (xObject.is())
136 xReceiver.set(xObject->getComponent(), uno::UNO_QUERY);
137
138 if (xReceiver.is())
139 {
140 xReceiver->attachDataProvider(xDataProvider);
141
142 uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(m_pDocShell->GetModel(), uno::UNO_QUERY);
143 xReceiver->attachNumberFormatsSupplier(xNumberFormatsSupplier);
144
145 uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({
146 { "CellRangeRepresentation", uno::makeAny(rDataPilotName) },
147 { "HasCategories", uno::makeAny(true) },
148 { "DataRowSource", uno::makeAny(chart::ChartDataRowSource_COLUMNS) }
149 }));
150 xReceiver->setArguments(aArgs);
151 }
152
153 SdrOle2Obj* pObject = new SdrOle2Obj(
154 *pModel,
155 svt::EmbeddedObjectRef(xObject, embed::Aspects::MSOLE_CONTENT),
156 aName,
157 aInsRect);
158
159 if (xObject.is())
160 xObject->setVisualAreaSize(nAspect, aAwtSize);
161
162 pPage->InsertObject(pObject);
163 pModel->AddUndo(std::make_unique<SdrUndoInsertObj>(*pObject));
164 }
165
removeByName(const OUString & rName)166 void SAL_CALL TablePivotCharts::removeByName(const OUString& rName)
167 {
168 SolarMutexGuard aGuard;
169 SdrOle2Obj* pObject = sc::tools::findChartsByName(m_pDocShell, m_nTab, rName, sc::tools::ChartSourceType::PIVOT_TABLE);
170 if (pObject)
171 {
172 ScDocument& rDoc = m_pDocShell->GetDocument();
173 ScDrawLayer* pModel = rDoc.GetDrawLayer();
174 SdrPage* pPage = pModel->GetPage(sal_uInt16(m_nTab));
175 pModel->AddUndo(std::make_unique<SdrUndoDelObj>(*pObject));
176 pPage->RemoveObject(pObject->GetOrdNum());
177 }
178 }
179
180 // XIndexAccess
getCount()181 sal_Int32 SAL_CALL TablePivotCharts::getCount()
182 {
183 SolarMutexGuard aGuard;
184 sal_Int32 nCount = 0;
185
186 if (!m_pDocShell)
187 return nCount;
188
189 sc::tools::ChartIterator aIterator(m_pDocShell, m_nTab, sc::tools::ChartSourceType::PIVOT_TABLE);
190
191 SdrOle2Obj* pOleObject = aIterator.next();
192 while (pOleObject)
193 {
194 if (pOleObject->GetObjRef().is())
195 nCount++;
196 pOleObject = aIterator.next();
197 }
198 return nCount;
199 }
200
getByIndex(sal_Int32 nIndex)201 uno::Any SAL_CALL TablePivotCharts::getByIndex(sal_Int32 nIndex)
202 {
203 SolarMutexGuard aGuard;
204 SdrOle2Obj* pObject = sc::tools::getChartByIndex(m_pDocShell, m_nTab, nIndex,
205 sc::tools::ChartSourceType::PIVOT_TABLE);
206 if (!pObject)
207 throw lang::IndexOutOfBoundsException();
208
209 OUString aName;
210 uno::Reference<embed::XEmbeddedObject> xObject = pObject->GetObjRef();
211 if (xObject.is())
212 aName = m_pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName(xObject);
213
214 if (aName.isEmpty())
215 throw lang::IndexOutOfBoundsException();
216
217 uno::Reference<table::XTablePivotChart> xChart(new TablePivotChart(m_pDocShell, m_nTab, aName));
218 if (!xChart.is())
219 throw lang::IndexOutOfBoundsException();
220
221 return uno::makeAny(xChart);
222 }
223
getElementType()224 uno::Type SAL_CALL TablePivotCharts::getElementType()
225 {
226 SolarMutexGuard aGuard;
227 return cppu::UnoType<table::XTablePivotChart>::get();
228 }
229
hasElements()230 sal_Bool SAL_CALL TablePivotCharts::hasElements()
231 {
232 SolarMutexGuard aGuard;
233 return getCount() != 0;
234 }
235
getByName(OUString const & rName)236 uno::Any SAL_CALL TablePivotCharts::getByName(OUString const & rName)
237 {
238 SolarMutexGuard aGuard;
239
240 if (!sc::tools::findChartsByName(m_pDocShell, m_nTab, rName, sc::tools::ChartSourceType::PIVOT_TABLE))
241 throw container::NoSuchElementException();
242
243 uno::Reference<table::XTablePivotChart> xChart(new TablePivotChart(m_pDocShell, m_nTab, rName));
244 if (!xChart.is())
245 throw container::NoSuchElementException();
246
247 return uno::makeAny(xChart);
248 }
249
getElementNames()250 uno::Sequence<OUString> SAL_CALL TablePivotCharts::getElementNames()
251 {
252 SolarMutexGuard aGuard;
253
254 std::vector<OUString> aElements;
255 sc::tools::ChartIterator aIterator(m_pDocShell, m_nTab, sc::tools::ChartSourceType::PIVOT_TABLE);
256
257 SdrOle2Obj* pOleObject = aIterator.next();
258 while (pOleObject)
259 {
260 uno::Reference<embed::XEmbeddedObject> xObject = pOleObject->GetObjRef();
261 if (xObject.is())
262 {
263 OUString aName = m_pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName(xObject);
264 aElements.push_back(aName);
265 }
266 pOleObject = aIterator.next();
267 }
268 return comphelper::containerToSequence(aElements);
269 }
270
hasByName(OUString const & rName)271 sal_Bool SAL_CALL TablePivotCharts::hasByName(OUString const & rName)
272 {
273 SolarMutexGuard aGuard;
274
275 return sc::tools::findChartsByName(m_pDocShell, m_nTab, rName, sc::tools::ChartSourceType::PIVOT_TABLE) != nullptr;
276 }
277
278 } // end sc namespace
279
280 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
281