tdf#158394 Automatic scaling of icons for navigation bar

Added handling for the viewAdded and
viewChanged events, which cause navigation bar
icons to change if they don't fit the current
presentation area size.

This handler is only applied when automatic
scaling of the navigation bar is enabled, so it
shouldn't impact performance when the bar isn't
used or a fixed size is selected.

Icon sizes:
XLarge for UHD and above
Large for FHD and up
Small for anything smaller than FHD

Change-Id: I9f6599291d57aca9991c8d2dd2969d1edb36080e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196157
Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
Tested-by: Jenkins
Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@collabora.com>
This commit is contained in:
Vladislav Tarakanov
2026-01-26 10:59:04 +01:00
committed by Samuel Mehrbrodt
parent a583258169
commit b6bec20772
4 changed files with 165 additions and 2 deletions
@@ -83,6 +83,18 @@ void SlideOverlayButton::setVisible(const bool bVisible)
mrScreenUpdater.requestImmediateUpdate();
}
void SlideOverlayButton::clear()
{
mrEventMultiplexer.removeViewHandler(
std::dynamic_pointer_cast<ViewEventHandler>(shared_from_this()));
mrEventMultiplexer.removeClickHandler(
std::dynamic_pointer_cast<MouseEventHandler>(shared_from_this()));
for (auto& item : maViews)
{
item.second->getContentCanvas()->clear();
}
}
css::geometry::IntegerSize2D SlideOverlayButton::getSize() const { return mxIconBitmap->getSize(); }
basegfx::B2DPoint SlideOverlayButton::calcSpritePos(UnoViewSharedPtr const& rView) const
@@ -66,6 +66,8 @@ public:
css::geometry::IntegerSize2D getSize() const;
basegfx::B2DPoint calcSpritePos(UnoViewSharedPtr const& rView) const;
void clear();
private:
SlideOverlayButton(css::uno::Reference<css::rendering::XBitmap> xIconBitmap,
css::awt::Point pPosition,
+145 -2
View File
@@ -63,6 +63,9 @@
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
#include <vcl/canvastools.hxx>
#include <vcl/vclenum.hxx>
#include <unoviewcontainer.hxx>
#include <transitionfactory.hxx>
#include <eventmultiplexer.hxx>
@@ -101,6 +104,18 @@ namespace box2d::utils { class box2DWorld;
namespace {
constexpr OUString BMP_PREV_SLIDE_SMALL = u"sd/res/prevslide_small.png"_ustr;
constexpr OUString BMP_NEXT_SLIDE_SMALL = u"sd/res/nextslide_small.png"_ustr;
constexpr OUString BMP_MENU_SLIDE_SMALL = u"sd/res/slideshowmenu_small.png"_ustr;
constexpr OUString BMP_PREV_SLIDE_LARGE = u"sd/res/prevslide_large.png"_ustr;
constexpr OUString BMP_NEXT_SLIDE_LARGE = u"sd/res/nextslide_large.png"_ustr;
constexpr OUString BMP_MENU_SLIDE_LARGE = u"sd/res/slideshowmenu_large.png"_ustr;
constexpr OUString BMP_PREV_SLIDE_EXTRALARGE = u"sd/res/prevslide_extralarge.png"_ustr;
constexpr OUString BMP_NEXT_SLIDE_EXTRALARGE = u"sd/res/nextslide_extralarge.png"_ustr;
constexpr OUString BMP_MENU_SLIDE_EXTRALARGE = u"sd/res/slideshowmenu_extralarge.png"_ustr;
/** During animations the update() method tells its caller to call it as
soon as possible. This gives us more time to render the next frame and
still maintain a steady frame rate. This class is responsible for
@@ -266,6 +281,9 @@ public:
*/
bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode );
void handleViewChangedEvent( const sal_Int32 width, const sal_Int32 height );
/** Obtain a MediaTempFile for the specified url. */
virtual std::shared_ptr<avmedia::MediaTempFile> getMediaTempFile(const OUString& aUrl) override;
@@ -406,6 +424,11 @@ private:
*/
void rewindEffectToPreviousSlide();
void updateNavbarIcons(
const OUString& prevSlideIconPath,
const OUString& contextMenuIconPath,
const OUString& nextSlideIconPath );
/// all registered views
UnoViewContainer maViewContainer;
@@ -448,6 +471,8 @@ private:
std::shared_ptr<SlideOverlayButton> mpNavigationMenu;
std::shared_ptr<SlideOverlayButton> mpNavigationNext;
NavbarButtonSize maCurNavbarBtnSize;
std::shared_ptr<PointerSymbol> mpPointerSymbol;
/// the current slide transition sound object:
@@ -498,7 +523,8 @@ private:
struct SlideShowImpl::SeparateListenerImpl : public EventHandler,
public ViewRepaintHandler,
public HyperlinkHandler,
public AnimationEventHandler
public AnimationEventHandler,
public ViewEventHandler
{
SlideShowImpl& mrShow;
ScreenUpdater& mrScreenUpdater;
@@ -550,6 +576,23 @@ struct SlideShowImpl::SeparateListenerImpl : public EventHandler,
{
return mrShow.handleAnimationEvent(rNode);
}
// ViewEventHandler
virtual void viewAdded(const UnoViewSharedPtr& rView) override
{
auto size = rView->getUnoView()->getCanvasArea();
mrShow.handleViewChangedEvent(size.Width, size.Height);
}
virtual void viewRemoved(const UnoViewSharedPtr& /*rView*/) override { }
virtual void viewChanged(const UnoViewSharedPtr& rView) override
{
auto size = rView->getUnoView()->getCanvasArea();
mrShow.handleViewChangedEvent(size.Width, size.Height);
}
virtual void viewsChanged() override { }
};
SlideShowImpl::SlideShowImpl(
@@ -574,7 +617,7 @@ SlideShowImpl::SlideShowImpl(
mpBox2DDummyPtr(),
mpListener(),
mpRehearseTimingsActivity(),
mpWaitSymbol(),
maCurNavbarBtnSize(),
mpPointerSymbol(),
mpCurrentSlideTransitionSound(),
mxComponentContext(std::move( xContext )),
@@ -1280,6 +1323,52 @@ void SlideShowImpl::rewindEffectToPreviousSlide()
maScreenUpdater.commitUpdates();
}
void SlideShowImpl::updateNavbarIcons(
const OUString& prevSlideIconPath,
const OUString& contextMenuIconPath,
const OUString& nextSlideIconPath )
{
mpNavigationPrev->clear();
Bitmap prevSlideBm(prevSlideIconPath);
const uno::Reference<rendering::XBitmap> xPrevSBitmap( vcl::unotools::xBitmapFromBitmap(prevSlideBm) );
if (xPrevSBitmap.is())
{
mpNavigationPrev = SlideOverlayButton::create(
xPrevSBitmap, { 20, 10 }, [this](basegfx::B2DPoint) { notifySlideEnded(true); },
maScreenUpdater, maEventMultiplexer, maViewContainer);
}
mpNavigationMenu->clear();
Bitmap menuBm(contextMenuIconPath);
const uno::Reference<rendering::XBitmap> xMenuBitmap( vcl::unotools::xBitmapFromBitmap(menuBm) );
if (xMenuBitmap.is())
{
mpNavigationMenu = SlideOverlayButton::create(
xMenuBitmap, { xMenuBitmap->getSize().Width + 48, 10 }, [this](basegfx::B2DPoint pos) {
maListenerContainer.forEach(
[pos](const uno::Reference<presentation::XSlideShowListener>& xListener) {
uno::Reference<presentation::XSlideShowNavigationListener> xNavListener(
xListener, uno::UNO_QUERY);
if (xNavListener.is())
xNavListener->contextMenuShow(
css::awt::Point(static_cast<sal_Int32>(floor(pos.getX())),
static_cast<sal_Int32>(floor(pos.getY()))));
});
},
maScreenUpdater, maEventMultiplexer, maViewContainer);
}
mpNavigationNext->clear();
Bitmap nextSlideBm(nextSlideIconPath);
const uno::Reference<rendering::XBitmap> xNextSBitmap( vcl::unotools::xBitmapFromBitmap(nextSlideBm) );
if (xNextSBitmap.is())
{
mpNavigationNext = SlideOverlayButton::create(
xNextSBitmap, { 2 * xPrevSBitmap->getSize().Width + 76, 10 }, [this](basegfx::B2DPoint) { notifySlideEnded(false); },
maScreenUpdater, maEventMultiplexer, maViewContainer);
}
}
sal_Bool SlideShowImpl::startShapeActivity(
uno::Reference<drawing::XShape> const& /*xShape*/ )
{
@@ -1878,6 +1967,24 @@ sal_Bool SlideShowImpl::setProperty( beans::PropertyValue const& rProperty )
return true;
}
if (rProperty.Name == "NavigationBarAutoscale")
{
bool isAutoscale;
if (!(rProperty.Value >>= isAutoscale))
return false;
if (isAutoscale)
{
maEventMultiplexer.addViewHandler( mpListener );
}
else
{
maEventMultiplexer.removeViewHandler( mpListener );
}
return true;
}
if ( rProperty.Name == "PointerSymbolBitmap" )
{
uno::Reference<rendering::XBitmap> xBitmap;
@@ -2501,6 +2608,42 @@ bool SlideShowImpl::handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
return true;
}
void SlideShowImpl::handleViewChangedEvent( const sal_Int32 width, const sal_Int32 height )
{
NavbarButtonSize newSize = NavbarButtonSize::Small;
sal_Int32 screenArea = width * height;
if (screenArea >= 3840 * 2160 /* UHD and above */)
{
newSize = NavbarButtonSize::XLarge;
}
else if (screenArea >= 1920 * 1080 /* FHD and above */)
{
newSize = NavbarButtonSize::Large;
}
if (newSize != maCurNavbarBtnSize)
{
maCurNavbarBtnSize = newSize;
switch ( maCurNavbarBtnSize ) {
case NavbarButtonSize::Large:
{
updateNavbarIcons(BMP_PREV_SLIDE_LARGE, BMP_MENU_SLIDE_LARGE, BMP_NEXT_SLIDE_LARGE);
}
break;
case NavbarButtonSize::XLarge:
{
updateNavbarIcons(BMP_PREV_SLIDE_EXTRALARGE, BMP_MENU_SLIDE_EXTRALARGE, BMP_NEXT_SLIDE_EXTRALARGE);
}
break;
default:
{
updateNavbarIcons(BMP_PREV_SLIDE_SMALL, BMP_MENU_SLIDE_SMALL, BMP_NEXT_SLIDE_SMALL);
}
break;
}
}
}
std::shared_ptr<avmedia::MediaTempFile> SlideShowImpl::getMediaTempFile(const OUString& aUrl)
{
std::shared_ptr<avmedia::MediaTempFile> aRet;