1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
25 #include <gridwin.hxx>
26 #include <tabvwsh.hxx>
28 #include <viewdata.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>
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>
52 using namespace css::sheet
;
53 using css::sheet::DataPilotFieldOrientation
;
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
);
62 return DataPilotFieldOrientation_HIDDEN
;
64 DataPilotFieldOrientation nOrient
= DataPilotFieldOrientation_HIDDEN
;
66 // Check for page field first.
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
)
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
);
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();
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
131 mpFilterButton
->getPopupBoundingBox(aPopupPos
, aPopupSize
);
132 tools::Rectangle
aRect(aPopupPos
, aPopupSize
);
133 if (aRect
.Contains(rMEvt
.GetPosPixel()))
135 if ( DoPageFieldSelection( nCol
, nRow
) )
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
);
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
);
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.
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.
174 tools::Long nField
= pDPObj
->GetHeaderDim(aDimPos
, nOrient
);
181 if (bPopup
&& DPTestFieldPopupArrow(rMEvt
, aPos
, aDimPos
, pDPObj
))
183 // field name pop up menu has been launched. Don't activate
191 DPTestMouse( rMEvt
, true );
195 else if ( pDPObj
->IsFilterButton(aPos
) )
197 ReleaseMouse(); // may have been captured in ButtonDown
199 ScQueryParam aQueryParam
;
201 const ScSheetSourceDesc
* pDesc
= pDPObj
->GetSheetDesc();
202 OSL_ENSURE(pDesc
, "no sheet source for filter button");
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
);
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
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
);
251 if (!pDPObj
->GetSaveData()->GetDrillDown())
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
);
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
295 Point aPixel
= rMEvt
.GetPosPixel();
299 if ( aPixel
.X() < 0 )
301 if ( aPixel
.Y() < 0 )
303 Size aSize
= GetOutputSizePixel();
304 if ( aPixel
.X() >= aSize
.Width() )
306 if ( aPixel
.Y() >= aSize
.Height() )
308 if ( nDx
!= 0 || nDy
!= 0 )
310 UpdateDragRect( false, tools::Rectangle() );
313 mrViewData
.GetView()->ScrollX( nDx
, WhichH(eWhich
) );
315 mrViewData
.GetView()->ScrollY( nDy
, WhichV(eWhich
) );
322 mrViewData
.GetPosFromPixel( aPixel
.X(), aPixel
.Y(), eWhich
, nPosX
, nPosY
);
325 mrViewData
.GetMouseQuadrant( aPixel
, eWhich
, nPosX
, nPosY
, bMouseLeft
, bMouseTop
);
327 ScAddress
aPos( nPosX
, nPosY
, mrViewData
.GetTabNo() );
329 tools::Rectangle aPosRect
;
330 DataPilotFieldOrientation nOrient
;
332 bool bHasRange
= pDragDPObj
->GetHeaderDrag( aPos
, bMouseLeft
, bMouseTop
, nDPField
,
333 aPosRect
, nOrient
, nDimPos
);
334 UpdateDragRect( bHasRange
&& bMove
, aPosRect
);
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
;
345 ePointer
= PointerStyle::NotAllowed
;
346 else if ( bHasRange
)
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;
355 SetPointer( ePointer
);
357 else // execute change
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
);
370 ScDPSaveData
aSaveData( *pDragDPObj
->GetSaveData() );
372 ScDPSaveDimension
* pDim
;
374 pDim
= aSaveData
.GetDataLayoutDimension();
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
392 mrViewData
.GetView()->SetTimer( this, rMEvt
); // repeat event
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
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
);
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);
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
);
462 struct DPFieldPopupData
: public ScCheckListMenuControl::ExtendedData
464 ScDPLabelData maLabels
;
469 struct DPMultiFieldPopupData
: public DPFieldPopupData
471 std::vector
<tools::Long
> maFieldIndices
;
472 std::vector
<OUString
> maFieldNames
;
475 class DPFieldPopupOKAction
: public ScCheckListMenuControl::Action
478 explicit DPFieldPopupOKAction(ScGridWindow
* p
) :
481 virtual bool execute() override
483 mpGridWindow
->UpdateDPFromFieldPopupMenu();
487 VclPtr
<ScGridWindow
> mpGridWindow
;
490 class DPFieldChangedAction
: public ScCheckListMenuControl::Action
493 explicit DPFieldChangedAction(ScGridWindow
* p
) :
496 virtual bool execute() override
498 mpGridWindow
->UpdateDPPopupMenuForFieldChange();
502 VclPtr
<ScGridWindow
> mpGridWindow
;
505 class PopupSortAction
: public ScCheckListMenuControl::Action
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
)
515 , mnUserListIndex(nUserListIndex
)
516 , mpViewShell(pViewShell
)
519 virtual bool execute() override
524 mpViewShell
->DataPilotSort(mpDPObject
, mnDimIndex
, true);
527 mpViewShell
->DataPilotSort(mpDPObject
, mnDimIndex
, false);
530 mpViewShell
->DataPilotSort(mpDPObject
, mnDimIndex
, true, &mnUserListIndex
);
539 ScDPObject
* mpDPObject
;
540 tools::Long mnDimIndex
;
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
)
563 rDPData
.mnDim
= nDimIndex
;
567 OUString aDimName
= pDPObj
->GetDimName(rDPData
.mnDim
, bIsDataLayout
);
568 pDPObj
->BuildAllDimensionMembers();
569 const ScDPSaveData
* pSaveData
= pDPObj
->GetSaveData();
570 const ScDPSaveDimension
* pDim
= pSaveData
->GetExistingDimensionByName(aDimName
);
572 // This should never happen.
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
;
584 void ScGridWindow::DPLaunchMultiFieldPopupMenu(const Point
& rScreenPosition
, const Size
& rScreenSize
,
585 ScDPObject
* pDPObj
, DataPilotFieldOrientation nOrient
)
592 std::unique_ptr
<DPMultiFieldPopupData
> pDPData(new DPMultiFieldPopupData
);
593 pDPObj
->GetFieldIdsNames(nOrient
, pDPData
->maFieldIndices
, pDPData
->maFieldNames
);
595 if (pDPData
->maFieldIndices
.empty())
598 tools::Long nDimIndex
= pDPData
->maFieldIndices
[0];
600 bool bDimOrientNotPage
= true;
601 if (!lcl_FillDPFieldPopupData(nDimIndex
, pDPObj
, *pDPData
, bDimOrientNotPage
))
604 mpDPFieldPopup
.reset();
606 weld::Window
* pPopupParent
= GetFrameWeld();
607 mpDPFieldPopup
.reset(new ScCheckListMenuControl(pPopupParent
, mrViewData
,
610 mpDPFieldPopup
->addFields(pDPData
->maFieldNames
);
611 DPSetupFieldPopup(std::move(pDPData
), bDimOrientNotPage
, pDPObj
, true);
613 DPConfigFieldPopup();
615 if (IsMouseCaptured())
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();
632 // Use special string for an empty name.
633 mpDPFieldPopup
->addMember(ScResId(STR_EMPTYDATA
), 0.0, rMem
.mbVisible
, false);
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
,
643 if (!mpDPFieldPopup
|| !pDPObj
)
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
));
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);
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()
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
))
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())
729 tools::Rectangle
aCellRect(rScrPos
, rScrSize
);
730 mpDPFieldPopup
->launch(pPopupParent
, aCellRect
);
733 void ScGridWindow::UpdateDPPopupMenuForFieldChange()
738 DPMultiFieldPopupData
* pDPData
= static_cast<DPMultiFieldPopupData
*>(mpDPFieldPopup
->getExtendedData());
742 if (pDPData
->maFieldIndices
.empty())
745 tools::Long nIndex
= mpDPFieldPopup
->getField();
749 tools::Long nDimIndex
= pDPData
->maFieldIndices
[nIndex
];
750 if (nDimIndex
== pDPData
->mnDim
)
753 bool bDimOrientNotPage
= true;
754 if (!lcl_FillDPFieldPopupData(nDimIndex
, pDPData
->mpDPObj
, *pDPData
, bDimOrientNotPage
))
757 mpDPFieldPopup
->clearMembers();
759 DPPopulateFieldMembers(pDPData
->maLabels
);
761 mpDPFieldPopup
->initMembers();
764 void ScGridWindow::UpdateDPFromFieldPopupMenu()
766 typedef std::unordered_map
<OUString
, OUString
> MemNameMapType
;
771 DPFieldPopupData
* pDPData
= static_cast<DPFieldPopupData
*>(mpDPFieldPopup
->getExtendedData());
775 ScDPObject
* pDPObj
= pDPData
->mpDPObj
;
776 ScDPSaveData
* pSaveData
= pDPObj
->GetSaveData();
779 OUString aDimName
= pDPObj
->GetDimName(pDPData
->mnDim
, bIsDataLayout
);
780 ScDPSaveDimension
* pDim
= pSaveData
->GetDimensionByName(aDimName
);
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.
806 aResult
.emplace(aName
, rItem
.bValid
);
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);
822 template <typename T
>
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();
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
);
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
)
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
892 nDragStartX
= nStartX
;
893 nDragStartY
= nStartY
;
901 UpdateDragRectOverlay();
906 sal_uInt16
ScGridWindow::HitPageBreak( const Point
& rMouse
, ScRange
* pSource
,
907 SCCOLROW
* pBreak
, SCCOLROW
* pPrev
)
909 sal_uInt16 nFound
= SC_PD_NONE
; // 0
914 ScPageBreakData
* pPageData
= mrViewData
.GetView()->GetPageBreakData();
922 tools::Long nMouseX
= rMouse
.X();
923 tools::Long nMouseY
= rMouse
.Y();
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 )
936 else if ( nMouseX
>= aBR
.X() - 6 )
939 nHitX
= nPosX
+1; // left edge of the next cell
941 if ( nMouseY
<= aTL
.Y() + 2 )
946 else if ( nMouseY
>= aBR
.Y() - 4 )
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() );
969 nFound
= SC_PD_RANGE_TL
;
971 nFound
= SC_PD_RANGE_BL
;
973 nFound
= SC_PD_RANGE_L
;
978 nFound
= SC_PD_RANGE_TR
;
980 nFound
= SC_PD_RANGE_BR
;
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
;
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
;
1004 nPrev
= pRowEnd
[nRowPos
-1]+1;
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
;
1020 nPrev
= pColEnd
[nColPos
-1]+1;
1022 nPrev
= aRange
.aStart
.Col();
1030 *pSource
= aSource
; // print break
1032 *pBreak
= nBreak
; // X/Y position of the moved page break
1034 *pPrev
= nPrev
; // X/Y beginning of the page, which is above the break
1038 void ScGridWindow::PagebreakMove( const MouseEvent
& rMEvt
, bool bUp
)
1040 //! Combine scrolling and switching with RFMouseMove !
1041 //! (Inverting before scrolling is different)
1045 bool bTimer
= false;
1046 Point aPos
= rMEvt
.GetPosPixel();
1049 if ( aPos
.X() < 0 ) nDx
= -1;
1050 if ( aPos
.Y() < 0 ) nDy
= -1;
1051 Size aSize
= GetOutputSizePixel();
1052 if ( aPos
.X() >= aSize
.Width() )
1054 if ( aPos
.Y() >= aSize
.Height() )
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
) );
1069 // Switching when fixating (so Scrolling works)
1071 if ( eWhich
== mrViewData
.GetActivePart() ) //??
1073 if ( mrViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
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
)
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
);
1094 // Searching for a position between the cells (before nPosX / nPosY)
1097 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
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
);
1105 bool bToEnd
= false;
1106 ScRange aDrawRange
= aPagebreakSource
;
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 );
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 );
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
)
1143 aDrawRange
.aEnd
.SetCol( nPosX
-1 );
1147 if ( nPagebreakMouse
& SC_PD_RANGE_B
)
1150 aDrawRange
.aEnd
.SetRow( nPosY
-1 );
1154 if ( aDrawRange
.aStart
.Col() > aDrawRange
.aEnd
.Col() ||
1155 aDrawRange
.aStart
.Row() > aDrawRange
.aEnd
.Row() )
1159 if ( !bPagebreakDrawn
|| bUp
|| aDrawRange
!= aPagebreakDrag
)
1163 if ( bPagebreakDrawn
)
1166 bPagebreakDrawn
= false;
1168 aPagebreakDrag
= aDrawRange
;
1169 if ( !bUp
&& !bHide
)
1172 bPagebreakDrawn
= true;
1174 UpdateDragRectOverlay();
1177 // when ButtonUp execute the changes
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());
1189 bool bColumn
= ( nPagebreakMouse
== SC_PD_BREAK_H
);
1190 SCCOLROW nNew
= bColumn
? static_cast<SCCOLROW
>(nPosX
) : static_cast<SCCOLROW
>(nPosY
);
1191 if ( nNew
!= nPagebreakBreak
)
1195 OUString aUndo
= ScResId( STR_UNDO_DRAG_BREAK
);
1196 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, mrViewData
.GetViewShell()->GetViewShellId() );
1199 bool bGrow
= !bHide
&& nNew
> nPagebreakBreak
;
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 );
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
) ))
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 );
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
) ))
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
)
1271 OUString aNewRanges
;
1272 sal_uInt16 nOldCount
= rDoc
.GetPrintRangeCount( nTab
);
1275 for (sal_uInt16 nPos
=0; nPos
<nOldCount
; nPos
++)
1277 const ScRange
* pOld
= rDoc
.GetPrintRange( nTab
, nPos
);
1281 if ( *pOld
!= aPagebreakSource
)
1282 aTemp
= pOld
->Format(rDoc
, ScRefFlags::VALID
);
1284 aTemp
= aPagebreakDrag
.Format(rDoc
, ScRefFlags::VALID
);
1285 if (!aTemp
.isEmpty())
1287 if ( !aNewRanges
.isEmpty() )
1289 aNewRanges
+= aTemp
;
1295 aNewRanges
= aPagebreakDrag
.Format(rDoc
, ScRefFlags::VALID
);
1297 pViewFunc
->SetPrintRanges( rDoc
.IsPrintEntireSheet( nTab
), &aNewRanges
, nullptr, nullptr, false );
1301 // Timer for Scrolling
1304 mrViewData
.GetView()->SetTimer( this, rMEvt
); // repeat event
1306 mrViewData
.GetView()->ResetTimer();
1309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */