diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /svx/source/stbctrls | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | svx/source/stbctrls/insctrl.cxx | 83 | ||||
-rw-r--r-- | svx/source/stbctrls/modctrl.cxx | 159 | ||||
-rw-r--r-- | svx/source/stbctrls/modctrl_internal.hxx | 30 | ||||
-rw-r--r-- | svx/source/stbctrls/pszctrl.cxx | 486 | ||||
-rw-r--r-- | svx/source/stbctrls/selctrl.cxx | 195 | ||||
-rw-r--r-- | svx/source/stbctrls/stbctrls.h | 35 | ||||
-rw-r--r-- | svx/source/stbctrls/xmlsecctrl.cxx | 162 | ||||
-rw-r--r-- | svx/source/stbctrls/zoomctrl.cxx | 229 | ||||
-rw-r--r-- | svx/source/stbctrls/zoomsliderctrl.cxx | 392 |
9 files changed, 1771 insertions, 0 deletions
diff --git a/svx/source/stbctrls/insctrl.cxx b/svx/source/stbctrls/insctrl.cxx new file mode 100644 index 000000000..3ad0fdc1e --- /dev/null +++ b/svx/source/stbctrls/insctrl.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/status.hxx> +#include <svl/eitem.hxx> +#include <tools/debug.hxx> + +#include <svx/strings.hrc> + +#include <svx/insctrl.hxx> +#include <svx/dialmgr.hxx> + +SFX_IMPL_STATUSBAR_CONTROL(SvxInsertStatusBarControl, SfxBoolItem); + +SvxInsertStatusBarControl::SvxInsertStatusBarControl( sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb ) : + + SfxStatusBarControl( _nSlotId, _nId, rStb ), + bInsert( true ) +{ +} + +SvxInsertStatusBarControl::~SvxInsertStatusBarControl() +{ +} + +void SvxInsertStatusBarControl::StateChangedAtStatusBarControl( sal_uInt16 , SfxItemState eState, + const SfxPoolItem* pState ) +{ + if ( SfxItemState::DEFAULT != eState ) + GetStatusBar().SetItemText( GetId(), "" ); + else + { + DBG_ASSERT( dynamic_cast<const SfxBoolItem*>( pState) != nullptr, "invalid item type" ); + const SfxBoolItem* pItem = static_cast<const SfxBoolItem*>(pState); + bInsert = pItem->GetValue(); + + if ( bInsert ) + GetStatusBar().SetQuickHelpText( GetId(), SvxResId( RID_SVXSTR_INSERT_HELPTEXT ) ); + else + GetStatusBar().SetQuickHelpText( GetId(), SvxResId( RID_SVXSTR_OVERWRITE_HELPTEXT ) ); + + DrawItemText_Impl(); + } +} + +void SvxInsertStatusBarControl::Paint( const UserDrawEvent& ) +{ +} + +void SvxInsertStatusBarControl::DrawItemText_Impl() +{ + OUString aText = ""; + // tdf#107918 on macOS without an Insert key it's hard to figure out how to switch modes + // so we show both Insert and Overwrite +#ifdef MACOSX + if ( bInsert ) + aText = SvxResId( RID_SVXSTR_INSERT_TEXT ); +#endif + if ( !bInsert ) + aText = SvxResId( RID_SVXSTR_OVERWRITE_TEXT ); + + GetStatusBar().SetItemText( GetId(), aText ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/stbctrls/modctrl.cxx b/svx/source/stbctrls/modctrl.cxx new file mode 100644 index 000000000..d65817526 --- /dev/null +++ b/svx/source/stbctrls/modctrl.cxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/status.hxx> +#include <vcl/image.hxx> +#include <vcl/timer.hxx> +#include <vcl/idle.hxx> +#include <vcl/event.hxx> +#include <svl/eitem.hxx> +#include <tools/debug.hxx> + +#include <svx/strings.hrc> +#include <svx/modctrl.hxx> +#include <svx/dialmgr.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include "modctrl_internal.hxx" +#include <bitmaps.hlst> + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::PropertyValue; + +SFX_IMPL_STATUSBAR_CONTROL(SvxModifyControl, SfxBoolItem); + +struct SvxModifyControl::ImplData +{ + enum ModificationState + { + MODIFICATION_STATE_NO = 0, + MODIFICATION_STATE_YES, + MODIFICATION_STATE_FEEDBACK, + MODIFICATION_STATE_SIZE + }; + + Idle maIdle { "svx::SvxModifyControl maIdle" }; + Image maImages[MODIFICATION_STATE_SIZE]; + + ModificationState mnModState; + + ImplData(): + mnModState(MODIFICATION_STATE_NO) + { + maImages[MODIFICATION_STATE_NO] = Image(StockImage::Yes, RID_SVXBMP_DOC_MODIFIED_NO); + maImages[MODIFICATION_STATE_YES] = Image(StockImage::Yes, RID_SVXBMP_DOC_MODIFIED_YES); + maImages[MODIFICATION_STATE_FEEDBACK] = Image(StockImage::Yes, RID_SVXBMP_DOC_MODIFIED_FEEDBACK); + + maIdle.SetPriority(TaskPriority::LOWEST); + } +}; + +SvxModifyControl::SvxModifyControl( sal_uInt16 _nSlotId, sal_uInt16 _nId, StatusBar& rStb ) : + SfxStatusBarControl( _nSlotId, _nId, rStb ), + mxImpl(std::make_shared<ImplData>()) +{ + mxImpl->maIdle.SetInvokeHandler( LINK(this, SvxModifyControl, OnTimer) ); +} + + +void SvxModifyControl::StateChangedAtStatusBarControl( sal_uInt16, SfxItemState eState, + const SfxPoolItem* pState ) +{ + if ( SfxItemState::DEFAULT != eState ) + return; + + DBG_ASSERT( dynamic_cast<const SfxBoolItem*>( pState) != nullptr, "invalid item type" ); + const SfxBoolItem* pItem = static_cast<const SfxBoolItem*>(pState); + mxImpl->maIdle.Stop(); + + bool modified = pItem->GetValue(); + bool start = ( !modified && mxImpl->mnModState == ImplData::MODIFICATION_STATE_YES); // should timer be started and feedback image displayed ? + + mxImpl->mnModState = (start ? ImplData::MODIFICATION_STATE_FEEDBACK : (modified ? ImplData::MODIFICATION_STATE_YES : ImplData::MODIFICATION_STATE_NO)); + + _repaint(); + + TranslateId pResId = modified ? RID_SVXSTR_DOC_MODIFIED_YES : RID_SVXSTR_DOC_MODIFIED_NO; + GetStatusBar().SetQuickHelpText(GetId(), SvxResId(pResId)); + + if ( start ) + mxImpl->maIdle.Start(); +} + + +IMPL_LINK( SvxModifyControl, OnTimer, Timer *, pTimer, void ) +{ + if (pTimer == nullptr) + return; + + pTimer->Stop(); + mxImpl->mnModState = ImplData::MODIFICATION_STATE_NO; + + _repaint(); +} + + +void SvxModifyControl::_repaint() +{ + GetStatusBar().SetItemData( GetId(), nullptr ); // force repaint +} + +/** + * Given a bounding rectangle and an image, determine the top-left position + * of the image so that the image would look centered both horizontally and + * vertically. + * + * @param rBoundingRect bounding rectangle + * @param rImg image + * + * @return Point top-left corner of the centered image position + */ +Point centerImage(const tools::Rectangle& rBoundingRect, const Image& rImg) +{ + Size aImgSize = rImg.GetSizePixel(); + Size aRectSize = rBoundingRect.GetSize(); + tools::Long nXOffset = (aRectSize.getWidth() - aImgSize.getWidth())/2; + tools::Long nYOffset = (aRectSize.getHeight() - aImgSize.getHeight())/2; + Point aPt = rBoundingRect.TopLeft(); + aPt += Point(nXOffset, nYOffset); + return aPt; +} + +void SvxModifyControl::Paint( const UserDrawEvent& rUsrEvt ) +{ + vcl::RenderContext* pDev = rUsrEvt.GetRenderContext(); + tools::Rectangle aRect(rUsrEvt.GetRect()); + + ImplData::ModificationState state = mxImpl->mnModState; + Point aPt = centerImage(aRect, mxImpl->maImages[state]); + pDev->DrawImage(aPt, mxImpl->maImages[state]); +} + +void SvxModifyControl::Click() +{ + if (mxImpl->mnModState != ImplData::MODIFICATION_STATE_YES) + // document not modified. nothing to do here. + return; + + Sequence<PropertyValue> aArgs; + execute(".uno:Save", aArgs); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/stbctrls/modctrl_internal.hxx b/svx/source/stbctrls/modctrl_internal.hxx new file mode 100644 index 000000000..d6d3d6834 --- /dev/null +++ b/svx/source/stbctrls/modctrl_internal.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SVX_SOURCE_STBCTRLS_MODCTRL_INTERNAL_HXX +#define INCLUDED_SVX_SOURCE_STBCTRLS_MODCTRL_INTERNAL_HXX + +#include <tools/gen.hxx> + +class Image; + +Point centerImage(const tools::Rectangle& rBoundingRect, const Image& rImg); + +#endif // INCLUDED_SVX_SOURCE_STBCTRLS_MODCTRL_INTERNAL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/stbctrls/pszctrl.cxx b/svx/source/stbctrls/pszctrl.cxx new file mode 100644 index 000000000..129ac67eb --- /dev/null +++ b/svx/source/stbctrls/pszctrl.cxx @@ -0,0 +1,486 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <comphelper/propertyvalue.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/event.hxx> +#include <vcl/fieldvalues.hxx> +#include <vcl/status.hxx> +#include <vcl/image.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <vcl/weldutils.hxx> +#include <svl/stritem.hxx> +#include <svl/ptitem.hxx> +#include <sfx2/module.hxx> +#include <svl/intitem.hxx> +#include <sal/log.hxx> + +#include <svx/pszctrl.hxx> + +#define PAINT_OFFSET 5 + +#include <editeng/sizeitem.hxx> +#include "stbctrls.h" + +#include <svx/svxids.hrc> +#include <bitmaps.hlst> +#include <unotools/localedatawrapper.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> + +/* [Description] + + Function used to create a text representation of + a metric value + + nVal is the metric value in the unit eUnit. + + [cross reference] + + <SvxPosSizeStatusBarControl::Paint(const UserDrawEvent&)> +*/ + +OUString SvxPosSizeStatusBarControl::GetMetricStr_Impl( tools::Long nVal ) const +{ + // deliver and set the Metric of the application + FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() ); + + OUString sMetric; + const sal_Unicode cSep = Application::GetSettings().GetLocaleDataWrapper().getNumDecimalSep()[0]; + sal_Int64 nConvVal = vcl::ConvertValue( nVal * 100, 0, 0, FieldUnit::MM_100TH, eOutUnit ); + + if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) ) + sMetric += "-"; + sMetric += OUString::number(nConvVal / 100); + + if( FieldUnit::NONE != eOutUnit ) + { + sMetric += OUStringChar(cSep); + sal_Int64 nFract = nConvVal % 100; + + if ( nFract < 0 ) + nFract *= -1; + if ( nFract < 10 ) + sMetric += "0"; + sMetric += OUString::number(nFract); + } + + return sMetric; +} + + +SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem); + +namespace { + +class FunctionPopup_Impl +{ + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Menu> m_xMenu; + sal_uInt32 m_nSelected; + static sal_uInt16 id_to_function(std::string_view rIdent); + static OString function_to_id(sal_uInt16 nFunc); +public: + explicit FunctionPopup_Impl(sal_uInt32 nCheckEncoded); + OString Execute(weld::Window* pParent, const tools::Rectangle& rRect) + { + return m_xMenu->popup_at_rect(pParent, rRect); + } + sal_uInt32 GetSelected(std::string_view curident) const; +}; + +} + +sal_uInt16 FunctionPopup_Impl::id_to_function(std::string_view rIdent) +{ + if (rIdent == "avg") + return PSZ_FUNC_AVG; + else if (rIdent == "counta") + return PSZ_FUNC_COUNT2; + else if (rIdent == "count") + return PSZ_FUNC_COUNT; + else if (rIdent == "max") + return PSZ_FUNC_MAX; + else if (rIdent == "min") + return PSZ_FUNC_MIN; + else if (rIdent == "sum") + return PSZ_FUNC_SUM; + else if (rIdent == "selection") + return PSZ_FUNC_SELECTION_COUNT; + else if (rIdent == "none") + return PSZ_FUNC_NONE; + return 0; +} + +OString FunctionPopup_Impl::function_to_id(sal_uInt16 nFunc) +{ + switch (nFunc) + { + case PSZ_FUNC_AVG: + return "avg"; + case PSZ_FUNC_COUNT2: + return "counta"; + case PSZ_FUNC_COUNT: + return "count"; + case PSZ_FUNC_MAX: + return "max"; + case PSZ_FUNC_MIN: + return "min"; + case PSZ_FUNC_SUM: + return "sum"; + case PSZ_FUNC_SELECTION_COUNT: + return "selection"; + case PSZ_FUNC_NONE: + return "none"; + } + return OString(); +} + +FunctionPopup_Impl::FunctionPopup_Impl(sal_uInt32 nCheckEncoded) + : m_xBuilder(Application::CreateBuilder(nullptr, "svx/ui/functionmenu.ui")) + , m_xMenu(m_xBuilder->weld_menu("menu")) + , m_nSelected(nCheckEncoded) +{ + for ( sal_uInt16 nCheck = 1; nCheck < 32; ++nCheck ) + if ( nCheckEncoded & (1u << nCheck) ) + m_xMenu->set_active(function_to_id(nCheck), true); +} + +sal_uInt32 FunctionPopup_Impl::GetSelected(std::string_view curident) const +{ + sal_uInt32 nSelected = m_nSelected; + sal_uInt16 nCurItemId = id_to_function(curident); + if ( nCurItemId == PSZ_FUNC_NONE ) + nSelected = ( 1 << PSZ_FUNC_NONE ); + else + { + nSelected &= (~( 1u << PSZ_FUNC_NONE )); // Clear the "None" bit + nSelected ^= ( 1u << nCurItemId ); // Toggle the bit corresponding to nCurItemId + if ( !nSelected ) + nSelected = ( 1u << PSZ_FUNC_NONE ); + } + return nSelected; +} + +struct SvxPosSizeStatusBarControl_Impl + +/* [Description] + + This implementation-structure of the class SvxPosSizeStatusBarControl + is done for the un-linking of the changes of the exported interface such as + the toning down of symbols that are visible externally. + + One instance exists for each SvxPosSizeStatusBarControl-instance + during its life time +*/ + +{ + Point aPos; // valid when a position is shown + Size aSize; // valid when a size is shown + OUString aStr; // valid when a text is shown + bool bPos; // show position ? + bool bSize; // set size ? + bool bTable; // set table index ? + bool bHasMenu; // set StarCalc popup menu ? + sal_uInt32 nFunctionSet; // the selected StarCalc functions encoded in 32 bits + Image aPosImage; // Image to show the position + Image aSizeImage; // Image to show the size +}; + +/* [Description] + + Ctor(): + Create an instance of the implementation class, + load the images for the position and size +*/ + +#define STR_POSITION ".uno:Position" +#define STR_TABLECELL ".uno:StateTableCell" +#define STR_FUNC ".uno:StatusBarFunc" + +SvxPosSizeStatusBarControl::SvxPosSizeStatusBarControl( sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb ) : + SfxStatusBarControl( _nSlotId, _nId, rStb ), + pImpl( new SvxPosSizeStatusBarControl_Impl ) +{ + pImpl->bPos = false; + pImpl->bSize = false; + pImpl->bTable = false; + pImpl->bHasMenu = false; + pImpl->nFunctionSet = 0; + pImpl->aPosImage = Image(StockImage::Yes, RID_SVXBMP_POSITION); + pImpl->aSizeImage = Image(StockImage::Yes, RID_SVXBMP_SIZE); + + addStatusListener( STR_POSITION); // SID_ATTR_POSITION + addStatusListener( STR_TABLECELL); // SID_TABLE_CELL + addStatusListener( STR_FUNC); // SID_PSZ_FUNCTION + ImplUpdateItemText(); +} + +/* [Description] + + Dtor(): + remove the pointer to the implementation class, so that the timer is stopped + +*/ + +SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl() +{ +} + + +/* [Description] + + SID_PSZ_FUNCTION activates the popup menu for Calc: + + Status overview + Depending on the type of the item, a special setting is enabled, the others disabled. + + NULL/Void SfxPointItem SvxSizeItem SfxStringItem + ------------------------------------------------------------------------ + Position sal_False FALSE + Size FALSE TRUE FALSE + Text sal_False sal_False TRUE + +*/ + +void SvxPosSizeStatusBarControl::StateChangedAtStatusBarControl( sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState ) +{ + // Because the combi-controller, always sets the current Id as HelpId + // first clean the cached HelpText + GetStatusBar().SetHelpText( GetId(), "" ); + + switch ( nSID ) + { + case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break; + case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break; + case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break; + default: break; + } + + if ( nSID == SID_PSZ_FUNCTION ) + { + if ( eState == SfxItemState::DEFAULT ) + { + pImpl->bHasMenu = true; + if ( auto pUInt32Item = dynamic_cast< const SfxUInt32Item* >(pState) ) + pImpl->nFunctionSet = pUInt32Item->GetValue(); + } + else + pImpl->bHasMenu = false; + } + else if ( SfxItemState::DEFAULT != eState ) + { + // don't switch to empty display before an empty state was + // notified for all display types + + if ( nSID == SID_TABLE_CELL ) + pImpl->bTable = false; + else if ( nSID == SID_ATTR_POSITION ) + pImpl->bPos = false; + else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE + pImpl->bSize = false; + else + { + SAL_WARN( "svx.stbcrtls","unknown slot id"); + } + } + else if ( auto pPointItem = dynamic_cast<const SfxPointItem*>( pState) ) + { + // show position + pImpl->aPos = pPointItem->GetValue(); + pImpl->bPos = true; + pImpl->bTable = false; + } + else if ( auto pSizeItem = dynamic_cast<const SvxSizeItem*>( pState) ) + { + // show size + pImpl->aSize = pSizeItem->GetSize(); + pImpl->bSize = true; + pImpl->bTable = false; + } + else if ( auto pStringItem = dynamic_cast<const SfxStringItem*>( pState) ) + { + // show string (table cel or different) + pImpl->aStr = pStringItem->GetValue(); + pImpl->bTable = true; + pImpl->bPos = false; + pImpl->bSize = false; + } + else + { + SAL_WARN( "svx.stbcrtls", "invalid item type" ); + pImpl->bPos = false; + pImpl->bSize = false; + pImpl->bTable = false; + } + + GetStatusBar().SetItemData( GetId(), nullptr ); + + ImplUpdateItemText(); +} + + +/* [Description] + + execute popup menu, when the status enables this +*/ + +void SvxPosSizeStatusBarControl::Command( const CommandEvent& rCEvt ) +{ + if ( rCEvt.GetCommand() == CommandEventId::ContextMenu && pImpl->bHasMenu ) + { + sal_uInt32 nSelect = pImpl->nFunctionSet; + if (!nSelect) + nSelect = ( 1 << PSZ_FUNC_NONE ); + tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1,1)); + weld::Window* pParent = weld::GetPopupParent(GetStatusBar(), aRect); + FunctionPopup_Impl aMenu(nSelect); + OString sIdent = aMenu.Execute(pParent, aRect); + if (!sIdent.isEmpty()) + { + nSelect = aMenu.GetSelected(sIdent); + if (nSelect) + { + if (nSelect == (1 << PSZ_FUNC_NONE)) + nSelect = 0; + + css::uno::Any a; + SfxUInt32Item aItem( SID_PSZ_FUNCTION, nSelect ); + aItem.QueryValue( a ); + css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue( + "StatusBarFunc", a) }; + execute( ".uno:StatusBarFunc", aArgs ); + } + } + } + else + SfxStatusBarControl::Command( rCEvt ); +} + + +/* [Description] + + Depending on the type to be shown, the value us shown. First the + rectangle is repainted (removed). +*/ + +void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt ) +{ + vcl::RenderContext* pDev = rUsrEvt.GetRenderContext(); + + const tools::Rectangle& rRect = rUsrEvt.GetRect(); + StatusBar& rBar = GetStatusBar(); + Point aItemPos = rBar.GetItemTextPos( GetId() ); + Color aOldLineColor = pDev->GetLineColor(); + Color aOldFillColor = pDev->GetFillColor(); + pDev->SetLineColor(); + pDev->SetFillColor( pDev->GetBackground().GetColor() ); + + if ( pImpl->bPos || pImpl->bSize ) + { + // count the position for showing the size + tools::Long nSizePosX = + rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET; + // draw position + Point aPnt = rRect.TopLeft(); + aPnt.setY( aItemPos.Y() ); + aPnt.AdjustX(PAINT_OFFSET ); + pDev->DrawImage( aPnt, pImpl->aPosImage ); + aPnt.AdjustX(pImpl->aPosImage.GetSizePixel().Width() ); + aPnt.AdjustX(PAINT_OFFSET ); + OUString aStr = GetMetricStr_Impl( pImpl->aPos.X()) + " / " + + GetMetricStr_Impl( pImpl->aPos.Y()); + tools::Rectangle aRect(aPnt, Point(nSizePosX, rRect.Bottom())); + pDev->DrawRect(aRect); + vcl::Region aOrigRegion(pDev->GetClipRegion()); + pDev->SetClipRegion(vcl::Region(aRect)); + pDev->DrawText(aPnt, aStr); + pDev->SetClipRegion(aOrigRegion); + + // draw the size, when available + aPnt.setX( nSizePosX ); + + if ( pImpl->bSize ) + { + pDev->DrawImage( aPnt, pImpl->aSizeImage ); + aPnt.AdjustX(pImpl->aSizeImage.GetSizePixel().Width() ); + Point aDrwPnt = aPnt; + aPnt.AdjustX(PAINT_OFFSET ); + aStr = GetMetricStr_Impl( pImpl->aSize.Width() ) + " x " + + GetMetricStr_Impl( pImpl->aSize.Height() ); + aRect = tools::Rectangle(aDrwPnt, rRect.BottomRight()); + pDev->DrawRect(aRect); + aOrigRegion = pDev->GetClipRegion(); + pDev->SetClipRegion(vcl::Region(aRect)); + pDev->DrawText(aPnt, aStr); + pDev->SetClipRegion(aOrigRegion); + } + else + pDev->DrawRect( tools::Rectangle( aPnt, rRect.BottomRight() ) ); + } + else if ( pImpl->bTable ) + { + pDev->DrawRect( rRect ); + pDev->DrawText( Point( + rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImpl->aStr ) / 2, + aItemPos.Y() ), pImpl->aStr ); + } + else + { + // Empty display if neither size nor table position are available. + // Date/Time are no longer used (#65302#). + pDev->DrawRect( rRect ); + } + + pDev->SetLineColor( aOldLineColor ); + pDev->SetFillColor( aOldFillColor ); +} + +void SvxPosSizeStatusBarControl::ImplUpdateItemText() +{ + // set only strings as text at the statusBar, so that the Help-Tips + // can work with the text, when it is too long for the statusBar + OUString aText; + int nCharsWidth = -1; + if ( pImpl->bPos || pImpl->bSize ) + { + aText = GetMetricStr_Impl( pImpl->aPos.X()) + " / " + + GetMetricStr_Impl( pImpl->aPos.Y()); + // widest X/Y string looks like "-999,99" + nCharsWidth = 1 + 6 + 3 + 6; // icon + x + slash + y + if ( pImpl->bSize ) + { + aText += " " + GetMetricStr_Impl( pImpl->aSize.Width() ) + " x " + + GetMetricStr_Impl( pImpl->aSize.Height() ); + nCharsWidth += 1 + 1 + 4 + 3 + 4; // icon + space + w + x + h + } + } + else if ( pImpl->bTable ) + aText = pImpl->aStr; + + GetStatusBar().SetItemText( GetId(), aText, nCharsWidth ); +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/stbctrls/selctrl.cxx b/svx/source/stbctrls/selctrl.cxx new file mode 100644 index 000000000..8c32f3ed8 --- /dev/null +++ b/svx/source/stbctrls/selctrl.cxx @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <string_view> + +#include <comphelper/propertyvalue.hxx> +#include <vcl/event.hxx> +#include <vcl/status.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weldutils.hxx> +#include <svl/intitem.hxx> +#include <tools/urlobj.hxx> + +#include <svx/selctrl.hxx> + +#include <bitmaps.hlst> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> + +SFX_IMPL_STATUSBAR_CONTROL(SvxSelectionModeControl, SfxUInt16Item); + +namespace { + +/// Popup menu to select the selection type +class SelectionTypePopup +{ + weld::Window* m_pPopupParent; + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Menu> m_xMenu; + static OString state_to_id(sal_uInt16 nState); +public: + SelectionTypePopup(weld::Window* pPopupParent, sal_uInt16 nCurrent); + OUString GetItemTextForState(sal_uInt16 nState) { return m_xMenu->get_label(state_to_id(nState)); } + OString popup_at_rect(const tools::Rectangle& rRect) + { + return m_xMenu->popup_at_rect(m_pPopupParent, rRect); + } + void HideSelectionType(const OString& rIdent) + { + m_xMenu->remove(rIdent); + } + static sal_uInt16 id_to_state(std::string_view ident); +}; + +} + +sal_uInt16 SelectionTypePopup::id_to_state(std::string_view ident) +{ + if (ident == "block") + return 3; + else if (ident == "adding") + return 2; + else if (ident == "extending") + return 1; + else // fall through + return 0; +} + +OString SelectionTypePopup::state_to_id(sal_uInt16 nState) +{ + switch (nState) + { + default: // fall through + case 0: return "standard"; + case 1: return "extending"; + case 2: return "adding"; + case 3: return "block"; + } +} + +SelectionTypePopup::SelectionTypePopup(weld::Window* pPopupParent, sal_uInt16 nCurrent) + : m_pPopupParent(pPopupParent) + , m_xBuilder(Application::CreateBuilder(m_pPopupParent, "svx/ui/selectionmenu.ui")) + , m_xMenu(m_xBuilder->weld_menu("menu")) +{ + m_xMenu->set_active(state_to_id(nCurrent), true); +} + +SvxSelectionModeControl::SvxSelectionModeControl( sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb ) : + SfxStatusBarControl( _nSlotId, _nId, rStb ), + mnState( 0 ), + maImages{Image(StockImage::Yes, RID_SVXBMP_STANDARD_SELECTION), + Image(StockImage::Yes, RID_SVXBMP_EXTENDING_SELECTION), + Image(StockImage::Yes, RID_SVXBMP_ADDING_SELECTION), + Image(StockImage::Yes, RID_SVXBMP_BLOCK_SELECTION)}, + mbFeatureEnabled(false) +{ + GetStatusBar().SetQuickHelpText(GetId(), u""); +} + +void SvxSelectionModeControl::StateChangedAtStatusBarControl( sal_uInt16, SfxItemState eState, + const SfxPoolItem* pState ) +{ + mbFeatureEnabled = SfxItemState::DEFAULT == eState; + if (mbFeatureEnabled) + { + DBG_ASSERT( dynamic_cast< const SfxUInt16Item* >(pState) != nullptr, "invalid item type" ); + const SfxUInt16Item* pItem = static_cast<const SfxUInt16Item*>(pState); + mnState = pItem->GetValue(); + SelectionTypePopup aPop(GetStatusBar().GetFrameWeld(), mnState); + GetStatusBar().SetQuickHelpText(GetId(), + SvxResId(RID_SVXSTR_SELECTIONMODE_HELPTEXT). + replaceFirst("%1", aPop.GetItemTextForState(mnState))); + GetStatusBar().Invalidate(); + } +} + +bool SvxSelectionModeControl::MouseButtonDown( const MouseEvent& rEvt ) +{ + if (!mbFeatureEnabled) + return true; + + ::tools::Rectangle aRect(rEvt.GetPosPixel(), Size(1, 1)); + weld::Window* pPopupParent = weld::GetPopupParent(GetStatusBar(), aRect); + SelectionTypePopup aPop(pPopupParent, mnState); + + // Check if Calc is opened; if true, hide block selection mode tdf#122280 + const css::uno::Reference < css::frame::XModel > xModel = m_xFrame->getController()->getModel(); + css::uno::Reference< css::lang::XServiceInfo > xServices( xModel, css::uno::UNO_QUERY ); + if ( xServices.is() ) + { + bool bSpecModeCalc = xServices->supportsService("com.sun.star.sheet.SpreadsheetDocument"); + if (bSpecModeCalc) + aPop.HideSelectionType("block"); + } + + OString sIdent = aPop.popup_at_rect(aRect); + if (!sIdent.isEmpty()) + { + sal_uInt16 nNewState = SelectionTypePopup::id_to_state(sIdent); + if ( nNewState != mnState ) + { + mnState = nNewState; + + css::uno::Any a; + SfxUInt16Item aState( GetSlotId(), mnState ); + aState.QueryValue( a ); + INetURLObject aObj( m_aCommandURL ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue( + aObj.GetURLPath(), a) }; + execute( aArgs ); + } + } + + return true; +} + +void SvxSelectionModeControl::Click() +{ +} + +void SvxSelectionModeControl::Paint( const UserDrawEvent& rUsrEvt ) +{ + const tools::Rectangle aControlRect = getControlRect(); + vcl::RenderContext* pDev = rUsrEvt.GetRenderContext(); + tools::Rectangle aRect = rUsrEvt.GetRect(); + + Size aImgSize( maImages[mnState].GetSizePixel() ); + + Point aPos( aRect.Left() + ( aControlRect.GetWidth() - aImgSize.Width() ) / 2, + aRect.Top() + ( aControlRect.GetHeight() - aImgSize.Height() ) / 2 ); + + if (mbFeatureEnabled) + pDev->DrawImage(aPos, maImages[mnState]); + else + pDev->DrawImage(aPos, Image()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/stbctrls/stbctrls.h b/svx/source/stbctrls/stbctrls.h new file mode 100644 index 000000000..3b12d6f95 --- /dev/null +++ b/svx/source/stbctrls/stbctrls.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SVX_SOURCE_STBCTRLS_STBCTRLS_H +#define INCLUDED_SVX_SOURCE_STBCTRLS_STBCTRLS_H + +// IDs as in SUBTOTAL_FUNC of Calc + +#define PSZ_FUNC_AVG 1 +#define PSZ_FUNC_COUNT2 3 +#define PSZ_FUNC_COUNT 2 +#define PSZ_FUNC_MAX 4 +#define PSZ_FUNC_MIN 5 +#define PSZ_FUNC_SUM 9 +#define PSZ_FUNC_SELECTION_COUNT 13 +#define PSZ_FUNC_NONE 16 + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/stbctrls/xmlsecctrl.cxx b/svx/source/stbctrls/xmlsecctrl.cxx new file mode 100644 index 000000000..0a26128d9 --- /dev/null +++ b/svx/source/stbctrls/xmlsecctrl.cxx @@ -0,0 +1,162 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <comphelper/propertyvalue.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/image.hxx> +#include <vcl/event.hxx> +#include <vcl/status.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weldutils.hxx> +#include <sfx2/signaturestate.hxx> +#include <sfx2/module.hxx> + +#include <svl/intitem.hxx> + +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> +#include <svx/xmlsecctrl.hxx> +#include <tools/urlobj.hxx> +#include <bitmaps.hlst> +#include <sal/log.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> + +SFX_IMPL_STATUSBAR_CONTROL( XmlSecStatusBarControl, SfxUInt16Item ); + +struct XmlSecStatusBarControl::XmlSecStatusBarControl_Impl +{ + SignatureState mnState; + Image maImage; + Image maImageBroken; + Image maImageNotValidated; +}; + + +XmlSecStatusBarControl::XmlSecStatusBarControl( sal_uInt16 _nSlotId, sal_uInt16 _nId, StatusBar& _rStb ) + :SfxStatusBarControl( _nSlotId, _nId, _rStb ) + ,mpImpl( new XmlSecStatusBarControl_Impl ) +{ + mpImpl->mnState = SignatureState::UNKNOWN; + + mpImpl->maImage = Image(StockImage::Yes, RID_SVXBMP_SIGNET); + mpImpl->maImageBroken = Image(StockImage::Yes, RID_SVXBMP_SIGNET_BROKEN); + mpImpl->maImageNotValidated = Image(StockImage::Yes, RID_SVXBMP_SIGNET_NOTVALIDATED); +} + +XmlSecStatusBarControl::~XmlSecStatusBarControl() +{ +} + +void XmlSecStatusBarControl::StateChangedAtStatusBarControl( sal_uInt16, SfxItemState eState, const SfxPoolItem* pState ) +{ + if( SfxItemState::DEFAULT != eState ) + { + mpImpl->mnState = SignatureState::UNKNOWN; + } + else if( auto pUint16Item = dynamic_cast< const SfxUInt16Item* >(pState) ) + { + mpImpl->mnState = static_cast<SignatureState>(pUint16Item->GetValue()); + } + else + { + SAL_WARN( "svx.stbcrtls", "+XmlSecStatusBarControl::StateChangedAtStatusBarControl(): invalid item type" ); + mpImpl->mnState = SignatureState::UNKNOWN; + } + + GetStatusBar().SetItemData( GetId(), nullptr ); // necessary ? + + GetStatusBar().SetItemText( GetId(), "" ); // necessary ? + + TranslateId pResId = RID_SVXSTR_XMLSEC_NO_SIG; + if ( mpImpl->mnState == SignatureState::OK ) + pResId = RID_SVXSTR_XMLSEC_SIG_OK; + else if ( mpImpl->mnState == SignatureState::BROKEN ) + pResId = RID_SVXSTR_XMLSEC_SIG_NOT_OK; + else if ( mpImpl->mnState == SignatureState::NOTVALIDATED ) + pResId = RID_SVXSTR_XMLSEC_SIG_OK_NO_VERIFY; + else if ( mpImpl->mnState == SignatureState::PARTIAL_OK ) + pResId = RID_SVXSTR_XMLSEC_SIG_CERT_OK_PARTIAL_SIG; + + GetStatusBar().SetQuickHelpText(GetId(), SvxResId(pResId)); +} + +void XmlSecStatusBarControl::Command( const CommandEvent& rCEvt ) +{ + if( rCEvt.GetCommand() == CommandEventId::ContextMenu ) + { + tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1, 1)); + weld::Window* pPopupParent = weld::GetPopupParent(GetStatusBar(), aRect); + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "svx/ui/xmlsecstatmenu.ui")); + std::unique_ptr<weld::Menu> xPopMenu(xBuilder->weld_menu("menu")); + if (!xPopMenu->popup_at_rect(pPopupParent, aRect).isEmpty()) + { + css::uno::Any a; + SfxUInt16Item aState( GetSlotId(), 0 ); + aState.QueryValue( a ); + INetURLObject aObj( m_aCommandURL ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue( + aObj.GetURLPath(), a) }; + execute( aArgs ); + } + } + else + SfxStatusBarControl::Command( rCEvt ); +} + +void XmlSecStatusBarControl::Paint( const UserDrawEvent& rUsrEvt ) +{ + vcl::RenderContext* pDev = rUsrEvt.GetRenderContext(); + + tools::Rectangle aRect = rUsrEvt.GetRect(); + Color aOldLineColor = pDev->GetLineColor(); + Color aOldFillColor = pDev->GetFillColor(); + + pDev->SetLineColor(); + pDev->SetFillColor( pDev->GetBackground().GetColor() ); + + tools::Long yOffset = (aRect.GetHeight() - mpImpl->maImage.GetSizePixel().Height()) / 2; + + if( mpImpl->mnState == SignatureState::OK ) + { + aRect.AdjustTop(yOffset ); + pDev->DrawImage( aRect.TopLeft(), mpImpl->maImage ); + } + else if( mpImpl->mnState == SignatureState::BROKEN ) + { + aRect.AdjustTop(yOffset ); + pDev->DrawImage( aRect.TopLeft(), mpImpl->maImageBroken ); + } + else if( mpImpl->mnState == SignatureState::NOTVALIDATED + || mpImpl->mnState == SignatureState::PARTIAL_OK) + { + aRect.AdjustTop(yOffset ); + pDev->DrawImage( aRect.TopLeft(), mpImpl->maImageNotValidated ); + } + else + pDev->DrawRect( aRect ); + + pDev->SetLineColor( aOldLineColor ); + pDev->SetFillColor( aOldFillColor ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/stbctrls/zoomctrl.cxx b/svx/source/stbctrls/zoomctrl.cxx new file mode 100644 index 000000000..57cf99bbd --- /dev/null +++ b/svx/source/stbctrls/zoomctrl.cxx @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <comphelper/propertyvalue.hxx> +#include <i18nutil/unicode.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/event.hxx> +#include <vcl/svapp.hxx> +#include <vcl/status.hxx> +#include <vcl/weldutils.hxx> +#include <vcl/settings.hxx> +#include <tools/urlobj.hxx> +#include <sal/log.hxx> + +#include <svx/strings.hrc> + +#include <svx/zoomctrl.hxx> +#include <sfx2/zoomitem.hxx> +#include <svx/dialmgr.hxx> +#include "modctrl_internal.hxx" +#include <bitmaps.hlst> + +#include <com/sun/star/beans/PropertyValue.hpp> + +SFX_IMPL_STATUSBAR_CONTROL(SvxZoomStatusBarControl,SvxZoomItem); + +namespace { + +class ZoomPopup_Impl +{ +public: + ZoomPopup_Impl(weld::Window* pPopupParent, sal_uInt16 nZ, SvxZoomEnableFlags nValueSet); + + sal_uInt16 GetZoom(std::string_view ident) const; + + OString popup_at_rect(const tools::Rectangle& rRect) + { + return m_xMenu->popup_at_rect(m_pPopupParent, rRect); + } + +private: + weld::Window* m_pPopupParent; + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Menu> m_xMenu; + sal_uInt16 nZoom; +}; + +} + +ZoomPopup_Impl::ZoomPopup_Impl(weld::Window* pPopupParent, sal_uInt16 nZ, SvxZoomEnableFlags nValueSet) + : m_pPopupParent(pPopupParent) + , m_xBuilder(Application::CreateBuilder(m_pPopupParent, "svx/ui/zoommenu.ui")) + , m_xMenu(m_xBuilder->weld_menu("menu")) + , nZoom(nZ) +{ + if ( !(SvxZoomEnableFlags::N50 & nValueSet) ) + m_xMenu->set_sensitive("50", false); + if ( !(SvxZoomEnableFlags::N100 & nValueSet) ) + m_xMenu->set_sensitive("100", false); + if ( !(SvxZoomEnableFlags::N150 & nValueSet) ) + m_xMenu->set_sensitive("150", false); + if ( !(SvxZoomEnableFlags::N200 & nValueSet) ) + m_xMenu->set_sensitive("200", false); + if ( !(SvxZoomEnableFlags::OPTIMAL & nValueSet) ) + m_xMenu->set_sensitive("optimal", false); + if ( !(SvxZoomEnableFlags::WHOLEPAGE & nValueSet) ) + m_xMenu->set_sensitive("page", false); + if ( !(SvxZoomEnableFlags::PAGEWIDTH & nValueSet) ) + m_xMenu->set_sensitive("width", false); +} + +sal_uInt16 ZoomPopup_Impl::GetZoom(std::string_view ident) const +{ + sal_uInt16 nRet = nZoom; + + if (ident == "200") + nRet = 200; + else if (ident == "150") + nRet = 150; + else if (ident == "100") + nRet = 100; + else if (ident == "75") + nRet = 75; + else if (ident == "50") + nRet = 50; + else if (ident == "optimal" || ident == "width" || ident == "page") + nRet = 0; + + return nRet; +} + +SvxZoomStatusBarControl::SvxZoomStatusBarControl( sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb ) : + + SfxStatusBarControl( _nSlotId, _nId, rStb ), + nZoom( 100 ), + nValueSet( SvxZoomEnableFlags::ALL ) +{ + GetStatusBar().SetQuickHelpText(GetId(), SvxResId(RID_SVXSTR_ZOOMTOOL_HINT)); + ImplUpdateItemText(); +} + +void SvxZoomStatusBarControl::StateChangedAtStatusBarControl( sal_uInt16, SfxItemState eState, + const SfxPoolItem* pState ) +{ + if( SfxItemState::DEFAULT != eState ) + { + GetStatusBar().SetItemText( GetId(), "" ); + nValueSet = SvxZoomEnableFlags::NONE; + } + else if ( auto pItem = dynamic_cast< const SfxUInt16Item* >(pState) ) + { + nZoom = pItem->GetValue(); + ImplUpdateItemText(); + + if ( auto pZoomItem = dynamic_cast<const SvxZoomItem*>(pState) ) + { + nValueSet = pZoomItem->GetValueSet(); + } + else + { + SAL_INFO( "svx", "use SfxZoomItem for SID_ATTR_ZOOM" ); + nValueSet = SvxZoomEnableFlags::ALL; + } + } +} + +void SvxZoomStatusBarControl::ImplUpdateItemText() +{ + // workaround - don't bother updating when we don't have a real zoom value + if (nZoom) + { + OUString aStr(unicode::formatPercent(nZoom, Application::GetSettings().GetUILanguageTag())); + GetStatusBar().SetItemText( GetId(), aStr ); + } +} + +void SvxZoomStatusBarControl::Paint( const UserDrawEvent& ) +{ +} + +void SvxZoomStatusBarControl::Command( const CommandEvent& rCEvt ) +{ + if ( CommandEventId::ContextMenu == rCEvt.GetCommand() && bool(nValueSet) ) + { + ::tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1, 1)); + weld::Window* pPopupParent = weld::GetPopupParent(GetStatusBar(), aRect); + ZoomPopup_Impl aPop(pPopupParent, nZoom, nValueSet); + + OString sIdent = aPop.popup_at_rect(aRect); + if (!sIdent.isEmpty() && (nZoom != aPop.GetZoom(sIdent) || !nZoom)) + { + nZoom = aPop.GetZoom(sIdent); + ImplUpdateItemText(); + SvxZoomItem aZoom(SvxZoomType::PERCENT, nZoom, GetId()); + + if (sIdent == "optimal") + aZoom.SetType(SvxZoomType::OPTIMAL); + else if (sIdent == "width") + aZoom.SetType(SvxZoomType::PAGEWIDTH); + else if (sIdent == "page") + aZoom.SetType(SvxZoomType::WHOLEPAGE); + + css::uno::Any a; + aZoom.QueryValue( a ); + INetURLObject aObj( m_aCommandURL ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue( + aObj.GetURLPath(), a) }; + execute( aArgs ); + } + } + else + SfxStatusBarControl::Command( rCEvt ); +} + +SFX_IMPL_STATUSBAR_CONTROL(SvxZoomPageStatusBarControl,SfxVoidItem); + +SvxZoomPageStatusBarControl::SvxZoomPageStatusBarControl(sal_uInt16 _nSlotId, + sal_uInt16 _nId, StatusBar& rStb) + : SfxStatusBarControl(_nSlotId, _nId, rStb) + , maImage(StockImage::Yes, RID_SVXBMP_ZOOM_PAGE) +{ + GetStatusBar().SetQuickHelpText(GetId(), SvxResId(RID_SVXSTR_FIT_SLIDE)); +} + +void SvxZoomPageStatusBarControl::Paint(const UserDrawEvent& rUsrEvt) +{ + vcl::RenderContext* pDev = rUsrEvt.GetRenderContext(); + tools::Rectangle aRect = rUsrEvt.GetRect(); + Point aPt = centerImage(aRect, maImage); + pDev->DrawImage(aPt, maImage); +} + +bool SvxZoomPageStatusBarControl::MouseButtonDown(const MouseEvent&) +{ + SvxZoomItem aZoom( SvxZoomType::WHOLEPAGE, 0, GetId() ); + + css::uno::Any a; + aZoom.QueryValue( a ); + INetURLObject aObj( m_aCommandURL ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs{ comphelper::makePropertyValue( + aObj.GetURLPath(), a) }; + execute( aArgs ); + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/stbctrls/zoomsliderctrl.cxx b/svx/source/stbctrls/zoomsliderctrl.cxx new file mode 100644 index 000000000..c0790b074 --- /dev/null +++ b/svx/source/stbctrls/zoomsliderctrl.cxx @@ -0,0 +1,392 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svx/zoomsliderctrl.hxx> + +#include <comphelper/propertyvalue.hxx> +#include <vcl/status.hxx> +#include <vcl/image.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <vcl/event.hxx> +#include <svx/zoomslideritem.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <basegfx/utils/zoomtools.hxx> +#include <bitmaps.hlst> +#include <com/sun/star/beans/PropertyValue.hpp> + +#include <set> + +SFX_IMPL_STATUSBAR_CONTROL( SvxZoomSliderControl, SvxZoomSliderItem ); + +struct SvxZoomSliderControl::SvxZoomSliderControl_Impl +{ + sal_uInt16 mnCurrentZoom; + sal_uInt16 mnMinZoom; + sal_uInt16 mnMaxZoom; + sal_uInt16 mnSliderCenter; + std::vector< tools::Long > maSnappingPointOffsets; + std::vector< sal_uInt16 > maSnappingPointZooms; + Image maSliderButton; + Image maIncreaseButton; + Image maDecreaseButton; + bool mbValuesSet; + bool mbDraggingStarted; + + SvxZoomSliderControl_Impl() : + mnCurrentZoom( 0 ), + mnMinZoom( 0 ), + mnMaxZoom( 0 ), + mnSliderCenter( 0 ), + mbValuesSet( false ), + mbDraggingStarted( false ) {} +}; + +const tools::Long nSliderXOffset = 20; +const tools::Long nSnappingEpsilon = 5; // snapping epsilon in pixels +const tools::Long nSnappingPointsMinDist = nSnappingEpsilon; // minimum distance of two adjacent snapping points + +// nOffset refers to the origin of the control: +// + ----------- - +sal_uInt16 SvxZoomSliderControl::Offset2Zoom( tools::Long nOffset ) const +{ + const tools::Long nControlWidth = getControlRect().GetWidth(); + sal_uInt16 nRet = 0; + + if ( nOffset < nSliderXOffset ) + return mxImpl->mnMinZoom; + + if ( nOffset > nControlWidth - nSliderXOffset ) + return mxImpl->mnMaxZoom; + + // check for snapping points: + sal_uInt16 nCount = 0; + for ( const tools::Long nCurrent : mxImpl->maSnappingPointOffsets ) + { + if ( std::abs(nCurrent - nOffset) < nSnappingEpsilon ) + { + nOffset = nCurrent; + nRet = mxImpl->maSnappingPointZooms[ nCount ]; + break; + } + ++nCount; + } + + if ( 0 == nRet ) + { + if ( nOffset < nControlWidth / 2 ) + { + // first half of slider + const tools::Long nFirstHalfRange = mxImpl->mnSliderCenter - mxImpl->mnMinZoom; + const tools::Long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset; + const tools::Long nZoomPerSliderPixel = (1000 * nFirstHalfRange) / nHalfSliderWidth; + const tools::Long nOffsetToSliderLeft = nOffset - nSliderXOffset; + nRet = mxImpl->mnMinZoom + sal_uInt16( nOffsetToSliderLeft * nZoomPerSliderPixel / 1000 ); + } + else + { + // second half of slider + const tools::Long nSecondHalfRange = mxImpl->mnMaxZoom - mxImpl->mnSliderCenter; + const tools::Long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset; + const tools::Long nZoomPerSliderPixel = 1000 * nSecondHalfRange / nHalfSliderWidth; + const tools::Long nOffsetToSliderCenter = nOffset - nControlWidth/2; + nRet = mxImpl->mnSliderCenter + sal_uInt16( nOffsetToSliderCenter * nZoomPerSliderPixel / 1000 ); + } + } + + if ( nRet < mxImpl->mnMinZoom ) + nRet = mxImpl->mnMinZoom; + else if ( nRet > mxImpl->mnMaxZoom ) + nRet = mxImpl->mnMaxZoom; + + return nRet; +} + +// returns the offset to the left control border +tools::Long SvxZoomSliderControl::Zoom2Offset( sal_uInt16 nCurrentZoom ) const +{ + const tools::Long nControlWidth = getControlRect().GetWidth(); + tools::Long nRet = nSliderXOffset; + + const tools::Long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset; + + if ( nCurrentZoom <= mxImpl->mnSliderCenter ) + { + nCurrentZoom = nCurrentZoom - mxImpl->mnMinZoom; + const tools::Long nFirstHalfRange = mxImpl->mnSliderCenter - mxImpl->mnMinZoom; + const tools::Long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nFirstHalfRange; + const tools::Long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000; + nRet += nOffset; + } + else + { + nCurrentZoom = nCurrentZoom - mxImpl->mnSliderCenter; + const tools::Long nSecondHalfRange = mxImpl->mnMaxZoom - mxImpl->mnSliderCenter; + const tools::Long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nSecondHalfRange; + const tools::Long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000; + nRet += nHalfSliderWidth + nOffset; + } + + return nRet; +} + +SvxZoomSliderControl::SvxZoomSliderControl( sal_uInt16 _nSlotId, sal_uInt16 _nId, StatusBar& rStatusBar ) : + SfxStatusBarControl( _nSlotId, _nId, rStatusBar ), + mxImpl( new SvxZoomSliderControl_Impl ) +{ + mxImpl->maSliderButton = Image(StockImage::Yes, RID_SVXBMP_SLIDERBUTTON); + mxImpl->maIncreaseButton = Image(StockImage::Yes, RID_SVXBMP_SLIDERINCREASE); + mxImpl->maDecreaseButton = Image(StockImage::Yes, RID_SVXBMP_SLIDERDECREASE); +} + +SvxZoomSliderControl::~SvxZoomSliderControl() +{ +} + +void SvxZoomSliderControl::StateChangedAtStatusBarControl( sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState ) +{ + if ( (SfxItemState::DEFAULT != eState) || pState->IsVoidItem() ) + { + GetStatusBar().SetItemText( GetId(), "" ); + mxImpl->mbValuesSet = false; + } + else + { + assert( dynamic_cast<const SvxZoomSliderItem*>( pState) && "invalid item type: should be a SvxZoomSliderItem" ); + mxImpl->mnCurrentZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetValue(); + mxImpl->mnMinZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetMinZoom(); + mxImpl->mnMaxZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetMaxZoom(); + mxImpl->mnSliderCenter= 100; + mxImpl->mbValuesSet = true; + + if ( mxImpl->mnSliderCenter == mxImpl->mnMaxZoom ) + mxImpl->mnSliderCenter = mxImpl->mnMinZoom + static_cast<sal_uInt16>((mxImpl->mnMaxZoom - mxImpl->mnMinZoom) * 0.5); + + + DBG_ASSERT( mxImpl->mnMinZoom <= mxImpl->mnCurrentZoom && + mxImpl->mnMinZoom < mxImpl->mnSliderCenter && + mxImpl->mnMaxZoom >= mxImpl->mnCurrentZoom && + mxImpl->mnMaxZoom > mxImpl->mnSliderCenter, + "Looks like the zoom slider item is corrupted" ); + + const css::uno::Sequence < sal_Int32 > rSnappingPoints = static_cast<const SvxZoomSliderItem*>( pState )->GetSnappingPoints(); + mxImpl->maSnappingPointOffsets.clear(); + mxImpl->maSnappingPointZooms.clear(); + + // get all snapping points: + std::set< sal_uInt16 > aTmpSnappingPoints; + for ( const sal_Int32 nSnappingPoint : rSnappingPoints ) + { + aTmpSnappingPoints.insert( static_cast<sal_uInt16>(nSnappingPoint) ); + } + + // remove snapping points that are too close to each other: + tools::Long nLastOffset = 0; + + for ( const sal_uInt16 nCurrent : aTmpSnappingPoints ) + { + const tools::Long nCurrentOffset = Zoom2Offset( nCurrent ); + + if ( nCurrentOffset - nLastOffset >= nSnappingPointsMinDist ) + { + mxImpl->maSnappingPointOffsets.push_back( nCurrentOffset ); + mxImpl->maSnappingPointZooms.push_back( nCurrent ); + nLastOffset = nCurrentOffset; + } + } + } + + forceRepaint(); +} + +void SvxZoomSliderControl::Paint( const UserDrawEvent& rUsrEvt ) +{ + if ( !mxImpl->mbValuesSet ) + return; + + const tools::Rectangle aControlRect = getControlRect(); + vcl::RenderContext* pDev = rUsrEvt.GetRenderContext(); + tools::Rectangle aRect = rUsrEvt.GetRect(); + tools::Rectangle aSlider = aRect; + + tools::Long nSliderHeight = 1 * pDev->GetDPIScaleFactor(); + tools::Long nSnappingHeight = 2 * pDev->GetDPIScaleFactor(); + + aSlider.AdjustTop((aControlRect.GetHeight() - nSliderHeight)/2 ); + aSlider.SetBottom( aSlider.Top() + nSliderHeight - 1 ); + aSlider.AdjustLeft(nSliderXOffset ); + aSlider.AdjustRight( -nSliderXOffset ); + + Color aOldLineColor = pDev->GetLineColor(); + Color aOldFillColor = pDev->GetFillColor(); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() ); + pDev->SetFillColor( rStyleSettings.GetDarkShadowColor() ); + + // draw slider + pDev->DrawRect( aSlider ); + // shadow + pDev->SetLineColor( rStyleSettings.GetShadowColor() ); + pDev->DrawLine(Point(aSlider.Left()+1,aSlider.Bottom()+1), Point(aSlider.Right()+1,aSlider.Bottom()+1)); + pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() ); + + // draw snapping points: + for ( const auto& rSnappingPoint : mxImpl->maSnappingPointOffsets ) + { + tools::Long nSnapPosX = aRect.Left() + rSnappingPoint; + + pDev->DrawRect( tools::Rectangle( nSnapPosX - 1, aSlider.Top() - nSnappingHeight, + nSnapPosX, aSlider.Bottom() + nSnappingHeight ) ); + } + + // draw slider button + Point aImagePoint = aRect.TopLeft(); + aImagePoint.AdjustX(Zoom2Offset( mxImpl->mnCurrentZoom ) ); + aImagePoint.AdjustX( -(mxImpl->maSliderButton.GetSizePixel().Width()/2) ); + aImagePoint.AdjustY((aControlRect.GetHeight() - mxImpl->maSliderButton.GetSizePixel().Height())/2 ); + pDev->DrawImage( aImagePoint, mxImpl->maSliderButton ); + + // draw decrease button + aImagePoint = aRect.TopLeft(); + aImagePoint.AdjustX((nSliderXOffset - mxImpl->maDecreaseButton.GetSizePixel().Width())/2 ); + aImagePoint.AdjustY((aControlRect.GetHeight() - mxImpl->maDecreaseButton.GetSizePixel().Height())/2 ); + pDev->DrawImage( aImagePoint, mxImpl->maDecreaseButton ); + + // draw increase button + aImagePoint.setX( aRect.Left() + aControlRect.GetWidth() - mxImpl->maIncreaseButton.GetSizePixel().Width() - (nSliderXOffset - mxImpl->maIncreaseButton.GetSizePixel().Height())/2 ); + pDev->DrawImage( aImagePoint, mxImpl->maIncreaseButton ); + + pDev->SetLineColor( aOldLineColor ); + pDev->SetFillColor( aOldFillColor ); +} + +bool SvxZoomSliderControl::MouseButtonDown( const MouseEvent & rEvt ) +{ + if ( !mxImpl->mbValuesSet ) + return true; + + const tools::Rectangle aControlRect = getControlRect(); + const Point aPoint = rEvt.GetPosPixel(); + const sal_Int32 nXDiff = aPoint.X() - aControlRect.Left(); + + tools::Long nIncDecWidth = mxImpl->maIncreaseButton.GetSizePixel().Width(); + + const tools::Long nButtonLeftOffset = (nSliderXOffset - nIncDecWidth)/2; + const tools::Long nButtonRightOffset = (nSliderXOffset + nIncDecWidth)/2; + + const tools::Long nOldZoom = mxImpl->mnCurrentZoom; + + // click to - button + if ( nXDiff >= nButtonLeftOffset && nXDiff <= nButtonRightOffset ) + mxImpl->mnCurrentZoom = basegfx::zoomtools::zoomOut( static_cast<int>(mxImpl->mnCurrentZoom) ); + // click to + button + else if ( nXDiff >= aControlRect.GetWidth() - nSliderXOffset + nButtonLeftOffset && + nXDiff <= aControlRect.GetWidth() - nSliderXOffset + nButtonRightOffset ) + mxImpl->mnCurrentZoom = basegfx::zoomtools::zoomIn( static_cast<int>(mxImpl->mnCurrentZoom) ); + // click to slider + else if( nXDiff >= nSliderXOffset && nXDiff <= aControlRect.GetWidth() - nSliderXOffset ) + { + mxImpl->mnCurrentZoom = Offset2Zoom( nXDiff ); + mxImpl->mbDraggingStarted = true; + } + + if ( mxImpl->mnCurrentZoom < mxImpl->mnMinZoom ) + mxImpl->mnCurrentZoom = mxImpl->mnMinZoom; + else if ( mxImpl->mnCurrentZoom > mxImpl->mnMaxZoom ) + mxImpl->mnCurrentZoom = mxImpl->mnMaxZoom; + + if ( nOldZoom == mxImpl->mnCurrentZoom ) + return true; + + repaintAndExecute(); + + return true; +} + +bool SvxZoomSliderControl::MouseButtonUp( const MouseEvent & ) +{ + mxImpl->mbDraggingStarted = false; + return true; +} + +bool SvxZoomSliderControl::MouseMove( const MouseEvent & rEvt ) +{ + if ( !mxImpl->mbValuesSet ) + return true; + + const short nButtons = rEvt.GetButtons(); + const tools::Rectangle aControlRect = getControlRect(); + const Point aPoint = rEvt.GetPosPixel(); + const sal_Int32 nXDiff = aPoint.X() - aControlRect.Left(); + + // check mouse move with button pressed + if ( 1 == nButtons && mxImpl->mbDraggingStarted ) + { + if ( nXDiff >= nSliderXOffset && nXDiff <= aControlRect.GetWidth() - nSliderXOffset ) + { + mxImpl->mnCurrentZoom = Offset2Zoom( nXDiff ); + + repaintAndExecute(); + } + } + + // Tooltips + + tools::Long nIncDecWidth = mxImpl->maIncreaseButton.GetSizePixel().Width(); + + const tools::Long nButtonLeftOffset = (nSliderXOffset - nIncDecWidth)/2; + const tools::Long nButtonRightOffset = (nSliderXOffset + nIncDecWidth)/2; + + // click to - button + if ( nXDiff >= nButtonLeftOffset && nXDiff <= nButtonRightOffset ) + GetStatusBar().SetQuickHelpText(GetId(), SvxResId(RID_SVXSTR_ZOOM_OUT)); + // click to + button + else if ( nXDiff >= aControlRect.GetWidth() - nSliderXOffset + nButtonLeftOffset && + nXDiff <= aControlRect.GetWidth() - nSliderXOffset + nButtonRightOffset ) + GetStatusBar().SetQuickHelpText(GetId(), SvxResId(RID_SVXSTR_ZOOM_IN)); + else + // don't hide the slider and its handle with a tooltip during zooming + GetStatusBar().SetQuickHelpText(GetId(), ""); + + return true; +} + +void SvxZoomSliderControl::forceRepaint() const +{ + GetStatusBar().SetItemData(GetId(), nullptr); +} + +void SvxZoomSliderControl::repaintAndExecute() +{ + forceRepaint(); + + // commit state change + SvxZoomSliderItem aZoomSliderItem(mxImpl->mnCurrentZoom); + + css::uno::Any any; + aZoomSliderItem.QueryValue(any); + + css::uno::Sequence<css::beans::PropertyValue> aArgs{ comphelper::makePropertyValue("ZoomSlider", + any) }; + execute(aArgs); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |