sd: add support for shuffling slides from canvas page

added .uno:ReshufflePages which when executed will re-order the pages
based on the position of their previews on the canvas page.

Sorting logic:
1. Sort the previews based on their y-center
2. Form a row if the y-centers are within a tolerance limit
3. Sort the row based on their x-center (also considering RTL locale)
4. Repeat for each rows

Signed-off-by: Mohit Marathe <mohit.marathe@collabora.com>
Change-Id: If654e0cc14686aed2ad6cd69f2dc81249924ee2c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192940
Reviewed-by: Michael Stahl <michael.stahl@collabora.com>
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196798
Tested-by: Jenkins
This commit is contained in:
Mohit Marathe
2026-01-12 19:25:26 +01:00
committed by Michael Stahl
parent dd9b5ec78b
commit b162ae4be3
7 changed files with 123 additions and 1 deletions
@@ -2215,6 +2215,14 @@
<value>1</value>
</prop>
</node>
<node oor:name=".uno:ReshufflePages" oor:op="replace">
<prop oor:name="Label" oor:type="xs:string">
<value xml:lang="en-US">Re-order pages</value>
</prop>
<prop oor:name="Properties" oor:type="xs:int">
<value>1</value>
</prop>
</node>
<node oor:name=".uno:AssignLayout?WhatLayout:long=20" oor:op="replace">
<prop oor:name="Label" oor:type="xs:string">
<value xml:lang="en-US">Blank Slide</value>
+1
View File
@@ -347,6 +347,7 @@
// FREE
#define SID_INSERTPAGE_QUICK (SID_SD_START+352)
#define SID_INSERT_CANVAS_SLIDE (SID_SD_START+353)
#define SID_SHUFFLE_PAGES (SID_SD_START+354)
// FREE
#define SID_INSERT_FLD_PAGE_TITLE (SID_SD_START+356)
#define SID_INSERT_FLD_DATE_VAR (SID_SD_START+357)
+4
View File
@@ -1069,6 +1069,10 @@ public:
bool bUndo = true,
const OUString& sNewName = OUString());
/** Re-order the pages based on the position of their previews on canvas page.
*/
void ReshufflePages();
private:
void UpdatePageRelativeURLsImpl(const std::function<void(const SvxFieldItem & rFieldItem, editeng::SvxFieldItemUpdater& rFieldItemUpdater)>& rItemCallback);
+5
View File
@@ -165,6 +165,11 @@ interface DrawView
ExecMethod = FuTemporary ;
StateMethod = GetMenuState ;
]
SID_SHUFFLE_PAGES
[
ExecMethod = FuTemporary ;
StateMethod = GetMenuState ;
]
SID_HYPERLINK_SETLINK // ole : no, status : no
[
ExecMethod = FuTemporary ;
+17
View File
@@ -1690,6 +1690,23 @@ SfxVoidItem InsertCanvasSlide SID_INSERT_CANVAS_SLIDE
GroupId = SfxGroupId::Insert;
]
SfxVoidItem ReshufflePages SID_SHUFFLE_PAGES
()
[
AutoUpdate = FALSE,
FastCall = FALSE,
ReadOnlyDoc = FALSE,
Toggle = FALSE,
Container = FALSE,
RecordAbsolute = FALSE,
RecordPerSet;
AccelConfig = TRUE,
MenuConfig = TRUE,
ToolBoxConfig = TRUE,
GroupId = SfxGroupId::Modify;
]
SfxVoidItem InsertPageField SID_INSERT_FLD_PAGE
()
[
+78 -1
View File
@@ -17,6 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <algorithm>
#include <vcl/settings.hxx>
#include <sal/log.hxx>
@@ -1470,6 +1471,79 @@ void SdDrawDocument::SetupNewPage (
}
}
void SdDrawDocument::ReshufflePages()
{
SdrObjList* pObjList = mpCanvasPage.get();
std::vector<SdrPageObj*> aPageOrder;
SdrObjListIter aIter(pObjList, SdrIterMode::Flat);
for (SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next())
{
if (pObj->GetObjIdentifier() == SdrObjKind::Page)
{
SdrPageObj* pPageObj = static_cast<SdrPageObj*>(pObj);
aPageOrder.push_back(pPageObj);
}
}
// Sort the previews by comparing their y-center (compare x-center as a tie-breaker)
std::sort(aPageOrder.begin(), aPageOrder.end(),
[](const SdrPageObj* pObj1, const SdrPageObj* pObj2) {
const ::tools::Rectangle& rect1 = pObj1->GetSnapRect();
const ::tools::Rectangle& rect2 = pObj2->GetSnapRect();
const ::tools::Long yCenter1 = (rect1.Top() + rect1.Bottom()) / 2;
const ::tools::Long yCenter2 = (rect2.Top() + rect2.Bottom()) / 2;
if (yCenter1 != yCenter2)
return yCenter1 < yCenter2;
const ::tools::Long xCenter1 = (rect1.Left() + rect1.Right()) / 2;
const ::tools::Long xCenter2 = (rect2.Left() + rect2.Right()) / 2;
return xCenter1 < xCenter2;
}
);
const bool bIsRTL = AllSettings::GetLayoutRTL();
// Form a row, and sort them based on their x-center
for (size_t rowStart = 0; rowStart < aPageOrder.size();)
{
const ::tools::Rectangle& rect0 = aPageOrder[rowStart]->GetSnapRect();
const ::tools::Long top = rect0.Top();
const ::tools::Long bottom = rect0.Bottom();
size_t rowEnd = rowStart;
while (rowEnd < aPageOrder.size())
{
const ::tools::Rectangle& rect = aPageOrder[rowEnd]->GetSnapRect();
const ::tools::Long yCenter = (rect.Top() + rect.Bottom()) / 2;
if (yCenter < top || yCenter > bottom)
break;
rowEnd++;
}
std::stable_sort(aPageOrder.begin() + rowStart, aPageOrder.begin() + rowEnd,
[&bIsRTL](const SdrPageObj* pObj1, const SdrPageObj* pObj2) {
const ::tools::Rectangle& rect1 = pObj1->GetSnapRect();
const ::tools::Rectangle& rect2 = pObj2->GetSnapRect();
const ::tools::Long xCenter1 = (rect1.Left() + rect1.Right()) / 2;
const ::tools::Long xCenter2 = (rect2.Left() + rect2.Right()) / 2;
return bIsRTL ? (xCenter1 > xCenter2) : (xCenter1 < xCenter2);
});
}
for (size_t i = 0; i < aPageOrder.size(); i++)
{
SdPage* pPage = static_cast<SdPage*>(aPageOrder[i]->GetReferencedPage());
sal_uInt16 nCurrentPageNum = pPage->GetPageNum();
sal_uInt16 nTargetPageNum = 2 * i + 1;
MovePage(nCurrentPageNum, nTargetPageNum); // Standard page
MovePage(nCurrentPageNum + 1, nTargetPageNum + 1); // Notes page
}
}
sal_uInt16 SdDrawDocument::GetOrInsertCanvasPage()
{
if (HasCanvasPage())
@@ -1478,7 +1552,10 @@ sal_uInt16 SdDrawDocument::GetOrInsertCanvasPage()
sal_uInt16 nLastPageNum = GetSdPageCount(PageKind::Standard);
SdPage* pLastStandardPage = GetSdPage(nLastPageNum - 1, PageKind::Standard);
sal_uInt16 nCanvasPageNum = CreatePage(pLastStandardPage, PageKind::Standard, u"Canvas Page"_ustr, u"Canvas notes page"_ustr, AutoLayout::AUTOLAYOUT_NONE, AutoLayout::AUTOLAYOUT_NONE, false, true, pLastStandardPage->GetPageNum() + 2);
sal_uInt16 nCanvasPageNum = CreatePage(pLastStandardPage, PageKind::Standard,
u"Canvas Page"_ustr, u"Canvas notes page"_ustr,
AutoLayout::AUTOLAYOUT_NONE, AutoLayout::AUTOLAYOUT_NONE,
false, true, pLastStandardPage->GetPageNum() + 2);
SdPage* pCanvasPage = GetSdPage(nCanvasPageNum, PageKind::Standard);
if (!pCanvasPage)
+10
View File
@@ -1408,6 +1408,16 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq)
}
break;
case SID_SHUFFLE_PAGES:
{
if (!GetDoc()->HasCanvasPage())
break;
GetDoc()->ReshufflePages();
Cancel();
rReq.Done();
}
break;
case SID_DUPLICATE_PAGE:
{
auto slideSorter = sd::slidesorter::SlideSorterViewShell::GetSlideSorter(GetViewShellBase());