tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / view / gridwin2.cxx
blob5b85d3c66fd5f75cb8df9d1bed667bd0af015162
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 <scitems.hxx>
21 #include <vcl/settings.hxx>
22 #include <comphelper/lok.hxx>
24 #include <attrib.hxx>
25 #include <gridwin.hxx>
26 #include <tabvwsh.hxx>
27 #include <docsh.hxx>
28 #include <viewdata.hxx>
29 #include <pivot.hxx>
30 #include <uiitems.hxx>
31 #include <scresid.hxx>
32 #include <globstr.hrc>
33 #include <strings.hrc>
34 #include <pagedata.hxx>
35 #include <dpobject.hxx>
36 #include <dpsave.hxx>
37 #include <dpshttab.hxx>
38 #include <dbdocfun.hxx>
39 #include <checklistmenu.hxx>
40 #include <dpcontrol.hxx>
41 #include <userlist.hxx>
42 #include <scabstdlg.hxx>
44 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
45 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
47 #include <unordered_map>
48 #include <memory>
49 #include <vector>
51 using namespace css;
52 using namespace css::sheet;
53 using css::sheet::DataPilotFieldOrientation;
54 using std::vector;
56 DataPilotFieldOrientation ScGridWindow::GetDPFieldOrientation( SCCOL nCol, SCROW nRow ) const
58 ScDocument& rDoc = mrViewData.GetDocument();
59 SCTAB nTab = mrViewData.GetTabNo();
60 ScDPObject* pDPObj = rDoc.GetDPAtCursor(nCol, nRow, nTab);
61 if (!pDPObj)
62 return DataPilotFieldOrientation_HIDDEN;
64 DataPilotFieldOrientation nOrient = DataPilotFieldOrientation_HIDDEN;
66 // Check for page field first.
67 if (nCol > 0)
69 // look for the dimension header left of the drop-down arrow
70 tools::Long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
71 if ( nField >= 0 && nOrient == DataPilotFieldOrientation_PAGE )
73 bool bIsDataLayout = false;
74 OUString aFieldName = pDPObj->GetDimName( nField, bIsDataLayout );
75 if ( !aFieldName.isEmpty() && !bIsDataLayout )
76 return DataPilotFieldOrientation_PAGE;
80 nOrient = DataPilotFieldOrientation_HIDDEN;
82 // Now, check for row/column field.
83 tools::Long nField = pDPObj->GetHeaderDim(ScAddress(nCol, nRow, nTab), nOrient);
84 if (nField >= 0 && (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW) )
86 bool bIsDataLayout = false;
87 OUString aFieldName = pDPObj->GetDimName(nField, bIsDataLayout);
88 if (!aFieldName.isEmpty() && !bIsDataLayout)
89 return nOrient;
92 return DataPilotFieldOrientation_HIDDEN;
95 // private method for mouse button handling
96 bool ScGridWindow::DoPageFieldSelection( SCCOL nCol, SCROW nRow )
98 if (GetDPFieldOrientation( nCol, nRow ) == DataPilotFieldOrientation_PAGE)
100 LaunchPageFieldMenu( nCol, nRow );
101 return true;
103 return false;
106 bool ScGridWindow::DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt )
108 ScDocument& rDoc = mrViewData.GetDocument();
109 SCTAB nTab = mrViewData.GetTabNo();
110 Point aScrPos = mrViewData.GetScrPos(nCol, nRow, eWhich);
111 Point aDiffPix = rMEvt.GetPosPixel();
113 aDiffPix -= aScrPos;
114 bool bLOKActive = comphelper::LibreOfficeKit::isActive();
115 bool bLayoutRTL = rDoc.IsLayoutRTL( nTab );
116 if ( bLayoutRTL && !bLOKActive )
117 aDiffPix.setX( -aDiffPix.X() );
119 tools::Long nSizeX, nSizeY;
120 mrViewData.GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
121 // The button height should not use the merged cell height, should still use single row height
122 nSizeY = ScViewData::ToPixel(rDoc.GetRowHeight(nRow, nTab), mrViewData.GetPPTY());
123 Size aScrSize(nSizeX-1, nSizeY-1);
125 // Check if the mouse cursor is clicking on the popup arrow box.
126 mpFilterButton.reset(new ScDPFieldButton(GetOutDev(), &GetSettings().GetStyleSettings(), &mrViewData.GetZoomY(), &rDoc));
127 mpFilterButton->setBoundingBox(aScrPos, aScrSize, bLayoutRTL && !bLOKActive);
128 mpFilterButton->setPopupLeft(bLayoutRTL && bLOKActive ? false : bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL
129 Point aPopupPos;
130 Size aPopupSize;
131 mpFilterButton->getPopupBoundingBox(aPopupPos, aPopupSize);
132 tools::Rectangle aRect(aPopupPos, aPopupSize);
133 if (aRect.Contains(rMEvt.GetPosPixel()))
135 if ( DoPageFieldSelection( nCol, nRow ) )
136 return true;
138 bool bFilterActive = IsAutoFilterActive(nCol, nRow, nTab);
139 mpFilterButton->setHasHiddenMember(bFilterActive);
140 mpFilterButton->setDrawBaseButton(false);
141 mpFilterButton->setDrawPopupButton(true);
142 mpFilterButton->setPopupPressed(true);
143 mpFilterButton->draw();
144 LaunchAutoFilterMenu(nCol, nRow);
145 return true;
148 return false;
151 void ScGridWindow::DoPushPivotButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt, bool bButton, bool bPopup, bool bMultiField )
153 ScDocument& rDoc = mrViewData.GetDocument();
154 SCTAB nTab = mrViewData.GetTabNo();
156 ScDPObject* pDPObj = rDoc.GetDPAtCursor(nCol, nRow, nTab);
158 if (pDPObj)
160 DataPilotFieldOrientation nOrient = DataPilotFieldOrientation_HIDDEN;
161 ScAddress aPos( nCol, nRow, nTab );
162 ScAddress aDimPos = aPos;
163 if (!bButton && bPopup && aDimPos.Col() > 0)
164 // For page field selection cell, the real field position is to the left.
165 aDimPos.IncCol(-1);
167 if (bMultiField && DPTestMultiFieldPopupArrow(rMEvt, aPos, pDPObj))
169 // Multi-field pop up menu has been launched. Don't activate
170 // field move or regular popup.
171 return;
174 tools::Long nField = pDPObj->GetHeaderDim(aDimPos, nOrient);
175 if ( nField >= 0 )
177 bDPMouse = false;
178 nDPField = nField;
179 pDragDPObj = pDPObj;
181 if (bPopup && DPTestFieldPopupArrow(rMEvt, aPos, aDimPos, pDPObj))
183 // field name pop up menu has been launched. Don't activate
184 // field move.
185 return;
188 if (bButton)
190 bDPMouse = true;
191 DPTestMouse( rMEvt, true );
192 StartTracking();
195 else if ( pDPObj->IsFilterButton(aPos) )
197 ReleaseMouse(); // may have been captured in ButtonDown
199 ScQueryParam aQueryParam;
200 SCTAB nSrcTab = 0;
201 const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
202 OSL_ENSURE(pDesc, "no sheet source for filter button");
203 if (pDesc)
205 aQueryParam = pDesc->GetQueryParam();
206 nSrcTab = pDesc->GetSourceRange().aStart.Tab();
209 SfxItemSetFixed<SCITEM_QUERYDATA, SCITEM_QUERYDATA> aArgSet( mrViewData.GetViewShell()->GetPool() );
210 aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA, &mrViewData, &aQueryParam ) );
212 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
214 ScopedVclPtr<AbstractScPivotFilterDlg> pDlg(
215 pFact->CreateScPivotFilterDlg(
216 mrViewData.GetViewShell()->GetFrameWeld(), aArgSet, nSrcTab));
217 if ( pDlg->Execute() == RET_OK )
219 ScSheetSourceDesc aNewDesc(&rDoc);
220 if (pDesc)
221 aNewDesc = *pDesc;
223 const ScQueryItem& rQueryItem = pDlg->GetOutputItem();
224 aNewDesc.SetQueryParam(rQueryItem.GetQueryData());
226 ScDPObject aNewObj( *pDPObj );
227 aNewObj.SetSheetDesc( aNewDesc );
228 ScDBDocFunc aFunc( *mrViewData.GetDocShell() );
229 aFunc.DataPilotUpdate( pDPObj, &aNewObj, true, false );
230 mrViewData.GetView()->CursorPosChanged(); // shells may be switched
234 else
236 OSL_FAIL("Nothing here");
240 void ScGridWindow::DoPushPivotToggle( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt )
242 bool bLayoutRTL = mrViewData.GetDocument().IsLayoutRTL( mrViewData.GetTabNo() );
244 ScDocument& rDoc = mrViewData.GetDocument();
245 SCTAB nTab = mrViewData.GetTabNo();
247 ScDPObject* pDPObj = rDoc.GetDPAtCursor(nCol, nRow, nTab);
248 if (!pDPObj)
249 return;
251 if (!pDPObj->GetSaveData()->GetDrillDown())
252 return;
254 // Get the geometry of the cell.
255 Point aScrPos = mrViewData.GetScrPos(nCol, nRow, eWhich);
256 tools::Long nSizeX, nSizeY;
257 mrViewData.GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
258 Size aScrSize(nSizeX - 1, nSizeY - 1);
260 sal_uInt16 nIndent = 0;
261 if (const ScIndentItem* pIndentItem = rDoc.GetAttr(nCol, nRow, nTab, ATTR_INDENT))
262 nIndent = pIndentItem->GetValue();
264 // Check if the mouse cursor is clicking on the toggle +/- box.
265 ScDPFieldButton aBtn(GetOutDev(), &GetSettings().GetStyleSettings(), &GetMapMode().GetScaleY());
266 aBtn.setBoundingBox(aScrPos, aScrSize, bLayoutRTL);
267 aBtn.setDrawToggleButton(true, true, nIndent);
268 Point aPopupPos;
269 Size aPopupSize;
270 aBtn.getToggleBoundingBox(aPopupPos, aPopupSize);
271 tools::Rectangle aRect(aPopupPos, aPopupSize);
272 if (aRect.Contains(rMEvt.GetPosPixel()))
274 // Mouse cursor inside the toggle +/- box.
275 sheet::DataPilotTableHeaderData aData;
276 ScAddress aCellPos(nCol, nRow, nTab);
277 pDPObj->GetHeaderPositionData(aCellPos, aData);
278 ScDPObject aNewObj(*pDPObj);
279 pDPObj->ToggleDetails(aData, &aNewObj);
280 ScDBDocFunc aFunc(*mrViewData.GetDocShell());
281 aFunc.DataPilotUpdate(pDPObj, &aNewObj, true, false);
285 // Data Pilot interaction
287 void ScGridWindow::DPTestMouse( const MouseEvent& rMEvt, bool bMove )
289 OSL_ENSURE(pDragDPObj, "pDragDPObj missing");
291 // scroll window if at edges
292 //! move this to separate method
294 bool bTimer = false;
295 Point aPixel = rMEvt.GetPosPixel();
297 SCCOL nDx = 0;
298 SCROW nDy = 0;
299 if ( aPixel.X() < 0 )
300 nDx = -1;
301 if ( aPixel.Y() < 0 )
302 nDy = -1;
303 Size aSize = GetOutputSizePixel();
304 if ( aPixel.X() >= aSize.Width() )
305 nDx = 1;
306 if ( aPixel.Y() >= aSize.Height() )
307 nDy = 1;
308 if ( nDx != 0 || nDy != 0 )
310 UpdateDragRect( false, tools::Rectangle() );
312 if ( nDx != 0)
313 mrViewData.GetView()->ScrollX( nDx, WhichH(eWhich) );
314 if ( nDy != 0 )
315 mrViewData.GetView()->ScrollY( nDy, WhichV(eWhich) );
317 bTimer = true;
320 SCCOL nPosX;
321 SCROW nPosY;
322 mrViewData.GetPosFromPixel( aPixel.X(), aPixel.Y(), eWhich, nPosX, nPosY );
323 bool bMouseLeft;
324 bool bMouseTop;
325 mrViewData.GetMouseQuadrant( aPixel, eWhich, nPosX, nPosY, bMouseLeft, bMouseTop );
327 ScAddress aPos( nPosX, nPosY, mrViewData.GetTabNo() );
329 tools::Rectangle aPosRect;
330 DataPilotFieldOrientation nOrient;
331 tools::Long nDimPos;
332 bool bHasRange = pDragDPObj->GetHeaderDrag( aPos, bMouseLeft, bMouseTop, nDPField,
333 aPosRect, nOrient, nDimPos );
334 UpdateDragRect( bHasRange && bMove, aPosRect );
336 bool bIsDataLayout;
337 sal_Int32 nDimFlags = 0;
338 OUString aDimName = pDragDPObj->GetDimName( nDPField, bIsDataLayout, &nDimFlags );
339 bool bAllowed = !bHasRange || ScDPObject::IsOrientationAllowed( nOrient, nDimFlags );
341 if (bMove) // set mouse pointer
343 PointerStyle ePointer = PointerStyle::PivotDelete;
344 if ( !bAllowed )
345 ePointer = PointerStyle::NotAllowed;
346 else if ( bHasRange )
347 switch (nOrient)
349 case DataPilotFieldOrientation_COLUMN: ePointer = PointerStyle::PivotCol; break;
350 case DataPilotFieldOrientation_ROW: ePointer = PointerStyle::PivotRow; break;
351 case DataPilotFieldOrientation_PAGE:
352 case DataPilotFieldOrientation_DATA: ePointer = PointerStyle::PivotField; break;
353 default: break;
355 SetPointer( ePointer );
357 else // execute change
359 if (!bHasRange)
360 nOrient = DataPilotFieldOrientation_HIDDEN;
362 if ( bIsDataLayout && ( nOrient != DataPilotFieldOrientation_COLUMN &&
363 nOrient != DataPilotFieldOrientation_ROW ) )
365 // removing data layout is not allowed
366 mrViewData.GetView()->ErrorMessage(STR_PIVOT_MOVENOTALLOWED);
368 else if ( bAllowed )
370 ScDPSaveData aSaveData( *pDragDPObj->GetSaveData() );
372 ScDPSaveDimension* pDim;
373 if ( bIsDataLayout )
374 pDim = aSaveData.GetDataLayoutDimension();
375 else
376 pDim = aSaveData.GetDimensionByName(aDimName);
377 pDim->SetOrientation( nOrient );
378 aSaveData.SetPosition( pDim, nDimPos );
380 //! docfunc method with ScDPSaveData as argument?
382 ScDPObject aNewObj( *pDragDPObj );
383 aNewObj.SetSaveData( aSaveData );
384 ScDBDocFunc aFunc( *mrViewData.GetDocShell() );
385 // when dragging fields, allow re-positioning (bAllowMove)
386 aFunc.DataPilotUpdate( pDragDPObj, &aNewObj, true, false, true );
387 mrViewData.GetView()->CursorPosChanged(); // shells may be switched
391 if (bTimer && bMove)
392 mrViewData.GetView()->SetTimer( this, rMEvt ); // repeat event
393 else
394 mrViewData.GetView()->ResetTimer();
397 bool ScGridWindow::DPTestFieldPopupArrow(
398 const MouseEvent& rMEvt, const ScAddress& rPos, const ScAddress& rDimPos, ScDPObject* pDPObj)
400 bool bLayoutRTL = mrViewData.GetDocument().IsLayoutRTL( mrViewData.GetTabNo() );
401 bool bLOK = comphelper::LibreOfficeKit::isActive();
403 // Get the geometry of the cell.
404 Point aScrPos = mrViewData.GetScrPos(rPos.Col(), rPos.Row(), eWhich);
405 tools::Long nSizeX, nSizeY;
406 mrViewData.GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeX, nSizeY);
407 Size aScrSize(nSizeX-1, nSizeY-1);
409 // Check if the mouse cursor is clicking on the popup arrow box.
410 ScDPFieldButton aBtn(GetOutDev(), &GetSettings().GetStyleSettings(), &GetMapMode().GetScaleY());
411 aBtn.setBoundingBox(aScrPos, aScrSize, bLayoutRTL);
412 aBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now
413 Point aPopupPos;
414 Size aPopupSize;
415 aBtn.getPopupBoundingBox(aPopupPos, aPopupSize);
416 tools::Rectangle aRect(aPopupPos, aPopupSize);
417 if (aRect.Contains(rMEvt.GetPosPixel()))
419 // Mouse cursor inside the popup arrow box. Launch the field menu.
420 DPLaunchFieldPopupMenu(bLOK ? aScrPos : OutputToScreenPixel(aScrPos), aScrSize, rDimPos, pDPObj);
421 return true;
424 return false;
427 bool ScGridWindow::DPTestMultiFieldPopupArrow(
428 const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj)
430 bool bLayoutRTL = mrViewData.GetDocument().IsLayoutRTL( mrViewData.GetTabNo() );
431 bool bLOK = comphelper::LibreOfficeKit::isActive();
433 // Get the geometry of the cell.
434 Point aScrPos = mrViewData.GetScrPos(rPos.Col(), rPos.Row(), eWhich);
435 tools::Long nSizeX, nSizeY;
436 mrViewData.GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeX, nSizeY);
437 Size aScrSize(nSizeX - 1, nSizeY - 1);
439 // Check if the mouse cursor is clicking on the popup arrow box.
440 ScDPFieldButton aBtn(GetOutDev(), &GetSettings().GetStyleSettings(), &GetMapMode().GetScaleY());
441 aBtn.setBoundingBox(aScrPos, aScrSize, bLayoutRTL);
442 aBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now
443 aBtn.setDrawPopupButtonMulti(true);
444 Point aPopupPos;
445 Size aPopupSize;
446 aBtn.getPopupBoundingBox(aPopupPos, aPopupSize);
447 tools::Rectangle aRect(aPopupPos, aPopupSize);
448 if (aRect.Contains(rMEvt.GetPosPixel()))
450 DataPilotFieldOrientation nOrient;
451 pDPObj->GetHeaderDim(rPos, nOrient);
452 // Mouse cursor inside the popup arrow box. Launch the multi-field menu.
453 DPLaunchMultiFieldPopupMenu(bLOK ? aScrPos : OutputToScreenPixel(aScrPos), aScrSize, pDPObj, nOrient);
454 return true;
457 return false;
460 namespace {
462 struct DPFieldPopupData : public ScCheckListMenuControl::ExtendedData
464 ScDPLabelData maLabels;
465 ScDPObject* mpDPObj;
466 tools::Long mnDim;
469 struct DPMultiFieldPopupData : public DPFieldPopupData
471 std::vector<tools::Long> maFieldIndices;
472 std::vector<OUString> maFieldNames;
475 class DPFieldPopupOKAction : public ScCheckListMenuControl::Action
477 public:
478 explicit DPFieldPopupOKAction(ScGridWindow* p) :
479 mpGridWindow(p) {}
481 virtual bool execute() override
483 mpGridWindow->UpdateDPFromFieldPopupMenu();
484 return true;
486 private:
487 VclPtr<ScGridWindow> mpGridWindow;
490 class DPFieldChangedAction : public ScCheckListMenuControl::Action
492 public:
493 explicit DPFieldChangedAction(ScGridWindow* p) :
494 mpGridWindow(p) {}
496 virtual bool execute() override
498 mpGridWindow->UpdateDPPopupMenuForFieldChange();
499 return true;
501 private:
502 VclPtr<ScGridWindow> mpGridWindow;
505 class PopupSortAction : public ScCheckListMenuControl::Action
507 public:
508 enum SortType { ASCENDING, DESCENDING, CUSTOM };
510 explicit PopupSortAction(ScDPObject* pDPObject, tools::Long nDimIndex, SortType eType,
511 sal_uInt16 nUserListIndex, ScTabViewShell* pViewShell)
512 : mpDPObject(pDPObject)
513 , mnDimIndex(nDimIndex)
514 , meType(eType)
515 , mnUserListIndex(nUserListIndex)
516 , mpViewShell(pViewShell)
519 virtual bool execute() override
521 switch (meType)
523 case ASCENDING:
524 mpViewShell->DataPilotSort(mpDPObject, mnDimIndex, true);
525 break;
526 case DESCENDING:
527 mpViewShell->DataPilotSort(mpDPObject, mnDimIndex, false);
528 break;
529 case CUSTOM:
530 mpViewShell->DataPilotSort(mpDPObject, mnDimIndex, true, &mnUserListIndex);
531 break;
532 default:
535 return true;
538 private:
539 ScDPObject* mpDPObject;
540 tools::Long mnDimIndex;
541 SortType meType;
542 sal_uInt16 mnUserListIndex;
543 ScTabViewShell* mpViewShell;
548 void ScGridWindow::DPLaunchFieldPopupMenu(const Point& rScreenPosition, const Size& rScreenSize,
549 const ScAddress& rAddress, ScDPObject* pDPObject)
551 DataPilotFieldOrientation nOrient;
552 tools::Long nDimIndex = pDPObject->GetHeaderDim(rAddress, nOrient);
554 DPLaunchFieldPopupMenu(rScreenPosition, rScreenSize, nDimIndex, pDPObject);
557 bool lcl_FillDPFieldPopupData(tools::Long nDimIndex, ScDPObject* pDPObj,
558 DPFieldPopupData& rDPData, bool& bDimOrientNotPage)
560 if (!pDPObj)
561 return false;
563 rDPData.mnDim = nDimIndex;
564 pDPObj->GetSource();
566 bool bIsDataLayout;
567 OUString aDimName = pDPObj->GetDimName(rDPData.mnDim, bIsDataLayout);
568 pDPObj->BuildAllDimensionMembers();
569 const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
570 const ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName);
571 if (!pDim)
572 // This should never happen.
573 return false;
575 bDimOrientNotPage = pDim->GetOrientation() != DataPilotFieldOrientation_PAGE;
577 // We need to get the list of field members.
578 pDPObj->FillLabelData(rDPData.mnDim, rDPData.maLabels);
579 rDPData.mpDPObj = pDPObj;
581 return true;
584 void ScGridWindow::DPLaunchMultiFieldPopupMenu(const Point& rScreenPosition, const Size& rScreenSize,
585 ScDPObject* pDPObj, DataPilotFieldOrientation nOrient)
587 if (!pDPObj)
588 return;
590 pDPObj->GetSource();
592 std::unique_ptr<DPMultiFieldPopupData> pDPData(new DPMultiFieldPopupData);
593 pDPObj->GetFieldIdsNames(nOrient, pDPData->maFieldIndices, pDPData->maFieldNames);
595 if (pDPData->maFieldIndices.empty())
596 return;
598 tools::Long nDimIndex = pDPData->maFieldIndices[0];
600 bool bDimOrientNotPage = true;
601 if (!lcl_FillDPFieldPopupData(nDimIndex, pDPObj, *pDPData, bDimOrientNotPage))
602 return;
604 mpDPFieldPopup.reset();
606 weld::Window* pPopupParent = GetFrameWeld();
607 mpDPFieldPopup.reset(new ScCheckListMenuControl(pPopupParent, mrViewData,
608 false, -1, true));
610 mpDPFieldPopup->addFields(pDPData->maFieldNames);
611 DPSetupFieldPopup(std::move(pDPData), bDimOrientNotPage, pDPObj, true);
613 DPConfigFieldPopup();
615 if (IsMouseCaptured())
616 ReleaseMouse();
618 tools::Rectangle aCellRect(rScreenPosition, rScreenSize);
619 mpDPFieldPopup->launch(pPopupParent, aCellRect);
622 void ScGridWindow::DPPopulateFieldMembers(const ScDPLabelData& rLabelData)
624 // Populate field members.
625 size_t n = rLabelData.maMembers.size();
626 mpDPFieldPopup->setMemberSize(n);
627 for (size_t i = 0; i < n; ++i)
629 const ScDPLabelData::Member& rMem = rLabelData.maMembers[i];
630 OUString aName = rMem.getDisplayName();
631 if (aName.isEmpty())
632 // Use special string for an empty name.
633 mpDPFieldPopup->addMember(ScResId(STR_EMPTYDATA), 0.0, rMem.mbVisible, false);
634 else
635 mpDPFieldPopup->addMember(rMem.getDisplayName(), 0.0, rMem.mbVisible, false);
639 void ScGridWindow::DPSetupFieldPopup(std::unique_ptr<ScCheckListMenuControl::ExtendedData> pDPData,
640 bool bDimOrientNotPage, ScDPObject* pDPObj,
641 bool bMultiField)
643 if (!mpDPFieldPopup || !pDPObj)
644 return;
646 const ScDPLabelData& rLabelData = static_cast<DPFieldPopupData*>(pDPData.get())->maLabels;
647 const tools::Long nDimIndex = static_cast<DPFieldPopupData*>(pDPData.get())->mnDim;
648 mpDPFieldPopup->setExtendedData(std::move(pDPData));
650 if (bMultiField)
651 mpDPFieldPopup->setFieldChangedAction(new DPFieldChangedAction(this));
653 mpDPFieldPopup->setOKAction(new DPFieldPopupOKAction(this));
654 DPPopulateFieldMembers(rLabelData);
656 if (bDimOrientNotPage)
658 vector<OUString> aUserSortNames;
659 ScUserList& rUserList = ScGlobal::GetUserList();
660 size_t nUserListSize = rUserList.size();
661 aUserSortNames.reserve(nUserListSize);
662 for (size_t i = 0; i < nUserListSize; ++i)
664 const ScUserListData& rData = rUserList[i];
665 aUserSortNames.push_back(rData.GetString());
668 // Populate the menus.
669 ScTabViewShell* pViewShell = mrViewData.GetViewShell();
670 mpDPFieldPopup->addMenuItem(
671 ScResId(STR_MENU_SORT_ASC),
672 new PopupSortAction(pDPObj, nDimIndex, PopupSortAction::ASCENDING, 0, pViewShell));
673 mpDPFieldPopup->addMenuItem(
674 ScResId(STR_MENU_SORT_DESC),
675 new PopupSortAction(pDPObj, nDimIndex, PopupSortAction::DESCENDING, 0, pViewShell));
677 ScListSubMenuControl* pSubMenu = mpDPFieldPopup->addSubMenuItem(ScResId(STR_MENU_SORT_CUSTOM), !aUserSortNames.empty(), false);
678 if (pSubMenu)
680 size_t n = aUserSortNames.size();
681 for (size_t i = 0; i < n; ++i)
683 pSubMenu->addMenuItem(aUserSortNames[i],
684 new PopupSortAction(pDPObj, nDimIndex, PopupSortAction::CUSTOM, sal_uInt16(i), pViewShell));
686 pSubMenu->resizeToFitMenuItems();
690 mpDPFieldPopup->initMembers();
693 void ScGridWindow::DPConfigFieldPopup()
695 if (!mpDPFieldPopup)
696 return;
698 ScCheckListMenuControl::Config aConfig;
699 aConfig.mbAllowEmptySet = false;
700 aConfig.mbRTL = mrViewData.GetDocument().IsLayoutRTL(mrViewData.GetTabNo());
701 mpDPFieldPopup->setConfig(aConfig);
704 void ScGridWindow::DPLaunchFieldPopupMenu(const Point& rScrPos, const Size& rScrSize,
705 tools::Long nDimIndex, ScDPObject* pDPObj)
707 std::unique_ptr<DPFieldPopupData> pDPData(new DPFieldPopupData);
708 bool bDimOrientNotPage = true;
709 if (!lcl_FillDPFieldPopupData(nDimIndex, pDPObj, *pDPData, bDimOrientNotPage))
710 return;
712 mpDPFieldPopup.reset();
714 vcl::ILibreOfficeKitNotifier* pNotifier = nullptr;
715 if (comphelper::LibreOfficeKit::isActive())
716 pNotifier = SfxViewShell::Current();
718 weld::Window* pPopupParent = GetFrameWeld();
719 mpDPFieldPopup.reset(new ScCheckListMenuControl(pPopupParent, mrViewData,
720 false, -1, pNotifier));
722 DPSetupFieldPopup(std::move(pDPData), bDimOrientNotPage, pDPObj);
724 DPConfigFieldPopup();
726 if (IsMouseCaptured())
727 ReleaseMouse();
729 tools::Rectangle aCellRect(rScrPos, rScrSize);
730 mpDPFieldPopup->launch(pPopupParent, aCellRect);
733 void ScGridWindow::UpdateDPPopupMenuForFieldChange()
735 if (!mpDPFieldPopup)
736 return;
738 DPMultiFieldPopupData* pDPData = static_cast<DPMultiFieldPopupData*>(mpDPFieldPopup->getExtendedData());
739 if (!pDPData)
740 return;
742 if (pDPData->maFieldIndices.empty())
743 return;
745 tools::Long nIndex = mpDPFieldPopup->getField();
746 if (nIndex < 0)
747 return;
749 tools::Long nDimIndex = pDPData->maFieldIndices[nIndex];
750 if (nDimIndex == pDPData->mnDim)
751 return;
753 bool bDimOrientNotPage = true;
754 if (!lcl_FillDPFieldPopupData(nDimIndex, pDPData->mpDPObj, *pDPData, bDimOrientNotPage))
755 return;
757 mpDPFieldPopup->clearMembers();
759 DPPopulateFieldMembers(pDPData->maLabels);
761 mpDPFieldPopup->initMembers();
764 void ScGridWindow::UpdateDPFromFieldPopupMenu()
766 typedef std::unordered_map<OUString, OUString> MemNameMapType;
768 if (!mpDPFieldPopup)
769 return;
771 DPFieldPopupData* pDPData = static_cast<DPFieldPopupData*>(mpDPFieldPopup->getExtendedData());
772 if (!pDPData)
773 return;
775 ScDPObject* pDPObj = pDPData->mpDPObj;
776 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
778 bool bIsDataLayout;
779 OUString aDimName = pDPObj->GetDimName(pDPData->mnDim, bIsDataLayout);
780 ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aDimName);
781 if (!pDim)
782 return;
784 // Build a map of layout names to original names.
785 const ScDPLabelData& rLabelData = pDPData->maLabels;
786 MemNameMapType aMemNameMap;
787 for (const auto& rMember : rLabelData.maMembers)
788 aMemNameMap.emplace(rMember.maLayoutName, rMember.maName);
790 // The raw result may contain a mixture of layout names and original names.
791 ScCheckListMenuControl::ResultType aRawResult;
792 mpDPFieldPopup->getResult(aRawResult);
794 std::unordered_map<OUString, bool> aResult;
795 for (const auto& rItem : aRawResult)
797 MemNameMapType::const_iterator itrNameMap = aMemNameMap.find(rItem.aName);
798 if (itrNameMap == aMemNameMap.end())
800 // This is an original member name. Use it as-is.
801 OUString aName = rItem.aName;
802 if (aName == ScResId(STR_EMPTYDATA))
803 // Translate the special empty name into an empty string.
804 aName.clear();
806 aResult.emplace(aName, rItem.bValid);
808 else
810 // This is a layout name. Get the original member name and use it.
811 aResult.emplace(itrNameMap->second, rItem.bValid);
814 pDim->UpdateMemberVisibility(aResult);
816 ScDBDocFunc aFunc(*mrViewData.GetDocShell());
817 aFunc.UpdatePivotTable(*pDPObj, true, false);
820 namespace {
822 template <typename T>
823 inline
824 T lcl_getValidValue(T value, T defvalue)
826 return (value <0) ? defvalue : value;
829 } // anonymous namespace
831 bool ScGridWindow::UpdateVisibleRange()
833 ScDocument const& rDoc = mrViewData.GetDocument();
834 SCCOL nPosX = 0;
835 SCROW nPosY = 0;
836 SCCOL nXRight = rDoc.MaxCol();
837 SCROW nYBottom = rDoc.MaxRow();
839 if (comphelper::LibreOfficeKit::isActive())
841 ScTabViewShell* pViewShell = mrViewData.GetViewShell();
842 nPosX = lcl_getValidValue(pViewShell->GetLOKStartHeaderCol(), nPosX);
843 nPosY = lcl_getValidValue(pViewShell->GetLOKStartHeaderRow(), nPosY);
844 nXRight = lcl_getValidValue(pViewShell->GetLOKEndHeaderCol(), nXRight);
845 nYBottom = lcl_getValidValue(pViewShell->GetLOKEndHeaderRow(), nYBottom);
847 else
849 nPosX = mrViewData.GetPosX(eHWhich);
850 nPosY = mrViewData.GetPosY(eVWhich);
851 nXRight = nPosX + mrViewData.VisibleCellsX(eHWhich);
852 if (nXRight > rDoc.MaxCol())
853 nXRight = rDoc.MaxCol();
854 nYBottom = nPosY + mrViewData.VisibleCellsY(eVWhich);
855 if (nYBottom > rDoc.MaxRow())
856 nYBottom = rDoc.MaxRow();
859 // Store the current visible range.
860 return maVisibleRange.set(nPosX, nPosY, nXRight, nYBottom);
863 void ScGridWindow::DPMouseMove( const MouseEvent& rMEvt )
865 DPTestMouse( rMEvt, true );
868 void ScGridWindow::DPMouseButtonUp( const MouseEvent& rMEvt )
870 bDPMouse = false;
871 ReleaseMouse();
873 DPTestMouse( rMEvt, false );
874 SetPointer( PointerStyle::Arrow );
877 void ScGridWindow::UpdateDragRect( bool bShowRange, const tools::Rectangle& rPosRect )
879 SCCOL nStartX = ( rPosRect.Left() >= 0 ) ? static_cast<SCCOL>(rPosRect.Left()) : SCCOL_MAX;
880 SCROW nStartY = ( rPosRect.Top() >= 0 ) ? static_cast<SCROW>(rPosRect.Top()) : SCROW_MAX;
881 SCCOL nEndX = ( rPosRect.Right() >= 0 ) ? static_cast<SCCOL>(rPosRect.Right()) : SCCOL_MAX;
882 SCROW nEndY = ( rPosRect.Bottom() >= 0 ) ? static_cast<SCROW>(rPosRect.Bottom()) : SCROW_MAX;
884 if ( bShowRange == bDragRect && nDragStartX == nStartX && nDragEndX == nEndX &&
885 nDragStartY == nStartY && nDragEndY == nEndY )
887 return; // everything unchanged
890 if ( bShowRange )
892 nDragStartX = nStartX;
893 nDragStartY = nStartY;
894 nDragEndX = nEndX;
895 nDragEndY = nEndY;
896 bDragRect = true;
898 else
899 bDragRect = false;
901 UpdateDragRectOverlay();
904 // Page-Break Mode
906 sal_uInt16 ScGridWindow::HitPageBreak( const Point& rMouse, ScRange* pSource,
907 SCCOLROW* pBreak, SCCOLROW* pPrev )
909 sal_uInt16 nFound = SC_PD_NONE; // 0
910 ScRange aSource;
911 SCCOLROW nBreak = 0;
912 SCCOLROW nPrev = 0;
914 ScPageBreakData* pPageData = mrViewData.GetView()->GetPageBreakData();
915 if ( pPageData )
917 bool bHori = false;
918 bool bVert = false;
919 SCCOL nHitX = 0;
920 SCROW nHitY = 0;
922 tools::Long nMouseX = rMouse.X();
923 tools::Long nMouseY = rMouse.Y();
924 SCCOL nPosX;
925 SCROW nPosY;
926 mrViewData.GetPosFromPixel( nMouseX, nMouseY, eWhich, nPosX, nPosY );
927 Point aTL = mrViewData.GetScrPos( nPosX, nPosY, eWhich );
928 Point aBR = mrViewData.GetScrPos( nPosX+1, nPosY+1, eWhich );
930 // Horizontal more tolerances as for vertical, because there is more space
931 if ( nMouseX <= aTL.X() + 4 )
933 bHori = true;
934 nHitX = nPosX;
936 else if ( nMouseX >= aBR.X() - 6 )
938 bHori = true;
939 nHitX = nPosX+1; // left edge of the next cell
941 if ( nMouseY <= aTL.Y() + 2 )
943 bVert = true;
944 nHitY = nPosY;
946 else if ( nMouseY >= aBR.Y() - 4 )
948 bVert = true;
949 nHitY = nPosY+1; // upper edge of the next cell
952 if ( bHori || bVert )
954 sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
955 for (sal_uInt16 nPos=0; nPos<nCount && !nFound; nPos++)
957 ScPrintRangeData& rData = pPageData->GetData(nPos);
958 ScRange aRange = rData.GetPrintRange();
959 bool bLHit = ( bHori && nHitX == aRange.aStart.Col() );
960 bool bRHit = ( bHori && nHitX == aRange.aEnd.Col() + 1 );
961 bool bTHit = ( bVert && nHitY == aRange.aStart.Row() );
962 bool bBHit = ( bVert && nHitY == aRange.aEnd.Row() + 1 );
963 bool bInsideH = ( nPosX >= aRange.aStart.Col() && nPosX <= aRange.aEnd.Col() );
964 bool bInsideV = ( nPosY >= aRange.aStart.Row() && nPosY <= aRange.aEnd.Row() );
966 if ( bLHit )
968 if ( bTHit )
969 nFound = SC_PD_RANGE_TL;
970 else if ( bBHit )
971 nFound = SC_PD_RANGE_BL;
972 else if ( bInsideV )
973 nFound = SC_PD_RANGE_L;
975 else if ( bRHit )
977 if ( bTHit )
978 nFound = SC_PD_RANGE_TR;
979 else if ( bBHit )
980 nFound = SC_PD_RANGE_BR;
981 else if ( bInsideV )
982 nFound = SC_PD_RANGE_R;
984 else if ( bTHit && bInsideH )
985 nFound = SC_PD_RANGE_T;
986 else if ( bBHit && bInsideH )
987 nFound = SC_PD_RANGE_B;
988 if (nFound)
989 aSource = aRange;
991 // breaks
993 if ( bVert && bInsideH && !nFound )
995 size_t nRowCount = rData.GetPagesY();
996 const SCROW* pRowEnd = rData.GetPageEndY();
997 for (size_t nRowPos=0; nRowPos+1<nRowCount; nRowPos++)
998 if ( pRowEnd[nRowPos]+1 == nHitY )
1000 nFound = SC_PD_BREAK_V;
1001 aSource = aRange;
1002 nBreak = nHitY;
1003 if ( nRowPos )
1004 nPrev = pRowEnd[nRowPos-1]+1;
1005 else
1006 nPrev = aRange.aStart.Row();
1009 if ( bHori && bInsideV && !nFound )
1011 size_t nColCount = rData.GetPagesX();
1012 const SCCOL* pColEnd = rData.GetPageEndX();
1013 for (size_t nColPos=0; nColPos+1<nColCount; nColPos++)
1014 if ( pColEnd[nColPos]+1 == nHitX )
1016 nFound = SC_PD_BREAK_H;
1017 aSource = aRange;
1018 nBreak = nHitX;
1019 if ( nColPos )
1020 nPrev = pColEnd[nColPos-1]+1;
1021 else
1022 nPrev = aRange.aStart.Col();
1029 if (pSource)
1030 *pSource = aSource; // print break
1031 if (pBreak)
1032 *pBreak = nBreak; // X/Y position of the moved page break
1033 if (pPrev)
1034 *pPrev = nPrev; // X/Y beginning of the page, which is above the break
1035 return nFound;
1038 void ScGridWindow::PagebreakMove( const MouseEvent& rMEvt, bool bUp )
1040 //! Combine scrolling and switching with RFMouseMove !
1041 //! (Inverting before scrolling is different)
1043 // Scrolling
1045 bool bTimer = false;
1046 Point aPos = rMEvt.GetPosPixel();
1047 SCCOL nDx = 0;
1048 SCROW nDy = 0;
1049 if ( aPos.X() < 0 ) nDx = -1;
1050 if ( aPos.Y() < 0 ) nDy = -1;
1051 Size aSize = GetOutputSizePixel();
1052 if ( aPos.X() >= aSize.Width() )
1053 nDx = 1;
1054 if ( aPos.Y() >= aSize.Height() )
1055 nDy = 1;
1056 if ( nDx != 0 || nDy != 0 )
1058 if ( bPagebreakDrawn ) // invert
1060 bPagebreakDrawn = false;
1061 UpdateDragRectOverlay();
1064 if ( nDx != 0 ) mrViewData.GetView()->ScrollX( nDx, WhichH(eWhich) );
1065 if ( nDy != 0 ) mrViewData.GetView()->ScrollY( nDy, WhichV(eWhich) );
1066 bTimer = true;
1069 // Switching when fixating (so Scrolling works)
1071 if ( eWhich == mrViewData.GetActivePart() ) //??
1073 if ( mrViewData.GetHSplitMode() == SC_SPLIT_FIX )
1074 if ( nDx > 0 )
1076 if ( eWhich == SC_SPLIT_TOPLEFT )
1077 mrViewData.GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
1078 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
1079 mrViewData.GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
1082 if ( mrViewData.GetVSplitMode() == SC_SPLIT_FIX )
1083 if ( nDy > 0 )
1085 if ( eWhich == SC_SPLIT_TOPLEFT )
1086 mrViewData.GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
1087 else if ( eWhich == SC_SPLIT_TOPRIGHT )
1088 mrViewData.GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
1092 // from here new
1094 // Searching for a position between the cells (before nPosX / nPosY)
1095 SCCOL nPosX;
1096 SCROW nPosY;
1097 mrViewData.GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1098 bool bLeft, bTop;
1099 mrViewData.GetMouseQuadrant( aPos, eWhich, nPosX, nPosY, bLeft, bTop );
1100 if ( !bLeft ) ++nPosX;
1101 if ( !bTop ) ++nPosY;
1103 bool bBreak = ( nPagebreakMouse == SC_PD_BREAK_H || nPagebreakMouse == SC_PD_BREAK_V );
1104 bool bHide = false;
1105 bool bToEnd = false;
1106 ScRange aDrawRange = aPagebreakSource;
1107 if ( bBreak )
1109 if ( nPagebreakMouse == SC_PD_BREAK_H )
1111 if ( nPosX > aPagebreakSource.aStart.Col() &&
1112 nPosX <= aPagebreakSource.aEnd.Col() + 1 ) // to the end is also allowed
1114 bToEnd = ( nPosX == aPagebreakSource.aEnd.Col() + 1 );
1115 aDrawRange.aStart.SetCol( nPosX );
1116 aDrawRange.aEnd.SetCol( nPosX - 1 );
1118 else
1119 bHide = true;
1121 else
1123 if ( nPosY > aPagebreakSource.aStart.Row() &&
1124 nPosY <= aPagebreakSource.aEnd.Row() + 1 ) // to the end is also allowed
1126 bToEnd = ( nPosY == aPagebreakSource.aEnd.Row() + 1 );
1127 aDrawRange.aStart.SetRow( nPosY );
1128 aDrawRange.aEnd.SetRow( nPosY - 1 );
1130 else
1131 bHide = true;
1134 else
1136 if ( nPagebreakMouse & SC_PD_RANGE_L )
1137 aDrawRange.aStart.SetCol( nPosX );
1138 if ( nPagebreakMouse & SC_PD_RANGE_T )
1139 aDrawRange.aStart.SetRow( nPosY );
1140 if ( nPagebreakMouse & SC_PD_RANGE_R )
1142 if ( nPosX > 0 )
1143 aDrawRange.aEnd.SetCol( nPosX-1 );
1144 else
1145 bHide = true;
1147 if ( nPagebreakMouse & SC_PD_RANGE_B )
1149 if ( nPosY > 0 )
1150 aDrawRange.aEnd.SetRow( nPosY-1 );
1151 else
1152 bHide = true;
1154 if ( aDrawRange.aStart.Col() > aDrawRange.aEnd.Col() ||
1155 aDrawRange.aStart.Row() > aDrawRange.aEnd.Row() )
1156 bHide = true;
1159 if ( !bPagebreakDrawn || bUp || aDrawRange != aPagebreakDrag )
1161 // draw...
1163 if ( bPagebreakDrawn )
1165 // invert
1166 bPagebreakDrawn = false;
1168 aPagebreakDrag = aDrawRange;
1169 if ( !bUp && !bHide )
1171 // revert
1172 bPagebreakDrawn = true;
1174 UpdateDragRectOverlay();
1177 // when ButtonUp execute the changes
1179 if ( bUp )
1181 ScViewFunc* pViewFunc = mrViewData.GetView();
1182 ScDocShell* pDocSh = mrViewData.GetDocShell();
1183 ScDocument& rDoc = pDocSh->GetDocument();
1184 SCTAB nTab = mrViewData.GetTabNo();
1185 bool bUndo (rDoc.IsUndoEnabled());
1187 if ( bBreak )
1189 bool bColumn = ( nPagebreakMouse == SC_PD_BREAK_H );
1190 SCCOLROW nNew = bColumn ? static_cast<SCCOLROW>(nPosX) : static_cast<SCCOLROW>(nPosY);
1191 if ( nNew != nPagebreakBreak )
1193 if (bUndo)
1195 OUString aUndo = ScResId( STR_UNDO_DRAG_BREAK );
1196 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo, 0, mrViewData.GetViewShell()->GetViewShellId() );
1199 bool bGrow = !bHide && nNew > nPagebreakBreak;
1200 if ( bColumn )
1202 if (rDoc.HasColBreak(static_cast<SCCOL>(nPagebreakBreak), nTab) & ScBreakType::Manual)
1204 ScAddress aOldAddr( static_cast<SCCOL>(nPagebreakBreak), nPosY, nTab );
1205 pViewFunc->DeletePageBreak( true, true, &aOldAddr, false );
1207 if ( !bHide && !bToEnd ) // not at the end
1209 ScAddress aNewAddr( static_cast<SCCOL>(nNew), nPosY, nTab );
1210 pViewFunc->InsertPageBreak( true, true, &aNewAddr, false );
1212 if ( bGrow )
1214 // change last break to hard, and change scaling
1215 bool bManualBreak(rDoc.HasColBreak(static_cast<SCCOL>(nPagebreakPrev), nTab) & ScBreakType::Manual);
1216 if ( static_cast<SCCOL>(nPagebreakPrev) > aPagebreakSource.aStart.Col() && !bManualBreak )
1218 ScAddress aPrev( static_cast<SCCOL>(nPagebreakPrev), nPosY, nTab );
1219 pViewFunc->InsertPageBreak( true, true, &aPrev, false );
1222 if (!pDocSh->AdjustPrintZoom( ScRange(
1223 static_cast<SCCOL>(nPagebreakPrev),0,nTab, static_cast<SCCOL>(nNew-1),0,nTab ) ))
1224 bGrow = false;
1227 else
1229 if (rDoc.HasRowBreak(nPagebreakBreak, nTab) & ScBreakType::Manual)
1231 ScAddress aOldAddr( nPosX, nPagebreakBreak, nTab );
1232 pViewFunc->DeletePageBreak( false, true, &aOldAddr, false );
1234 if ( !bHide && !bToEnd ) // not at the end
1236 ScAddress aNewAddr( nPosX, nNew, nTab );
1237 pViewFunc->InsertPageBreak( false, true, &aNewAddr, false );
1239 if ( bGrow )
1241 // change last break to hard, and change scaling
1242 bool bManualBreak(rDoc.HasRowBreak(nPagebreakPrev, nTab) & ScBreakType::Manual);
1243 if ( nPagebreakPrev > aPagebreakSource.aStart.Row() && !bManualBreak )
1245 ScAddress aPrev( nPosX, nPagebreakPrev, nTab );
1246 pViewFunc->InsertPageBreak( false, true, &aPrev, false );
1249 if (!pDocSh->AdjustPrintZoom( ScRange(
1250 0,nPagebreakPrev,nTab, 0,nNew-1,nTab ) ))
1251 bGrow = false;
1255 if (bUndo)
1257 pDocSh->GetUndoManager()->LeaveListAction();
1260 if (!bGrow) // otherwise has already happened in AdjustPrintZoom
1262 pViewFunc->UpdatePageBreakData( true );
1263 pDocSh->SetDocumentModified();
1267 else if ( bHide || aPagebreakDrag != aPagebreakSource )
1269 // set print range
1271 OUString aNewRanges;
1272 sal_uInt16 nOldCount = rDoc.GetPrintRangeCount( nTab );
1273 if ( nOldCount )
1275 for (sal_uInt16 nPos=0; nPos<nOldCount; nPos++)
1277 const ScRange* pOld = rDoc.GetPrintRange( nTab, nPos );
1278 if ( pOld )
1280 OUString aTemp;
1281 if ( *pOld != aPagebreakSource )
1282 aTemp = pOld->Format(rDoc, ScRefFlags::VALID);
1283 else if ( !bHide )
1284 aTemp = aPagebreakDrag.Format(rDoc, ScRefFlags::VALID);
1285 if (!aTemp.isEmpty())
1287 if ( !aNewRanges.isEmpty() )
1288 aNewRanges += ";";
1289 aNewRanges += aTemp;
1294 else if (!bHide)
1295 aNewRanges = aPagebreakDrag.Format(rDoc, ScRefFlags::VALID);
1297 pViewFunc->SetPrintRanges( rDoc.IsPrintEntireSheet( nTab ), &aNewRanges, nullptr, nullptr, false );
1301 // Timer for Scrolling
1303 if (bTimer && !bUp)
1304 mrViewData.GetView()->SetTimer( this, rMEvt ); // repeat event
1305 else
1306 mrViewData.GetView()->ResetTimer();
1309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */