/src/libreoffice/sc/source/ui/docshell/olinefun.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 <sfx2/bindings.hxx> |
21 | | |
22 | | #include <olinefun.hxx> |
23 | | |
24 | | #include <docsh.hxx> |
25 | | #include <olinetab.hxx> |
26 | | #include <tabvwsh.hxx> |
27 | | #include <undodat.hxx> |
28 | | #include <globstr.hrc> |
29 | | #include <sc.hrc> |
30 | | |
31 | | #include <comphelper/lok.hxx> |
32 | | |
33 | | |
34 | | static void lcl_InvalidateOutliner( SfxBindings* pBindings ) |
35 | 375 | { |
36 | 375 | if ( pBindings ) |
37 | 0 | { |
38 | 0 | pBindings->Invalidate( SID_OUTLINE_SHOW ); |
39 | 0 | pBindings->Invalidate( SID_OUTLINE_HIDE ); |
40 | 0 | pBindings->Invalidate( SID_OUTLINE_REMOVE ); |
41 | |
|
42 | 0 | pBindings->Invalidate( SID_STATUS_SUM ); // because of enabling/disabling |
43 | 0 | pBindings->Invalidate( SID_ATTR_SIZE ); |
44 | 0 | } |
45 | 375 | } |
46 | | |
47 | | //! Move PaintWidthHeight to DocShell ? |
48 | | |
49 | | static void lcl_PaintWidthHeight( ScDocShell& rDocShell, SCTAB nTab, |
50 | | bool bColumns, SCCOLROW nStart, SCCOLROW nEnd ) |
51 | 0 | { |
52 | 0 | ScDocument& rDoc = rDocShell.GetDocument(); |
53 | |
|
54 | 0 | PaintPartFlags nParts = PaintPartFlags::Grid; |
55 | 0 | SCCOL nStartCol = 0; |
56 | 0 | SCROW nStartRow = 0; |
57 | 0 | SCCOL nEndCol = rDoc.MaxCol(); // for testing if merged |
58 | 0 | SCROW nEndRow = rDoc.MaxRow(); |
59 | 0 | if ( bColumns ) |
60 | 0 | { |
61 | 0 | nParts |= PaintPartFlags::Top; |
62 | 0 | nStartCol = static_cast<SCCOL>(nStart); |
63 | 0 | nEndCol = static_cast<SCCOL>(nEnd); |
64 | 0 | } |
65 | 0 | else |
66 | 0 | { |
67 | 0 | nParts |= PaintPartFlags::Left; |
68 | 0 | nStartRow = nStart; |
69 | 0 | nEndRow = nEnd; |
70 | 0 | } |
71 | 0 | if (rDoc.HasAttrib( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, |
72 | 0 | HasAttrFlags::Merged | HasAttrFlags::Overlapped )) |
73 | 0 | { |
74 | 0 | nStartCol = 0; |
75 | 0 | nStartRow = 0; |
76 | 0 | } |
77 | 0 | rDocShell.PostPaint( nStartCol,nStartRow,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, nParts ); |
78 | 0 | } |
79 | | |
80 | | void ScOutlineDocFunc::MakeOutline( const ScRange& rRange, bool bColumns, bool bRecord, bool bApi ) |
81 | 354 | { |
82 | 354 | SCCOL nStartCol = rRange.aStart.Col(); |
83 | 354 | SCROW nStartRow = rRange.aStart.Row(); |
84 | 354 | SCCOL nEndCol = rRange.aEnd.Col(); |
85 | 354 | SCROW nEndRow = rRange.aEnd.Row(); |
86 | 354 | SCTAB nTab = rRange.aStart.Tab(); |
87 | | |
88 | 354 | ScDocument& rDoc = rDocShell.GetDocument(); |
89 | 354 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab, true ); |
90 | 354 | std::unique_ptr<ScOutlineTable> pUndoTab; |
91 | | |
92 | 354 | if (bRecord && !rDoc.IsUndoEnabled()) |
93 | 354 | bRecord = false; |
94 | | |
95 | 354 | if (bRecord) |
96 | 0 | pUndoTab.reset(new ScOutlineTable( *pTable )); |
97 | | |
98 | 354 | ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray(); |
99 | | |
100 | 354 | bool bRes; |
101 | 354 | bool bSize = false; |
102 | 354 | if ( bColumns ) |
103 | 30 | bRes = rArray.Insert( nStartCol, nEndCol, bSize ); |
104 | 324 | else |
105 | 324 | bRes = rArray.Insert( nStartRow, nEndRow, bSize ); |
106 | | |
107 | 354 | if ( bRes ) |
108 | 354 | { |
109 | 354 | if (bRecord) |
110 | 0 | { |
111 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
112 | 0 | std::make_unique<ScUndoMakeOutline>( rDocShell, |
113 | 0 | nStartCol,nStartRow,nTab,nEndCol,nEndRow,nTab, |
114 | 0 | std::move(pUndoTab), bColumns, true ) ); |
115 | 0 | } |
116 | | |
117 | 354 | rDoc.SetStreamValid(nTab, false); |
118 | | |
119 | 354 | PaintPartFlags nParts = PaintPartFlags::NONE; // Data range hasn't been changed |
120 | 354 | if ( bColumns ) |
121 | 30 | nParts |= PaintPartFlags::Top; |
122 | 324 | else |
123 | 324 | nParts |= PaintPartFlags::Left; |
124 | 354 | if ( bSize ) |
125 | 107 | nParts |= PaintPartFlags::Size; |
126 | | |
127 | 354 | rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, nParts ); |
128 | 354 | rDocShell.SetDocumentModified(); |
129 | 354 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
130 | 354 | } |
131 | 0 | else |
132 | 0 | { |
133 | 0 | if (!bApi) |
134 | 0 | rDocShell.ErrorMessage(STR_MSSG_MAKEOUTLINE_0); // "Grouping not possible" |
135 | 0 | } |
136 | 354 | } |
137 | | |
138 | | void ScOutlineDocFunc::RemoveOutline( const ScRange& rRange, bool bColumns, bool bRecord, bool bApi ) |
139 | 0 | { |
140 | 0 | bool bDone = false; |
141 | |
|
142 | 0 | SCCOL nStartCol = rRange.aStart.Col(); |
143 | 0 | SCROW nStartRow = rRange.aStart.Row(); |
144 | 0 | SCCOL nEndCol = rRange.aEnd.Col(); |
145 | 0 | SCROW nEndRow = rRange.aEnd.Row(); |
146 | 0 | SCTAB nTab = rRange.aStart.Tab(); |
147 | |
|
148 | 0 | ScDocument& rDoc = rDocShell.GetDocument(); |
149 | |
|
150 | 0 | if (bRecord && !rDoc.IsUndoEnabled()) |
151 | 0 | bRecord = false; |
152 | 0 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); |
153 | 0 | if (pTable) |
154 | 0 | { |
155 | 0 | std::unique_ptr<ScOutlineTable> pUndoTab; |
156 | 0 | if (bRecord) |
157 | 0 | pUndoTab.reset(new ScOutlineTable( *pTable )); |
158 | |
|
159 | 0 | ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray(); |
160 | |
|
161 | 0 | bool bRes; |
162 | 0 | bool bSize = false; |
163 | 0 | if ( bColumns ) |
164 | 0 | bRes = rArray.Remove( nStartCol, nEndCol, bSize ); |
165 | 0 | else |
166 | 0 | bRes = rArray.Remove( nStartRow, nEndRow, bSize ); |
167 | |
|
168 | 0 | if ( bRes ) |
169 | 0 | { |
170 | 0 | if (bRecord) |
171 | 0 | { |
172 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
173 | 0 | std::make_unique<ScUndoMakeOutline>( rDocShell, |
174 | 0 | nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, |
175 | 0 | std::move(pUndoTab), bColumns, false ) ); |
176 | 0 | } |
177 | |
|
178 | 0 | rDoc.SetStreamValid(nTab, false); |
179 | |
|
180 | 0 | PaintPartFlags nParts = PaintPartFlags::NONE; // Data range hasn't been changed |
181 | 0 | if ( bColumns ) |
182 | 0 | nParts |= PaintPartFlags::Top; |
183 | 0 | else |
184 | 0 | nParts |= PaintPartFlags::Left; |
185 | 0 | if ( bSize ) |
186 | 0 | nParts |= PaintPartFlags::Size; |
187 | |
|
188 | 0 | rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, nParts ); |
189 | 0 | rDocShell.SetDocumentModified(); |
190 | 0 | bDone = true; |
191 | 0 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
192 | | |
193 | | // we are not enabling again -> no UpdatePageBreaks |
194 | 0 | } |
195 | 0 | } |
196 | |
|
197 | 0 | if (!bDone && !bApi) |
198 | 0 | rDocShell.ErrorMessage(STR_MSSG_REMOVEOUTLINE_0); // "Ungrouping not possible" |
199 | 0 | } |
200 | | |
201 | | bool ScOutlineDocFunc::RemoveAllOutlines( SCTAB nTab, bool bRecord ) |
202 | 0 | { |
203 | 0 | bool bSuccess = false; |
204 | 0 | ScDocument& rDoc = rDocShell.GetDocument(); |
205 | |
|
206 | 0 | if (bRecord && !rDoc.IsUndoEnabled()) |
207 | 0 | bRecord = false; |
208 | 0 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); |
209 | 0 | if (pTable) |
210 | 0 | { |
211 | 0 | if (bRecord) |
212 | 0 | { |
213 | 0 | SCCOLROW nCol1, nCol2, nRow1, nRow2; |
214 | 0 | pTable->GetColArray().GetRange( nCol1, nCol2 ); |
215 | 0 | pTable->GetRowArray().GetRange( nRow1, nRow2 ); |
216 | 0 | SCCOL nStartCol = static_cast<SCCOL>(nCol1); |
217 | 0 | SCROW nStartRow = nRow1; |
218 | 0 | SCCOL nEndCol = static_cast<SCCOL>(nCol2); |
219 | 0 | SCROW nEndRow = nRow2; |
220 | |
|
221 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
222 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true ); |
223 | 0 | rDoc.CopyToDocument(nStartCol, 0, nTab, nEndCol, rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
224 | 0 | rDoc.CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
225 | |
|
226 | 0 | std::unique_ptr<ScOutlineTable> pUndoTab(new ScOutlineTable( *pTable )); |
227 | |
|
228 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
229 | 0 | std::make_unique<ScUndoRemoveAllOutlines>( rDocShell, |
230 | 0 | nStartCol, nStartRow, nTab, |
231 | 0 | nEndCol, nEndRow, nTab, |
232 | 0 | std::move(pUndoDoc), std::move(pUndoTab) ) ); |
233 | 0 | } |
234 | |
|
235 | 0 | SelectLevel( nTab, true, pTable->GetColArray().GetDepth(), false, false ); |
236 | 0 | SelectLevel( nTab, false, pTable->GetRowArray().GetDepth(), false, false ); |
237 | 0 | rDoc.SetOutlineTable( nTab, nullptr ); |
238 | |
|
239 | 0 | rDoc.UpdatePageBreaks( nTab ); |
240 | |
|
241 | 0 | rDoc.SetStreamValid(nTab, false); |
242 | |
|
243 | 0 | rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, |
244 | 0 | PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top | PaintPartFlags::Size ); |
245 | 0 | rDocShell.SetDocumentModified(); |
246 | 0 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
247 | 0 | bSuccess = true; |
248 | 0 | } |
249 | |
|
250 | 0 | return bSuccess; |
251 | 0 | } |
252 | | |
253 | | void ScOutlineDocFunc::AutoOutline( const ScRange& rRange, bool bRecord ) |
254 | 0 | { |
255 | 0 | SCCOL nStartCol = rRange.aStart.Col(); |
256 | 0 | SCROW nStartRow = rRange.aStart.Row(); |
257 | 0 | SCCOL nEndCol = rRange.aEnd.Col(); |
258 | 0 | SCROW nEndRow = rRange.aEnd.Row(); |
259 | 0 | SCTAB nTab = rRange.aStart.Tab(); |
260 | |
|
261 | 0 | ScDocument& rDoc = rDocShell.GetDocument(); |
262 | |
|
263 | 0 | if (bRecord && !rDoc.IsUndoEnabled()) |
264 | 0 | bRecord = false; |
265 | 0 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); |
266 | |
|
267 | 0 | ScDocumentUniquePtr pUndoDoc; |
268 | 0 | std::unique_ptr<ScOutlineTable> pUndoTab; |
269 | |
|
270 | 0 | if ( pTable ) |
271 | 0 | { |
272 | 0 | if ( bRecord ) |
273 | 0 | { |
274 | 0 | pUndoTab.reset(new ScOutlineTable( *pTable )); |
275 | |
|
276 | 0 | SCCOLROW nCol1, nCol2, nRow1, nRow2; |
277 | 0 | pTable->GetColArray().GetRange( nCol1, nCol2 ); |
278 | 0 | pTable->GetRowArray().GetRange( nRow1, nRow2 ); |
279 | 0 | SCCOL nOutStartCol = static_cast<SCCOL>(nCol1); |
280 | 0 | SCROW nOutStartRow = nRow1; |
281 | 0 | SCCOL nOutEndCol = static_cast<SCCOL>(nCol2); |
282 | 0 | SCROW nOutEndRow = nRow2; |
283 | |
|
284 | 0 | pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); |
285 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true ); |
286 | 0 | rDoc.CopyToDocument(nOutStartCol, 0, nTab, nOutEndCol, rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
287 | 0 | rDoc.CopyToDocument(0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
288 | 0 | } |
289 | | |
290 | | // enable |
291 | 0 | SelectLevel( nTab, true, pTable->GetColArray().GetDepth(), false, false ); |
292 | 0 | SelectLevel( nTab, false, pTable->GetRowArray().GetDepth(), false, false ); |
293 | 0 | rDoc.SetOutlineTable( nTab, nullptr ); |
294 | 0 | } |
295 | |
|
296 | 0 | rDoc.DoAutoOutline( nStartCol,nStartRow, nEndCol,nEndRow, nTab ); |
297 | |
|
298 | 0 | if (bRecord) |
299 | 0 | { |
300 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
301 | 0 | std::make_unique<ScUndoAutoOutline>( rDocShell, |
302 | 0 | nStartCol, nStartRow, nTab, |
303 | 0 | nEndCol, nEndRow, nTab, |
304 | 0 | std::move(pUndoDoc), std::move(pUndoTab) ) ); |
305 | 0 | } |
306 | |
|
307 | 0 | rDoc.SetStreamValid(nTab, false); |
308 | |
|
309 | 0 | rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Left | PaintPartFlags::Top | PaintPartFlags::Size ); |
310 | 0 | rDocShell.SetDocumentModified(); |
311 | 0 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
312 | 0 | } |
313 | | |
314 | | bool ScOutlineDocFunc::SelectLevel( SCTAB nTab, bool bColumns, sal_uInt16 nLevel, |
315 | | bool bRecord, bool bPaint ) |
316 | 0 | { |
317 | 0 | ScDocument& rDoc = rDocShell.GetDocument(); |
318 | 0 | ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); |
319 | |
|
320 | 0 | if (bRecord && !rDoc.IsUndoEnabled()) |
321 | 0 | bRecord = false; |
322 | 0 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); // already there |
323 | 0 | if (!pTable) |
324 | 0 | return false; |
325 | 0 | ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray(); |
326 | |
|
327 | 0 | SCCOLROW nStart, nEnd; |
328 | 0 | rArray.GetRange( nStart, nEnd ); |
329 | | |
330 | | // TODO undo can mess things up when another view is editing a cell in the range of group entry |
331 | | // this is a temporarily workaround |
332 | 0 | if (!comphelper::LibreOfficeKit::isActive() && bRecord ) |
333 | 0 | { |
334 | 0 | std::unique_ptr<ScOutlineTable> pUndoTab(new ScOutlineTable( *pTable )); |
335 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
336 | 0 | if (bColumns) |
337 | 0 | { |
338 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, true ); |
339 | 0 | rDoc.CopyToDocument(static_cast<SCCOL>(nStart), 0, nTab, |
340 | 0 | static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, |
341 | 0 | *pUndoDoc); |
342 | 0 | } |
343 | 0 | else |
344 | 0 | { |
345 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true ); |
346 | 0 | rDoc.CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
347 | 0 | } |
348 | |
|
349 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
350 | 0 | std::make_unique<ScUndoOutlineLevel>( rDocShell, |
351 | 0 | nStart, nEnd, nTab, //! calculate start and end |
352 | 0 | std::move(pUndoDoc), std::move(pUndoTab), |
353 | 0 | bColumns, nLevel ) ); |
354 | 0 | } |
355 | |
|
356 | 0 | ScSubOutlineIterator aIter( &rArray ); // all entries |
357 | 0 | ScOutlineEntry* pEntry; |
358 | 0 | while ((pEntry=aIter.GetNext()) != nullptr) |
359 | 0 | { |
360 | 0 | SCCOLROW nThisStart = pEntry->GetStart(); |
361 | 0 | SCCOLROW nThisEnd = pEntry->GetEnd(); |
362 | |
|
363 | 0 | sal_uInt16 nThisLevel = aIter.LastLevel(); |
364 | 0 | bool bShow = (nThisLevel < nLevel); |
365 | |
|
366 | 0 | if (!bShow && pViewSh && ScTabViewShell::isAnyEditViewInRange(pViewSh, bColumns, nThisStart, nThisEnd)) |
367 | 0 | continue; |
368 | | |
369 | 0 | if (bShow) // enable |
370 | 0 | { |
371 | 0 | pEntry->SetHidden( false ); |
372 | 0 | pEntry->SetVisible( true ); |
373 | 0 | } |
374 | 0 | else if ( nThisLevel == nLevel ) // disable |
375 | 0 | { |
376 | 0 | pEntry->SetHidden( true ); |
377 | 0 | pEntry->SetVisible( true ); |
378 | 0 | } |
379 | 0 | else // hidden below |
380 | 0 | { |
381 | 0 | if (comphelper::LibreOfficeKit::isActive() && nThisLevel > 0) |
382 | 0 | { |
383 | 0 | pEntry->SetHidden( true ); |
384 | 0 | const ScOutlineEntry* pParentEntry = rArray.GetEntryByPos(nThisLevel - 1, nThisStart); |
385 | 0 | if (pParentEntry && pParentEntry->IsHidden()) |
386 | 0 | pEntry->SetVisible( false ); |
387 | 0 | } |
388 | 0 | else |
389 | 0 | { |
390 | 0 | pEntry->SetVisible( false ); |
391 | 0 | } |
392 | 0 | } |
393 | |
|
394 | 0 | for (SCCOLROW i=nThisStart; i<=nThisEnd; i++) |
395 | 0 | { |
396 | 0 | if ( bColumns ) |
397 | 0 | rDoc.ShowCol( static_cast<SCCOL>(i), nTab, bShow ); |
398 | 0 | else |
399 | 0 | { |
400 | | // show several rows together, don't show filtered rows |
401 | 0 | SCROW nFilterEnd = i; |
402 | 0 | bool bFiltered = rDoc.RowFiltered( i, nTab, nullptr, &nFilterEnd ); |
403 | 0 | nFilterEnd = std::min( nThisEnd, nFilterEnd ); |
404 | 0 | if ( !bShow || !bFiltered ) |
405 | 0 | rDoc.ShowRows( i, nFilterEnd, nTab, bShow ); |
406 | 0 | i = nFilterEnd; |
407 | 0 | } |
408 | 0 | } |
409 | 0 | } |
410 | |
|
411 | 0 | rDoc.SetDrawPageSize(nTab); |
412 | 0 | rDoc.UpdatePageBreaks( nTab ); |
413 | |
|
414 | 0 | if ( pViewSh ) |
415 | 0 | pViewSh->OnLOKShowHideColRow(bColumns, nStart - 1); |
416 | |
|
417 | 0 | if (bPaint) |
418 | 0 | lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd ); |
419 | |
|
420 | 0 | rDocShell.SetDocumentModified(); |
421 | 0 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
422 | |
|
423 | 0 | return true; |
424 | 0 | } |
425 | | |
426 | | bool ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, bool bRecord ) |
427 | 0 | { |
428 | 0 | bool bDone = false; |
429 | |
|
430 | 0 | SCCOL nStartCol = rRange.aStart.Col(); |
431 | 0 | SCROW nStartRow = rRange.aStart.Row(); |
432 | 0 | SCCOL nEndCol = rRange.aEnd.Col(); |
433 | 0 | SCROW nEndRow = rRange.aEnd.Row(); |
434 | 0 | SCTAB nTab = rRange.aStart.Tab(); |
435 | |
|
436 | 0 | ScDocument& rDoc = rDocShell.GetDocument(); |
437 | |
|
438 | 0 | if (bRecord && !rDoc.IsUndoEnabled()) |
439 | 0 | bRecord = false; |
440 | 0 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); |
441 | |
|
442 | 0 | if (pTable) |
443 | 0 | { |
444 | 0 | ScOutlineEntry* pEntry; |
445 | 0 | SCCOLROW nStart; |
446 | 0 | SCCOLROW nEnd; |
447 | 0 | SCCOLROW nMin; |
448 | 0 | SCCOLROW nMax; |
449 | 0 | SCCOLROW i; |
450 | | |
451 | | // TODO undo can mess things up when another view is editing a cell in the range of group entry |
452 | | // this is a temporarily workaround |
453 | 0 | if ( !comphelper::LibreOfficeKit::isActive() && bRecord ) |
454 | 0 | { |
455 | 0 | std::unique_ptr<ScOutlineTable> pUndoTab(new ScOutlineTable( *pTable )); |
456 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
457 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true ); |
458 | 0 | rDoc.CopyToDocument(nStartCol, 0, nTab, nEndCol, rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
459 | 0 | rDoc.CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
460 | |
|
461 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
462 | 0 | std::make_unique<ScUndoOutlineBlock>( rDocShell, |
463 | 0 | nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, |
464 | 0 | std::move(pUndoDoc), std::move(pUndoTab), true ) ); |
465 | 0 | } |
466 | | |
467 | | // Columns |
468 | |
|
469 | 0 | nMin=rDoc.MaxCol(); |
470 | 0 | nMax=0; |
471 | 0 | ScOutlineArray& rColArray = pTable->GetColArray(); |
472 | 0 | ScSubOutlineIterator aColIter( &rColArray ); |
473 | 0 | while ((pEntry=aColIter.GetNext()) != nullptr) |
474 | 0 | { |
475 | 0 | nStart = pEntry->GetStart(); |
476 | 0 | nEnd = pEntry->GetEnd(); |
477 | 0 | if ( nStart>=nStartCol && nEnd<=nEndCol ) |
478 | 0 | { |
479 | 0 | pEntry->SetHidden( false ); |
480 | 0 | pEntry->SetVisible( true ); |
481 | 0 | if (nStart<nMin) nMin=nStart; |
482 | 0 | if (nEnd>nMax) nMax=nEnd; |
483 | 0 | } |
484 | 0 | } |
485 | 0 | const SCCOLROW nMinStartCol = nMin; |
486 | 0 | for ( i=nMin; i<=nMax; i++ ) |
487 | 0 | rDoc.ShowCol( static_cast<SCCOL>(i), nTab, true ); |
488 | | |
489 | | // Rows |
490 | |
|
491 | 0 | nMin=rDoc.MaxRow(); |
492 | 0 | nMax=0; |
493 | 0 | ScOutlineArray& rRowArray = pTable->GetRowArray(); |
494 | 0 | ScSubOutlineIterator aRowIter( &rRowArray ); |
495 | 0 | while ((pEntry=aRowIter.GetNext()) != nullptr) |
496 | 0 | { |
497 | 0 | nStart = pEntry->GetStart(); |
498 | 0 | nEnd = pEntry->GetEnd(); |
499 | 0 | if ( nStart>=nStartRow && nEnd<=nEndRow ) |
500 | 0 | { |
501 | 0 | pEntry->SetHidden( false ); |
502 | 0 | pEntry->SetVisible( true ); |
503 | 0 | if (nStart<nMin) nMin=nStart; |
504 | 0 | if (nEnd>nMax) nMax=nEnd; |
505 | 0 | } |
506 | 0 | } |
507 | 0 | const SCCOLROW nMinStartRow = nMin; |
508 | 0 | for ( i=nMin; i<=nMax; i++ ) |
509 | 0 | { |
510 | | // show several rows together, don't show filtered rows |
511 | 0 | SCROW nFilterEnd = i; |
512 | 0 | bool bFiltered = rDoc.RowFiltered( i, nTab, nullptr, &nFilterEnd ); |
513 | 0 | nFilterEnd = std::min( nMax, nFilterEnd ); |
514 | 0 | if ( !bFiltered ) |
515 | 0 | rDoc.ShowRows( i, nFilterEnd, nTab, true ); |
516 | 0 | i = nFilterEnd; |
517 | 0 | } |
518 | | |
519 | |
|
520 | 0 | rDoc.SetDrawPageSize(nTab); |
521 | 0 | rDoc.UpdatePageBreaks( nTab ); |
522 | |
|
523 | 0 | ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); |
524 | 0 | if ( pViewSh ) |
525 | 0 | { |
526 | 0 | pViewSh->OnLOKShowHideColRow(/*columns: */ true, nMinStartCol - 1); |
527 | 0 | pViewSh->OnLOKShowHideColRow(/*columns: */ false, nMinStartRow - 1); |
528 | 0 | } |
529 | |
|
530 | 0 | rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top ); |
531 | 0 | rDocShell.SetDocumentModified(); |
532 | 0 | bDone = true; |
533 | |
|
534 | 0 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
535 | 0 | } |
536 | |
|
537 | 0 | return bDone; |
538 | 0 | } |
539 | | |
540 | | bool ScOutlineDocFunc::HideMarkedOutlines( const ScRange& rRange, bool bRecord ) |
541 | 9 | { |
542 | 9 | bool bDone = false; |
543 | | |
544 | 9 | SCCOL nStartCol = rRange.aStart.Col(); |
545 | 9 | SCROW nStartRow = rRange.aStart.Row(); |
546 | 9 | SCCOL nEndCol = rRange.aEnd.Col(); |
547 | 9 | SCROW nEndRow = rRange.aEnd.Row(); |
548 | 9 | SCTAB nTab = rRange.aStart.Tab(); |
549 | | |
550 | 9 | ScDocument& rDoc = rDocShell.GetDocument(); |
551 | | |
552 | 9 | if (bRecord && !rDoc.IsUndoEnabled()) |
553 | 9 | bRecord = false; |
554 | 9 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); |
555 | | |
556 | 9 | if (pTable) |
557 | 9 | { |
558 | 9 | const ScOutlineEntry* pEntry; |
559 | 9 | size_t nColLevel; |
560 | 9 | size_t nRowLevel; |
561 | 9 | sal_uInt16 nCount; |
562 | 9 | SCCOLROW nStart; |
563 | 9 | SCCOLROW nEnd; |
564 | 9 | sal_uInt16 i; |
565 | | |
566 | 9 | SCCOLROW nEffStartCol = nStartCol; |
567 | 9 | SCCOLROW nEffEndCol = nEndCol; |
568 | 9 | ScOutlineArray& rColArray = pTable->GetColArray(); |
569 | 9 | rColArray.FindTouchedLevel( nStartCol, nEndCol, nColLevel ); |
570 | 9 | rColArray.ExtendBlock( nColLevel, nEffStartCol, nEffEndCol ); |
571 | 9 | SCCOLROW nEffStartRow = nStartRow; |
572 | 9 | SCCOLROW nEffEndRow = nEndRow; |
573 | 9 | ScOutlineArray& rRowArray = pTable->GetRowArray(); |
574 | 9 | rRowArray.FindTouchedLevel( nStartRow, nEndRow, nRowLevel ); |
575 | 9 | rRowArray.ExtendBlock( nRowLevel, nEffStartRow, nEffEndRow ); |
576 | | |
577 | | // TODO undo can mess things up when another view is editing a cell in the range of group entry |
578 | | // this is a temporarily workaround |
579 | 9 | if ( !comphelper::LibreOfficeKit::isActive() && bRecord ) |
580 | 0 | { |
581 | 0 | std::unique_ptr<ScOutlineTable> pUndoTab(new ScOutlineTable( *pTable )); |
582 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
583 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true ); |
584 | 0 | rDoc.CopyToDocument(static_cast<SCCOL>(nEffStartCol), 0, nTab, |
585 | 0 | static_cast<SCCOL>(nEffEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, |
586 | 0 | false, *pUndoDoc); |
587 | 0 | rDoc.CopyToDocument(0, nEffStartRow, nTab, rDoc.MaxCol(), nEffEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
588 | |
|
589 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
590 | 0 | std::make_unique<ScUndoOutlineBlock>( rDocShell, |
591 | 0 | nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, |
592 | 0 | std::move(pUndoDoc), std::move(pUndoTab), false ) ); |
593 | 0 | } |
594 | | |
595 | | // Columns |
596 | | |
597 | 9 | nCount = rColArray.GetCount(nColLevel); |
598 | 18 | for ( i=0; i<nCount; i++ ) |
599 | 9 | { |
600 | 9 | pEntry = rColArray.GetEntry(nColLevel,i); |
601 | 9 | nStart = pEntry->GetStart(); |
602 | 9 | nEnd = pEntry->GetEnd(); |
603 | | |
604 | 9 | if ( static_cast<SCCOLROW>(nStartCol)<=nEnd && static_cast<SCCOLROW>(nEndCol)>=nStart ) |
605 | 8 | HideOutline( nTab, true, nColLevel, i, false, false ); |
606 | 9 | } |
607 | | |
608 | | // Rows |
609 | | |
610 | 9 | nCount = rRowArray.GetCount(nRowLevel); |
611 | 13 | for ( i=0; i<nCount; i++ ) |
612 | 4 | { |
613 | 4 | pEntry = rRowArray.GetEntry(nRowLevel,i); |
614 | 4 | nStart = pEntry->GetStart(); |
615 | 4 | nEnd = pEntry->GetEnd(); |
616 | | |
617 | 4 | if ( nStartRow<=nEnd && nEndRow>=nStart ) |
618 | 4 | HideOutline( nTab, false, nRowLevel, i, false, false ); |
619 | 4 | } |
620 | | |
621 | 9 | rDoc.SetDrawPageSize(nTab); |
622 | 9 | rDoc.UpdatePageBreaks( nTab ); |
623 | | |
624 | 9 | rDocShell.PostPaint( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top ); |
625 | | |
626 | 9 | rDocShell.SetDocumentModified(); |
627 | 9 | bDone = true; |
628 | | |
629 | 9 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
630 | 9 | } |
631 | | |
632 | 9 | return bDone; |
633 | 9 | } |
634 | | |
635 | | void ScOutlineDocFunc::ShowOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, |
636 | | bool bRecord, bool bPaint ) |
637 | 0 | { |
638 | 0 | ScDocument& rDoc = rDocShell.GetDocument(); |
639 | 0 | if (bRecord && !rDoc.IsUndoEnabled()) |
640 | 0 | bRecord = false; |
641 | |
|
642 | 0 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); |
643 | 0 | if (!pTable) |
644 | 0 | return; |
645 | | |
646 | 0 | ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray(); |
647 | 0 | ScOutlineEntry* pEntry = rArray.GetEntry( nLevel, nEntry ); |
648 | 0 | SCCOLROW nStart = pEntry->GetStart(); |
649 | 0 | SCCOLROW nEnd = pEntry->GetEnd(); |
650 | | |
651 | | // TODO undo can mess things up when another view is editing a cell in the range of group entry |
652 | | // this is a temporarily workaround |
653 | 0 | if ( !comphelper::LibreOfficeKit::isActive() && bRecord ) |
654 | 0 | { |
655 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
656 | 0 | if (bColumns) |
657 | 0 | { |
658 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, true ); |
659 | 0 | rDoc.CopyToDocument(static_cast<SCCOL>(nStart), 0, nTab, |
660 | 0 | static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, |
661 | 0 | *pUndoDoc); |
662 | 0 | } |
663 | 0 | else |
664 | 0 | { |
665 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true ); |
666 | 0 | rDoc.CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
667 | 0 | } |
668 | |
|
669 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
670 | 0 | std::make_unique<ScUndoDoOutline>( rDocShell, |
671 | 0 | nStart, nEnd, nTab, std::move(pUndoDoc), //! calc start and end |
672 | 0 | bColumns, nLevel, nEntry, true ) ); |
673 | 0 | } |
674 | |
|
675 | 0 | pEntry->SetHidden(false); |
676 | 0 | SCCOLROW i; |
677 | 0 | for ( i = nStart; i <= nEnd; i++ ) |
678 | 0 | { |
679 | 0 | if ( bColumns ) |
680 | 0 | rDoc.ShowCol( static_cast<SCCOL>(i), nTab, true ); |
681 | 0 | else |
682 | 0 | { |
683 | | // show several rows together, don't show filtered rows |
684 | 0 | SCROW nFilterEnd = i; |
685 | 0 | bool bFiltered = rDoc.RowFiltered( i, nTab, nullptr, &nFilterEnd ); |
686 | 0 | nFilterEnd = std::min( nEnd, nFilterEnd ); |
687 | 0 | if ( !bFiltered ) |
688 | 0 | rDoc.ShowRows( i, nFilterEnd, nTab, true ); |
689 | 0 | i = nFilterEnd; |
690 | 0 | } |
691 | 0 | } |
692 | |
|
693 | 0 | ScSubOutlineIterator aIter( &rArray, nLevel, nEntry ); |
694 | 0 | while ((pEntry=aIter.GetNext()) != nullptr) |
695 | 0 | { |
696 | 0 | if ( pEntry->IsHidden() ) |
697 | 0 | { |
698 | 0 | SCCOLROW nSubStart = pEntry->GetStart(); |
699 | 0 | SCCOLROW nSubEnd = pEntry->GetEnd(); |
700 | 0 | if ( bColumns ) |
701 | 0 | for ( i = nSubStart; i <= nSubEnd; i++ ) |
702 | 0 | rDoc.ShowCol( static_cast<SCCOL>(i), nTab, false ); |
703 | 0 | else |
704 | 0 | rDoc.ShowRows( nSubStart, nSubEnd, nTab, false ); |
705 | 0 | } |
706 | 0 | } |
707 | |
|
708 | 0 | rArray.SetVisibleBelow( nLevel, nEntry, true, true ); |
709 | |
|
710 | 0 | rDoc.SetDrawPageSize(nTab); |
711 | 0 | rDoc.InvalidatePageBreaks(nTab); |
712 | 0 | rDoc.UpdatePageBreaks( nTab ); |
713 | |
|
714 | 0 | ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); |
715 | 0 | if ( pViewSh ) |
716 | 0 | pViewSh->OnLOKShowHideColRow(bColumns, nStart - 1); |
717 | |
|
718 | 0 | if (bPaint) |
719 | 0 | lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd ); |
720 | |
|
721 | 0 | rDocShell.SetDocumentModified(); |
722 | |
|
723 | 0 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
724 | 0 | } |
725 | | |
726 | | bool ScOutlineDocFunc::HideOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, |
727 | | bool bRecord, bool bPaint ) |
728 | 12 | { |
729 | 12 | ScDocument& rDoc = rDocShell.GetDocument(); |
730 | 12 | if (bRecord && !rDoc.IsUndoEnabled()) |
731 | 0 | bRecord = false; |
732 | | |
733 | 12 | ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab ); |
734 | 12 | if (!pTable) |
735 | 0 | return false; |
736 | 12 | ScOutlineArray& rArray = bColumns ? pTable->GetColArray() : pTable->GetRowArray(); |
737 | 12 | ScOutlineEntry* pEntry = rArray.GetEntry( nLevel, nEntry ); |
738 | 12 | SCCOLROW nStart = pEntry->GetStart(); |
739 | 12 | SCCOLROW nEnd = pEntry->GetEnd(); |
740 | | |
741 | 12 | ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); |
742 | 12 | if (pViewSh && ScTabViewShell::isAnyEditViewInRange(pViewSh, bColumns, nStart, nEnd)) |
743 | 0 | return false; |
744 | | |
745 | | // TODO undo can mess things up when another view is editing a cell in the range of group entry |
746 | | // this is a temporarily workaround |
747 | 12 | if ( !comphelper::LibreOfficeKit::isActive() && bRecord ) |
748 | 0 | { |
749 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
750 | 0 | if (bColumns) |
751 | 0 | { |
752 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, true ); |
753 | 0 | rDoc.CopyToDocument(static_cast<SCCOL>(nStart), 0, nTab, |
754 | 0 | static_cast<SCCOL>(nEnd), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, |
755 | 0 | *pUndoDoc); |
756 | 0 | } |
757 | 0 | else |
758 | 0 | { |
759 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true ); |
760 | 0 | rDoc.CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc); |
761 | 0 | } |
762 | |
|
763 | 0 | rDocShell.GetUndoManager()->AddUndoAction( |
764 | 0 | std::make_unique<ScUndoDoOutline>( rDocShell, |
765 | 0 | nStart, nEnd, nTab, std::move(pUndoDoc), |
766 | 0 | bColumns, nLevel, nEntry, false ) ); |
767 | 0 | } |
768 | | |
769 | 12 | pEntry->SetHidden(true); |
770 | 12 | SCCOLROW i; |
771 | 12 | if ( bColumns ) |
772 | 27 | for ( i = nStart; i <= nEnd; i++ ) |
773 | 19 | rDoc.ShowCol( static_cast<SCCOL>(i), nTab, false ); |
774 | 4 | else |
775 | 4 | rDoc.ShowRows( nStart, nEnd, nTab, false ); |
776 | | |
777 | 12 | rArray.SetVisibleBelow( nLevel, nEntry, false ); |
778 | | |
779 | 12 | rDoc.SetDrawPageSize(nTab); |
780 | 12 | rDoc.InvalidatePageBreaks(nTab); |
781 | 12 | rDoc.UpdatePageBreaks( nTab ); |
782 | | |
783 | 12 | if ( pViewSh ) |
784 | 0 | pViewSh->OnLOKShowHideColRow(bColumns, nStart - 1); |
785 | | |
786 | 12 | if (bPaint) |
787 | 0 | lcl_PaintWidthHeight( rDocShell, nTab, bColumns, nStart, nEnd ); |
788 | | |
789 | 12 | rDocShell.SetDocumentModified(); |
790 | | |
791 | 12 | lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); |
792 | | |
793 | | |
794 | 12 | return true; //! always ??? |
795 | 12 | } |
796 | | |
797 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |