diff options
Diffstat (limited to '')
-rw-r--r-- | svx/source/stbctrls/insctrl.cxx | 83 | ||||
-rw-r--r-- | svx/source/stbctrls/modctrl.cxx | 160 | ||||
-rw-r--r-- | svx/source/stbctrls/modctrl_internal.hxx | 30 | ||||
-rw-r--r-- | svx/source/stbctrls/pszctrl.cxx | 480 | ||||
-rw-r--r-- | svx/source/stbctrls/selctrl.cxx | 164 | ||||
-rw-r--r-- | svx/source/stbctrls/stbctrls.h | 35 | ||||
-rw-r--r-- | svx/source/stbctrls/xmlsecctrl.cxx | 160 | ||||
-rw-r--r-- | svx/source/stbctrls/zoomctrl.cxx | 228 | ||||
-rw-r--r-- | svx/source/stbctrls/zoomsliderctrl.cxx | 398 |
9 files changed, 1738 insertions, 0 deletions
diff --git a/svx/source/stbctrls/insctrl.cxx b/svx/source/stbctrls/insctrl.cxx new file mode 100644 index 000000000..8139d6329 --- /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::StateChanged( 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..ef1f8a68b --- /dev/null +++ b/svx/source/stbctrls/modctrl.cxx @@ -0,0 +1,160 @@ +/* -*- 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; + 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); + maIdle.SetDebugName("svx::SvxModifyControl maIdle"); + } +}; + +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::StateChanged( 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(); + + const char* 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(); + long nXOffset = (aRectSize.getWidth() - aImgSize.getWidth())/2; + 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..ebadad17c --- /dev/null +++ b/svx/source/stbctrls/pszctrl.cxx @@ -0,0 +1,480 @@ +/* -*- 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/builder.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/event.hxx> +#include <vcl/fieldvalues.hxx> +#include <vcl/status.hxx> +#include <vcl/menu.hxx> +#include <vcl/image.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.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( long nVal ) +{ + // 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 +{ + VclBuilder m_aBuilder; + VclPtr<PopupMenu> m_xMenu; + sal_uInt32 m_nSelected; + static sal_uInt16 id_to_function(const OString& rIdent); + sal_uInt16 function_to_id(sal_uInt16 nFunc) const; +public: + explicit FunctionPopup_Impl( sal_uInt32 nCheckEncoded ); + sal_uInt16 Execute(vcl::Window* pWindow, const Point& rPopupPos) { return m_xMenu->Execute(pWindow, rPopupPos); } + sal_uInt32 GetSelected() const; +}; + +} + +sal_uInt16 FunctionPopup_Impl::id_to_function(const OString& 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; +} + +sal_uInt16 FunctionPopup_Impl::function_to_id(sal_uInt16 nFunc) const +{ + switch (nFunc) + { + case PSZ_FUNC_AVG: + return m_xMenu->GetItemId("avg"); + case PSZ_FUNC_COUNT2: + return m_xMenu->GetItemId("counta"); + case PSZ_FUNC_COUNT: + return m_xMenu->GetItemId("count"); + case PSZ_FUNC_MAX: + return m_xMenu->GetItemId("max"); + case PSZ_FUNC_MIN: + return m_xMenu->GetItemId("min"); + case PSZ_FUNC_SUM: + return m_xMenu->GetItemId("sum"); + case PSZ_FUNC_SELECTION_COUNT: + return m_xMenu->GetItemId("selection"); + case PSZ_FUNC_NONE: + return m_xMenu->GetItemId("none"); + } + return 0; +} + +FunctionPopup_Impl::FunctionPopup_Impl(sal_uInt32 nCheckEncoded) + : m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/functionmenu.ui", "") + , m_xMenu(m_aBuilder.get_menu("menu")) + , m_nSelected(nCheckEncoded) +{ + for ( sal_uInt16 nCheck = 1; nCheck < 32; ++nCheck ) + if ( nCheckEncoded & (1 << nCheck) ) + m_xMenu->CheckItem(function_to_id(nCheck)); +} + +sal_uInt32 FunctionPopup_Impl::GetSelected() const +{ + sal_uInt32 nSelected = m_nSelected; + sal_uInt16 nCurItemId = id_to_function(m_xMenu->GetCurItemIdent()); + if ( nCurItemId == PSZ_FUNC_NONE ) + nSelected = ( 1 << PSZ_FUNC_NONE ); + else + { + nSelected &= (~( 1 << PSZ_FUNC_NONE )); // Clear the "None" bit + nSelected ^= ( 1 << nCurItemId ); // Toggle the bit corresponding to nCurItemId + if ( !nSelected ) + nSelected = ( 1 << 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::StateChanged( 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 ); + FunctionPopup_Impl aMenu(nSelect); + if (aMenu.Execute(&GetStatusBar(), rCEvt.GetMousePosPixel())) + { + nSelect = aMenu.GetSelected(); + if (nSelect) + { + if (nSelect == (1 << PSZ_FUNC_NONE)) + nSelect = 0; + + css::uno::Any a; + SfxUInt32Item aItem( SID_PSZ_FUNCTION, nSelect ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 ); + aArgs[0].Name = "StatusBarFunc"; + aItem.QueryValue( a ); + aArgs[0].Value = 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 + 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..df54a7ae4 --- /dev/null +++ b/svx/source/stbctrls/selctrl.cxx @@ -0,0 +1,164 @@ +/* -*- 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/builder.hxx> +#include <vcl/event.hxx> +#include <vcl/menu.hxx> +#include <vcl/status.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> + +SFX_IMPL_STATUSBAR_CONTROL(SvxSelectionModeControl, SfxUInt16Item); + +namespace { + +/// Popup menu to select the selection type +class SelectionTypePopup +{ + VclBuilder m_aBuilder; + VclPtr<PopupMenu> m_xMenu; + static sal_uInt16 id_to_state(const OString& rIdent); + sal_uInt16 state_to_id(sal_uInt16 nState) const; +public: + explicit SelectionTypePopup(sal_uInt16 nCurrent); + OUString GetItemTextForState(sal_uInt16 nState) { return m_xMenu->GetItemText(state_to_id(nState)); } + sal_uInt16 GetState() const { return id_to_state(m_xMenu->GetCurItemIdent()); } + sal_uInt16 Execute(vcl::Window* pWindow, const Point& rPopupPos) { return m_xMenu->Execute(pWindow, rPopupPos); } + void HideSelectionType(const OString& rIdent) { m_xMenu->HideItem(m_xMenu->GetItemId(rIdent)); } +}; + +} + +sal_uInt16 SelectionTypePopup::id_to_state(const OString& rIdent) +{ + if (rIdent == "block") + return 3; + else if (rIdent == "adding") + return 2; + else if (rIdent == "extending") + return 1; + else // fall through + return 0; +} + +sal_uInt16 SelectionTypePopup::state_to_id(sal_uInt16 nState) const +{ + switch (nState) + { + default: // fall through + case 0: return m_xMenu->GetItemId("standard"); + case 1: return m_xMenu->GetItemId("extending"); + case 2: return m_xMenu->GetItemId("adding"); + case 3: return m_xMenu->GetItemId("block"); + } +} + +SelectionTypePopup::SelectionTypePopup(sal_uInt16 nCurrent) + : m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/selectionmenu.ui", "") + , m_xMenu(m_aBuilder.get_menu("menu")) +{ + m_xMenu->CheckItem(state_to_id(nCurrent)); +} + +SvxSelectionModeControl::SvxSelectionModeControl( sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb ) : + SfxStatusBarControl( _nSlotId, _nId, rStb ), + mnState( 0 ), + maImage(StockImage::Yes, RID_SVXBMP_SELECTION) +{ + GetStatusBar().SetItemText( GetId(), "" ); +} + +void SvxSelectionModeControl::StateChanged( sal_uInt16, SfxItemState eState, + const SfxPoolItem* pState ) +{ + if ( SfxItemState::DEFAULT == eState ) + { + DBG_ASSERT( dynamic_cast< const SfxUInt16Item* >(pState) != nullptr, "invalid item type" ); + const SfxUInt16Item* pItem = static_cast<const SfxUInt16Item*>(pState); + mnState = pItem->GetValue(); + + SelectionTypePopup aPop(mnState); + GetStatusBar().SetQuickHelpText(GetId(), aPop.GetItemTextForState(mnState)); + } +} + +bool SvxSelectionModeControl::MouseButtonDown( const MouseEvent& rEvt ) +{ + SelectionTypePopup aPop(mnState); + StatusBar& rStatusbar = GetStatusBar(); + + // 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"); + } + + if (rEvt.IsMiddle() && aPop.Execute(&rStatusbar, rEvt.GetPosPixel())) + { + sal_uInt16 nNewState = aPop.GetState(); + if ( nNewState != mnState ) + { + mnState = nNewState; + + css::uno::Any a; + SfxUInt16Item aState( GetSlotId(), mnState ); + INetURLObject aObj( m_aCommandURL ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 ); + aArgs[0].Name = aObj.GetURLPath(); + aState.QueryValue( a ); + aArgs[0].Value = a; + + execute( aArgs ); + } + } + + return true; +} + + +void SvxSelectionModeControl::Paint( const UserDrawEvent& rUsrEvt ) +{ + const tools::Rectangle aControlRect = getControlRect(); + vcl::RenderContext* pDev = rUsrEvt.GetRenderContext(); + tools::Rectangle aRect = rUsrEvt.GetRect(); + + Size aImgSize( maImage.GetSizePixel() ); + + Point aPos( aRect.Left() + ( aControlRect.GetWidth() - aImgSize.Width() ) / 2, + aRect.Top() + ( aControlRect.GetHeight() - aImgSize.Height() ) / 2 ); + + pDev->DrawImage( aPos, maImage ); +} + +/* 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..c7b2bf2dc --- /dev/null +++ b/svx/source/stbctrls/xmlsecctrl.cxx @@ -0,0 +1,160 @@ +/* -*- 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/builder.hxx> +#include <vcl/menu.hxx> +#include <vcl/image.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/event.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::StateChanged( 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::StateChanged(): invalid item type" ); + mpImpl->mnState = SignatureState::UNKNOWN; + } + + GetStatusBar().SetItemData( GetId(), nullptr ); // necessary ? + + GetStatusBar().SetItemText( GetId(), "" ); // necessary ? + + const char* 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 ) + { + VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/xmlsecstatmenu.ui", ""); + VclPtr<PopupMenu> aPopupMenu(aBuilder.get_menu("menu")); + if (aPopupMenu->Execute(&GetStatusBar(), rCEvt.GetMousePosPixel())) + { + css::uno::Any a; + SfxUInt16Item aState( GetSlotId(), 0 ); + INetURLObject aObj( m_aCommandURL ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 ); + aArgs[0].Name = aObj.GetURLPath(); + aState.QueryValue( a ); + aArgs[0].Value = 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() ); + + 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..7ac0bc81a --- /dev/null +++ b/svx/source/stbctrls/zoomctrl.cxx @@ -0,0 +1,228 @@ +/* -*- 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 <i18nutil/unicode.hxx> +#include <vcl/builder.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/event.hxx> +#include <vcl/svapp.hxx> +#include <vcl/status.hxx> +#include <vcl/menu.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( sal_uInt16 nZ, SvxZoomEnableFlags nValueSet ); + + sal_uInt16 GetZoom(); + OString const & GetCurItemIdent() const { return m_xMenu->GetCurItemIdent(); } + + sal_uInt16 Execute(vcl::Window* pWindow, const Point& rPopupPos) + { + return m_xMenu->Execute(pWindow, rPopupPos); + } + +private: + VclBuilder m_aBuilder; + VclPtr<PopupMenu> m_xMenu; + sal_uInt16 nZoom; +}; + +} + +ZoomPopup_Impl::ZoomPopup_Impl( sal_uInt16 nZ, SvxZoomEnableFlags nValueSet ) + : m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/zoommenu.ui", "") + , m_xMenu(m_aBuilder.get_menu("menu")) + , nZoom(nZ) +{ + if ( !(SvxZoomEnableFlags::N50 & nValueSet) ) + m_xMenu->EnableItem("50", false); + if ( !(SvxZoomEnableFlags::N100 & nValueSet) ) + m_xMenu->EnableItem("100", false); + if ( !(SvxZoomEnableFlags::N150 & nValueSet) ) + m_xMenu->EnableItem("150", false); + if ( !(SvxZoomEnableFlags::N200 & nValueSet) ) + m_xMenu->EnableItem("200", false); + if ( !(SvxZoomEnableFlags::OPTIMAL & nValueSet) ) + m_xMenu->EnableItem("optimal", false); + if ( !(SvxZoomEnableFlags::WHOLEPAGE & nValueSet) ) + m_xMenu->EnableItem("page", false); + if ( !(SvxZoomEnableFlags::PAGEWIDTH & nValueSet) ) + m_xMenu->EnableItem("width", false); +} + +sal_uInt16 ZoomPopup_Impl::GetZoom() +{ + OString sIdent = GetCurItemIdent(); + if (sIdent == "200") + nZoom = 200; + else if (sIdent == "150") + nZoom = 150; + else if (sIdent == "100") + nZoom = 100; + else if (sIdent == "75") + nZoom = 75; + else if (sIdent == "50") + nZoom = 50; + else if (sIdent == "optimal" || sIdent == "width" || sIdent == "page") + nZoom = 0; + + return nZoom; +} + +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::StateChanged( 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) ) + { + ZoomPopup_Impl aPop(nZoom, nValueSet); + StatusBar& rStatusbar = GetStatusBar(); + + if (aPop.Execute(&rStatusbar, rCEvt.GetMousePosPixel()) && (nZoom != aPop.GetZoom() || !nZoom)) + { + nZoom = aPop.GetZoom(); + ImplUpdateItemText(); + SvxZoomItem aZoom(SvxZoomType::PERCENT, nZoom, GetId()); + + OString sIdent = aPop.GetCurItemIdent(); + 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; + INetURLObject aObj( m_aCommandURL ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 ); + aArgs[0].Name = aObj.GetURLPath(); + aZoom.QueryValue( a ); + aArgs[0].Value = 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; + INetURLObject aObj( m_aCommandURL ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 ); + aArgs[0].Name = aObj.GetURLPath(); + aZoom.QueryValue( a ); + aArgs[0].Value = 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..7cf9ff0c8 --- /dev/null +++ b/svx/source/stbctrls/zoomsliderctrl.cxx @@ -0,0 +1,398 @@ +/* -*- 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 <vcl/status.hxx> +#include <vcl/menu.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< 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 ), + maSnappingPointOffsets(), + maSnappingPointZooms(), + maSliderButton(), + maIncreaseButton(), + maDecreaseButton(), + mbValuesSet( false ), + mbDraggingStarted( false ) {} +}; + +const long nSliderXOffset = 20; +const long nSnappingEpsilon = 5; // snapping epsilon in pixels +const long nSnappingPointsMinDist = nSnappingEpsilon; // minimum distance of two adjacent snapping points + +// nOffset refers to the origin of the control: +// + ----------- - +sal_uInt16 SvxZoomSliderControl::Offset2Zoom( long nOffset ) const +{ + const 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 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 long nFirstHalfRange = mxImpl->mnSliderCenter - mxImpl->mnMinZoom; + const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset; + const long nZoomPerSliderPixel = (1000 * nFirstHalfRange) / nHalfSliderWidth; + const long nOffsetToSliderLeft = nOffset - nSliderXOffset; + nRet = mxImpl->mnMinZoom + sal_uInt16( nOffsetToSliderLeft * nZoomPerSliderPixel / 1000 ); + } + else + { + // second half of slider + const long nSecondHalfRange = mxImpl->mnMaxZoom - mxImpl->mnSliderCenter; + const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset; + const long nZoomPerSliderPixel = 1000 * nSecondHalfRange / nHalfSliderWidth; + const 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 +long SvxZoomSliderControl::Zoom2Offset( sal_uInt16 nCurrentZoom ) const +{ + const long nControlWidth = getControlRect().GetWidth(); + long nRet = nSliderXOffset; + + const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset; + + if ( nCurrentZoom <= mxImpl->mnSliderCenter ) + { + nCurrentZoom = nCurrentZoom - mxImpl->mnMinZoom; + const long nFirstHalfRange = mxImpl->mnSliderCenter - mxImpl->mnMinZoom; + const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nFirstHalfRange; + const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000; + nRet += nOffset; + } + else + { + nCurrentZoom = nCurrentZoom - mxImpl->mnSliderCenter; + const long nSecondHalfRange = mxImpl->mnMaxZoom - mxImpl->mnSliderCenter; + const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nSecondHalfRange; + const 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::StateChanged( sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState ) +{ + if ( (SfxItemState::DEFAULT != eState) || pState->IsVoidItem() ) + { + GetStatusBar().SetItemText( GetId(), "" ); + mxImpl->mbValuesSet = false; + } + else + { + OSL_ENSURE( dynamic_cast<const SvxZoomSliderItem*>( pState) != nullptr, "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: + long nLastOffset = 0; + + for ( const sal_uInt16 nCurrent : aTmpSnappingPoints ) + { + const 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; + + long nSliderHeight = 1 * pDev->GetDPIScaleFactor(); + 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 ) + { + 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.TopLeft().X() + 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(); + + long nIncDecWidth = mxImpl->maIncreaseButton.GetSizePixel().Width(); + + const long nButtonLeftOffset = (nSliderXOffset - nIncDecWidth)/2; + const long nButtonRightOffset = (nSliderXOffset + nIncDecWidth)/2; + + const 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 + + long nIncDecWidth = mxImpl->maIncreaseButton.GetSizePixel().Width(); + + const long nButtonLeftOffset = (nSliderXOffset - nIncDecWidth)/2; + const 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(1); + aArgs[0].Name = "ZoomSlider"; + aArgs[0].Value = any; + + execute(aArgs); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |