/src/libreoffice/sw/source/uibase/table/tablemgr.cxx
Line | Count | Source |
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 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <com/sun/star/chart/ChartDataRowSource.hpp> |
21 | | #include <com/sun/star/chart2/data/XDataProvider.hpp> |
22 | | #include <com/sun/star/chart2/data/XDataReceiver.hpp> |
23 | | #include <com/sun/star/chart2/XChartDocument.hpp> |
24 | | #include <com/sun/star/beans/PropertyState.hpp> |
25 | | #include <com/sun/star/embed/EmbedVerbs.hpp> |
26 | | #include <com/sun/star/embed/XEmbeddedObject.hpp> |
27 | | |
28 | | #include <comphelper/classids.hxx> |
29 | | #include <svx/charthelper.hxx> |
30 | | #include <svtools/embedhlp.hxx> |
31 | | |
32 | | #include <edtwin.hxx> |
33 | | #include <wrtsh.hxx> |
34 | | #include <view.hxx> |
35 | | #include <swundo.hxx> |
36 | | #include <tablemgr.hxx> |
37 | | #include <frmfmt.hxx> |
38 | | #include <swabstdlg.hxx> |
39 | | #include <swcli.hxx> |
40 | | #include <docsh.hxx> |
41 | | #include <unotbl.hxx> |
42 | | #include <unochart.hxx> |
43 | | |
44 | | #include <comphelper/lok.hxx> |
45 | | |
46 | | using namespace ::com::sun::star; |
47 | | |
48 | | // Determine the width |
49 | | SwTwips SwTableFUNC::GetColWidth(sal_uInt16 nNum) const |
50 | 0 | { |
51 | 0 | SwTwips nWidth = 0; |
52 | |
|
53 | 0 | if( m_aCols.Count() > 0 ) |
54 | 0 | { |
55 | 0 | if(m_aCols.Count() == GetColCount()) |
56 | 0 | { |
57 | 0 | if(nNum == m_aCols.Count()) |
58 | 0 | nWidth = m_aCols.GetRight() - m_aCols[nNum-1]; |
59 | 0 | else |
60 | 0 | { |
61 | 0 | if(nNum == 0) |
62 | 0 | nWidth = m_aCols[nNum] - m_aCols.GetLeft(); |
63 | 0 | else |
64 | 0 | nWidth = m_aCols[nNum] - m_aCols[nNum-1]; |
65 | 0 | } |
66 | 0 | } |
67 | 0 | else |
68 | 0 | { |
69 | 0 | SwTwips nRValid = nNum < GetColCount() ? |
70 | 0 | m_aCols[GetRightSeparator(nNum)] : |
71 | 0 | m_aCols.GetRight(); |
72 | 0 | SwTwips nLValid = nNum ? |
73 | 0 | m_aCols[GetRightSeparator(nNum - 1)] : |
74 | 0 | m_aCols.GetLeft(); |
75 | 0 | nWidth = nRValid - nLValid; |
76 | 0 | } |
77 | 0 | } |
78 | 0 | else |
79 | 0 | nWidth = m_aCols.GetRight(); |
80 | 0 | return nWidth; |
81 | 0 | } |
82 | | |
83 | | SwTwips SwTableFUNC::GetMaxColWidth( sal_uInt16 nNum ) const |
84 | 0 | { |
85 | 0 | OSL_ENSURE(nNum <= m_aCols.Count(), "Index out of Area"); |
86 | |
|
87 | 0 | if ( GetColCount() > 0 ) |
88 | 0 | { |
89 | | // The maximum width arises from the own width and |
90 | | // the width each of the neighbor cells reduced by MINLAY. |
91 | 0 | SwTwips nMax; |
92 | 0 | if(nNum == 0) |
93 | 0 | nMax = GetColWidth(1) - MINLAY; |
94 | 0 | else |
95 | 0 | { |
96 | 0 | nMax = GetColWidth(nNum-1); |
97 | 0 | if(nNum == GetColCount()) |
98 | 0 | nMax -= MINLAY; |
99 | 0 | else |
100 | 0 | nMax += GetColWidth(nNum+1) - 2 * MINLAY; |
101 | 0 | } |
102 | 0 | return nMax + GetColWidth(nNum); |
103 | 0 | } |
104 | 0 | else |
105 | 0 | return GetColWidth(nNum); |
106 | 0 | } |
107 | | |
108 | | void SwTableFUNC::SetColWidth(sal_uInt16 nNum, SwTwips nNewWidth ) |
109 | 0 | { |
110 | | // set current width |
111 | | // move all of the following |
112 | 0 | bool bCurrentOnly = false; |
113 | |
|
114 | 0 | if ( m_aCols.Count() > 0 ) |
115 | 0 | { |
116 | 0 | if(m_aCols.Count() != GetColCount()) |
117 | 0 | bCurrentOnly = true; |
118 | 0 | SwTwips nWidth = GetColWidth(nNum); |
119 | |
|
120 | 0 | int nDiff = static_cast<int>(nNewWidth - nWidth); |
121 | 0 | if( !nNum ) |
122 | 0 | m_aCols[ GetRightSeparator(0) ] += nDiff; |
123 | 0 | else if( nNum < GetColCount() ) |
124 | 0 | { |
125 | 0 | if(nDiff < GetColWidth(nNum + 1) - MINLAY) |
126 | 0 | m_aCols[ GetRightSeparator(nNum) ] += nDiff; |
127 | 0 | else |
128 | 0 | { |
129 | 0 | int nDiffLeft = nDiff - static_cast<int>(GetColWidth(nNum + 1)) + int(MINLAY); |
130 | 0 | m_aCols[ GetRightSeparator(nNum) ] += (nDiff - nDiffLeft); |
131 | 0 | m_aCols[ GetRightSeparator(nNum - 1) ] -= nDiffLeft; |
132 | 0 | } |
133 | 0 | } |
134 | 0 | else |
135 | 0 | m_aCols[ GetRightSeparator(nNum-1) ] -= nDiff; |
136 | 0 | } |
137 | 0 | else |
138 | 0 | m_aCols.SetRight( std::min( nNewWidth, SwTwips(m_aCols.GetRightMax()) ) ); |
139 | |
|
140 | 0 | m_pSh->StartAllAction(); |
141 | 0 | m_pSh->SetTabCols( m_aCols, bCurrentOnly ); |
142 | 0 | m_pSh->EndAllAction(); |
143 | 0 | } |
144 | | |
145 | | void SwTableFUNC::InitTabCols() |
146 | 0 | { |
147 | 0 | OSL_ENSURE(m_pSh, "no Shell"); |
148 | |
|
149 | 0 | if( m_pFormat && m_pSh) |
150 | 0 | m_pSh->GetTabCols( m_aCols ); |
151 | 0 | } |
152 | | |
153 | | SwTableFUNC::SwTableFUNC(SwWrtShell *pShell) |
154 | 0 | : m_pFormat(pShell->GetTableFormat()), |
155 | 0 | m_pSh(pShell) |
156 | 0 | { |
157 | 0 | } |
158 | | |
159 | | SwTableFUNC::~SwTableFUNC() |
160 | 0 | { |
161 | 0 | } |
162 | | |
163 | | void SwTableFUNC::UpdateChart() |
164 | 0 | { |
165 | | //Update of the fields triggered by the user, all Charts of |
166 | | //the table will be brought up to date |
167 | 0 | SwFrameFormat *pFormat2 = m_pSh->GetTableFormat(); |
168 | 0 | if ( pFormat2 && m_pSh->HasOLEObj( pFormat2->GetName() ) ) |
169 | 0 | { |
170 | 0 | m_pSh->StartAllAction(); |
171 | 0 | m_pSh->UpdateCharts( pFormat2->GetName() ); |
172 | 0 | m_pSh->EndAllAction(); |
173 | 0 | } |
174 | 0 | } |
175 | | |
176 | | uno::Reference< frame::XModel > SwTableFUNC::InsertChart( |
177 | | uno::Reference< chart2::data::XDataProvider > const &rxDataProvider, |
178 | | bool bFillWithData, |
179 | | const OUString &rCellRange, |
180 | | SwFlyFrameFormat** ppFlyFrameFormat ) |
181 | 0 | { |
182 | 0 | uno::Reference< frame::XModel > xChartModel; |
183 | 0 | m_pSh->StartUndo( SwUndoId::UI_INSERT_CHART ); |
184 | 0 | m_pSh->StartAllAction(); |
185 | |
|
186 | 0 | UIName aName; |
187 | 0 | if (m_pSh->IsCursorInTable()) |
188 | 0 | { |
189 | 0 | aName = m_pSh->GetTableFormat()->GetName(); |
190 | | // insert node before table |
191 | 0 | m_pSh->MoveTable( GotoCurrTable, fnTableStart ); |
192 | 0 | m_pSh->Up( false ); |
193 | 0 | if ( m_pSh->IsCursorInTable() ) |
194 | 0 | { |
195 | 0 | if ( aName != m_pSh->GetTableFormat()->GetName() ) |
196 | 0 | m_pSh->Down( false ); // two adjacent tables |
197 | 0 | } |
198 | 0 | m_pSh->SplitNode(); |
199 | 0 | } |
200 | | |
201 | | // insert chart |
202 | 0 | OUString aObjName; |
203 | 0 | comphelper::EmbeddedObjectContainer aCnt; |
204 | 0 | uno::Reference < embed::XEmbeddedObject > xObj = |
205 | 0 | aCnt.CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aObjName ); |
206 | |
|
207 | 0 | ::svt::EmbeddedObjectRef aEmbObjRef( xObj, css::embed::Aspects::MSOLE_CONTENT ); |
208 | 0 | if ( xObj.is() ) |
209 | 0 | { |
210 | |
|
211 | 0 | SwFlyFrameFormat* pTmp = nullptr; |
212 | 0 | m_pSh->InsertOleObject( aEmbObjRef, &pTmp ); |
213 | 0 | if (ppFlyFrameFormat) |
214 | 0 | *ppFlyFrameFormat = pTmp; |
215 | |
|
216 | 0 | xChartModel.set( xObj->getComponent(), uno::UNO_QUERY ); |
217 | 0 | if( xChartModel.is() ) |
218 | 0 | { |
219 | | // Create a default chart type. |
220 | 0 | uno::Reference<chart2::XChartDocument> xChartDoc(xChartModel, uno::UNO_QUERY); |
221 | 0 | if (xChartDoc.is()) |
222 | 0 | xChartDoc->createDefaultChart(); |
223 | |
|
224 | 0 | xChartModel->lockControllers(); //#i79578# don't request a new replacement image for charts to often - block change notifications |
225 | 0 | } |
226 | | |
227 | | // set the table name at the OLE-node |
228 | 0 | if (!aName.isEmpty()) |
229 | 0 | m_pSh->SetChartName( aName ); |
230 | 0 | } |
231 | 0 | m_pSh->EndAllAction(); |
232 | |
|
233 | 0 | if (xObj.is()) |
234 | 0 | { |
235 | | // Let the chart be activated after the inserting |
236 | 0 | SfxInPlaceClient* pClient = m_pSh->GetView().FindIPClient( xObj, &m_pSh->GetView().GetEditWin() ); |
237 | 0 | if ( !pClient ) |
238 | 0 | { |
239 | 0 | pClient = new SwOleClient( &m_pSh->GetView(), &m_pSh->GetView().GetEditWin(), aEmbObjRef ); |
240 | 0 | m_pSh->SetCheckForOLEInCaption( true ); |
241 | 0 | } |
242 | 0 | m_pSh->CalcAndSetScale( aEmbObjRef ); |
243 | | //#50270# We don't need to handle errors, |
244 | | //this does the DoVerb in the SfxViewShell. |
245 | 0 | ErrCodeMsg nErr = pClient->DoVerb(embed::EmbedVerbs::MS_OLEVERB_SHOW); |
246 | 0 | (void) nErr; |
247 | | |
248 | | // #i121334# |
249 | 0 | ChartHelper::AdaptDefaultsForChart( xObj ); |
250 | 0 | } |
251 | |
|
252 | 0 | uno::Reference< chart2::data::XDataReceiver > xDataReceiver( xChartModel, uno::UNO_QUERY ); |
253 | 0 | if (bFillWithData && xDataReceiver.is() && rxDataProvider.is()) |
254 | 0 | { |
255 | 0 | xDataReceiver->attachDataProvider( rxDataProvider ); |
256 | |
|
257 | 0 | uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_pSh->GetView().GetDocShell()->GetModel(), uno::UNO_QUERY ); |
258 | 0 | xDataReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier ); |
259 | | |
260 | | // default values for ranges that do not consist of a single row or column |
261 | 0 | bool bHasCategories = true; |
262 | 0 | bool bFirstCellAsLabel = true; |
263 | 0 | chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; |
264 | |
|
265 | 0 | SwRangeDescriptor aDesc; |
266 | 0 | FillRangeDescriptor( aDesc, rCellRange ); |
267 | 0 | bool bSingleRowCol = aDesc.nTop == aDesc.nBottom || aDesc.nLeft == aDesc.nRight; |
268 | 0 | if (bSingleRowCol) |
269 | 0 | { |
270 | 0 | aDesc.Normalize(); |
271 | 0 | sal_Int32 nRowLen = aDesc.nRight - aDesc.nLeft + 1; |
272 | 0 | sal_Int32 nColLen = aDesc.nBottom - aDesc.nTop + 1; |
273 | |
|
274 | 0 | bHasCategories = false; |
275 | 0 | if (nRowLen == 1 && nColLen == 1) |
276 | 0 | bFirstCellAsLabel = false; |
277 | 0 | else if (nRowLen > 1) |
278 | 0 | eDataRowSource = chart::ChartDataRowSource_ROWS; |
279 | 0 | else if (nColLen > 1) |
280 | 0 | eDataRowSource = chart::ChartDataRowSource_COLUMNS; |
281 | 0 | else { |
282 | 0 | OSL_FAIL("unexpected state" ); |
283 | 0 | } |
284 | 0 | } |
285 | |
|
286 | 0 | uno::Sequence< beans::PropertyValue > aArgs{ |
287 | 0 | beans::PropertyValue( |
288 | 0 | u"CellRangeRepresentation"_ustr, -1, |
289 | 0 | uno::Any( rCellRange ), beans::PropertyState_DIRECT_VALUE ), |
290 | 0 | beans::PropertyValue( |
291 | 0 | u"HasCategories"_ustr, -1, |
292 | 0 | uno::Any( bHasCategories ), beans::PropertyState_DIRECT_VALUE ), |
293 | 0 | beans::PropertyValue( |
294 | 0 | u"FirstCellAsLabel"_ustr, -1, |
295 | 0 | uno::Any( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ), |
296 | 0 | beans::PropertyValue( |
297 | 0 | u"DataRowSource"_ustr, -1, |
298 | 0 | uno::Any( eDataRowSource ), beans::PropertyState_DIRECT_VALUE ) |
299 | 0 | }; |
300 | 0 | xDataReceiver->setArguments( aArgs ); |
301 | 0 | } |
302 | |
|
303 | 0 | m_pSh->EndUndo( SwUndoId::UI_INSERT_CHART ); |
304 | |
|
305 | 0 | if( xChartModel.is() ) |
306 | 0 | xChartModel->unlockControllers(); //#i79578# don't request a new replacement image for charts to often |
307 | 0 | return xChartModel; |
308 | 0 | } |
309 | | |
310 | | sal_uInt16 SwTableFUNC::GetCurColNum() const |
311 | 0 | { |
312 | 0 | const size_t nPos = m_pSh->GetCurTabColNum(); |
313 | 0 | size_t nCount = 0; |
314 | 0 | for( size_t i = 0; i < nPos; i++ ) |
315 | 0 | if(m_aCols.IsHidden(i)) |
316 | 0 | nCount ++; |
317 | 0 | return nPos - nCount; |
318 | 0 | } |
319 | | |
320 | | sal_uInt16 SwTableFUNC::GetColCount() const |
321 | 0 | { |
322 | 0 | size_t nCount = 0; |
323 | 0 | for(size_t i = 0; i < m_aCols.Count(); i++ ) |
324 | 0 | if(m_aCols.IsHidden(i)) |
325 | 0 | nCount ++; |
326 | 0 | return m_aCols.Count() - nCount; |
327 | 0 | } |
328 | | |
329 | | int SwTableFUNC::GetRightSeparator(int nNum) const |
330 | 0 | { |
331 | 0 | OSL_ENSURE( nNum < static_cast<int>(GetColCount()) ,"Index out of range"); |
332 | 0 | int i = 0; |
333 | 0 | while( nNum >= 0 ) |
334 | 0 | { |
335 | 0 | if( !m_aCols.IsHidden(i) ) |
336 | 0 | nNum--; |
337 | 0 | i++; |
338 | 0 | } |
339 | 0 | return i - 1; |
340 | 0 | } |
341 | | |
342 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |