sd/source/ui/inc/ViewShell.hxx | 1 sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx | 1 sd/source/ui/view/drawview.cxx | 1 sd/source/ui/view/sdwindow.cxx | 12 - sd/source/ui/view/viewshe2.cxx | 97 ++++++++-- sd/source/ui/view/viewshel.cxx | 7 6 files changed, 95 insertions(+), 24 deletions(-)
New commits: commit dfb412699b96e12b2758be0e422c3e775f183d17 Author: Sarper Akdemir <[email protected]> AuthorDate: Tue Apr 23 16:00:32 2024 +0200 Commit: Sarper Akdemir <[email protected]> CommitDate: Wed Apr 24 11:28:00 2024 +0200 tdf#38164: sd: allow panning across pages when zoomed in Change-Id: I513b2b8cbdc91733e551da71a1e6782fecc981a3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166542 Tested-by: Jenkins Reviewed-by: Sarper Akdemir <[email protected]> diff --git a/sd/source/ui/inc/ViewShell.hxx b/sd/source/ui/inc/ViewShell.hxx index 6ee126db9027..9e5e8e068160 100644 --- a/sd/source/ui/inc/ViewShell.hxx +++ b/sd/source/ui/inc/ViewShell.hxx @@ -382,6 +382,7 @@ public: */ virtual void ShowUIControls (bool bVisible); bool IsPageFlipMode() const; + bool CanPanAcrossPages() const; /** Set the given window as new parent window. This is not possible for all views, so the return value tells the caller if the relocation diff --git a/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx index 9203c06e8f9f..e8fc847a4a7b 100644 --- a/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx @@ -176,6 +176,7 @@ void CurrentSlideManager::SetCurrentSlideAtViewShellBase (const SharedPageDescri pDrawViewShell->SwitchPage(nPageNumber); TabControl& rPageTabControl = pDrawViewShell->GetPageTabControl(); rPageTabControl.SetCurPageId(rPageTabControl.GetPageId(nPageNumber)); + pDrawViewShell->UpdateScrollBars(); } } } diff --git a/sd/source/ui/view/drawview.cxx b/sd/source/ui/view/drawview.cxx index 6792250fd8e7..99c166002cbd 100644 --- a/sd/source/ui/view/drawview.cxx +++ b/sd/source/ui/view/drawview.cxx @@ -407,6 +407,7 @@ void DrawView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) if ( mnPOCHSmph == 0 && eHintKind == SdrHintKind::PageOrderChange ) { mpDrawViewShell->ResetActualPage(); + mpDrawViewShell->UpdateScrollBars(); } else if ( eHintKind == SdrHintKind::LayerChange || eHintKind == SdrHintKind::LayerOrderChange ) { diff --git a/sd/source/ui/view/sdwindow.cxx b/sd/source/ui/view/sdwindow.cxx index ab8a7bbd8889..8f71c17db957 100644 --- a/sd/source/ui/view/sdwindow.cxx +++ b/sd/source/ui/view/sdwindow.cxx @@ -667,8 +667,6 @@ void Window::SetVisibleXY(double fX, double fY) double Window::GetVisibleWidth() const { Size aWinSize = PixelToLogic(GetOutputSizePixel()); - if ( aWinSize.Width() > maViewSize.Width() ) - aWinSize.setWidth( maViewSize.Width() ); return maViewSize.Width() == 0 ? 0 : (static_cast<double>(aWinSize.Width()) / maViewSize.Width()); } @@ -680,8 +678,6 @@ double Window::GetVisibleWidth() const double Window::GetVisibleHeight() const { Size aWinSize = PixelToLogic(GetOutputSizePixel()); - if ( aWinSize.Height() > maViewSize.Height() ) - aWinSize.setHeight( maViewSize.Height() ); return maViewSize.Height() == 0 ? 0 : (static_cast<double>(aWinSize.Height()) / maViewSize.Height()); } @@ -705,7 +701,7 @@ Point Window::GetVisibleCenter() */ double Window::GetScrlLineWidth() const { - return (GetVisibleWidth() * SCROLL_LINE_FACT); + return std::min(1.0, GetVisibleWidth()) * SCROLL_LINE_FACT; } /** @@ -714,7 +710,7 @@ double Window::GetScrlLineWidth() const */ double Window::GetScrlLineHeight() const { - return (GetVisibleHeight() * SCROLL_LINE_FACT); + return std::min(1.0, GetVisibleHeight()) * SCROLL_LINE_FACT; } /** @@ -723,7 +719,7 @@ double Window::GetScrlLineHeight() const */ double Window::GetScrlPageWidth() const { - return (GetVisibleWidth() * SCROLL_PAGE_FACT); + return std::min(1.0, GetVisibleWidth()) * SCROLL_PAGE_FACT; } /** @@ -732,7 +728,7 @@ double Window::GetScrlPageWidth() const */ double Window::GetScrlPageHeight() const { - return (GetVisibleHeight() * SCROLL_PAGE_FACT); + return std::min(1.0, GetVisibleHeight()) * SCROLL_PAGE_FACT; } /** diff --git a/sd/source/ui/view/viewshe2.cxx b/sd/source/ui/view/viewshe2.cxx index b7ae44f2c3e1..18658fc8c929 100644 --- a/sd/source/ui/view/viewshe2.cxx +++ b/sd/source/ui/view/viewshe2.cxx @@ -63,6 +63,19 @@ using namespace com::sun::star; +namespace +{ +inline double getViewToScrollScalarForPanAcrossPages(sal_uInt16 nTotalPages, double fVisibleHeight, + ::tools::Long nScrollRangeMax) +{ + // fTotalScrollableRange is (1 - fVisibleHeight) for all of the + // pages except the last one. Because switch to the next page + // happens when the view reaches bottom. + double fTotalScrollableRange = (nTotalPages - 1) * (1 - fVisibleHeight) + 1.0; + return nScrollRangeMax / fTotalScrollableRange; +} +} + namespace sd { /** @@ -72,7 +85,7 @@ void ViewShell::UpdateScrollBars() { if (mpHorizontalScrollBar) { - ::tools::Long nW = static_cast<::tools::Long>(mpContentWindow->GetVisibleWidth() * 32000); + ::tools::Long nW = static_cast<::tools::Long>(std::min(1.0, mpContentWindow->GetVisibleWidth()) * 32000); ::tools::Long nX = static_cast<::tools::Long>(mpContentWindow->GetVisibleX() * 32000); mpHorizontalScrollBar->SetVisibleSize(nW); mpHorizontalScrollBar->SetThumbPos(nX); @@ -85,10 +98,32 @@ void ViewShell::UpdateScrollBars() if (mpVerticalScrollBar) { - ::tools::Long nH = static_cast<::tools::Long>(mpContentWindow->GetVisibleHeight() * 32000); - ::tools::Long nY = static_cast<::tools::Long>(mpContentWindow->GetVisibleY() * 32000); + if (CanPanAcrossPages()) + { + SdPage* pPage = static_cast<DrawViewShell*>(this)->GetActualPage(); + sal_uInt16 nCurPage = (pPage->GetPageNum() - 1) / 2; + sal_uInt16 nTotalPages = GetDoc()->GetSdPageCount(pPage->GetPageKind()); - if(IsPageFlipMode()) // ie in zoom mode where no panning + // nRangeMax is max int, and not ::tools::Long since the underlying + // implementation weld::Scrollbar uses int + ::tools::Long nRangeMax = std::numeric_limits<int>::max(); + double fVisibleHeight = std::min(mpContentWindow->GetVisibleHeight(), 1.0); + double fMappingFactor + = getViewToScrollScalarForPanAcrossPages(nTotalPages, fVisibleHeight, nRangeMax); + double fVisibleY = std::max(0.0, mpContentWindow->GetVisibleY()); + double fCurrentThumbPos = nCurPage * (1 - fVisibleHeight) + fVisibleY; + double fScrollLineHeight + = mpContentWindow->GetScrlLineHeight() * (1.0 - fVisibleHeight); + double fScrollPageHeight + = mpContentWindow->GetScrlPageHeight() * (1.0 - fVisibleHeight); + + mpVerticalScrollBar->SetRange(Range(0, nRangeMax)); + mpVerticalScrollBar->SetVisibleSize(fVisibleHeight * fMappingFactor); + mpVerticalScrollBar->SetThumbPos(fCurrentThumbPos * fMappingFactor); + mpVerticalScrollBar->SetLineSize(fScrollLineHeight * fMappingFactor); + mpVerticalScrollBar->SetPageSize(fScrollPageHeight * fMappingFactor); + } + else if (IsPageFlipMode()) // ie in zoom mode where no panning { SdPage* pPage = static_cast<DrawViewShell*>(this)->GetActualPage(); sal_uInt16 nCurPage = (pPage->GetPageNum() - 1) / 2; @@ -99,8 +134,11 @@ void ViewShell::UpdateScrollBars() mpVerticalScrollBar->SetLineSize(256); mpVerticalScrollBar->SetPageSize(256); } - else + else // single page pan mode { + ::tools::Long nH = static_cast<::tools::Long>(std::min(1.0, mpContentWindow->GetVisibleHeight()) * 32000); + ::tools::Long nY = static_cast<::tools::Long>(mpContentWindow->GetVisibleY() * 32000); + mpVerticalScrollBar->SetRange(Range(0,32000)); mpVerticalScrollBar->SetVisibleSize(nH); mpVerticalScrollBar->SetThumbPos(nY); @@ -180,18 +218,8 @@ IMPL_LINK_NOARG(ViewShell, VScrollHdl, weld::Scrollbar&, void) */ void ViewShell::VirtVScrollHdl(ScrollAdaptor* pVScroll) { - if(IsPageFlipMode()) - { - SdPage* pPage = static_cast<DrawViewShell*>(this)->GetActualPage(); - sal_uInt16 nCurPage = (pPage->GetPageNum() - 1) >> 1; - sal_uInt16 nNewPage = static_cast<sal_uInt16>(pVScroll->GetThumbPos())/256; - if( nCurPage != nNewPage ) - static_cast<DrawViewShell*>(this)->SwitchPage(nNewPage); - } - else //panning mode + auto doScrollView = [&](double fY) { - double fY = static_cast<double>(pVScroll->GetThumbPos()) / pVScroll->GetRange().Len(); - ::sd::View* pView = GetView(); OutlinerView* pOLV = nullptr; @@ -222,7 +250,44 @@ void ViewShell::VirtVScrollHdl(ScrollAdaptor* pVScroll) if (mbHasRulers) UpdateVRuler(); + }; + if (CanPanAcrossPages()) + { + SdPage* pPage = static_cast<DrawViewShell*>(this)->GetActualPage(); + sal_uInt16 nCurPage = (pPage->GetPageNum() - 1) >> 1; + sal_uInt16 nTotalPages = GetDoc()->GetSdPageCount(pPage->GetPageKind()); + + double fVisibleHeight = mpContentWindow->GetVisibleHeight(); + double fMappingFactor = getViewToScrollScalarForPanAcrossPages(nTotalPages, fVisibleHeight, + pVScroll->GetRange().Max()); + + double fScrollableDistancePerPage = 1 - std::min(fVisibleHeight, 1.0); + + sal_uInt16 nNewPage + = std::min((pVScroll->GetThumbPos() / fMappingFactor) / fScrollableDistancePerPage, + static_cast<double>(nTotalPages - 1)); + + if (nCurPage != nNewPage) + static_cast<DrawViewShell*>(this)->SwitchPage(nNewPage); + + double fNewPageStart = nNewPage * fScrollableDistancePerPage; + double fY = (pVScroll->GetThumbPos() / fMappingFactor) - fNewPageStart; + + doScrollView(fY); + } + else if (IsPageFlipMode()) + { + SdPage* pPage = static_cast<DrawViewShell*>(this)->GetActualPage(); + sal_uInt16 nCurPage = (pPage->GetPageNum() - 1) >> 1; + sal_uInt16 nNewPage = static_cast<sal_uInt16>(pVScroll->GetThumbPos())/256; + if( nCurPage != nNewPage ) + static_cast<DrawViewShell*>(this)->SwitchPage(nNewPage); + } + else // single page panning mode + { + double fY = static_cast<double>(pVScroll->GetThumbPos()) / pVScroll->GetRange().Len(); + doScrollView(fY); } } diff --git a/sd/source/ui/view/viewshel.cxx b/sd/source/ui/view/viewshel.cxx index 9d0c7c98b7db..b341c8a29d85 100644 --- a/sd/source/ui/view/viewshel.cxx +++ b/sd/source/ui/view/viewshel.cxx @@ -111,6 +111,13 @@ private: namespace sd { +/// When true, scrolling to bottom of a page switches to the next page. +bool ViewShell::CanPanAcrossPages() const +{ + return dynamic_cast<const DrawViewShell*>(this) && mpContentWindow && + mpContentWindow->GetVisibleHeight() < 1.0; +} + bool ViewShell::IsPageFlipMode() const { return dynamic_cast< const DrawViewShell *>( this ) != nullptr && mpContentWindow &&
