diff options
Diffstat (limited to 'svx/source/sidebar')
56 files changed, 11525 insertions, 0 deletions
diff --git a/svx/source/sidebar/ContextChangeEventMultiplexer.cxx b/svx/source/sidebar/ContextChangeEventMultiplexer.cxx new file mode 100644 index 0000000000..dd44e706ae --- /dev/null +++ b/svx/source/sidebar/ContextChangeEventMultiplexer.cxx @@ -0,0 +1,89 @@ +/* -*- 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/sidebar/ContextChangeEventMultiplexer.hxx> + +#include <com/sun/star/ui/ContextChangeEventObject.hpp> +#include <com/sun/star/ui/XContextChangeEventMultiplexer.hpp> +#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <comphelper/lok.hxx> +#include <comphelper/processfactory.hxx> +#include <sfx2/lokhelper.hxx> +#include <sfx2/viewsh.hxx> + +using namespace css; +using namespace css::uno; + + +void ContextChangeEventMultiplexer::NotifyContextChange ( + const css::uno::Reference<css::frame::XController>& rxController, + const vcl::EnumContext::Context eContext) +{ + if (!(rxController.is() && rxController->getFrame().is())) + return; + + const css::ui::ContextChangeEventObject aEvent( + rxController, + GetModuleName(rxController->getFrame()), + vcl::EnumContext::GetContextName(eContext)); + + css::uno::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer ( + css::ui::ContextChangeEventMultiplexer::get( + ::comphelper::getProcessComponentContext())); + if (xMultiplexer.is()) + xMultiplexer->broadcastContextChangeEvent(aEvent, rxController); + + // notify the LOK too after all the change have taken effect. + if (comphelper::LibreOfficeKit::isActive()) + { + SfxLokHelper::notifyContextChange(aEvent); + } +} + + +void ContextChangeEventMultiplexer::NotifyContextChange ( + const SfxViewShell* pViewShell, + const vcl::EnumContext::Context eContext) +{ + if (pViewShell != nullptr) + NotifyContextChange(pViewShell->GetController(), eContext); +} + + +OUString ContextChangeEventMultiplexer::GetModuleName ( + const css::uno::Reference<css::frame::XFrame>& rxFrame) +{ + try + { + const Reference<frame::XModuleManager> xModuleManager = + frame::ModuleManager::create( comphelper::getProcessComponentContext() ); + return xModuleManager->identify(rxFrame); + } + catch (const Exception&) + { + // An exception typically means that a context change is notified + // during initialization or destruction of a view. + // Ignore it. + } + return vcl::EnumContext::GetApplicationName( + vcl::EnumContext::Application::NONE); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/EmptyPanel.cxx b/svx/source/sidebar/EmptyPanel.cxx new file mode 100644 index 0000000000..7641b6e9df --- /dev/null +++ b/svx/source/sidebar/EmptyPanel.cxx @@ -0,0 +1,33 @@ +/* -*- 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 "EmptyPanel.hxx" + +namespace svx::sidebar +{ +EmptyPanel::EmptyPanel(weld::Widget* pParent) + : PanelLayout(pParent, "EmptyPanel", "svx/ui/sidebarempty.ui") +{ +} + +EmptyPanel::~EmptyPanel() {} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/EmptyPanel.hxx b/svx/source/sidebar/EmptyPanel.hxx new file mode 100644 index 0000000000..feec59a06e --- /dev/null +++ b/svx/source/sidebar/EmptyPanel.hxx @@ -0,0 +1,40 @@ +/* -*- 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_SIDEBAR_EMPTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_EMPTYPANEL_HXX + +#include <sfx2/sidebar/PanelLayout.hxx> + +namespace svx::sidebar +{ +/** Display a panel that tells the user that the current deck is + intentionally empty. +*/ +class EmptyPanel final : public PanelLayout +{ +public: + explicit EmptyPanel(weld::Widget* pParent); + virtual ~EmptyPanel() override; +}; + +} // end of namespace svx::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/PanelFactory.cxx b/svx/source/sidebar/PanelFactory.cxx new file mode 100644 index 0000000000..f55575d1ab --- /dev/null +++ b/svx/source/sidebar/PanelFactory.cxx @@ -0,0 +1,220 @@ +/* -*- 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 <config_features.h> + +#include "text/TextPropertyPanel.hxx" +#include "styles/StylesPropertyPanel.hxx" +#include "paragraph/ParaPropertyPanel.hxx" +#include "lists/ListsPropertyPanel.hxx" +#include "area/AreaPropertyPanel.hxx" +#include "fontwork/FontworkPropertyPanel.hxx" +#include "shadow/ShadowPropertyPanel.hxx" +#include "effect/EffectPropertyPanel.hxx" +#include "graphic/GraphicPropertyPanel.hxx" +#include "line/LinePropertyPanel.hxx" +#include "possize/PosSizePropertyPanel.hxx" +#include "textcolumns/TextColumnsPropertyPanel.hxx" +#include <DefaultShapesPanel.hxx> +#if HAVE_FEATURE_AVMEDIA +#include "media/MediaPlaybackPanel.hxx" +#endif +#include <GalleryControl.hxx> +#include "EmptyPanel.hxx" +#include <sfx2/sidebar/SidebarPanelBase.hxx> +#include <sfx2/templdlg.hxx> +#include <vcl/weldutils.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/compbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ui/XSidebar.hpp> +#include <com/sun/star/ui/XUIElementFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +using namespace css; +using namespace css::uno; +using namespace svx::sidebar; + + +namespace { + +/* Why this is not used ? Doesn't it need to inherit from XServiceInfo ? +constexpr OUStringLiteral IMPLEMENTATION_NAME = u"org.apache.openoffice.comp.svx.sidebar.PanelFactory"; +constexpr OUStringLiteral SERVICE_NAME = u"com.sun.star.ui.UIElementFactory"; +*/ + +typedef comphelper::WeakComponentImplHelper< css::ui::XUIElementFactory, css::lang::XServiceInfo > + PanelFactoryInterfaceBase; + +class PanelFactory + : public PanelFactoryInterfaceBase +{ +public: + PanelFactory(); + PanelFactory(const PanelFactory&) = delete; + PanelFactory& operator=(const PanelFactory&) = delete; + + // XUIElementFactory + css::uno::Reference<css::ui::XUIElement> SAL_CALL createUIElement ( + const OUString& rsResourceURL, + const ::css::uno::Sequence<css::beans::PropertyValue>& rArguments) override; + + OUString SAL_CALL getImplementationName() override + { return "org.apache.openoffice.comp.svx.sidebar.PanelFactory"; } + + sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { return cppu::supportsService(this, ServiceName); } + + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { return {"com.sun.star.ui.UIElementFactory"}; } +}; + +PanelFactory::PanelFactory() +{ +} + +Reference<ui::XUIElement> SAL_CALL PanelFactory::createUIElement ( + const OUString& rsResourceURL, + const ::css::uno::Sequence<css::beans::PropertyValue>& rArguments) +{ + const ::comphelper::NamedValueCollection aArguments (rArguments); + Reference<frame::XFrame> xFrame (aArguments.getOrDefault("Frame", Reference<frame::XFrame>())); + Reference<awt::XWindow> xParentWindow (aArguments.getOrDefault("ParentWindow", Reference<awt::XWindow>())); + Reference<ui::XSidebar> xSidebar (aArguments.getOrDefault("Sidebar", Reference<ui::XSidebar>())); + const sal_uInt64 nBindingsValue (aArguments.getOrDefault("SfxBindings", sal_uInt64(0))); + SfxBindings* pBindings = reinterpret_cast<SfxBindings*>(nBindingsValue); + + weld::Widget* pParent(nullptr); + if (weld::TransportAsXWindow* pTunnel = dynamic_cast<weld::TransportAsXWindow*>(xParentWindow.get())) + pParent = pTunnel->getWidget(); + + if (!pParent) + throw RuntimeException( + "PanelFactory::createUIElement called without ParentWindow", + nullptr); + if ( ! xFrame.is()) + throw RuntimeException( + "PanelFactory::createUIElement called without Frame", + nullptr); + if (pBindings == nullptr) + throw RuntimeException( + "PanelFactory::createUIElement called without SfxBindings", + nullptr); + + std::unique_ptr<PanelLayout> xControl; + ui::LayoutSize aLayoutSize (-1,-1,-1); + + if (rsResourceURL.endsWith("/TextPropertyPanel")) + { + xControl = TextPropertyPanel::Create(pParent, xFrame); + } + else if (rsResourceURL.endsWith("/StylesPropertyPanel")) + { + xControl = StylesPropertyPanel::Create(pParent, xFrame); + } + else if (rsResourceURL.endsWith("/ParaPropertyPanel")) + { + xControl = ParaPropertyPanel::Create(pParent, xFrame, pBindings, xSidebar); + } + else if (rsResourceURL.endsWith("/ListsPropertyPanel")) + { + xControl = ListsPropertyPanel::Create(pParent, xFrame); + } + else if (rsResourceURL.endsWith("/AreaPropertyPanel")) + { + xControl = AreaPropertyPanel::Create(pParent, xFrame, pBindings); + } + else if (rsResourceURL.endsWith("/FontworkPropertyPanel")) + { + xControl = FontworkPropertyPanel::Create(pParent, xFrame); + } + else if (rsResourceURL.endsWith("/ShadowPropertyPanel")) + { + xControl = ShadowPropertyPanel::Create(pParent, pBindings); + } + else if (rsResourceURL.endsWith("/EffectPropertyPanel")) + { + xControl = EffectPropertyPanel::Create(pParent, pBindings); + } + else if (rsResourceURL.endsWith("/GraphicPropertyPanel")) + { + xControl = GraphicPropertyPanel::Create(pParent, pBindings); + } + else if (rsResourceURL.endsWith("/LinePropertyPanel")) + { + xControl = LinePropertyPanel::Create(pParent, xFrame, pBindings); + } + else if (rsResourceURL.endsWith("/PosSizePropertyPanel")) + { + xControl = PosSizePropertyPanel::Create(pParent, xFrame, pBindings, xSidebar); + } + else if (rsResourceURL.endsWith("/DefaultShapesPanel")) + { + xControl = DefaultShapesPanel::Create(pParent, xFrame); + } +#if HAVE_FEATURE_AVMEDIA + else if (rsResourceURL.endsWith("/MediaPlaybackPanel")) + { + xControl = MediaPlaybackPanel::Create(pParent, pBindings); + } +#endif + else if (rsResourceURL.endsWith("/GalleryPanel")) + { + xControl = std::make_unique<GalleryControl>(pParent); + aLayoutSize = ui::LayoutSize(300,-1,400); + } + else if (rsResourceURL.endsWith("/StyleListPanel")) + { + xControl = std::make_unique<SfxTemplatePanelControl>(pBindings, pParent); + aLayoutSize = ui::LayoutSize(0,-1,-1); + } + else if (rsResourceURL.endsWith("/EmptyPanel")) + { + xControl = std::make_unique<EmptyPanel>(pParent); + aLayoutSize = ui::LayoutSize(20,-1, 50); + } + else if (rsResourceURL.endsWith("/TextColumnsPropertyPanel")) + { + xControl = TextColumnsPropertyPanel::Create(pParent, pBindings); + } + + if (xControl) + { + return sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xControl), + aLayoutSize); + } + else + return Reference<ui::XUIElement>(); +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +org_apache_openoffice_comp_svx_sidebar_PanelFactory_get_implementation( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new PanelFactory); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/SelectionAnalyzer.cxx b/svx/source/sidebar/SelectionAnalyzer.cxx new file mode 100644 index 0000000000..dc8073ec6c --- /dev/null +++ b/svx/source/sidebar/SelectionAnalyzer.cxx @@ -0,0 +1,479 @@ +/* -*- 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/sidebar/SelectionAnalyzer.hxx> +#include <svx/svdmark.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdpage.hxx> +#include <svx/fontworkbar.hxx> + +using vcl::EnumContext; + +namespace svx::sidebar +{ +EnumContext::Context SelectionAnalyzer::GetContextForSelection_SC(const SdrMarkList& rMarkList) +{ + EnumContext::Context eContext = EnumContext::Context::Unknown; + + switch (rMarkList.GetMarkCount()) + { + case 0: + // Empty selection. Return Context::Unknown to let the caller + // substitute it with the default context. + break; + + case 1: + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + auto pTextObj = DynCastSdrTextObj(pObj); + if (pTextObj && pTextObj->IsInEditMode()) + { + eContext = EnumContext::Context::DrawText; + } + else if (svx::checkForFontWork(pObj)) + { + eContext = EnumContext::Context::DrawFontwork; + } + else + { + const SdrInventor nInv = pObj->GetObjInventor(); + const SdrObjKind nObjId = pObj->GetObjIdentifier(); + if (nInv == SdrInventor::Default) + eContext = GetContextForObjectId_SC(nObjId); + else if (nInv == SdrInventor::FmForm) + eContext = EnumContext::Context::Form; + } + break; + } + + default: + { + // Multi selection. + switch (GetInventorTypeFromMark(rMarkList)) + { + case SdrInventor::Default: + { + const SdrObjKind nObjId(GetObjectTypeFromMark(rMarkList)); + if (nObjId == SdrObjKind::NONE) + eContext = EnumContext::Context::MultiObject; + else + eContext = GetContextForObjectId_SC(nObjId); + break; + } + + case SdrInventor::FmForm: + eContext = EnumContext::Context::Form; + break; + + case SdrInventor::Unknown: + eContext = EnumContext::Context::MultiObject; + break; + + default: + break; + } + } + } + + return eContext; +} + +EnumContext::Context SelectionAnalyzer::GetContextForSelection_SD(const SdrMarkList& rMarkList, + const ViewType eViewType) +{ + EnumContext::Context eContext = EnumContext::Context::Unknown; + + // Note that some cases are handled by the caller. They rely on + // sd specific data. + switch (rMarkList.GetMarkCount()) + { + case 0: + switch (eViewType) + { + case ViewType::Standard: + eContext = EnumContext::Context::DrawPage; + break; + case ViewType::Master: + eContext = EnumContext::Context::MasterPage; + break; + case ViewType::Handout: + eContext = EnumContext::Context::HandoutPage; + break; + case ViewType::Notes: + eContext = EnumContext::Context::NotesPage; + break; + } + break; + + case 1: + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + auto pTextObj = DynCastSdrTextObj(pObj); + if (pTextObj && pTextObj->IsInEditMode()) + { + if (pObj->GetObjIdentifier() == SdrObjKind::Table) + { + // Let a table object take precedence over text + // edit mode. The panels for text editing are + // present for table context as well, anyway. + eContext = EnumContext::Context::Table; + } + else + eContext = EnumContext::Context::DrawText; + } + else if (svx::checkForFontWork(pObj)) + { + eContext = EnumContext::Context::DrawFontwork; + } + else + { + const SdrInventor nInv = pObj->GetObjInventor(); + SdrObjKind nObjId = pObj->GetObjIdentifier(); + if (nInv == SdrInventor::Default) + { + if (nObjId == SdrObjKind::Group) + { + nObjId = GetObjectTypeFromGroup(pObj); + if (nObjId == SdrObjKind::NONE) + nObjId = SdrObjKind::Group; + } + eContext = GetContextForObjectId_SD(nObjId, eViewType); + } + else if (nInv == SdrInventor::E3d) + { + eContext = EnumContext::Context::ThreeDObject; + } + else if (nInv == SdrInventor::FmForm) + { + eContext = EnumContext::Context::Form; + } + } + break; + } + + default: + { + switch (GetInventorTypeFromMark(rMarkList)) + { + case SdrInventor::Default: + { + const SdrObjKind nObjId = GetObjectTypeFromMark(rMarkList); + if (nObjId == SdrObjKind::NONE) + eContext = EnumContext::Context::MultiObject; + else + eContext = GetContextForObjectId_SD(nObjId, eViewType); + break; + } + + case SdrInventor::E3d: + eContext = EnumContext::Context::ThreeDObject; + break; + + case SdrInventor::FmForm: + eContext = EnumContext::Context::Form; + break; + + case SdrInventor::Unknown: + eContext = EnumContext::Context::MultiObject; + break; + + default: + break; + } + break; + } + } + + return eContext; +} + +EnumContext::Context SelectionAnalyzer::GetContextForObjectId_SC(const SdrObjKind nObjectId) +{ + switch (nObjectId) + { + case SdrObjKind::Caption: + case SdrObjKind::TitleText: + case SdrObjKind::OutlineText: + case SdrObjKind::Text: + case SdrObjKind::Measure: + case SdrObjKind::Rectangle: + case SdrObjKind::CircleOrEllipse: + case SdrObjKind::FreehandFill: + case SdrObjKind::PathFill: + case SdrObjKind::Polygon: + case SdrObjKind::CircleSection: + case SdrObjKind::CircleArc: + case SdrObjKind::CircleCut: + case SdrObjKind::CustomShape: + case SdrObjKind::Group: + return EnumContext::Context::Draw; + + case SdrObjKind::PolyLine: + case SdrObjKind::PathLine: + case SdrObjKind::FreehandLine: + case SdrObjKind::Line: + case SdrObjKind::Edge: + return EnumContext::Context::DrawLine; + + case SdrObjKind::Graphic: + return EnumContext::Context::Graphic; + + case SdrObjKind::OLE2: + return EnumContext::Context::OLE; + + case SdrObjKind::Media: + return EnumContext::Context::Media; + + default: + return EnumContext::Context::Unknown; + } +} + +EnumContext::Context SelectionAnalyzer::GetContextForObjectId_SD(const SdrObjKind nObjectId, + const ViewType eViewType) +{ + switch (nObjectId) + { + case SdrObjKind::Caption: + case SdrObjKind::Measure: + case SdrObjKind::Rectangle: + case SdrObjKind::CircleOrEllipse: + case SdrObjKind::FreehandFill: + case SdrObjKind::PathFill: + case SdrObjKind::Polygon: + case SdrObjKind::CircleSection: + case SdrObjKind::CircleArc: + case SdrObjKind::CircleCut: + case SdrObjKind::CustomShape: + case SdrObjKind::Group: + return EnumContext::Context::Draw; + + case SdrObjKind::Edge: + case SdrObjKind::PathLine: + case SdrObjKind::FreehandLine: + case SdrObjKind::PolyLine: + case SdrObjKind::Line: + return EnumContext::Context::DrawLine; + + case SdrObjKind::TitleText: + case SdrObjKind::OutlineText: + case SdrObjKind::Text: + return EnumContext::Context::TextObject; + + case SdrObjKind::Graphic: + return EnumContext::Context::Graphic; + + case SdrObjKind::OLE2: + return EnumContext::Context::OLE; + + case SdrObjKind::Media: + return EnumContext::Context::Media; + + case SdrObjKind::Table: + return EnumContext::Context::Table; + + case SdrObjKind::Page: + switch (eViewType) + { + case ViewType::Handout: + return EnumContext::Context::HandoutPage; + case ViewType::Notes: + return EnumContext::Context::NotesPage; + default: + return EnumContext::Context::Unknown; + } + + default: + return EnumContext::Context::Unknown; + } +} + +SdrInventor SelectionAnalyzer::GetInventorTypeFromMark(const SdrMarkList& rMarkList) +{ + const size_t nMarkCount(rMarkList.GetMarkCount()); + + if (nMarkCount < 1) + return SdrInventor::Unknown; + + SdrMark* pMark = rMarkList.GetMark(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + const SdrInventor nFirstInv = pObj->GetObjInventor(); + + for (size_t nIndex = 1; nIndex < nMarkCount; ++nIndex) + { + pMark = rMarkList.GetMark(nIndex); + pObj = pMark->GetMarkedSdrObj(); + const SdrInventor nInv(pObj->GetObjInventor()); + + if (nInv != nFirstInv) + return SdrInventor::Unknown; + } + + return nFirstInv; +} + +SdrObjKind SelectionAnalyzer::GetObjectTypeFromGroup(const SdrObject* pObj) +{ + SdrObjList* pObjList = pObj->GetSubList(); + if (pObjList) + { + const size_t nSubObjCount(pObjList->GetObjCount()); + + if (nSubObjCount > 0) + { + SdrObject* pSubObj = pObjList->GetObj(0); + SdrObjKind nResultType = pSubObj->GetObjIdentifier(); + + if (nResultType == SdrObjKind::Group) + nResultType = GetObjectTypeFromGroup(pSubObj); + + if (IsShapeType(nResultType)) + nResultType = SdrObjKind::CustomShape; + + if (IsTextObjType(nResultType)) + nResultType = SdrObjKind::Text; + + for (size_t nIndex = 1; nIndex < nSubObjCount; ++nIndex) + { + pSubObj = pObjList->GetObj(nIndex); + SdrObjKind nType(pSubObj->GetObjIdentifier()); + + if (nType == SdrObjKind::Group) + nType = GetObjectTypeFromGroup(pSubObj); + + if (IsShapeType(nType)) + nType = SdrObjKind::CustomShape; + + if ((nType == SdrObjKind::CustomShape) && (nResultType == SdrObjKind::Text)) + nType = SdrObjKind::Text; + + if (IsTextObjType(nType)) + nType = SdrObjKind::Text; + + if ((nType == SdrObjKind::Text) && (nResultType == SdrObjKind::CustomShape)) + nResultType = SdrObjKind::Text; + + if (nType != nResultType) + return SdrObjKind::NONE; + } + + return nResultType; + } + } + + return SdrObjKind::NONE; +} + +SdrObjKind SelectionAnalyzer::GetObjectTypeFromMark(const SdrMarkList& rMarkList) +{ + const size_t nMarkCount(rMarkList.GetMarkCount()); + + if (nMarkCount < 1) + return SdrObjKind::NONE; + + SdrMark* pMark = rMarkList.GetMark(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + SdrObjKind nResultType = pObj->GetObjIdentifier(); + + if (nResultType == SdrObjKind::Group) + nResultType = GetObjectTypeFromGroup(pObj); + + if (IsShapeType(nResultType)) + nResultType = SdrObjKind::CustomShape; + + if (IsTextObjType(nResultType)) + nResultType = SdrObjKind::Text; + + for (size_t nIndex = 1; nIndex < nMarkCount; ++nIndex) + { + pMark = rMarkList.GetMark(nIndex); + pObj = pMark->GetMarkedSdrObj(); + SdrObjKind nType = pObj->GetObjIdentifier(); + + if (nType == SdrObjKind::Group) + nType = GetObjectTypeFromGroup(pObj); + + if (IsShapeType(nType)) + nType = SdrObjKind::CustomShape; + + if ((nType == SdrObjKind::CustomShape) && (nResultType == SdrObjKind::Text)) + nType = SdrObjKind::Text; + + if (IsTextObjType(nType)) + nType = SdrObjKind::Text; + + if ((nType == SdrObjKind::Text) && (nResultType == SdrObjKind::CustomShape)) + nResultType = SdrObjKind::Text; + + if (nType != nResultType) + return SdrObjKind::NONE; + } + + return nResultType; +} + +bool SelectionAnalyzer::IsShapeType(const SdrObjKind nType) +{ + switch (nType) + { + case SdrObjKind::Line: + case SdrObjKind::CircleArc: + case SdrObjKind::PolyLine: + case SdrObjKind::PathLine: + case SdrObjKind::Rectangle: + case SdrObjKind::CircleOrEllipse: + case SdrObjKind::CircleSection: + case SdrObjKind::CircleCut: + case SdrObjKind::PathFill: + case SdrObjKind::CustomShape: + case SdrObjKind::Caption: + case SdrObjKind::Measure: + case SdrObjKind::Edge: + case SdrObjKind::Polygon: + case SdrObjKind::FreehandLine: + case SdrObjKind::FreehandFill: + + // #122145# adding SdrObjKind::OLE2 since these also allow line/fill style and may + // be multiselected/grouped with normal draw objects, e.g. math OLE objects + case SdrObjKind::OLE2: + return true; + + default: + return false; + } +} + +bool SelectionAnalyzer::IsTextObjType(const SdrObjKind nType) +{ + switch (nType) + { + case SdrObjKind::Text: + case SdrObjKind::TitleText: + case SdrObjKind::OutlineText: + return true; + + default: + return false; + } +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/SelectionChangeHandler.cxx b/svx/source/sidebar/SelectionChangeHandler.cxx new file mode 100644 index 0000000000..6affde64e7 --- /dev/null +++ b/svx/source/sidebar/SelectionChangeHandler.cxx @@ -0,0 +1,101 @@ +/* -*- 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/sidebar/SelectionChangeHandler.hxx> +#include <svx/sidebar/ContextChangeEventMultiplexer.hxx> + +#include <com/sun/star/view/XSelectionSupplier.hpp> + +#include <utility> +#include <vcl/EnumContext.hxx> + + +using namespace css; +using namespace css::uno; + +namespace svx::sidebar { + +SelectionChangeHandler::SelectionChangeHandler ( + std::function<OUString()> aSelectionChangeCallback, + const Reference<css::frame::XController>& rxController, + const vcl::EnumContext::Context eDefaultContext) + : maSelectionChangeCallback(std::move(aSelectionChangeCallback)), + mxController(rxController), + meDefaultContext(eDefaultContext), + mbIsConnected(false) +{ +} + + +SelectionChangeHandler::~SelectionChangeHandler() +{ +} + + +void SAL_CALL SelectionChangeHandler::selectionChanged (const lang::EventObject&) +{ + if (maSelectionChangeCallback) + { + const vcl::EnumContext::Context eContext ( + vcl::EnumContext::GetContextEnum(maSelectionChangeCallback())); + ContextChangeEventMultiplexer::NotifyContextChange( + mxController, + eContext==vcl::EnumContext::Context::Unknown + ? meDefaultContext + : eContext); + } +} + + +void SAL_CALL SelectionChangeHandler::disposing (const lang::EventObject&) +{ +} + + +void SelectionChangeHandler::disposing(std::unique_lock<std::mutex>&) +{ + if (mbIsConnected) + Disconnect(); +} + + +void SelectionChangeHandler::Connect() +{ + uno::Reference<view::XSelectionSupplier> xSupplier (mxController, uno::UNO_QUERY); + if (xSupplier.is()) + { + mbIsConnected = true; + xSupplier->addSelectionChangeListener(this); + } +} + + +void SelectionChangeHandler::Disconnect() +{ + uno::Reference<view::XSelectionSupplier> xSupplier (mxController, uno::UNO_QUERY); + if (xSupplier.is()) + { + mbIsConnected = false; + xSupplier->removeSelectionChangeListener(this); + } +} + + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/area/AreaPropertyPanel.cxx b/svx/source/sidebar/area/AreaPropertyPanel.cxx new file mode 100644 index 0000000000..951028d61f --- /dev/null +++ b/svx/source/sidebar/area/AreaPropertyPanel.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 "AreaPropertyPanel.hxx" +#include <svx/svxids.hrc> +#include <svx/xfltrit.hxx> +#include <svx/xflftrit.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <svl/itemset.hxx> + + +using namespace css; +using namespace css::uno; + +namespace svx::sidebar { + +AreaPropertyPanel::AreaPropertyPanel( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings) + : AreaPropertyPanelBase(pParent, rxFrame), + maStyleControl(SID_ATTR_FILL_STYLE, *pBindings, *this), + maColorControl(SID_ATTR_FILL_COLOR, *pBindings, *this), + maGradientControl(SID_ATTR_FILL_GRADIENT, *pBindings, *this), + maHatchControl(SID_ATTR_FILL_HATCH, *pBindings, *this), + maBitmapControl(SID_ATTR_FILL_BITMAP, *pBindings, *this), + maGradientListControl(SID_GRADIENT_LIST, *pBindings, *this), + maHatchListControl(SID_HATCH_LIST, *pBindings, *this), + maBitmapListControl(SID_BITMAP_LIST, *pBindings, *this), + maPatternListControl(SID_PATTERN_LIST, *pBindings, *this), + maFillTransparenceController(SID_ATTR_FILL_TRANSPARENCE, *pBindings, *this), + maFillFloatTransparenceController(SID_ATTR_FILL_FLOATTRANSPARENCE, *pBindings, *this), + maFillUseSlideBackgroundController(SID_ATTR_FILL_USE_SLIDE_BACKGROUND, *pBindings, *this), + mpBindings(pBindings) +{ +} + +AreaPropertyPanel::~AreaPropertyPanel() +{ + maStyleControl.dispose(); + maColorControl.dispose(); + maGradientControl.dispose(); + maHatchControl.dispose(); + maBitmapControl.dispose(); + maGradientListControl.dispose(); + maHatchListControl.dispose(); + maBitmapListControl.dispose(); + maPatternListControl.dispose(); + maFillTransparenceController.dispose(); + maFillFloatTransparenceController.dispose(); +} + +std::unique_ptr<PanelLayout> AreaPropertyPanel::Create ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to AreaPropertyPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to AreaPropertyPanel::Create", nullptr, 1); + if (pBindings == nullptr) + throw lang::IllegalArgumentException("no SfxBindings given to AreaPropertyPanel::Create", nullptr, 2); + + return std::make_unique<AreaPropertyPanel>(pParent, rxFrame, pBindings); +} + +void AreaPropertyPanel::setFillTransparence(const XFillTransparenceItem& rItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_TRANSPARENCE, + SfxCallMode::RECORD, { &rItem }); +} + +void AreaPropertyPanel::setFillUseBackground(const XFillStyleItem* pStyleItem, + const XFillUseSlideBackgroundItem& rItem) +{ + SfxPoolItemHolder aResult; + auto pDispatcher = GetBindings()->GetDispatcher(); + auto state = pDispatcher->QueryState(SID_ATTR_FILL_USE_SLIDE_BACKGROUND, aResult); + // FillUseSlideBackground is only available in Impress + if (state == SfxItemState::DISABLED) + { + setFillStyle(*pStyleItem); + } + else + { + pDispatcher->ExecuteList(SID_ATTR_FILL_USE_SLIDE_BACKGROUND, SfxCallMode::RECORD, + std::initializer_list<SfxPoolItem const*>{ &rItem, pStyleItem }); + } +} + +void AreaPropertyPanel::setFillFloatTransparence(const XFillFloatTransparenceItem& rItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_FLOATTRANSPARENCE, + SfxCallMode::RECORD, { &rItem }); +} + +void AreaPropertyPanel::setFillStyle(const XFillStyleItem& rItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_STYLE, + SfxCallMode::RECORD, { &rItem }); +} + +void AreaPropertyPanel::setFillStyleAndColor(const XFillStyleItem* pStyleItem, + const XFillColorItem& rColorItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_COLOR, + SfxCallMode::RECORD, pStyleItem + ? std::initializer_list<SfxPoolItem const*>{ &rColorItem, pStyleItem } + : std::initializer_list<SfxPoolItem const*>{ &rColorItem }); +} + +void AreaPropertyPanel::setFillStyleAndGradient(const XFillStyleItem* pStyleItem, + const XFillGradientItem& rGradientItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_GRADIENT, + SfxCallMode::RECORD, pStyleItem + ? std::initializer_list<SfxPoolItem const*>{ &rGradientItem, pStyleItem } + : std::initializer_list<SfxPoolItem const*>{ &rGradientItem }); +} + +void AreaPropertyPanel::setFillStyleAndHatch(const XFillStyleItem* pStyleItem, + const XFillHatchItem& rHatchItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_HATCH, + SfxCallMode::RECORD, pStyleItem + ? std::initializer_list<SfxPoolItem const*>{ &rHatchItem, pStyleItem } + : std::initializer_list<SfxPoolItem const*>{ &rHatchItem }); +} + +void AreaPropertyPanel::setFillStyleAndBitmap(const XFillStyleItem* pStyleItem, + const XFillBitmapItem& rBitmapItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_BITMAP, + SfxCallMode::RECORD, pStyleItem + ? std::initializer_list<SfxPoolItem const*>{ &rBitmapItem, pStyleItem } + : std::initializer_list<SfxPoolItem const*>{ &rBitmapItem }); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/area/AreaPropertyPanel.hxx b/svx/source/sidebar/area/AreaPropertyPanel.hxx new file mode 100644 index 0000000000..6c398e6ac0 --- /dev/null +++ b/svx/source/sidebar/area/AreaPropertyPanel.hxx @@ -0,0 +1,94 @@ +/* -*- 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_SIDEBAR_AREA_AREAPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_AREA_AREAPROPERTYPANEL_HXX + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> + +#include <svx/sidebar/AreaPropertyPanelBase.hxx> + +class XFillFloatTransparenceItem; +class XFillTransparenceItem; +class XFillUseSlideBackgroundItem; +class XFillStyleItem; +class XFillGradientItem; +class XFillColorItem; +class XFillHatchItem; +class XFillBitmapItem; + +namespace svx::sidebar { + +class AreaTransparencyGradientControl; + +class AreaPropertyPanel : public AreaPropertyPanelBase +{ +public: + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings); + + SfxBindings* GetBindings() { return mpBindings;} + + // constructor/destructor + AreaPropertyPanel( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings); + + virtual ~AreaPropertyPanel() override; + + virtual void setFillTransparence(const XFillTransparenceItem& rItem) override; + virtual void setFillUseBackground(const XFillStyleItem* pStyleItem, const XFillUseSlideBackgroundItem& rItem) override; + virtual void setFillFloatTransparence(const XFillFloatTransparenceItem& rItem) override; + virtual void setFillStyle(const XFillStyleItem& rItem) override; + virtual void setFillStyleAndColor(const XFillStyleItem* pStyleItem, const XFillColorItem& aColorItem) override; + virtual void setFillStyleAndGradient(const XFillStyleItem* pStyleItem, const XFillGradientItem& aGradientItem) override; + virtual void setFillStyleAndHatch(const XFillStyleItem* pStyleItem, const XFillHatchItem& aHatchItem) override; + virtual void setFillStyleAndBitmap(const XFillStyleItem* pStyleItem, const XFillBitmapItem& aHatchItem) override; + +private: + ::sfx2::sidebar::ControllerItem maStyleControl; + ::sfx2::sidebar::ControllerItem maColorControl; + ::sfx2::sidebar::ControllerItem maGradientControl; + ::sfx2::sidebar::ControllerItem maHatchControl; + ::sfx2::sidebar::ControllerItem maBitmapControl; + ::sfx2::sidebar::ControllerItem maGradientListControl; + ::sfx2::sidebar::ControllerItem maHatchListControl; + ::sfx2::sidebar::ControllerItem maBitmapListControl; + ::sfx2::sidebar::ControllerItem maPatternListControl; + ::sfx2::sidebar::ControllerItem maFillTransparenceController; + ::sfx2::sidebar::ControllerItem maFillFloatTransparenceController; + ::sfx2::sidebar::ControllerItem maFillUseSlideBackgroundController; + + SfxBindings* mpBindings; +}; + + +} // end of namespace svx::sidebar + + +#endif // INCLUDED_SVX_SOURCE_SIDEBAR_AREA_AREAPROPERTYPANEL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/area/AreaPropertyPanelBase.cxx b/svx/source/sidebar/area/AreaPropertyPanelBase.cxx new file mode 100644 index 0000000000..682b83fc89 --- /dev/null +++ b/svx/source/sidebar/area/AreaPropertyPanelBase.cxx @@ -0,0 +1,1424 @@ +/* -*- 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 <osl/diagnose.h> +#include <svx/sidebar/AreaPropertyPanelBase.hxx> +#include <svx/drawitem.hxx> +#include <svx/itemwin.hxx> +#include <svx/svxids.hrc> +#include <sfx2/objsh.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xfilluseslidebackgrounditem.hxx> +#include <svx/xtable.hxx> +#include <sfx2/sidebar/Panel.hxx> +#include <sfx2/opengrf.hxx> +#include <sfx2/weldutils.hxx> +#include <tools/urlobj.hxx> +#include <bitmaps.hlst> +#include <comphelper/lok.hxx> + +using namespace css; +using namespace css::uno; + +constexpr OUString SIDEBARGRADIENT = u"sidebargradient"_ustr; + +namespace svx::sidebar { + +namespace { + +enum eFillStyle +{ + NONE, + SOLID, + GRADIENT, + HATCH, + BITMAP, + PATTERN, + USE_BACKGROUND +}; + +} + +const sal_Int32 AreaPropertyPanelBase::DEFAULT_CENTERX = 50; +const sal_Int32 AreaPropertyPanelBase::DEFAULT_CENTERY = 50; +const sal_Int32 AreaPropertyPanelBase::DEFAULT_ANGLE = 0; +const sal_Int32 AreaPropertyPanelBase::DEFAULT_STARTVALUE = 0; +const sal_Int32 AreaPropertyPanelBase::DEFAULT_ENDVALUE = 16777215; +const sal_Int32 AreaPropertyPanelBase::DEFAULT_BORDER = 0; + +AreaPropertyPanelBase::AreaPropertyPanelBase( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame) + : PanelLayout(pParent, "AreaPropertyPanel", "svx/ui/sidebararea.ui"), + mxFrame(rxFrame), + meLastXFS(static_cast<sal_uInt16>(-1)), + mnLastPosHatch(0), + mnLastPosBitmap(0), + mnLastPosPattern(0), + mnLastTransSolid(50), + mxColorTextFT(m_xBuilder->weld_label("filllabel")), + mxLbFillType(m_xBuilder->weld_combo_box("fillstylearea")), + mxLbFillAttr(m_xBuilder->weld_combo_box("fillattrhb")), + mxLbFillGradFrom(new ColorListBox(m_xBuilder->weld_menu_button("fillgrad1"), [this]{ return GetFrameWeld(); })), + mxLbFillGradTo(new ColorListBox(m_xBuilder->weld_menu_button("fillgrad2"), [this]{ return GetFrameWeld(); })), + mxToolBoxColor(m_xBuilder->weld_toolbar("selectcolor")), + mxColorDispatch(new ToolbarUnoDispatcher(*mxToolBoxColor, *m_xBuilder, rxFrame)), + mxTrspTextFT(m_xBuilder->weld_label("transparencylabel")), + mxLBTransType(m_xBuilder->weld_combo_box("transtype")), + mxMTRTransparent(m_xBuilder->weld_metric_spin_button("settransparency", FieldUnit::PERCENT)), + mxSldTransparent(m_xBuilder->weld_scale("transparencyslider")), + mxBTNGradient(m_xBuilder->weld_toolbar("selectgradient")), + mxMTRAngle(m_xBuilder->weld_metric_spin_button("gradangle", FieldUnit::DEGREE)), + mxGradientStyle(m_xBuilder->weld_combo_box("gradientstyle")), + mxBmpImport(m_xBuilder->weld_button("bmpimport")), + maImgAxial(BMP_AXIAL), + maImgElli(BMP_ELLI), + maImgQuad(BMP_QUAD), + maImgRadial(BMP_RADIAL), + maImgSquare(BMP_SQUARE), + maImgLinear(BMP_LINEAR) +{ + Initialize(); +} + +AreaPropertyPanelBase::~AreaPropertyPanelBase() +{ + mxTrGrPopup.reset(); + mxColorTextFT.reset(); + mxLbFillType.reset(); + mxLbFillAttr.reset(); + mxColorDispatch.reset(); + mxToolBoxColor.reset(); + mxTrspTextFT.reset(); + mxLBTransType.reset(); + mxMTRTransparent.reset(); + mxSldTransparent.reset(); + mxBTNGradient.reset(); + mxMTRAngle.reset(); + mxLbFillGradFrom.reset(); + mxLbFillGradTo.reset(); + mxGradientStyle.reset(); + mxBmpImport.reset(); +} + +void AreaPropertyPanelBase::Initialize() +{ + SvxFillTypeBox::Fill(*mxLbFillType); + + mxLbFillAttr->set_size_request(42, -1); + + maGradientLinear.SetXOffset(DEFAULT_CENTERX); + maGradientLinear.SetYOffset(DEFAULT_CENTERY); + maGradientLinear.SetAngle(Degree10(DEFAULT_ANGLE)); + maGradientLinear.SetColorStops( + basegfx::BColorStops( + Color(DEFAULT_STARTVALUE).getBColor(), + Color(DEFAULT_ENDVALUE).getBColor())); + maGradientLinear.SetBorder(DEFAULT_BORDER); + maGradientLinear.SetGradientStyle(css::awt::GradientStyle_LINEAR); + + maGradientAxial = maGradientLinear; + maGradientAxial.SetGradientStyle(css::awt::GradientStyle_AXIAL); + + maGradientRadial = maGradientLinear; + maGradientRadial.SetGradientStyle(css::awt::GradientStyle_RADIAL); + + maGradientElliptical = maGradientLinear; + maGradientElliptical.SetGradientStyle(css::awt::GradientStyle_ELLIPTICAL); + + maGradientSquare = maGradientLinear; + maGradientSquare.SetGradientStyle(css::awt::GradientStyle_SQUARE); + + maGradientRect = maGradientLinear; + maGradientRect.SetGradientStyle(css::awt::GradientStyle_RECT); + + + mxLbFillType->connect_changed( LINK( this, AreaPropertyPanelBase, SelectFillTypeHdl ) ); + + Link<weld::ComboBox&,void> aLink = LINK( this, AreaPropertyPanelBase, SelectFillAttrHdl ); + mxLbFillAttr->connect_changed( aLink ); + mxGradientStyle->connect_changed( aLink ); + Link<ColorListBox&,void> aLink3 = LINK( this, AreaPropertyPanelBase, SelectFillColorHdl ); + mxLbFillGradFrom->SetSelectHdl( aLink3 ); + mxLbFillGradTo->SetSelectHdl( aLink3 ); + mxMTRAngle->connect_value_changed(LINK(this,AreaPropertyPanelBase, ChangeGradientAngle)); + + // set a small width to force widgets to take their final width from other widgets in the grid + mxLbFillGradFrom->get_widget().set_size_request(42, -1); + mxLbFillGradTo->get_widget().set_size_request(42, -1); + + mxLBTransType->connect_changed(LINK(this, AreaPropertyPanelBase, ChangeTrgrTypeHdl_Impl)); + + SetTransparency( 50 ); + mxMTRTransparent->connect_value_changed(LINK(this, AreaPropertyPanelBase, ModifyTransparentHdl_Impl)); + mxSldTransparent->connect_value_changed(LINK(this, AreaPropertyPanelBase, ModifyTransSliderHdl)); + + mxTrGrPopup = std::make_unique<AreaTransparencyGradientPopup>(mxFrame, *this, mxBTNGradient.get()); + + mxBTNGradient->set_item_popover(SIDEBARGRADIENT, mxTrGrPopup->getTopLevel()); + mxBTNGradient->connect_clicked(LINK(this, AreaPropertyPanelBase, ToolbarHdl_Impl)); + + mxBTNGradient->set_item_icon_name(SIDEBARGRADIENT, maImgLinear); + mxBTNGradient->hide(); + mxBmpImport->connect_clicked( LINK(this, AreaPropertyPanelBase, ClickImportBitmapHdl)); +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, ToolbarHdl_Impl, const OUString&, void) +{ + mxBTNGradient->set_menu_item_active(SIDEBARGRADIENT, !mxBTNGradient->get_menu_item_active(SIDEBARGRADIENT)); +} + +void AreaPropertyPanelBase::SetTransparency(sal_uInt16 nVal) +{ + mxSldTransparent->set_value(nVal); + mxMTRTransparent->set_value(nVal, FieldUnit::PERCENT); +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, ClickImportBitmapHdl, weld::Button&, void) +{ + SvxOpenGraphicDialog aDlg("Import", GetFrameWeld()); + aDlg.EnableLink(false); + if( aDlg.Execute() != ERRCODE_NONE ) + return; + + Graphic aGraphic; + auto xWait = std::make_unique<weld::WaitObject>(m_xContainer.get()); + ErrCode nError = aDlg.GetGraphic( aGraphic ); + xWait.reset(); + if( nError != ERRCODE_NONE ) + return; + + mxLbFillAttr->clear(); + + if (SfxObjectShell* pSh = SfxObjectShell::Current()) + { + INetURLObject aURL(aDlg.GetPath()); + OUString aFileName = aURL.GetLastName().getToken(0, '.'); + OUString aName = aFileName; + + XBitmapListRef pList = pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList(); + + tools::Long j = 1; + bool bValidBitmapName = false; + while( !bValidBitmapName ) + { + bValidBitmapName = true; + for( tools::Long i = 0; i < pList->Count() && bValidBitmapName; i++ ) + { + if( aName == pList->GetBitmap(i)->GetName() ) + { + bValidBitmapName = false; + aName = aFileName + OUString::number(j++); + } + } + } + + pList->Insert(std::make_unique<XBitmapEntry>(aGraphic, aName)); + pList->Save(); + + SvxFillAttrBox::Fill(*mxLbFillAttr, pList); + + mxLbFillAttr->set_active_text(aName); + SelectFillAttrHdl(*mxLbFillAttr); + } +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, SelectFillTypeHdl, weld::ComboBox&, void) +{ + FillStyleChanged(true); +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, SelectFillColorHdl, ColorListBox&, void) +{ + SelectFillAttrHdl_Impl(); +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, SelectFillAttrHdl, weld::ComboBox&, void) +{ + SelectFillAttrHdl_Impl(); +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, ChangeGradientAngle, weld::MetricSpinButton&, void) +{ + SelectFillAttrHdl_Impl(); +} + +void AreaPropertyPanelBase::SelectFillAttrHdl_Impl() +{ + sal_Int32 nPosFillStyle = static_cast<eFillStyle>(mxLbFillType->get_active()); + SfxObjectShell* pSh = SfxObjectShell::Current(); + + // #i122676# dependent from bFillStyleChange, do execute a single or two + // changes in one Execute call + const bool bFillStyleChange(static_cast<eFillStyle>(meLastXFS) != static_cast<eFillStyle>(nPosFillStyle)); + + switch(nPosFillStyle) + { + case eFillStyle::NONE: + { + if(bFillStyleChange) + { + const XFillStyleItem aXFillStyleItem(drawing::FillStyle_NONE); + // Need to disable the XFillUseSlideBackgroundItem + const XFillUseSlideBackgroundItem aXFillUseSlideBackgroundItem(false); + setFillUseBackground(&aXFillStyleItem, aXFillUseSlideBackgroundItem); + } + break; + } + case eFillStyle::SOLID: + { + if(bFillStyleChange) + { + // #i122676# Single FillStyle change call needed here + XFillStyleItem aXFillStyleItem(drawing::FillStyle_SOLID); + setFillStyle(aXFillStyleItem); + } + break; + } + case eFillStyle::GRADIENT: + { + + if (pSh && pSh->GetItem(SID_COLOR_TABLE)) + { + basegfx::BGradient aGradient(createColorStops()); + aGradient.SetAngle(Degree10(mxMTRAngle->get_value(FieldUnit::DEGREE) * 10)); + aGradient.SetGradientStyle(static_cast<css::awt::GradientStyle>(mxGradientStyle->get_active())); + + const XFillGradientItem aXFillGradientItem(mxLbFillAttr->get_active_text(), aGradient); + + // #i122676# Change FillStyle and Gradient in one call + XFillStyleItem aXFillStyleItem(drawing::FillStyle_GRADIENT); + setFillStyleAndGradient(bFillStyleChange ? &aXFillStyleItem : nullptr, aXFillGradientItem); + } + break; + } + case eFillStyle::HATCH: + { + sal_Int32 nPos = mxLbFillAttr->get_active(); + + if (nPos == -1) + { + nPos = mnLastPosHatch; + } + + if (nPos != -1 && pSh && pSh->GetItem(SID_HATCH_LIST)) + { + const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST); + + if(nPos < pItem->GetHatchList()->Count()) + { + const XHatch aHatch = pItem->GetHatchList()->GetHatch(nPos)->GetHatch(); + const XFillHatchItem aXFillHatchItem( mxLbFillAttr->get_active_text(), aHatch); + + // #i122676# Change FillStyle and Hatch in one call + XFillStyleItem aXFillStyleItem(drawing::FillStyle_HATCH); + setFillStyleAndHatch(bFillStyleChange ? &aXFillStyleItem : nullptr, aXFillHatchItem); + } + } + + if (nPos != -1) + { + mnLastPosHatch = nPos; + } + break; + } + case eFillStyle::BITMAP: + { + sal_Int32 nPos = mxLbFillAttr->get_active(); + + if (nPos == -1) + { + nPos = mnLastPosBitmap; + } + + if (nPos != -1 && pSh && pSh->GetItem(SID_BITMAP_LIST)) + { + const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST); + + if(nPos < pItem->GetBitmapList()->Count()) + { + const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(nPos); + const XFillBitmapItem aXFillBitmapItem(mxLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject()); + + // #i122676# Change FillStyle and Bitmap in one call + XFillStyleItem aXFillStyleItem(drawing::FillStyle_BITMAP); + setFillStyleAndBitmap(bFillStyleChange ? &aXFillStyleItem : nullptr, aXFillBitmapItem); + } + } + + if (nPos != -1) + { + mnLastPosBitmap = nPos; + } + break; + } + case eFillStyle::PATTERN: + { + sal_Int32 nPos = mxLbFillAttr->get_active(); + + if (nPos == -1) + { + nPos = mnLastPosPattern; + } + + if (nPos != -1 && pSh && pSh->GetItem(SID_PATTERN_LIST)) + { + const SvxPatternListItem * pItem = pSh->GetItem(SID_PATTERN_LIST); + + if(nPos < pItem->GetPatternList()->Count()) + { + const XBitmapEntry* pXPatternEntry = pItem->GetPatternList()->GetBitmap(nPos); + const XFillBitmapItem aXFillBitmapItem(mxLbFillAttr->get_active_text(), pXPatternEntry->GetGraphicObject()); + + // #i122676# Change FillStyle and Bitmap in one call + XFillStyleItem aXFillStyleItem(drawing::FillStyle_BITMAP); + setFillStyleAndBitmap(bFillStyleChange ? &aXFillStyleItem : nullptr, aXFillBitmapItem); + } + } + + if (nPos != -1) + { + mnLastPosPattern = nPos; + } + break; + } + } + if (m_pPanel && !comphelper::LibreOfficeKit::isActive()) + m_pPanel->TriggerDeckLayouting(); +} + +void AreaPropertyPanelBase::FillStyleChanged(bool bUpdateModel) +{ + sal_Int32 nPos = static_cast<eFillStyle>(mxLbFillType->get_active()); + mxLbFillAttr->clear(); + SfxObjectShell* pSh = SfxObjectShell::Current(); + if (!pSh) + return; + + bool bShowLbFillAttr = false; + bool bShowLbFillGradFrom = false; + bool bShowLbFillGradTo = false; + bool bShowGradientStyle = false; + bool bShowMTRAngle = false; + bool bShowToolBoxColor = false; + bool bShowBmpImport = false; + + // #i122676# Do no longer trigger two Execute calls, one for SID_ATTR_FILL_STYLE + // and one for setting the fill attribute itself, but add two SfxPoolItems to the + // call to get just one action at the SdrObject and to create only one Undo action, too. + // Checked that this works in all apps. + switch (nPos) + { + default: + case NONE: + { + if (bUpdateModel) + { + const XFillStyleItem aXFillStyleItem(drawing::FillStyle_NONE); + // Need to disable the XFillUseSlideBackgroundItem + const XFillUseSlideBackgroundItem aXFillUseSlideBackgroundItem(false); + setFillUseBackground(&aXFillStyleItem, aXFillUseSlideBackgroundItem); + } + + break; + } + case SOLID: + { + bShowToolBoxColor = true; + + if (bUpdateModel) + { + const Color aColor = mpColorItem ? mpColorItem->GetColorValue() : COL_AUTO; + const XFillColorItem aXFillColorItem("", aColor); + + // #i122676# change FillStyle and Color in one call + XFillStyleItem aXFillStyleItem(drawing::FillStyle_SOLID); + setFillStyleAndColor(&aXFillStyleItem, aXFillColorItem); + } + break; + } + case GRADIENT: + { + bShowLbFillGradFrom = true; + bShowLbFillGradTo = true; + bShowGradientStyle = true; + bShowMTRAngle = true; + + mxLbFillAttr->set_sensitive(true); + mxLbFillGradTo->set_sensitive(true); + mxLbFillGradFrom->set_sensitive(true); + mxGradientStyle->set_sensitive(true); + mxMTRAngle->set_sensitive(true); + mxLbFillAttr->clear(); + + if (bUpdateModel) + { + mxLbFillAttr->hide(); + mxToolBoxColor->hide(); + mxBmpImport->hide(); + + const SvxGradientListItem* pItem = pSh->GetItem(SID_GRADIENT_LIST); + if (pItem->GetGradientList()->Count() > 0) + { + const basegfx::BGradient aGradient + = pItem->GetGradientList()->GetGradient(0)->GetGradient(); + const OUString aName = pItem->GetGradientList()->GetGradient(0)->GetName(); + const XFillGradientItem aXFillGradientItem(aName, aGradient); + + // #i122676# change FillStyle and Gradient in one call + XFillStyleItem aXFillStyleItem(drawing::FillStyle_GRADIENT); + setFillStyleAndGradient(&aXFillStyleItem, aXFillGradientItem); + mxLbFillGradFrom->SelectEntry(Color(aGradient.GetColorStops().front().getStopColor())); + mxLbFillGradTo->SelectEntry(Color(aGradient.GetColorStops().back().getStopColor())); + + // MCGR: preserve ColorStops if given + // tdf#155901 We need offset of first and last stop, so include them. + if (aGradient.GetColorStops().size() >= 2) + maColorStops = aGradient.GetColorStops(); + else + maColorStops.clear(); + + mxMTRAngle->set_value(toDegrees(aGradient.GetAngle()), FieldUnit::DEGREE); + css::awt::GradientStyle eXGS = aGradient.GetGradientStyle(); + mxGradientStyle->set_active(sal::static_int_cast<sal_Int32>(eXGS)); + } + } + else + { + if (pSh->GetItem(SID_GRADIENT_LIST)) + { + SvxFillAttrBox::Fill(*mxLbFillAttr, + pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList()); + mxLbFillGradTo->SetNoSelection(); + mxLbFillGradFrom->SetNoSelection(); + if (mpFillGradientItem) + { + const OUString aString(mpFillGradientItem->GetName()); + mxLbFillAttr->set_active_text(aString); + const basegfx::BGradient aGradient = mpFillGradientItem->GetGradientValue(); + mxLbFillGradFrom->SelectEntry(Color(aGradient.GetColorStops().front().getStopColor())); + mxLbFillGradTo->SelectEntry(Color(aGradient.GetColorStops().back().getStopColor())); + + // MCGR: preserve ColorStops if given + // tdf#155901 We need offset of first and last stop, so include them. + if (aGradient.GetColorStops().size() >= 2) + maColorStops = aGradient.GetColorStops(); + else + maColorStops.clear(); + + mxGradientStyle->set_active( + sal::static_int_cast<sal_Int32>(aGradient.GetGradientStyle())); + if (mxGradientStyle->get_active() == sal_Int32(css::awt::GradientStyle_RADIAL)) + mxMTRAngle->set_sensitive(false); + else + mxMTRAngle->set_value(toDegrees(aGradient.GetAngle()), + FieldUnit::DEGREE); + } + else + { + mxLbFillAttr->set_active(-1); + } + } + else + { + mxLbFillAttr->set_active(-1); + } + } + break; + } + case HATCH: + { + bShowLbFillAttr = true; + + const SvxHatchListItem* pItem(pSh->GetItem(SID_HATCH_LIST)); + if (pItem) + { + const XHatchListRef& pXHatchList(pItem->GetHatchList()); + mxLbFillAttr->set_sensitive(true); + mxLbFillAttr->clear(); + SvxFillAttrBox::Fill(*mxLbFillAttr, pXHatchList); + + if (mnLastPosHatch != -1) + { + if (mnLastPosHatch < pXHatchList->Count()) + { + const XHatch aHatch = pXHatchList->GetHatch(mnLastPosHatch)->GetHatch(); + const OUString aName = pXHatchList->GetHatch(mnLastPosHatch)->GetName(); + const XFillHatchItem aXFillHatchItem(aName, aHatch); + + // #i122676# change FillStyle and Hatch in one call + if (bUpdateModel) + { + XFillStyleItem aXFillStyleItem(drawing::FillStyle_HATCH); + setFillStyleAndHatch(&aXFillStyleItem, aXFillHatchItem); + } + mxLbFillAttr->set_active(mnLastPosHatch); + } + } + } + else + { + mxLbFillAttr->set_sensitive(false); + } + break; + } + case BITMAP: + case PATTERN: + { + bShowLbFillAttr = true; + mxLbFillAttr->set_sensitive(true); + mxLbFillAttr->clear(); + + OUString aName; + GraphicObject aBitmap; + if (nPos == static_cast<sal_Int32>(BITMAP)) + { + if (!comphelper::LibreOfficeKit::isActive()) + bShowBmpImport = true; + const SvxBitmapListItem* pItem = pSh->GetItem(SID_BITMAP_LIST); + if (pItem) + { + const XBitmapListRef& pXBitmapList(pItem->GetBitmapList()); + SvxFillAttrBox::Fill(*mxLbFillAttr, pXBitmapList); + + if (mnLastPosBitmap != -1) + { + if (mnLastPosBitmap < pXBitmapList->Count()) + { + const XBitmapEntry* pXBitmapEntry + = pXBitmapList->GetBitmap(mnLastPosBitmap); + aBitmap = pXBitmapEntry->GetGraphicObject(); + aName = pXBitmapEntry->GetName(); + mxLbFillAttr->set_active(mnLastPosBitmap); + } + } + } + else + { + bShowBmpImport = false; + } + } + else if (nPos == static_cast<sal_Int32>(PATTERN)) + { + const SvxPatternListItem* pItem = pSh->GetItem(SID_PATTERN_LIST); + if (pItem) + { + const XPatternListRef& pXPatternList(pItem->GetPatternList()); + SvxFillAttrBox::Fill(*mxLbFillAttr, pXPatternList); + + if (mnLastPosPattern != -1) + { + if (mnLastPosPattern < pXPatternList->Count()) + { + const XBitmapEntry* pXPatternEntry + = pXPatternList->GetBitmap(mnLastPosPattern); + aBitmap = pXPatternEntry->GetGraphicObject(); + aName = pXPatternEntry->GetName(); + mxLbFillAttr->set_active(mnLastPosPattern); + } + } + } + else + { + bShowLbFillAttr = false; + } + } + if (bUpdateModel) + { + const XFillBitmapItem aXFillBitmapItem(aName, aBitmap); + const XFillStyleItem aXFillStyleItem(drawing::FillStyle_BITMAP); + setFillStyleAndBitmap(&aXFillStyleItem, aXFillBitmapItem); + } + break; + } + case USE_BACKGROUND: + { + // No transparencies here + mxLBTransType->hide(); + mxTrspTextFT->hide(); + mxMTRTransparent->hide(); + mxSldTransparent->hide(); + mxBTNGradient->hide(); + if (bUpdateModel) + { + const XFillStyleItem aXFillStyleItem(drawing::FillStyle_NONE); + const XFillUseSlideBackgroundItem aXFillUseSlideBackgroundItem(true); + setFillUseBackground(&aXFillStyleItem, aXFillUseSlideBackgroundItem); + break; + } + } + } + + mxLbFillAttr->set_visible(bShowLbFillAttr); + mxLbFillGradFrom->set_visible(bShowLbFillGradFrom); + mxLbFillGradTo->set_visible(bShowLbFillGradTo); + mxGradientStyle->set_visible(bShowGradientStyle); + mxMTRAngle->set_visible(bShowMTRAngle); + mxToolBoxColor->set_visible(bShowToolBoxColor); + mxBmpImport->set_visible(bShowBmpImport); + + meLastXFS = static_cast<sal_uInt16>(nPos); + + if (m_pPanel && !comphelper::LibreOfficeKit::isActive()) + m_pPanel->TriggerDeckLayouting(); +} + +void AreaPropertyPanelBase::ImpUpdateTransparencies() +{ + if(mpTransparenceItem || mpFloatTransparenceItem) + { + bool bZeroValue(false); + + if (mpTransparenceItem) + { + const sal_uInt16 nValue(mpTransparenceItem->GetValue()); + + if(!nValue) + { + bZeroValue = true; + } + else if(nValue <= 100) + { + mxLBTransType->set_sensitive(true); + mxTrspTextFT->set_sensitive(true); + mxLBTransType->set_active(1); + mxBTNGradient->hide(); + mxMTRTransparent->show(); + mxSldTransparent->show(); + mxMTRTransparent->set_sensitive(true); + mxSldTransparent->set_sensitive(true); + SetTransparency(nValue); + } + + if (!bZeroValue && mxTrGrPopup) + { + mxBTNGradient->set_menu_item_active(SIDEBARGRADIENT, false); + } + } + + if(bZeroValue && mpFloatTransparenceItem) + { + if(mpFloatTransparenceItem->IsEnabled()) + { + const basegfx::BGradient& rGradient = mpFloatTransparenceItem->GetGradientValue(); + sal_Int32 nEntryPos(0); + OUString* pImage = nullptr; + + mxLBTransType->set_sensitive(true); + mxTrspTextFT->set_sensitive(true); + mxMTRTransparent->hide(); + mxSldTransparent->hide(); + mxBTNGradient->set_sensitive(true); + mxBTNGradient->show(); + + switch(rGradient.GetGradientStyle()) + { + default: + case css::awt::GradientStyle_LINEAR: + { + nEntryPos = 2; + pImage = &maImgLinear; + break; + } + case css::awt::GradientStyle_AXIAL: + { + nEntryPos = 3; + pImage = &maImgAxial; + break; + } + case css::awt::GradientStyle_RADIAL: + { + nEntryPos = 4; + pImage = &maImgRadial; + break; + } + case css::awt::GradientStyle_ELLIPTICAL: + { + nEntryPos = 5; + pImage = &maImgElli; + break; + } + case css::awt::GradientStyle_SQUARE: + { + nEntryPos = 6; + pImage = &maImgQuad; + break; + } + case css::awt::GradientStyle_RECT: + { + nEntryPos = 7; + pImage = &maImgSquare; + break; + } + } + mxLBTransType->set_active(nEntryPos); + mxBTNGradient->set_item_icon_name(SIDEBARGRADIENT, *pImage); + mxTrGrPopup->Rearrange(mpFloatTransparenceItem.get()); + bZeroValue = false; + } + else + { + bZeroValue = true; + } + } + + if(bZeroValue) + { + mxLBTransType->set_sensitive(true); + mxTrspTextFT->set_sensitive(true); + mxLBTransType->set_active(0); + mxBTNGradient->hide(); + mxMTRTransparent->set_sensitive(true); + mxSldTransparent->set_sensitive(true); + mxMTRTransparent->show(); + mxSldTransparent->show(); + SetTransparency(0); + } + } + else + { + // no transparency at all + mxLBTransType->set_active(-1); + mxLBTransType->set_sensitive(false); + mxTrspTextFT->set_sensitive(false); + mxMTRTransparent->set_sensitive(false); + mxSldTransparent->set_sensitive(false); + mxMTRTransparent->show(); + mxSldTransparent->show(); + mxBTNGradient->set_sensitive(false); + mxBTNGradient->hide(); + } +} + +void AreaPropertyPanelBase::updateFillTransparence(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState) +{ + if (bDisabled) + { + mpTransparenceItem.reset(); + return; + } + else if (bDefaultOrSet) + { + if (pState) + { + const SfxUInt16Item* pItem = static_cast<const SfxUInt16Item*>(pState); + mpTransparenceItem.reset(pItem->Clone()); + } + else + { + mpTransparenceItem.reset(); + } + } + else + { + mpTransparenceItem.reset(); + } + + // update transparency settings dependent of mpTransparenceItem and mpFloatTransparenceItem + ImpUpdateTransparencies(); +} + +void AreaPropertyPanelBase::updateFillFloatTransparence(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState) +{ + if (bDisabled) + { + mpFloatTransparenceItem.reset(); + return; + } + + if (bDefaultOrSet) + { + if (pState) + { + const XFillFloatTransparenceItem* pItem = static_cast<const XFillFloatTransparenceItem*>(pState); + mpFloatTransparenceItem.reset(pItem->Clone()); + } + else + { + mpFloatTransparenceItem.reset(); + } + } + else + { + mpFloatTransparenceItem.reset(); + } + + // update transparency settings dependent of mpTransparenceItem and mpFloatTransparenceItem + ImpUpdateTransparencies(); +} + +void AreaPropertyPanelBase::updateFillStyle(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState) +{ + if(bDisabled) + { + mxLbFillType->set_sensitive(false); + mxColorTextFT->set_sensitive(false); + mxLbFillType->set_active(-1); + mxLbFillAttr->show(); + mxLbFillAttr->set_sensitive(false); + mxLbFillAttr->set_active(-1); + mxToolBoxColor->hide(); + meLastXFS = static_cast<sal_uInt16>(-1); + mpStyleItem.reset(); + } + else if (bDefaultOrSet && pState) + { + const XFillStyleItem* pItem = static_cast<const XFillStyleItem*>(pState); + mpStyleItem.reset(pItem->Clone()); + mxLbFillType->set_sensitive(true); + mxColorTextFT->set_sensitive(true); + drawing::FillStyle eXFS = mpStyleItem->GetValue(); + eFillStyle nPos = NONE; + switch(eXFS) + { + default: + case drawing::FillStyle_NONE: + { + mxLbFillAttr->hide(); + // "Use slide background" also uses FillStyle_NONE internally, + // don't switch listbox in that case (will be handled by updateFillUseBackground) + nPos = meLastXFS == USE_BACKGROUND ? USE_BACKGROUND : NONE; + break; + } + case drawing::FillStyle_SOLID: + nPos = SOLID; + break; + case drawing::FillStyle_GRADIENT: + nPos = GRADIENT; + break; + case drawing::FillStyle_HATCH: + nPos = HATCH; + break; + case drawing::FillStyle_BITMAP: + { + if(mpBitmapItem) + { + if(!mpBitmapItem->isPattern()) + nPos = BITMAP; + else + nPos = PATTERN; + } + else + nPos = BITMAP; + break; + } + } + meLastXFS = static_cast< sal_uInt16 >(mxLbFillType->get_active()); + mxLbFillType->set_active(static_cast< sal_Int32 >(nPos)); + FillStyleChanged(false); + return; + } + + mxLbFillType->set_active(-1); + mxLbFillAttr->show(); + mxLbFillAttr->set_sensitive(false); + mxLbFillAttr->set_active(-1); + mxToolBoxColor->hide(); + meLastXFS = static_cast<sal_uInt16>(-1); + mpStyleItem.reset(); +} + +void AreaPropertyPanelBase::updateFillGradient(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState) +{ + if (bDefaultOrSet) + { + const XFillGradientItem* pItem = static_cast<const XFillGradientItem*>(pState); + mpFillGradientItem.reset(pItem ? pItem->Clone() : nullptr); + } + + if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue()) + { + mxLbFillAttr->hide(); + mxLbFillGradFrom->show(); + mxLbFillGradTo->show(); + mxMTRAngle->show(); + mxGradientStyle->show(); + mxToolBoxColor->hide(); + + if (bDefaultOrSet) + { + mxLbFillType->set_active(GRADIENT); + FillStyleChanged(false); + } + else if(bDisabled) + { + mxLbFillGradFrom->SetNoSelection(); + mxLbFillGradTo->SetNoSelection(); + mxLbFillGradFrom->set_sensitive(false); + mxLbFillGradTo->set_sensitive(false); + mxMTRAngle->set_sensitive(false); + mxGradientStyle->set_sensitive(false); + } + else + { + mxLbFillGradFrom->SetNoSelection(); + mxLbFillGradTo->SetNoSelection(); + } + } +} + +void AreaPropertyPanelBase::updateFillHatch(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState) +{ + if (bDefaultOrSet) + { + const XFillHatchItem* pItem = static_cast<const XFillHatchItem*>(pState); + mpHatchItem.reset(pItem ? pItem->Clone() : nullptr); + } + + if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue()) + { + mxLbFillAttr->show(); + mxToolBoxColor->hide(); + + if (bDefaultOrSet) + { + mxLbFillAttr->set_sensitive(true); + mxLbFillType->set_active(HATCH); + FillStyleChanged(false); + } + else if(bDisabled) + { + mxLbFillAttr->set_sensitive(false); + mxLbFillAttr->set_active(-1); + } + else + { + mxLbFillAttr->set_active(-1); + } + } + FillStyleChanged(false); +} + +void AreaPropertyPanelBase::updateFillColor(bool bDefaultOrSet, const SfxPoolItem* pState) +{ + if (bDefaultOrSet) + { + const XFillColorItem* pItem = static_cast<const XFillColorItem*>(pState); + mpColorItem.reset(pItem ? pItem->Clone() : nullptr); + } + + if(mpStyleItem && drawing::FillStyle_SOLID == mpStyleItem->GetValue()) + { + mxLbFillAttr->hide(); + mxToolBoxColor->show(); + mxLbFillType->set_active(SOLID); + FillStyleChanged(false); + } +} + +void AreaPropertyPanelBase::updateFillBitmap(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState) +{ + if (bDefaultOrSet) + { + const XFillBitmapItem* pItem = static_cast<const XFillBitmapItem*>(pState); + mpBitmapItem.reset(pItem ? pItem->Clone() : nullptr); + } + + if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue()) + { + mxLbFillAttr->show(); + mxToolBoxColor->hide(); + + if (bDefaultOrSet) + { + if(mpBitmapItem->isPattern()) + mxLbFillType->set_active(PATTERN); + else + mxLbFillType->set_active(BITMAP); + FillStyleChanged(false); + } + else if(bDisabled) + { + mxLbFillAttr->hide(); + mxLbFillAttr->set_active(-1); + } + else + { + mxLbFillAttr->set_active(-1); + } + } +} + +void AreaPropertyPanelBase::updateFillUseBackground(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState) +{ + if (bDisabled) + return; + + if (bDefaultOrSet) + { + if (pState) + { + const XFillUseSlideBackgroundItem* pItem = static_cast<const XFillUseSlideBackgroundItem*>(pState); + // When XFillUseSlideBackgroundItem is set, select "Use Background Fill". + // When false, select "None" (only if "Use background fill" was selected beforehand) + int nPos = pItem->GetValue() ? USE_BACKGROUND : NONE; + if ((nPos == NONE && mxLbFillType->get_active() == USE_BACKGROUND) || nPos == USE_BACKGROUND) + { + mxLbFillType->set_active(nPos); + FillStyleChanged(false); + } + } + } +} + +void AreaPropertyPanelBase::NotifyItemUpdate( + sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState) +{ + const bool bDisabled(SfxItemState::DISABLED == eState); + const bool bDefaultOrSet(SfxItemState::DEFAULT <= eState); + const bool bDefault(SfxItemState::DEFAULT == eState); + + switch(nSID) + { + case SID_ATTR_FILL_TRANSPARENCE: + updateFillTransparence(bDisabled, bDefaultOrSet, pState); + break; + case SID_ATTR_FILL_FLOATTRANSPARENCE: + updateFillFloatTransparence(bDisabled, bDefaultOrSet, pState); + break; + case SID_ATTR_FILL_STYLE: + updateFillStyle(bDisabled, bDefaultOrSet, pState); + break; + case SID_ATTR_FILL_COLOR: + updateFillColor(bDefaultOrSet, pState); + break; + case SID_ATTR_FILL_GRADIENT: + updateFillGradient(bDisabled, bDefaultOrSet, pState); + break; + case SID_ATTR_FILL_HATCH: + updateFillHatch(bDisabled, bDefaultOrSet, pState); + break; + case SID_ATTR_FILL_BITMAP: + updateFillBitmap(bDisabled, bDefaultOrSet, pState); + break; + case SID_ATTR_FILL_USE_SLIDE_BACKGROUND: + updateFillUseBackground(bDisabled, bDefaultOrSet, pState); + break; + case SID_GRADIENT_LIST: + { + if(bDefault) + { + if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue()) + { + if(mpFillGradientItem) + { + const OUString aString( mpFillGradientItem->GetName() ); + const SfxObjectShell* pSh = SfxObjectShell::Current(); + mxLbFillAttr->clear(); + if (pSh) + { + mxLbFillAttr->set_sensitive(true); + SvxFillAttrBox::Fill(*mxLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList()); + } + mxLbFillAttr->set_active_text(aString); + } + else + { + mxLbFillAttr->set_active(-1); + } + } + } + break; + } + case SID_HATCH_LIST: + { + if(bDefault) + { + if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue()) + { + if(mpHatchItem) + { + const OUString aString( mpHatchItem->GetName() ); + const SfxObjectShell* pSh = SfxObjectShell::Current(); + mxLbFillAttr->clear(); + if (pSh) + { + mxLbFillAttr->set_sensitive(true); + SvxFillAttrBox::Fill(*mxLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList()); + } + mxLbFillAttr->set_active_text(aString); + } + else + { + mxLbFillAttr->set_active(-1); + } + } + } + break; + } + case SID_BITMAP_LIST: + case SID_PATTERN_LIST: + { + if(bDefault) + { + if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue()) + { + if(mpBitmapItem) + { + const OUString aString( mpBitmapItem->GetName() ); + const SfxObjectShell* pSh = SfxObjectShell::Current(); + mxLbFillAttr->clear(); + mxLbFillAttr->show(); + if (pSh) + { + if(nSID == SID_BITMAP_LIST) + SvxFillAttrBox::Fill(*mxLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList()); + else if(nSID == SID_PATTERN_LIST) + SvxFillAttrBox::Fill(*mxLbFillAttr, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList()); + } + mxLbFillAttr->set_active_text(aString); + } + else + { + mxLbFillAttr->set_active(-1); + } + } + } + break; + } + } + FillStyleChanged(false); +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, ModifyTransSliderHdl, weld::Scale&, void) +{ + const sal_uInt16 nVal = mxSldTransparent->get_value(); + SetTransparency(nVal); + const XFillTransparenceItem aLinearItem(nVal); + setFillTransparence(aLinearItem); +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, ChangeTrgrTypeHdl_Impl, weld::ComboBox&, void) +{ + sal_Int32 nSelectType = mxLBTransType->get_active(); + bool bGradient = false; + sal_uInt16 nTrans = 0; + + if(!nSelectType) + { + mxBTNGradient->hide(); + mxMTRTransparent->show(); + mxSldTransparent->show(); + mxMTRTransparent->set_sensitive(true); + mxSldTransparent->set_sensitive(true); + SetTransparency(0); + } + else if(1 == nSelectType) + { + mxBTNGradient->hide(); + mxMTRTransparent->show(); + mxSldTransparent->show(); + nTrans = mnLastTransSolid; + mxMTRTransparent->set_value(nTrans, FieldUnit::PERCENT); + mxLBTransType->set_active(1); + mxMTRTransparent->set_sensitive(true); + mxSldTransparent->set_sensitive(true); + } + else + { + mxBTNGradient->show(); + + switch (nSelectType) + { + case 2: + mxBTNGradient->set_item_icon_name(SIDEBARGRADIENT, maImgLinear); + break; + case 3: + mxBTNGradient->set_item_icon_name(SIDEBARGRADIENT, maImgAxial); + break; + case 4: + mxBTNGradient->set_item_icon_name(SIDEBARGRADIENT, maImgRadial); + break; + case 5: + mxBTNGradient->set_item_icon_name(SIDEBARGRADIENT, maImgElli); + break; + case 6: + mxBTNGradient->set_item_icon_name(SIDEBARGRADIENT, maImgQuad); + break; + case 7: + mxBTNGradient->set_item_icon_name(SIDEBARGRADIENT, maImgSquare); + break; + } + + mxMTRTransparent->hide(); + mxSldTransparent->hide(); + mxBTNGradient->set_sensitive(true); + bGradient = true; + } + + const XFillTransparenceItem aLinearItem(nTrans); + setFillTransparence(aLinearItem); + + if(nSelectType > 1) + { + nSelectType -= 2; + } + + basegfx::BGradient aTmpGradient; + + switch(static_cast<css::awt::GradientStyle>(nSelectType)) + { + case css::awt::GradientStyle_LINEAR: + aTmpGradient = maGradientLinear; + break; + case css::awt::GradientStyle_AXIAL: + aTmpGradient = maGradientAxial; + break; + case css::awt::GradientStyle_RADIAL: + aTmpGradient = maGradientRadial; + break; + case css::awt::GradientStyle_ELLIPTICAL: + aTmpGradient = maGradientElliptical; + break; + case css::awt::GradientStyle_SQUARE: + aTmpGradient = maGradientSquare; + break; + case css::awt::GradientStyle_RECT: + aTmpGradient = maGradientRect; + break; + default: + break; + } + + const XFillFloatTransparenceItem aGradientItem(aTmpGradient, bGradient); + setFillFloatTransparence(aGradientItem); +} + +IMPL_LINK_NOARG(AreaPropertyPanelBase, ModifyTransparentHdl_Impl, weld::MetricSpinButton&, void) +{ + const sal_uInt16 nTrans = static_cast<sal_uInt16>(mxMTRTransparent->get_value(FieldUnit::PERCENT)); + mnLastTransSolid = nTrans; + SetTransparency(nTrans); + const sal_Int32 nSelectType = mxLBTransType->get_active(); + + if(nTrans && !nSelectType) + { + mxLBTransType->set_active(1); + } + + const XFillTransparenceItem aLinearItem(nTrans); + setFillTransparence(aLinearItem); +} + +const basegfx::BGradient& AreaPropertyPanelBase::GetGradient (const css::awt::GradientStyle eStyle) const +{ + switch (eStyle) + { + default: + case css::awt::GradientStyle_LINEAR: + return maGradientLinear; + case css::awt::GradientStyle_AXIAL: + return maGradientAxial; + case css::awt::GradientStyle_RADIAL: + return maGradientRadial; + case css::awt::GradientStyle_ELLIPTICAL: + return maGradientElliptical; + case css::awt::GradientStyle_SQUARE: + return maGradientSquare; + case css::awt::GradientStyle_RECT: + return maGradientRect; + } +} + +void AreaPropertyPanelBase::SetGradient (const basegfx::BGradient& rGradient) +{ + switch (rGradient.GetGradientStyle()) + { + case css::awt::GradientStyle_LINEAR: + maGradientLinear = rGradient; + break; + case css::awt::GradientStyle_AXIAL: + maGradientAxial = rGradient; + break; + case css::awt::GradientStyle_RADIAL: + maGradientRadial = rGradient; + break; + case css::awt::GradientStyle_ELLIPTICAL: + maGradientElliptical = rGradient; + break; + case css::awt::GradientStyle_SQUARE: + maGradientSquare = rGradient; + break; + case css::awt::GradientStyle_RECT: + maGradientRect = rGradient; + break; + default: + break; + } +} + +sal_Int32 AreaPropertyPanelBase::GetSelectedTransparencyTypeIndex() const +{ + return mxLBTransType->get_active(); +} + +basegfx::BColorStops AreaPropertyPanelBase::createColorStops() +{ + basegfx::BColorStops aColorStops; + + if (maColorStops.size() >= 2) + { + aColorStops = maColorStops; + aColorStops.front() = basegfx::BColorStop(maColorStops.front().getStopOffset(), + mxLbFillGradFrom->GetSelectEntryColor().getBColor()); + aColorStops.back() = basegfx::BColorStop(maColorStops.back().getStopOffset(), + mxLbFillGradTo->GetSelectEntryColor().getBColor()); + } + else + { + aColorStops.emplace_back(0.0, mxLbFillGradFrom->GetSelectEntryColor().getBColor()); + aColorStops.emplace_back(1.0, mxLbFillGradTo->GetSelectEntryColor().getBColor()); + } + + return aColorStops; +} + +void AreaPropertyPanelBase::HandleContextChange( + const vcl::EnumContext& rContext) +{ + if (maContext.GetApplication() == rContext.GetApplication()) + return; + + maContext = rContext; + + switch (maContext.GetApplication()) + { + case vcl::EnumContext::Application::Impress: + if (!msUseBackgroundText.isEmpty()) + { + mxLbFillType->insert_text(USE_BACKGROUND, msUseBackgroundText); + msUseBackgroundText = OUString(); + } + break; + default: + if (msUseBackgroundText.isEmpty()) + { + msUseBackgroundText = mxLbFillType->get_text(USE_BACKGROUND); + mxLbFillType->remove(USE_BACKGROUND); + } + break; + } +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx b/svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx new file mode 100644 index 0000000000..680cf2cfc4 --- /dev/null +++ b/svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx @@ -0,0 +1,202 @@ +/* -*- 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/sidebar/AreaTransparencyGradientPopup.hxx> +#include <svx/sidebar/AreaPropertyPanelBase.hxx> +#include <svx/xflftrit.hxx> + +namespace svx::sidebar { + +AreaTransparencyGradientPopup::AreaTransparencyGradientPopup(const css::uno::Reference<css::frame::XFrame>& rFrame, + AreaPropertyPanelBase& rPanel, weld::Widget* pParent) + : WeldToolbarPopup(rFrame, pParent, "svx/ui/floatingareastyle.ui", "FloatingAreaStyle") + , mrAreaPropertyPanel(rPanel) + , mxCenterGrid(m_xBuilder->weld_widget("centergrid")) + , mxAngleGrid(m_xBuilder->weld_widget("anglegrid")) + , mxMtrTrgrCenterX(m_xBuilder->weld_metric_spin_button("centerx", FieldUnit::PERCENT)) + , mxMtrTrgrCenterY(m_xBuilder->weld_metric_spin_button("centery", FieldUnit::PERCENT)) + , mxMtrTrgrAngle(m_xBuilder->weld_metric_spin_button("angle", FieldUnit::DEGREE)) + , mxBtnLeft45(m_xBuilder->weld_toolbar("lefttoolbox")) + , mxBtnRight45(m_xBuilder->weld_toolbar("righttoolbox")) + , mxMtrTrgrStartValue(m_xBuilder->weld_metric_spin_button("start", FieldUnit::PERCENT)) + , mxMtrTrgrEndValue(m_xBuilder->weld_metric_spin_button("end", FieldUnit::PERCENT)) + , mxMtrTrgrBorder(m_xBuilder->weld_metric_spin_button("border", FieldUnit::PERCENT)) +{ + Link<weld::MetricSpinButton&,void> aLink = LINK(this, AreaTransparencyGradientPopup, ModifiedTrgrHdl_Impl); + mxMtrTrgrCenterX->connect_value_changed(aLink); + mxMtrTrgrCenterY->connect_value_changed(aLink); + mxMtrTrgrAngle->connect_value_changed(aLink); + mxMtrTrgrBorder->connect_value_changed(aLink); + mxMtrTrgrStartValue->connect_value_changed(aLink); + mxMtrTrgrEndValue->connect_value_changed(aLink); + mxBtnLeft45->connect_clicked(LINK(this, AreaTransparencyGradientPopup, Left_Click45_Impl)); + mxBtnRight45->connect_clicked(LINK(this, AreaTransparencyGradientPopup, Right_Click45_Impl)); +} + +AreaTransparencyGradientPopup::~AreaTransparencyGradientPopup() +{ +} + +void AreaTransparencyGradientPopup::InitStatus(XFillFloatTransparenceItem const * pGradientItem) +{ + const basegfx::BGradient& rGradient = pGradientItem->GetGradientValue(); + + basegfx::BGradient aGradient; + Color aStart(rGradient.GetColorStops().front().getStopColor()); + Color aEnd(rGradient.GetColorStops().back().getStopColor()); + + if (rGradient.GetXOffset() == AreaPropertyPanelBase::DEFAULT_CENTERX + && rGradient.GetYOffset() == AreaPropertyPanelBase::DEFAULT_CENTERY + && static_cast<sal_Int32>(toDegrees(rGradient.GetAngle())) == AreaPropertyPanelBase::DEFAULT_ANGLE + && static_cast<sal_uInt16>(((static_cast<sal_uInt16>(aStart.GetRed()) + 1) * 100) / 255) + == AreaPropertyPanelBase::DEFAULT_STARTVALUE + && static_cast<sal_uInt16>(((static_cast<sal_uInt16>(aEnd.GetRed()) + 1) * 100) / 255) + == AreaPropertyPanelBase::DEFAULT_ENDVALUE + && rGradient.GetBorder() == AreaPropertyPanelBase::DEFAULT_BORDER) + { + aGradient = mrAreaPropertyPanel.GetGradient(rGradient.GetGradientStyle()); + } + else + { + aGradient = rGradient; + } + mxMtrTrgrCenterX->set_value(aGradient.GetXOffset(), FieldUnit::PERCENT); + mxMtrTrgrCenterY->set_value(aGradient.GetYOffset(), FieldUnit::PERCENT); + mxMtrTrgrAngle->set_value(toDegrees(aGradient.GetAngle()), FieldUnit::DEGREE); + aStart = Color(aGradient.GetColorStops().front().getStopColor()); + aEnd = Color(aGradient.GetColorStops().back().getStopColor()); + mxMtrTrgrStartValue->set_value(static_cast<sal_uInt16>(((static_cast<sal_uInt16>(aStart.GetRed()) + 1) * 100) / 255), FieldUnit::PERCENT); + mxMtrTrgrEndValue->set_value(static_cast<sal_uInt16>(((static_cast<sal_uInt16>(aEnd.GetRed()) + 1) * 100) / 255), FieldUnit::PERCENT); + + // MCGR: preserve ColorStops if given + // tdf#155901 We need offset of first and last stop, so include them. + if (aGradient.GetColorStops().size() >= 2) + maColorStops = aGradient.GetColorStops(); + else + maColorStops.clear(); + + mxMtrTrgrBorder->set_value(aGradient.GetBorder(), FieldUnit::PERCENT); +} + +void AreaTransparencyGradientPopup::Rearrange(XFillFloatTransparenceItem const * pGradientItem) +{ + InitStatus(pGradientItem); + const basegfx::BGradient& rGradient = pGradientItem->GetGradientValue(); + css::awt::GradientStyle eXGS(rGradient.GetGradientStyle()); + + switch(eXGS) + { + case css::awt::GradientStyle_LINEAR: + case css::awt::GradientStyle_AXIAL: + mxCenterGrid->hide(); + mxAngleGrid->show(); + break; + case css::awt::GradientStyle_RADIAL: + mxCenterGrid->show(); + mxAngleGrid->hide(); + break; + case css::awt::GradientStyle_ELLIPTICAL: + case css::awt::GradientStyle_SQUARE: + case css::awt::GradientStyle_RECT: + mxCenterGrid->show(); + mxAngleGrid->show(); + break; + default: + break; + } +} + +void AreaTransparencyGradientPopup::ExecuteValueModify() +{ + //Added + sal_Int16 aMtrValue = static_cast<sal_Int16>(mxMtrTrgrAngle->get_value(FieldUnit::DEGREE)); + while(aMtrValue<0) + aMtrValue += 360; + sal_uInt16 nVal = aMtrValue/360; + nVal = aMtrValue - nVal*360; + mxMtrTrgrAngle->set_value(nVal, FieldUnit::DEGREE); + //End of new code + + basegfx::BColorStops aColorStops; + basegfx::BColor aStartBColor(mxMtrTrgrStartValue->get_value(FieldUnit::PERCENT) / 100.0); + aStartBColor.clamp(); + basegfx::BColor aEndBColor(mxMtrTrgrEndValue->get_value(FieldUnit::PERCENT) / 100.0); + aEndBColor.clamp(); + + if (maColorStops.size() >= 2) + { + aColorStops = maColorStops; + aColorStops.front() = basegfx::BColorStop(maColorStops.front().getStopOffset(), aStartBColor); + aColorStops.back() = basegfx::BColorStop(maColorStops.back().getStopOffset(), aEndBColor); + } + else + { + aColorStops.emplace_back(0.0, aStartBColor); + aColorStops.emplace_back(1.0, aEndBColor); + } + + basegfx::BGradient aTmpGradient( + aColorStops, + static_cast<css::awt::GradientStyle>(mrAreaPropertyPanel.GetSelectedTransparencyTypeIndex()-2), + Degree10(static_cast<sal_Int16>(mxMtrTrgrAngle->get_value(FieldUnit::DEGREE)) * 10), + static_cast<sal_uInt16>(mxMtrTrgrCenterX->get_value(FieldUnit::PERCENT)), + static_cast<sal_uInt16>(mxMtrTrgrCenterY->get_value(FieldUnit::PERCENT)), + static_cast<sal_uInt16>(mxMtrTrgrBorder->get_value(FieldUnit::PERCENT)), + 100, 100); + + mrAreaPropertyPanel.SetGradient(aTmpGradient); + + XFillFloatTransparenceItem aGradientItem(aTmpGradient, true ); + + mrAreaPropertyPanel.setFillFloatTransparence(aGradientItem); +} + +IMPL_LINK_NOARG(AreaTransparencyGradientPopup, ModifiedTrgrHdl_Impl, weld::MetricSpinButton&, void) +{ + ExecuteValueModify(); +} + +IMPL_LINK_NOARG(AreaTransparencyGradientPopup, Left_Click45_Impl, const OUString&, void) +{ + sal_uInt16 nTemp = static_cast<sal_uInt16>(mxMtrTrgrAngle->get_value(FieldUnit::DEGREE)); + if (nTemp>=315) + nTemp -= 360; + nTemp += 45; + mxMtrTrgrAngle->set_value(nTemp, FieldUnit::DEGREE); + ExecuteValueModify(); +} + +IMPL_LINK_NOARG(AreaTransparencyGradientPopup, Right_Click45_Impl, const OUString&, void) +{ + sal_uInt16 nTemp = static_cast<sal_uInt16>(mxMtrTrgrAngle->get_value(FieldUnit::DEGREE)); + if (nTemp<45) + nTemp += 360; + nTemp -= 45; + mxMtrTrgrAngle->set_value(nTemp, FieldUnit::DEGREE); + ExecuteValueModify(); +} + +void AreaTransparencyGradientPopup::GrabFocus() +{ + mxMtrTrgrCenterX->grab_focus(); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/effect/EffectPropertyPanel.cxx b/svx/source/sidebar/effect/EffectPropertyPanel.cxx new file mode 100644 index 0000000000..f6be6ddaff --- /dev/null +++ b/svx/source/sidebar/effect/EffectPropertyPanel.cxx @@ -0,0 +1,175 @@ +/* -*- 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/. + */ + +#include <sal/config.h> + +#include "EffectPropertyPanel.hxx" + +#include <sfx2/dispatch.hxx> +#include <svx/colorbox.hxx> +#include <svx/sdmetitm.hxx> +#include <svx/sdprcitm.hxx> +#include <svx/svddef.hxx> +#include <svx/svxids.hrc> +#include <svx/xcolit.hxx> +#include <svl/itemset.hxx> + +namespace svx::sidebar +{ +EffectPropertyPanel::EffectPropertyPanel(weld::Widget* pParent, SfxBindings* pBindings) + : PanelLayout(pParent, "EffectPropertyPanel", "svx/ui/sidebareffect.ui") + , maGlowColorController(SID_ATTR_GLOW_COLOR, *pBindings, *this) + , maGlowRadiusController(SID_ATTR_GLOW_RADIUS, *pBindings, *this) + , maGlowTransparencyController(SID_ATTR_GLOW_TRANSPARENCY, *pBindings, *this) + , mxFTTransparency(m_xBuilder->weld_label("transparency")) + , maSoftEdgeRadiusController(SID_ATTR_SOFTEDGE_RADIUS, *pBindings, *this) + , mpBindings(pBindings) + , mxGlowRadius(m_xBuilder->weld_metric_spin_button("LB_GLOW_RADIUS", FieldUnit::POINT)) + , mxLBGlowColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_GLOW_COLOR"), + [this] { return GetFrameWeld(); })) + , mxGlowTransparency( + m_xBuilder->weld_metric_spin_button("LB_GLOW_TRANSPARENCY", FieldUnit::PERCENT)) + , mxFTColor(m_xBuilder->weld_label("glowcolorlabel")) + , mxSoftEdgeRadius(m_xBuilder->weld_metric_spin_button("SB_SOFTEDGE_RADIUS", FieldUnit::POINT)) +{ + Initialize(); +} + +EffectPropertyPanel::~EffectPropertyPanel() +{ + mxGlowRadius.reset(); + mxLBGlowColor.reset(); + mxGlowTransparency.reset(); + mxFTColor.reset(); + mxFTTransparency.reset(); + mxSoftEdgeRadius.reset(); + + maGlowColorController.dispose(); + maGlowRadiusController.dispose(); + maGlowTransparencyController.dispose(); + maSoftEdgeRadiusController.dispose(); +} + +void EffectPropertyPanel::Initialize() +{ + mxGlowRadius->connect_value_changed(LINK(this, EffectPropertyPanel, ModifyGlowRadiusHdl)); + mxLBGlowColor->SetSelectHdl(LINK(this, EffectPropertyPanel, ModifyGlowColorHdl)); + mxGlowTransparency->connect_value_changed( + LINK(this, EffectPropertyPanel, ModifyGlowTransparencyHdl)); + mxSoftEdgeRadius->connect_value_changed( + LINK(this, EffectPropertyPanel, ModifySoftEdgeRadiusHdl)); +} + +IMPL_LINK_NOARG(EffectPropertyPanel, ModifySoftEdgeRadiusHdl, weld::MetricSpinButton&, void) +{ + SdrMetricItem aItem(SDRATTR_SOFTEDGE_RADIUS, mxSoftEdgeRadius->get_value(FieldUnit::MM_100TH)); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_SOFTEDGE_RADIUS, SfxCallMode::RECORD, + { &aItem }); +} + +IMPL_LINK_NOARG(EffectPropertyPanel, ModifyGlowColorHdl, ColorListBox&, void) +{ + XColorItem aItem(SDRATTR_GLOW_COLOR, mxLBGlowColor->GetSelectEntryColor()); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_GLOW_COLOR, SfxCallMode::RECORD, { &aItem }); +} + +IMPL_LINK_NOARG(EffectPropertyPanel, ModifyGlowRadiusHdl, weld::MetricSpinButton&, void) +{ + SdrMetricItem aItem(SDRATTR_GLOW_RADIUS, mxGlowRadius->get_value(FieldUnit::MM_100TH)); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_GLOW_RADIUS, SfxCallMode::RECORD, { &aItem }); +} + +IMPL_LINK_NOARG(EffectPropertyPanel, ModifyGlowTransparencyHdl, weld::MetricSpinButton&, void) +{ + SdrPercentItem aItem(SDRATTR_GLOW_TRANSPARENCY, + mxGlowTransparency->get_value(FieldUnit::PERCENT)); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_GLOW_TRANSPARENCY, SfxCallMode::RECORD, + { &aItem }); +} + +void EffectPropertyPanel::UpdateControls() +{ + const bool bEnabled = mxGlowRadius->get_value(FieldUnit::MM_100TH) != 0; + mxLBGlowColor->set_sensitive(bEnabled); + mxGlowTransparency->set_sensitive(bEnabled); + mxFTColor->set_sensitive(bEnabled); + mxFTTransparency->set_sensitive(bEnabled); +} + +void EffectPropertyPanel::NotifyItemUpdate(sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState) +{ + switch (nSID) + { + case SID_ATTR_SOFTEDGE_RADIUS: + { + if (eState >= SfxItemState::DEFAULT) + { + const SdrMetricItem* pRadiusItem = dynamic_cast<const SdrMetricItem*>(pState); + if (pRadiusItem) + { + mxSoftEdgeRadius->set_value(pRadiusItem->GetValue(), FieldUnit::MM_100TH); + } + } + } + break; + case SID_ATTR_GLOW_COLOR: + { + if (eState >= SfxItemState::DEFAULT) + { + const XColorItem* pColorItem = dynamic_cast<const XColorItem*>(pState); + if (pColorItem) + { + mxLBGlowColor->SelectEntry(pColorItem->GetColorValue()); + } + } + } + break; + case SID_ATTR_GLOW_RADIUS: + { + if (eState >= SfxItemState::DEFAULT) + { + const SdrMetricItem* pRadiusItem = dynamic_cast<const SdrMetricItem*>(pState); + if (pRadiusItem) + { + mxGlowRadius->set_value(pRadiusItem->GetValue(), FieldUnit::MM_100TH); + } + } + } + break; + case SID_ATTR_GLOW_TRANSPARENCY: + { + if (eState >= SfxItemState::DEFAULT) + { + if (auto pItem = dynamic_cast<const SdrPercentItem*>(pState)) + { + mxGlowTransparency->set_value(pItem->GetValue(), FieldUnit::PERCENT); + } + } + } + break; + } + UpdateControls(); +} + +std::unique_ptr<PanelLayout> EffectPropertyPanel::Create(weld::Widget* pParent, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw css::lang::IllegalArgumentException( + "no parent Window given to EffectPropertyPanel::Create", nullptr, 0); + if (pBindings == nullptr) + throw css::lang::IllegalArgumentException( + "no SfxBindings given to EffectPropertyPanel::Create", nullptr, 2); + + return std::make_unique<EffectPropertyPanel>(pParent, pBindings); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/effect/EffectPropertyPanel.hxx b/svx/source/sidebar/effect/EffectPropertyPanel.hxx new file mode 100644 index 0000000000..7edc219a47 --- /dev/null +++ b/svx/source/sidebar/effect/EffectPropertyPanel.hxx @@ -0,0 +1,61 @@ +/* -*- 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/. + */ +#ifndef INCLUDED_SVX_SOURCE_SIDEBAR_EFFECT_EFFECTPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_EFFECT_EFFECTPROPERTYPANEL_HXX + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> + +class ColorListBox; + +namespace svx::sidebar +{ +class EffectPropertyPanel : public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + EffectPropertyPanel(weld::Widget* pParent, SfxBindings* pBindings); + virtual ~EffectPropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent, SfxBindings* pBindings); + + virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState(const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override{}; + +private: + sfx2::sidebar::ControllerItem maGlowColorController; + sfx2::sidebar::ControllerItem maGlowRadiusController; + sfx2::sidebar::ControllerItem maGlowTransparencyController; + std::unique_ptr<weld::Label> mxFTTransparency; + sfx2::sidebar::ControllerItem maSoftEdgeRadiusController; + + SfxBindings* mpBindings; + + std::unique_ptr<weld::MetricSpinButton> mxGlowRadius; + std::unique_ptr<ColorListBox> mxLBGlowColor; + std::unique_ptr<weld::MetricSpinButton> mxGlowTransparency; + std::unique_ptr<weld::Label> mxFTColor; + std::unique_ptr<weld::MetricSpinButton> mxSoftEdgeRadius; + + void Initialize(); + void UpdateControls(); + + DECL_LINK(ModifyGlowColorHdl, ColorListBox&, void); + DECL_LINK(ModifyGlowRadiusHdl, weld::MetricSpinButton&, void); + DECL_LINK(ModifyGlowTransparencyHdl, weld::MetricSpinButton&, void); + DECL_LINK(ModifySoftEdgeRadiusHdl, weld::MetricSpinButton&, void); +}; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/fontwork/FontworkPropertyPanel.cxx b/svx/source/sidebar/fontwork/FontworkPropertyPanel.cxx new file mode 100644 index 0000000000..972141b7b0 --- /dev/null +++ b/svx/source/sidebar/fontwork/FontworkPropertyPanel.cxx @@ -0,0 +1,59 @@ +/* -*- 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 "FontworkPropertyPanel.hxx" + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <comphelper/lok.hxx> + +using namespace css; +using namespace css::uno; + +namespace svx +{ +namespace sidebar +{ +FontworkPropertyPanel::FontworkPropertyPanel(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame) + : PanelLayout(pParent, "FontworkPropertyPanel", "svx/ui/sidebarfontwork.ui") + , m_pToolbar(m_xBuilder->weld_toolbar("fontwork-toolbox")) + , m_xToolbar(new ToolbarUnoDispatcher(*m_pToolbar, *m_xBuilder, rxFrame)) +{ + if (comphelper::LibreOfficeKit::isActive()) + m_pToolbar->set_item_visible(".uno:ExtrusionToggle", false); +} + +std::unique_ptr<PanelLayout> +FontworkPropertyPanel::Create(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException( + "no parent Window given to FontworkPropertyPanel::Create", nullptr, 0); + if (!rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to FontworkPropertyPanel::Create", + nullptr, 1); + + return std::make_unique<FontworkPropertyPanel>(pParent, rxFrame); +} +} +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/fontwork/FontworkPropertyPanel.hxx b/svx/source/sidebar/fontwork/FontworkPropertyPanel.hxx new file mode 100644 index 0000000000..cded09b951 --- /dev/null +++ b/svx/source/sidebar/fontwork/FontworkPropertyPanel.hxx @@ -0,0 +1,48 @@ +/* -*- 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_SIDEBAR_AREA_FONTWORKPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_AREA_FONTWORKPROPERTYPANEL_HXX + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/weldutils.hxx> + +namespace svx +{ +namespace sidebar +{ +class FontworkPropertyPanel : public PanelLayout +{ +public: + static std::unique_ptr<PanelLayout> + Create(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame); + + // constructor/destructor + FontworkPropertyPanel(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame); + +private: + std::unique_ptr<weld::Toolbar> m_pToolbar; + std::unique_ptr<ToolbarUnoDispatcher> m_xToolbar; +}; +} +} // end of namespace svx::sidebar + +#endif // INCLUDED_SVX_SOURCE_SIDEBAR_AREA_FONTWORKPROPERTYPANEL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/graphic/GraphicPropertyPanel.cxx b/svx/source/sidebar/graphic/GraphicPropertyPanel.cxx new file mode 100644 index 0000000000..11a3130d46 --- /dev/null +++ b/svx/source/sidebar/graphic/GraphicPropertyPanel.cxx @@ -0,0 +1,247 @@ +/* -*- 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 "GraphicPropertyPanel.hxx" +#include <svx/strings.hrc> +#include <svx/svxids.hrc> +#include <svx/dialmgr.hxx> +#include <svl/intitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <svl/itemset.hxx> + +using namespace css; +using namespace css::uno; + + +// namespace open + +namespace svx::sidebar { + + +GraphicPropertyPanel::GraphicPropertyPanel( + weld::Widget* pParent, + SfxBindings* pBindings) +: PanelLayout(pParent, "GraphicPropertyPanel", "svx/ui/sidebargraphic.ui"), + maBrightControl(SID_ATTR_GRAF_LUMINANCE, *pBindings, *this), + maContrastControl(SID_ATTR_GRAF_CONTRAST, *pBindings, *this), + maTransparenceControl(SID_ATTR_GRAF_TRANSPARENCE, *pBindings, *this), + maRedControl(SID_ATTR_GRAF_RED, *pBindings, *this), + maGreenControl(SID_ATTR_GRAF_GREEN, *pBindings, *this), + maBlueControl(SID_ATTR_GRAF_BLUE, *pBindings, *this), + maGammaControl(SID_ATTR_GRAF_GAMMA, *pBindings, *this), + maModeControl(SID_ATTR_GRAF_MODE, *pBindings, *this), + mpBindings(pBindings), + mxMtrBrightness(m_xBuilder->weld_metric_spin_button("setbrightness", FieldUnit::PERCENT)), + mxMtrContrast(m_xBuilder->weld_metric_spin_button("setcontrast", FieldUnit::PERCENT)), + mxLBColorMode(m_xBuilder->weld_combo_box("setcolormode")), + mxMtrTrans(m_xBuilder->weld_metric_spin_button("setgraphtransparency", FieldUnit::PERCENT)) +{ + mxLBColorMode->set_size_request(mxLBColorMode->get_preferred_size().Width(), -1); + Initialize(); +} + +GraphicPropertyPanel::~GraphicPropertyPanel() +{ + mxMtrBrightness.reset(); + mxMtrContrast.reset(); + mxLBColorMode.reset(); + mxMtrTrans.reset(); + + maBrightControl.dispose(); + maContrastControl.dispose(); + maTransparenceControl.dispose(); + maRedControl.dispose(); + maGreenControl.dispose(); + maBlueControl.dispose(); + maGammaControl.dispose(); + maModeControl.dispose(); +} + +void GraphicPropertyPanel::Initialize() +{ + mxMtrBrightness->connect_value_changed( LINK( this, GraphicPropertyPanel, ModifyBrightnessHdl ) ); + mxMtrContrast->connect_value_changed( LINK( this, GraphicPropertyPanel, ModifyContrastHdl ) ); + mxMtrTrans->connect_value_changed( LINK( this, GraphicPropertyPanel, ModifyTransHdl ) ); + + mxLBColorMode->append_text(SvxResId(RID_SVXSTR_GRAFMODE_STANDARD)); + mxLBColorMode->append_text(SvxResId(RID_SVXSTR_GRAFMODE_GREYS)); + mxLBColorMode->append_text(SvxResId(RID_SVXSTR_GRAFMODE_MONO)); + mxLBColorMode->append_text(SvxResId(RID_SVXSTR_GRAFMODE_WATERMARK)); + mxLBColorMode->connect_changed( LINK( this, GraphicPropertyPanel, ClickColorModeHdl )); +} + +IMPL_LINK_NOARG( GraphicPropertyPanel, ModifyBrightnessHdl, weld::MetricSpinButton&, void ) +{ + const sal_Int16 nBright = mxMtrBrightness->get_value(FieldUnit::PERCENT); + const SfxInt16Item aBrightItem( SID_ATTR_GRAF_LUMINANCE, nBright ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_GRAF_LUMINANCE, + SfxCallMode::RECORD, { &aBrightItem }); +} + + +IMPL_LINK_NOARG( GraphicPropertyPanel, ModifyContrastHdl, weld::MetricSpinButton&, void ) +{ + const sal_Int16 nContrast = mxMtrContrast->get_value(FieldUnit::PERCENT); + const SfxInt16Item aContrastItem( SID_ATTR_GRAF_CONTRAST, nContrast ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_GRAF_CONTRAST, + SfxCallMode::RECORD, { &aContrastItem }); +} + + +IMPL_LINK_NOARG( GraphicPropertyPanel, ModifyTransHdl, weld::MetricSpinButton&, void ) +{ + const sal_Int16 nTrans = mxMtrTrans->get_value(FieldUnit::PERCENT); + const SfxUInt16Item aTransItem( SID_ATTR_GRAF_TRANSPARENCE, nTrans ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_GRAF_TRANSPARENCE, + SfxCallMode::RECORD, { &aTransItem }); +} + + +IMPL_LINK_NOARG( GraphicPropertyPanel, ClickColorModeHdl, weld::ComboBox&, void ) +{ + const sal_Int16 nTrans = mxLBColorMode->get_active(); + const SfxUInt16Item aTransItem( SID_ATTR_GRAF_MODE, nTrans ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_GRAF_MODE, + SfxCallMode::RECORD, { &aTransItem }); +} + +std::unique_ptr<PanelLayout> GraphicPropertyPanel::Create ( + weld::Widget* pParent, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to GraphicPropertyPanel::Create", nullptr, 0); + if (pBindings == nullptr) + throw lang::IllegalArgumentException("no SfxBindings given to GraphicPropertyPanel::Create", nullptr, 2); + + return std::make_unique<GraphicPropertyPanel>(pParent, pBindings); +} + +void GraphicPropertyPanel::NotifyItemUpdate( + sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState) +{ + switch( nSID ) + { + case SID_ATTR_GRAF_LUMINANCE: + { + if(eState >= SfxItemState::DEFAULT) + { + mxMtrBrightness->set_sensitive(true); + const SfxInt16Item* pItem = dynamic_cast< const SfxInt16Item* >(pState); + + if(pItem) + { + const sal_Int64 nBright = pItem->GetValue(); + mxMtrBrightness->set_value(nBright, FieldUnit::PERCENT); + } + } + else if(SfxItemState::DISABLED == eState) + { + mxMtrBrightness->set_sensitive(false); + } + else + { + mxMtrBrightness->set_sensitive(true); + mxMtrBrightness->set_text(OUString()); + } + break; + } + case SID_ATTR_GRAF_CONTRAST: + { + if(eState >= SfxItemState::DEFAULT) + { + mxMtrContrast->set_sensitive(true); + const SfxInt16Item* pItem = dynamic_cast< const SfxInt16Item* >(pState); + + if(pItem) + { + const sal_Int64 nContrast = pItem->GetValue(); + mxMtrContrast->set_value(nContrast, FieldUnit::PERCENT); + } + } + else if(SfxItemState::DISABLED == eState) + { + mxMtrContrast->set_sensitive(false); + } + else + { + mxMtrContrast->set_sensitive(true); + mxMtrContrast->set_text(OUString()); + } + break; + } + case SID_ATTR_GRAF_TRANSPARENCE: + { + if(eState >= SfxItemState::DEFAULT) + { + mxMtrTrans->set_sensitive(true); + const SfxUInt16Item* pItem = dynamic_cast< const SfxUInt16Item* >(pState); + + if(pItem) + { + const sal_Int64 nTrans = pItem->GetValue(); + mxMtrTrans->set_value(nTrans, FieldUnit::PERCENT); + } + } + else if(SfxItemState::DISABLED == eState) + { + mxMtrTrans->set_sensitive(false); + } + else + { + mxMtrTrans->set_sensitive(true); + mxMtrTrans->set_text(OUString()); + } + break; + } + case SID_ATTR_GRAF_MODE: + { + if(eState >= SfxItemState::DEFAULT) + { + mxLBColorMode->set_sensitive(true); + + if(pState) + { + const sal_uInt16 nTrans = static_cast< const SfxUInt16Item* >(pState)->GetValue(); + mxLBColorMode->set_active(nTrans); + } + } + else if(SfxItemState::DISABLED == eState) + { + mxLBColorMode->set_sensitive(false); + } + else + { + mxLBColorMode->set_sensitive(true); + mxLBColorMode->set_active(-1); + } + break; + } + } +} + +// namespace close + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/graphic/GraphicPropertyPanel.hxx b/svx/source/sidebar/graphic/GraphicPropertyPanel.hxx new file mode 100644 index 0000000000..8692394293 --- /dev/null +++ b/svx/source/sidebar/graphic/GraphicPropertyPanel.hxx @@ -0,0 +1,85 @@ +/* -*- 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_SIDEBAR_GRAPHIC_GRAPHICPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_GRAPHIC_GRAPHICPROPERTYPANEL_HXX + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> +#include <vcl/weld.hxx> + +namespace svx::sidebar { + +class GraphicPropertyPanel +: public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + virtual ~GraphicPropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + SfxBindings* pBindings); + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + SfxBindings* GetBindings() { return mpBindings;} + + // constructor/destructor + GraphicPropertyPanel( + weld::Widget* pParent, + SfxBindings* pBindings); + +private: + ::sfx2::sidebar::ControllerItem maBrightControl; + ::sfx2::sidebar::ControllerItem maContrastControl; + ::sfx2::sidebar::ControllerItem maTransparenceControl; + ::sfx2::sidebar::ControllerItem maRedControl; + ::sfx2::sidebar::ControllerItem maGreenControl; + ::sfx2::sidebar::ControllerItem maBlueControl; + ::sfx2::sidebar::ControllerItem maGammaControl; + ::sfx2::sidebar::ControllerItem maModeControl; + + SfxBindings* mpBindings; + + //ui controls + std::unique_ptr<weld::MetricSpinButton> mxMtrBrightness; + std::unique_ptr<weld::MetricSpinButton> mxMtrContrast; + std::unique_ptr<weld::ComboBox> mxLBColorMode; + std::unique_ptr<weld::MetricSpinButton> mxMtrTrans; + + DECL_LINK( ModifyBrightnessHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ModifyContrastHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ModifyTransHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ClickColorModeHdl, weld::ComboBox&, void ); + + void Initialize(); +}; + +} // end of namespace svx::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/inspector/InspectorTextPanel.cxx b/svx/source/sidebar/inspector/InspectorTextPanel.cxx new file mode 100644 index 0000000000..3ddba2db9e --- /dev/null +++ b/svx/source/sidebar/inspector/InspectorTextPanel.cxx @@ -0,0 +1,166 @@ +/* -*- 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 <o3tl/safeint.hxx> +#include <sal/config.h> + +#include <svx/dialmgr.hxx> + +#include <svx/sidebar/InspectorTextPanel.hxx> + +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <inspectorvalues.hrc> + +using namespace css; + +const int MinimumPanelWidth = 250; + +namespace svx::sidebar +{ +std::unique_ptr<PanelLayout> InspectorTextPanel::Create(weld::Widget* pParent) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to InspectorTextPanel::Create", + nullptr, 0); + return std::make_unique<InspectorTextPanel>(pParent); +} + +InspectorTextPanel::InspectorTextPanel(weld::Widget* pParent) + : PanelLayout(pParent, "InspectorTextPanel", "svx/ui/inspectortextpanel.ui") + , mpListBoxStyles(m_xBuilder->weld_tree_view("listbox_fonts")) +{ + mpListBoxStyles->set_size_request(MinimumPanelWidth, -1); + float fWidth = mpListBoxStyles->get_approximate_digit_width(); + std::vector<int> aWidths{ o3tl::narrowing<int>(fWidth * 29) }; + // 2nd column will fill remaining space + mpListBoxStyles->set_column_fixed_widths(aWidths); +} + +static bool GetPropertyValues(std::u16string_view rPropName, const uno::Any& rAny, + OUString& rString) +{ + if (bool bValue; rAny >>= bValue) + { + rString = SvxResId(bValue ? RID_TRUE : RID_FALSE); // tdf#139136 + } + else if (OUString aValue; (rAny >>= aValue) && !(aValue.isEmpty())) + { + rString = aValue; + } + else if (awt::FontSlant eValue; rAny >>= eValue) + { + rString = SvxResId(eValue == awt::FontSlant_ITALIC ? RID_ITALIC : RID_NORMAL); + } + else if (tools::Long nValueLong; rAny >>= nValueLong) + { + if (rPropName.find(u"Color") != std::u16string_view::npos) + rString = "0x" + OUString::number(nValueLong, 16); + else + rString = OUString::number(nValueLong); + } + else if (double fValue; rAny >>= fValue) + { + if (rPropName.find(u"Weight") != std::u16string_view::npos) + rString = SvxResId(fValue > 100 ? RID_BOLD : RID_NORMAL); + else + rString = OUString::number((round(fValue * 100)) / 100.00); + } + else if (short nValueShort; rAny >>= nValueShort) + { + rString = OUString::number(nValueShort); + } + else + return false; + + return true; +} + +static void FillBox_Impl(weld::TreeView& rListBoxStyles, const TreeNode& rCurrent, + const weld::TreeIter* pParent) +{ + std::unique_ptr<weld::TreeIter> pResult = rListBoxStyles.make_iterator(); + const OUString& rName = rCurrent.sNodeName; + OUString sPairValue; + + if (!(rCurrent.NodeType != TreeNode::SimpleProperty + || GetPropertyValues(rName, rCurrent.aValue, sPairValue))) + return; + + rListBoxStyles.insert(pParent, -1, &rName, nullptr, nullptr, nullptr, false, pResult.get()); + rListBoxStyles.set_sensitive(*pResult, !rCurrent.isGrey, 0); + rListBoxStyles.set_text_emphasis(*pResult, rCurrent.NodeType == TreeNode::Category, 0); + + if (rCurrent.NodeType == TreeNode::SimpleProperty) + { + rListBoxStyles.set_text(*pResult, sPairValue, 1); + rListBoxStyles.set_sensitive(*pResult, !rCurrent.isGrey, 1); + rListBoxStyles.set_text_emphasis(*pResult, false, 1); + } + else + { + // Necessary, without this the selection line will be truncated. + rListBoxStyles.set_text(*pResult, "", 1); + } + + for (const TreeNode& rChildNode : rCurrent.children) + FillBox_Impl(rListBoxStyles, rChildNode, pResult.get()); +} + +void InspectorTextPanel::updateEntries(const std::vector<TreeNode>& rStore, const sal_Int32 nParIdx) +{ + mpListBoxStyles->freeze(); + mpListBoxStyles->clear(); + for (const TreeNode& rChildNode : rStore) + { + FillBox_Impl(*mpListBoxStyles, rChildNode, nullptr); + } + + mpListBoxStyles->thaw(); + + weld::TreeView* pTreeDiagram = mpListBoxStyles.get(); + pTreeDiagram->all_foreach([pTreeDiagram](weld::TreeIter& rEntry) { + pTreeDiagram->expand_row(rEntry); + return false; + }); + + // Collapse "Default Paragraph Style" + + std::unique_ptr<weld::TreeIter> pEntry = mpListBoxStyles->make_iterator(); + if (!mpListBoxStyles->get_iter_first(*pEntry)) + return; + // skip the optional metadata items before "Default Paragraph Style" + for (sal_Int32 i = 0; i < nParIdx; ++i) + { + if (!mpListBoxStyles->iter_next_sibling(*pEntry)) + return; + } + if (!mpListBoxStyles->iter_next(*pEntry)) + return; + + mpListBoxStyles->collapse_row(*pEntry); +} + +InspectorTextPanel::~InspectorTextPanel() {} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/line/LinePropertyPanel.cxx b/svx/source/sidebar/line/LinePropertyPanel.cxx new file mode 100644 index 0000000000..83a33b9228 --- /dev/null +++ b/svx/source/sidebar/line/LinePropertyPanel.cxx @@ -0,0 +1,166 @@ +/* -*- 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 "LinePropertyPanel.hxx" +#include <svx/svxids.hrc> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xlncapit.hxx> +#include <svx/xlinjoit.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <svl/itemset.hxx> + +using namespace css; +using namespace css::uno; + +namespace svx::sidebar { + +LinePropertyPanel::LinePropertyPanel( + weld::Widget* pParent, + const uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings) +: LinePropertyPanelBase(pParent, rxFrame), + maStyleControl(SID_ATTR_LINE_STYLE, *pBindings, *this), + maDashControl (SID_ATTR_LINE_DASH, *pBindings, *this), + maWidthControl(SID_ATTR_LINE_WIDTH, *pBindings, *this), + maTransControl(SID_ATTR_LINE_TRANSPARENCE, *pBindings, *this), + maEdgeStyle(SID_ATTR_LINE_JOINT, *pBindings, *this), + maCapStyle(SID_ATTR_LINE_CAP, *pBindings, *this), + mpBindings(pBindings) +{ + setMapUnit(maWidthControl.GetCoreMetric()); +} + +LinePropertyPanel::~LinePropertyPanel() +{ + maStyleControl.dispose(); + maDashControl.dispose(); + maWidthControl.dispose(); + maTransControl.dispose(); + maEdgeStyle.dispose(); + maCapStyle.dispose(); +} + +std::unique_ptr<PanelLayout> LinePropertyPanel::Create ( + weld::Widget* pParent, + const uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to LinePropertyPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to LinePropertyPanel::Create", nullptr, 1); + if (pBindings == nullptr) + throw lang::IllegalArgumentException("no SfxBindings given to LinePropertyPanel::Create", nullptr, 2); + + return std::make_unique<LinePropertyPanel>(pParent, rxFrame, pBindings); +} + +void LinePropertyPanel::NotifyItemUpdate( + sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState) +{ + const bool bDisabled(SfxItemState::DISABLED == eState); + const bool bSetOrDefault = eState >= SfxItemState::DEFAULT; + + switch(nSID) + { + case SID_ATTR_LINE_TRANSPARENCE: + { + updateLineTransparence(bDisabled, bSetOrDefault, pState); + break; + } + case SID_ATTR_LINE_WIDTH: + { + updateLineWidth(bDisabled, bSetOrDefault, pState); + break; + } + case SID_ATTR_LINE_JOINT: + { + updateLineJoint(bDisabled, bSetOrDefault, pState); + break; + } + case SID_ATTR_LINE_CAP: + { + updateLineCap(bDisabled, bSetOrDefault, pState); + break; + } + } + ActivateControls(); +} + +void LinePropertyPanel::HandleContextChange( + const vcl::EnumContext& rContext) +{ + if(maContext == rContext) + { + // Nothing to do + return; + } + + maContext = rContext; + bool bShowArrows = false; + + switch(maContext.GetCombinedContext_DI()) + { + case CombinedEnumContext(Application::Calc, Context::DrawLine): + case CombinedEnumContext(Application::DrawImpress, Context::DrawLine): + case CombinedEnumContext(Application::DrawImpress, Context::Draw): + case CombinedEnumContext(Application::WriterVariants, Context::Draw): + // TODO : Implement DrawLine context in Writer + bShowArrows = true; + break; + } + + if (!bShowArrows) + disableArrowHead(); + else + enableArrowHead(); +} + +void LinePropertyPanel::setLineJoint(const XLineJointItem* pItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_LINE_JOINT, + SfxCallMode::RECORD, { pItem }); +} + +void LinePropertyPanel::setLineCap(const XLineCapItem* pItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_LINE_CAP, + SfxCallMode::RECORD, { pItem }); +} + +void LinePropertyPanel::setLineTransparency(const XLineTransparenceItem& rItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_LINE_STYLE, + SfxCallMode::RECORD, { &rItem }); +} + +void LinePropertyPanel::setLineWidth(const XLineWidthItem& rItem) +{ + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_LINE_WIDTH, + SfxCallMode::RECORD, { &rItem }); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/line/LinePropertyPanel.hxx b/svx/source/sidebar/line/LinePropertyPanel.hxx new file mode 100644 index 0000000000..7223cd9f1f --- /dev/null +++ b/svx/source/sidebar/line/LinePropertyPanel.hxx @@ -0,0 +1,96 @@ +/* -*- 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_SIDEBAR_LINE_LINEPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_LINE_LINEPROPERTYPANEL_HXX + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/IContextChangeReceiver.hxx> +#include <svx/sidebar/LinePropertyPanelBase.hxx> +#include <vcl/EnumContext.hxx> + +class XLineStyleItem; +class XLineDashItem; +class XLineStartItem; +class XLineEndItem; +class XLineEndList; +class XDashList; +class ListBox; +class ToolBox; + +namespace svx::sidebar +{ + +class LinePropertyPanel : public LinePropertyPanelBase, + public sfx2::sidebar::IContextChangeReceiver, + public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + virtual ~LinePropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings); + + virtual void HandleContextChange( + const vcl::EnumContext& rContext) override; + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + SfxBindings* GetBindings() { return mpBindings;} + + // constructor/destructor + LinePropertyPanel( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings); + + virtual void setLineWidth(const XLineWidthItem& rItem) override; + +protected: + + virtual void setLineTransparency(const XLineTransparenceItem& rItem) override; + virtual void setLineJoint(const XLineJointItem* pItem) override; + virtual void setLineCap(const XLineCapItem* pItem) override; + +private: + //ControllerItem + sfx2::sidebar::ControllerItem maStyleControl; + sfx2::sidebar::ControllerItem maDashControl; + sfx2::sidebar::ControllerItem maWidthControl; + sfx2::sidebar::ControllerItem maTransControl; + sfx2::sidebar::ControllerItem maEdgeStyle; + sfx2::sidebar::ControllerItem maCapStyle; + + SfxBindings* mpBindings; + vcl::EnumContext maContext; +}; + +} // end of namespace svx::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/line/LinePropertyPanelBase.cxx b/svx/source/sidebar/line/LinePropertyPanelBase.cxx new file mode 100644 index 0000000000..18fabcbcd9 --- /dev/null +++ b/svx/source/sidebar/line/LinePropertyPanelBase.cxx @@ -0,0 +1,468 @@ +/* -*- 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 <memory> +#include <svx/sidebar/LinePropertyPanelBase.hxx> +#include <sfx2/weldutils.hxx> +#include <svx/linectrl.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xlncapit.hxx> +#include <svx/xlinjoit.hxx> +#include <svx/xtable.hxx> +#include <bitmaps.hlst> + +using namespace css; +using namespace css::uno; + +constexpr OUString SELECTWIDTH = u"SelectWidth"_ustr; + +namespace svx::sidebar { + +// trigger disabling the arrows if the none line style is selected +class LineStyleNoneChange +{ +private: + LinePropertyPanelBase& m_rPanel; + +public: + LineStyleNoneChange(LinePropertyPanelBase& rPanel) + : m_rPanel(rPanel) + { + } + + void operator()(bool bLineStyleNone) + { + m_rPanel.SetNoneLineStyle(bLineStyleNone); + } +}; + +namespace +{ + SvxLineStyleToolBoxControl* getLineStyleToolBoxControl(const ToolbarUnoDispatcher& rToolBoxColor) + { + css::uno::Reference<css::frame::XToolbarController> xController = rToolBoxColor.GetControllerForCommand(".uno:XLineStyle"); + SvxLineStyleToolBoxControl* pToolBoxLineStyleControl = dynamic_cast<SvxLineStyleToolBoxControl*>(xController.get()); + return pToolBoxLineStyleControl; + } +} + + +LinePropertyPanelBase::LinePropertyPanelBase( + weld::Widget* pParent, + const uno::Reference<css::frame::XFrame>& rxFrame) +: PanelLayout(pParent, "LinePropertyPanel", "svx/ui/sidebarline.ui"), + mxTBColor(m_xBuilder->weld_toolbar("color")), + mxColorDispatch(new ToolbarUnoDispatcher(*mxTBColor, *m_xBuilder, rxFrame)), + mxLineStyleTB(m_xBuilder->weld_toolbar("linestyle")), + mxLineStyleDispatch(new ToolbarUnoDispatcher(*mxLineStyleTB, *m_xBuilder, rxFrame)), + mnWidthCoreValue(0), + mxFTWidth(m_xBuilder->weld_label("widthlabel")), + mxTBWidth(m_xBuilder->weld_toolbar("width")), + mxFTTransparency(m_xBuilder->weld_label("translabel")), + mxMFTransparent(m_xBuilder->weld_metric_spin_button("linetransparency", FieldUnit::PERCENT)), + mxFTEdgeStyle(m_xBuilder->weld_label("cornerlabel")), + mxLBEdgeStyle(m_xBuilder->weld_combo_box("edgestyle")), + mxFTCapStyle(m_xBuilder->weld_label("caplabel")), + mxLBCapStyle(m_xBuilder->weld_combo_box("linecapstyle")), + mxGridLineProps(m_xBuilder->weld_widget("lineproperties")), + mxBoxArrowProps(m_xBuilder->weld_widget("arrowproperties")), + mxLineWidthPopup(new LineWidthPopup(mxTBWidth.get(), *this)), + mxLineStyleNoneChange(new LineStyleNoneChange(*this)), + mnTrans(0), + meMapUnit(MapUnit::MapMM), + maIMGNone(BMP_NONE_ICON), + mbWidthValuable(true), + mbArrowSupported(true), + mbNoneLineStyle(false) +{ + Initialize(); +} + +LinePropertyPanelBase::~LinePropertyPanelBase() +{ + mxLineWidthPopup.reset(); + mxFTWidth.reset(); + mxTBWidth.reset(); + mxColorDispatch.reset(); + mxTBColor.reset(); + mxFTTransparency.reset(); + mxMFTransparent.reset(); + mxLineStyleDispatch.reset(); + mxLineStyleTB.reset(); + mxFTEdgeStyle.reset(); + mxLBEdgeStyle.reset(); + mxFTCapStyle.reset(); + mxLBCapStyle.reset(); + mxGridLineProps.reset(); + mxBoxArrowProps.reset(); +} + +void LinePropertyPanelBase::Initialize() +{ + mxTBWidth->set_item_popover(SELECTWIDTH, mxLineWidthPopup->getTopLevel()); + + maIMGWidthIcon[0] = XDashList::CreateBitmapForXDash(nullptr, 1); + maIMGWidthIcon[1] = XDashList::CreateBitmapForXDash(nullptr, 2); + maIMGWidthIcon[2] = XDashList::CreateBitmapForXDash(nullptr, 3); + maIMGWidthIcon[3] = XDashList::CreateBitmapForXDash(nullptr, 4); + maIMGWidthIcon[4] = XDashList::CreateBitmapForXDash(nullptr, 5); + maIMGWidthIcon[5] = XDashList::CreateBitmapForXDash(nullptr, 6); + maIMGWidthIcon[6] = XDashList::CreateBitmapForXDash(nullptr, 7); + maIMGWidthIcon[7] = XDashList::CreateBitmapForXDash(nullptr, 8); + + Graphic aGraf(maIMGWidthIcon[0]); + mxTBWidth->set_item_image(SELECTWIDTH, aGraf.GetXGraphic()); + mxTBWidth->connect_clicked(LINK(this, LinePropertyPanelBase, ToolboxWidthSelectHdl)); + + mxMFTransparent->connect_value_changed(LINK(this, LinePropertyPanelBase, ChangeTransparentHdl)); + + mxLBEdgeStyle->connect_changed( LINK( this, LinePropertyPanelBase, ChangeEdgeStyleHdl ) ); + + mxLBCapStyle->connect_changed( LINK( this, LinePropertyPanelBase, ChangeCapStyleHdl ) ); + + SvxLineStyleToolBoxControl* pLineStyleControl = getLineStyleToolBoxControl(*mxLineStyleDispatch); + pLineStyleControl->setLineStyleIsNoneFunction(*mxLineStyleNoneChange); +} + +void LinePropertyPanelBase::updateLineTransparence(bool bDisabled, bool bSetOrDefault, + const SfxPoolItem* pState) +{ + if(bDisabled) + { + mxFTTransparency->set_sensitive(false); + mxMFTransparent->set_sensitive(false); + } + else + { + mxFTTransparency->set_sensitive(true); + mxMFTransparent->set_sensitive(true); + } + + if(bSetOrDefault) + { + if (const XLineTransparenceItem* pItem = dynamic_cast<const XLineTransparenceItem*>(pState)) + { + mnTrans = pItem->GetValue(); + mxMFTransparent->set_value(mnTrans, FieldUnit::PERCENT); + return; + } + } + + mxMFTransparent->set_value(0, FieldUnit::PERCENT);//add + mxMFTransparent->set_text(OUString()); +} + +void LinePropertyPanelBase::updateLineWidth(bool bDisabled, bool bSetOrDefault, + const SfxPoolItem* pState) +{ + if(bDisabled) + { + mxTBWidth->set_sensitive(false); + mxFTWidth->set_sensitive(false); + } + else + { + mxTBWidth->set_sensitive(true); + mxFTWidth->set_sensitive(true); + } + + if(bSetOrDefault) + { + if (const XLineWidthItem* pItem = dynamic_cast<const XLineWidthItem*>(pState)) + { + mnWidthCoreValue = pItem->GetValue(); + mbWidthValuable = true; + SetWidthIcon(); + return; + } + } + + mbWidthValuable = false; + SetWidthIcon(); +} + +void LinePropertyPanelBase::updateLineJoint(bool bDisabled, bool bSetOrDefault, + const SfxPoolItem* pState) +{ + if(bDisabled) + { + mxLBEdgeStyle->set_sensitive(false); + mxFTEdgeStyle->set_sensitive(false); + } + else + { + mxLBEdgeStyle->set_sensitive(true); + mxFTEdgeStyle->set_sensitive(true); + } + + if(bSetOrDefault) + { + if (const XLineJointItem* pItem = dynamic_cast<const XLineJointItem*>(pState)) + { + sal_Int32 nEntryPos(0); + + switch(pItem->GetValue()) + { + case drawing::LineJoint_ROUND: + { + nEntryPos = 1; + break; + } + case drawing::LineJoint_NONE: + { + nEntryPos = 2; + break; + } + case drawing::LineJoint_MIDDLE: + case drawing::LineJoint_MITER: + { + nEntryPos = 3; + break; + } + case drawing::LineJoint_BEVEL: + { + nEntryPos = 4; + break; + } + + default: + break; + } + + if(nEntryPos) + { + mxLBEdgeStyle->set_active(nEntryPos - 1); + return; + } + } + } + + mxLBEdgeStyle->set_active(-1); +} + +void LinePropertyPanelBase::updateLineCap(bool bDisabled, bool bSetOrDefault, + const SfxPoolItem* pState) +{ + mxLBCapStyle->set_sensitive(!bDisabled); + mxFTCapStyle->set_sensitive(!bDisabled); + + if(bSetOrDefault) + { + if (const XLineCapItem* pItem = dynamic_cast<const XLineCapItem*>(pState)) + { + sal_Int32 nEntryPos(0); + + switch(pItem->GetValue()) + { + case drawing::LineCap_BUTT: + { + nEntryPos = 1; + break; + } + case drawing::LineCap_ROUND: + { + nEntryPos = 2; + break; + } + case drawing::LineCap_SQUARE: + { + nEntryPos = 3; + break; + } + + default: + break; + } + + if(nEntryPos) + { + mxLBCapStyle->set_active(nEntryPos - 1); + return; + } + } + } + + mxLBCapStyle->set_active(-1); +} + +IMPL_LINK_NOARG(LinePropertyPanelBase, ChangeEdgeStyleHdl, weld::ComboBox&, void) +{ + const sal_Int32 nPos(mxLBEdgeStyle->get_active()); + + if (nPos == -1 || !mxLBEdgeStyle->get_value_changed_from_saved()) + return; + + std::unique_ptr<XLineJointItem> pItem; + + switch(nPos) + { + case 0: // rounded + { + pItem.reset(new XLineJointItem(drawing::LineJoint_ROUND)); + break; + } + case 1: // none + { + pItem.reset(new XLineJointItem(drawing::LineJoint_NONE)); + break; + } + case 2: // mitered + { + pItem.reset(new XLineJointItem(drawing::LineJoint_MITER)); + break; + } + case 3: // beveled + { + pItem.reset(new XLineJointItem(drawing::LineJoint_BEVEL)); + break; + } + } + + setLineJoint(pItem.get()); +} + +IMPL_LINK_NOARG(LinePropertyPanelBase, ChangeCapStyleHdl, weld::ComboBox&, void) +{ + const sal_Int32 nPos(mxLBCapStyle->get_active()); + + if (!(nPos != -1 && mxLBCapStyle->get_value_changed_from_saved())) + return; + + std::unique_ptr<XLineCapItem> pItem; + + switch(nPos) + { + case 0: // flat + { + pItem.reset(new XLineCapItem(drawing::LineCap_BUTT)); + break; + } + case 1: // round + { + pItem.reset(new XLineCapItem(drawing::LineCap_ROUND)); + break; + } + case 2: // square + { + pItem.reset(new XLineCapItem(drawing::LineCap_SQUARE)); + break; + } + } + + setLineCap(pItem.get()); +} + +IMPL_LINK_NOARG(LinePropertyPanelBase, ToolboxWidthSelectHdl, const OUString&, void) +{ + mxTBWidth->set_menu_item_active(SELECTWIDTH, !mxTBWidth->get_menu_item_active(SELECTWIDTH)); +} + +void LinePropertyPanelBase::EndLineWidthPopup() +{ + mxTBWidth->set_menu_item_active(SELECTWIDTH, false); +} + +IMPL_LINK_NOARG( LinePropertyPanelBase, ChangeTransparentHdl, weld::MetricSpinButton&, void ) +{ + sal_uInt16 nVal = static_cast<sal_uInt16>(mxMFTransparent->get_value(FieldUnit::PERCENT)); + XLineTransparenceItem aItem( nVal ); + + setLineTransparency(aItem); +} + +void LinePropertyPanelBase::SetWidthIcon(int n) +{ + if (n == 0) + mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGNone); + else + { + Graphic aGraf(maIMGWidthIcon[n-1]); + mxTBWidth->set_item_image(SELECTWIDTH, aGraf.GetXGraphic()); + } +} + +void LinePropertyPanelBase::SetWidthIcon() +{ + if(!mbWidthValuable) + { + mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGNone); + return; + } + + tools::Long nVal = OutputDevice::LogicToLogic(mnWidthCoreValue * 10, meMapUnit, MapUnit::MapPoint); + + Graphic aGraf; + if(nVal <= 6) + aGraf = Graphic(maIMGWidthIcon[0]); + else if (nVal <= 9) + aGraf = Graphic(maIMGWidthIcon[1]); + else if (nVal <= 12) + aGraf = Graphic(maIMGWidthIcon[2]); + else if (nVal <= 19) + aGraf = Graphic(maIMGWidthIcon[3]); + else if (nVal <= 26) + aGraf = Graphic(maIMGWidthIcon[4]); + else if (nVal <= 37) + aGraf = Graphic(maIMGWidthIcon[5]); + else if (nVal <= 52) + aGraf = Graphic(maIMGWidthIcon[6]); + else + aGraf = Graphic(maIMGWidthIcon[7]); + mxTBWidth->set_item_image(SELECTWIDTH, aGraf.GetXGraphic()); +} + +void LinePropertyPanelBase::SetWidth(tools::Long nWidth) +{ + mnWidthCoreValue = nWidth; + mbWidthValuable = true; + mxLineWidthPopup->SetWidthSelect(mnWidthCoreValue, mbWidthValuable, meMapUnit); +} + +void LinePropertyPanelBase::ActivateControls() +{ + mxGridLineProps->set_sensitive(!mbNoneLineStyle); + mxBoxArrowProps->set_sensitive(!mbNoneLineStyle); + mxLineStyleTB->set_item_sensitive(".uno:LineEndStyle", !mbNoneLineStyle); + + mxBoxArrowProps->set_visible(mbArrowSupported); + mxLineStyleTB->set_item_visible(".uno:LineEndStyle", mbArrowSupported); +} + +void LinePropertyPanelBase::setMapUnit(MapUnit eMapUnit) +{ + meMapUnit = eMapUnit; + mxLineWidthPopup->SetWidthSelect(mnWidthCoreValue, mbWidthValuable, meMapUnit); +} + +void LinePropertyPanelBase::disableArrowHead() +{ + mbArrowSupported = false; + ActivateControls(); +} + +void LinePropertyPanelBase::enableArrowHead() +{ + mbArrowSupported = true; + ActivateControls(); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/line/LineWidthPopup.cxx b/svx/source/sidebar/line/LineWidthPopup.cxx new file mode 100644 index 0000000000..347bb2a3bb --- /dev/null +++ b/svx/source/sidebar/line/LineWidthPopup.cxx @@ -0,0 +1,223 @@ +/* -*- 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/sidebar/LineWidthPopup.hxx> +#include <svx/sidebar/LinePropertyPanelBase.hxx> +#include <com/sun/star/beans/NamedValue.hpp> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <svx/xlnwtit.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/viewoptions.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include "LineWidthValueSet.hxx" +#include <bitmaps.hlst> + +namespace svx::sidebar +{ +LineWidthPopup::LineWidthPopup(weld::Widget* pParent, LinePropertyPanelBase& rParent) + : WeldToolbarPopup(nullptr, pParent, "svx/ui/floatinglineproperty.ui", "FloatingLineProperty") + , m_rParent(rParent) + , m_sPt(SvxResId(RID_SVXSTR_PT)) + , m_eMapUnit(MapUnit::MapTwip) + , m_bVSFocus(true) + , m_bCustom(false) + , m_nCustomWidth(0) + , m_aIMGCus(StockImage::Yes, RID_SVXBMP_WIDTH_CUSTOM) + , m_aIMGCusGray(StockImage::Yes, RID_SVXBMP_WIDTH_CUSTOM_GRAY) + , m_xMFWidth(m_xBuilder->weld_metric_spin_button("spin", FieldUnit::POINT)) + , m_xVSWidth(new LineWidthValueSet()) + , m_xVSWidthWin(new weld::CustomWeld(*m_xBuilder, "lineset", *m_xVSWidth)) +{ + m_xVSWidth->SetStyle(m_xVSWidth->GetStyle() | WB_3DLOOK | WB_NO_DIRECTSELECT); + + maStrUnits[0] = "0.5"; + maStrUnits[1] = "0.8"; + maStrUnits[2] = "1.0"; + maStrUnits[3] = "1.5"; + maStrUnits[4] = "2.3"; + maStrUnits[5] = "3.0"; + maStrUnits[6] = "4.5"; + maStrUnits[7] = "6.0"; + maStrUnits[8] = SvxResId(RID_SVXSTR_WIDTH_LAST_CUSTOM); + + const LocaleDataWrapper& rLocaleWrapper(Application::GetSettings().GetLocaleDataWrapper()); + const sal_Unicode cSep = rLocaleWrapper.getNumDecimalSep()[0]; + + for (int i = 0; i <= 7; i++) + { + maStrUnits[i] = maStrUnits[i].replace('.', cSep); //Modify + maStrUnits[i] += " "; + maStrUnits[i] += m_sPt; + } + + for (sal_uInt16 i = 1; i <= 9; ++i) + { + m_xVSWidth->InsertItem(i); + m_xVSWidth->SetItemText(i, maStrUnits[i - 1]); + } + + m_xVSWidth->SetUnit(maStrUnits); + m_xVSWidth->SetItemData(1, reinterpret_cast<void*>(5)); + m_xVSWidth->SetItemData(2, reinterpret_cast<void*>(8)); + m_xVSWidth->SetItemData(3, reinterpret_cast<void*>(10)); + m_xVSWidth->SetItemData(4, reinterpret_cast<void*>(15)); + m_xVSWidth->SetItemData(5, reinterpret_cast<void*>(23)); + m_xVSWidth->SetItemData(6, reinterpret_cast<void*>(30)); + m_xVSWidth->SetItemData(7, reinterpret_cast<void*>(45)); + m_xVSWidth->SetItemData(8, reinterpret_cast<void*>(60)); + m_xVSWidth->SetImage(m_aIMGCusGray); + + m_xVSWidth->SetSelItem(0); + + m_xVSWidth->SetSelectHdl(LINK(this, LineWidthPopup, VSSelectHdl)); + m_xMFWidth->connect_value_changed(LINK(this, LineWidthPopup, MFModifyHdl)); +} + +LineWidthPopup::~LineWidthPopup() {} + +IMPL_LINK_NOARG(LineWidthPopup, VSSelectHdl, ValueSet*, void) +{ + sal_uInt16 iPos = m_xVSWidth->GetSelectedItemId(); + if (iPos >= 1 && iPos <= 8) + { + sal_IntPtr nVal = OutputDevice::LogicToLogic( + reinterpret_cast<sal_IntPtr>(m_xVSWidth->GetItemData(iPos)), MapUnit::MapPoint, + m_eMapUnit); + nVal = m_xMFWidth->denormalize(nVal); + XLineWidthItem aWidthItem(nVal); + m_rParent.setLineWidth(aWidthItem); + m_rParent.SetWidthIcon(iPos); + m_rParent.SetWidth(nVal); + } + else if (iPos == 9) + { //last custom + //modified + if (m_bCustom) + { + tools::Long nVal + = OutputDevice::LogicToLogic(m_nCustomWidth, MapUnit::MapPoint, m_eMapUnit); + nVal = m_xMFWidth->denormalize(nVal); + XLineWidthItem aWidthItem(nVal); + m_rParent.setLineWidth(aWidthItem); + m_rParent.SetWidth(nVal); + } + else + { + m_xVSWidth->SetNoSelection(); //add , set no selection and keep the last select item + m_xVSWidth->SetFormat(); + m_xVSWidth->Invalidate(); + } + //modify end + } + + if ((iPos >= 1 && iPos <= 8) || (iPos == 9 && m_bCustom)) //add + { + m_rParent.EndLineWidthPopup(); + } +} + +IMPL_LINK_NOARG(LineWidthPopup, MFModifyHdl, weld::MetricSpinButton&, void) +{ + if (m_xVSWidth->GetSelItem()) + { + m_xVSWidth->SetSelItem(0); + m_xVSWidth->SetFormat(); + m_xVSWidth->Invalidate(); + } + tools::Long nTmp = static_cast<tools::Long>(m_xMFWidth->get_value(FieldUnit::NONE)); + tools::Long nVal = OutputDevice::LogicToLogic(nTmp, MapUnit::MapPoint, m_eMapUnit); + sal_Int32 nNewWidth = static_cast<short>(m_xMFWidth->denormalize(nVal)); + XLineWidthItem aWidthItem(nNewWidth); + m_rParent.setLineWidth(aWidthItem); +} + +void LineWidthPopup::SetWidthSelect(tools::Long lValue, bool bValuable, MapUnit eMapUnit) +{ + m_bVSFocus = true; + m_xVSWidth->SetSelItem(0); + m_eMapUnit = eMapUnit; + SvtViewOptions aWinOpt(EViewType::Window, "PopupPanel_LineWidth"); + if (aWinOpt.Exists()) + { + css::uno::Sequence<css::beans::NamedValue> aSeq = aWinOpt.GetUserData(); + OUString aTmp; + if (aSeq.hasElements()) + aSeq[0].Value >>= aTmp; + + OUString aWinData(aTmp); + m_nCustomWidth = aWinData.toInt32(); + m_bCustom = true; + m_xVSWidth->SetImage(m_aIMGCus); + m_xVSWidth->SetCusEnable(true); + + OUString aStrTip = OUString::number(static_cast<double>(m_nCustomWidth) / 10) + m_sPt; + m_xVSWidth->SetItemText(9, aStrTip); + } + else + { + m_bCustom = false; + m_xVSWidth->SetImage(m_aIMGCusGray); + m_xVSWidth->SetCusEnable(false); + m_xVSWidth->SetItemText(9, maStrUnits[8]); + } + + if (bValuable) + { + sal_Int64 nVal = OutputDevice::LogicToLogic(lValue, eMapUnit, MapUnit::Map100thMM); + nVal = m_xMFWidth->normalize(nVal); + m_xMFWidth->set_value(nVal, FieldUnit::MM_100TH); + } + else + { + m_xMFWidth->set_text(""); + } + + OUString strCurrValue = m_xMFWidth->get_text(); + sal_uInt16 i = 0; + for (; i < 8; i++) + { + if (strCurrValue == maStrUnits[i]) + { + m_xVSWidth->SetSelItem(i + 1); + break; + } + } + + if (i >= 8) + { + m_bVSFocus = false; + m_xVSWidth->SetSelItem(0); + } + + m_xVSWidth->SetFormat(); + m_xVSWidth->Invalidate(); +} + +void LineWidthPopup::GrabFocus() +{ + if (m_bVSFocus) + m_xVSWidth->GrabFocus(); + else + m_xMFWidth->grab_focus(); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/line/LineWidthValueSet.cxx b/svx/source/sidebar/line/LineWidthValueSet.cxx new file mode 100644 index 0000000000..be518fe4fa --- /dev/null +++ b/svx/source/sidebar/line/LineWidthValueSet.cxx @@ -0,0 +1,172 @@ +/* -*- 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 "LineWidthValueSet.hxx" + +#include <i18nlangtag/mslangid.hxx> +#include <vcl/event.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +namespace svx::sidebar { + +LineWidthValueSet::LineWidthValueSet() + : ValueSet(nullptr) + , nSelItem(0) + , bCusEnable(false) +{ +} + +void LineWidthValueSet::Resize() +{ + SetColCount(); + SetLineCount(9); + ValueSet::Resize(); +} + +LineWidthValueSet::~LineWidthValueSet() +{ +} + +void LineWidthValueSet::SetUnit(std::array<OUString,9> const & strUnits) +{ + maStrUnits = strUnits; +} + +void LineWidthValueSet::SetSelItem(sal_uInt16 nSel) +{ + nSelItem = nSel; + if(nSel == 0) + { + SelectItem(1); // ,false); // 'false' nut supported by AOO + SetNoSelection(); + } + else + { + SelectItem(nSelItem); + GrabFocus(); + } +} + +void LineWidthValueSet::SetImage(const Image& img) +{ + imgCus = img; +} + +void LineWidthValueSet::SetCusEnable(bool bEnable) +{ + bCusEnable = bEnable; +} + +void LineWidthValueSet::UserDraw( const UserDrawEvent& rUDEvt ) +{ + tools::Rectangle aRect = rUDEvt.GetRect(); + vcl::RenderContext* pDev = rUDEvt.GetRenderContext(); + sal_uInt16 nItemId = rUDEvt.GetItemId(); + + tools::Long nRectHeight = aRect.GetHeight(); + tools::Long nRectWidth = aRect.GetWidth(); + Point aBLPos = aRect.TopLeft(); + + //const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + //Color aBackColor(0,0,200); + //const Color aTextColor = rStyleSettings.GetFieldTextColor(); + vcl::Font aOldFont = pDev->GetFont(); + Color aOldColor = pDev->GetLineColor(); + Color aOldFillColor = pDev->GetFillColor(); + + vcl::Font aFont(OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS, MsLangId::getConfiguredSystemLanguage(), GetDefaultFontFlags::OnlyOne)); + Size aSize = aFont.GetFontSize(); + aSize.setHeight( nRectHeight*3/5 ); + aFont.SetFontSize( aSize ); + + Point aLineStart(aBLPos.X() + 5, aBLPos.Y() + ( nRectHeight - nItemId )/2); + Point aLineEnd(aBLPos.X() + nRectWidth * 7 / 9 - 10, aBLPos.Y() + ( nRectHeight - nItemId )/2); + if (nItemId == 9) + { + Point aImgStart(aBLPos.X() + 5, aBLPos.Y() + ( nRectHeight - 23 ) / 2); + pDev->DrawImage(aImgStart, imgCus); + + tools::Rectangle aStrRect = aRect; + aStrRect.AdjustTop(nRectHeight/6 ); + aStrRect.AdjustBottom( -(nRectHeight/6) ); + aStrRect.AdjustLeft(imgCus.GetSizePixel().Width() + 20 ); + if(bCusEnable) + aFont.SetColor(Application::GetSettings().GetStyleSettings().GetFieldTextColor()); + else + aFont.SetColor(Application::GetSettings().GetStyleSettings().GetDisableColor()); + + pDev->SetFont(aFont); + pDev->DrawText(aStrRect, maStrUnits[ nItemId - 1 ], DrawTextFlags::EndEllipsis); + } + else + { + if( nSelItem == nItemId ) + { + tools::Rectangle aBackRect = aRect; + aBackRect.AdjustTop(3 ); + aBackRect.AdjustBottom( -2 ); + pDev->SetFillColor(Color(50,107,197)); + pDev->DrawRect(aBackRect); + } + else + { + pDev->SetFillColor( COL_TRANSPARENT ); + pDev->DrawRect(aRect); + } + + //draw text + if(nSelItem == nItemId ) + aFont.SetColor(COL_WHITE); + else + aFont.SetColor(Application::GetSettings().GetStyleSettings().GetFieldTextColor()); + pDev->SetFont(aFont); + Point aStart(aBLPos.X() + nRectWidth * 7 / 9 , aBLPos.Y() + nRectHeight/6); + pDev->DrawText(aStart, maStrUnits[ nItemId - 1 ]); //can't set DrawTextFlags::EndEllipsis here ,or the text will disappear + + //draw line + if( nSelItem == nItemId ) + pDev->SetLineColor(COL_WHITE); + else + pDev->SetLineColor(Application::GetSettings().GetStyleSettings().GetFieldTextColor()); + + for(sal_uInt16 i = 1; i <= nItemId; i++) + { + pDev->DrawLine(aLineStart,aLineEnd ); + aLineStart.setY(aLineStart.getY() + 1); + aLineEnd.setY (aLineEnd.getY() + 1); + } + } + + Invalidate( aRect ); + pDev->SetLineColor(aOldColor); + pDev->SetFillColor(aOldFillColor); + pDev->SetFont(aOldFont); +} + +void LineWidthValueSet::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + ValueSet::SetDrawingArea(pDrawingArea); + Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(80, 12 * 9), MapMode(MapUnit::MapAppFont))); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + SetOutputSizePixel(aSize); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/line/LineWidthValueSet.hxx b/svx/source/sidebar/line/LineWidthValueSet.hxx new file mode 100644 index 0000000000..225e706a6d --- /dev/null +++ b/svx/source/sidebar/line/LineWidthValueSet.hxx @@ -0,0 +1,55 @@ +/* -*- 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_SIDEBAR_LINE_LINEWIDTHVALUESET_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_LINE_LINEWIDTHVALUESET_HXX + +#include <svtools/valueset.hxx> +#include <vcl/image.hxx> +#include <array> + +namespace svx::sidebar { + +class LineWidthValueSet final : public ValueSet +{ +public: + explicit LineWidthValueSet(); + virtual ~LineWidthValueSet() override; + + void SetUnit(std::array<OUString,9> const & strUnits); + void SetSelItem(sal_uInt16 nSel); + sal_uInt16 GetSelItem() const { return nSelItem;} + void SetImage(const Image& img); + void SetCusEnable(bool bEnable); + + virtual void UserDraw( const UserDrawEvent& rUDEvt ) override; + virtual void Resize() override; + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + +private: + sal_uInt16 nSelItem; + std::array<OUString,9> maStrUnits; + Image imgCus; + bool bCusEnable; +}; + +} // end of namespace svx::sidebar + +#endif // INCLUDED_SVX_SOURCE_SIDEBAR_LINE_LINEWIDTHVALUESET_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/lists/ListsPropertyPanel.cxx b/svx/source/sidebar/lists/ListsPropertyPanel.cxx new file mode 100644 index 0000000000..58badf6796 --- /dev/null +++ b/svx/source/sidebar/lists/ListsPropertyPanel.cxx @@ -0,0 +1,61 @@ +/* -*- 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 "ListsPropertyPanel.hxx" +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +using namespace css; +using namespace css::uno; + +namespace svx::sidebar +{ +std::unique_ptr<PanelLayout> +ListsPropertyPanel::Create(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to ListsPropertyPanel::Create", + nullptr, 0); + if (!rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to ListsPropertyPanel::Create", + nullptr, 1); + + return std::make_unique<ListsPropertyPanel>(pParent, rxFrame); +} + +ListsPropertyPanel::ListsPropertyPanel(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame) + : PanelLayout(pParent, "ListsPropertyPanel", "svx/ui/sidebarlists.ui") + , mxTBxNumBullet(m_xBuilder->weld_toolbar("numberbullet")) + , mxNumBulletDispatcher(new ToolbarUnoDispatcher(*mxTBxNumBullet, *m_xBuilder, rxFrame)) + , mxTBxOutline(m_xBuilder->weld_toolbar("outline")) + , mxOutlineDispatcher(new ToolbarUnoDispatcher(*mxTBxOutline, *m_xBuilder, rxFrame)) +{ +} + +ListsPropertyPanel::~ListsPropertyPanel() +{ + mxOutlineDispatcher.reset(); + mxTBxOutline.reset(); + mxNumBulletDispatcher.reset(); + mxTBxNumBullet.reset(); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/lists/ListsPropertyPanel.hxx b/svx/source/sidebar/lists/ListsPropertyPanel.hxx new file mode 100644 index 0000000000..ec20bb4308 --- /dev/null +++ b/svx/source/sidebar/lists/ListsPropertyPanel.hxx @@ -0,0 +1,50 @@ +/* -*- 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_SIDEBAR_LISTS_LISTSPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_LISTS_LISTSPROPERTYPANEL_HXX + +#include <sfx2/weldutils.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> +#include <com/sun/star/frame/XFrame.hpp> + +namespace svx::sidebar +{ +class ListsPropertyPanel : public PanelLayout +{ +public: + virtual ~ListsPropertyPanel() override; + + static std::unique_ptr<PanelLayout> + Create(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame); + + ListsPropertyPanel(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame); + +private: + std::unique_ptr<weld::Toolbar> mxTBxNumBullet; + std::unique_ptr<ToolbarUnoDispatcher> mxNumBulletDispatcher; + std::unique_ptr<weld::Toolbar> mxTBxOutline; + std::unique_ptr<ToolbarUnoDispatcher> mxOutlineDispatcher; +}; + +} // end of namespace svx::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/media/MediaPlaybackPanel.cxx b/svx/source/sidebar/media/MediaPlaybackPanel.cxx new file mode 100644 index 0000000000..53c9190b83 --- /dev/null +++ b/svx/source/sidebar/media/MediaPlaybackPanel.cxx @@ -0,0 +1,176 @@ +/* -*- 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 "MediaPlaybackPanel.hxx" +#include <avmedia/mediaitem.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/dispatch.hxx> +#include <avmedia/MediaControlBase.hxx> +#include <svl/itemset.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +using namespace avmedia; + +namespace svx::sidebar { + +MediaPlaybackPanel::MediaPlaybackPanel ( + weld::Widget* pParent, + SfxBindings* pBindings) + : PanelLayout(pParent, "MediaPlaybackPanel", "svx/ui/mediaplayback.ui"), + maMediaController(SID_AVMEDIA_TOOLBOX, *pBindings, *this), + maIdle("MediaPlaybackPanel"), + mpBindings(pBindings) +{ + mxTimeEdit = m_xBuilder->weld_entry("timeedit"); + mxPlayToolBox = m_xBuilder->weld_toolbar("playtoolbox"); + mxMuteToolBox = m_xBuilder->weld_toolbar("mutetoolbox"); + mxTimeSlider = m_xBuilder->weld_scale("timeslider"); + mxVolumeSlider = m_xBuilder->weld_scale("volumeslider"); + mxZoomListBox = m_xBuilder->weld_combo_box("zoombox"); + + Initialize(); +} + +std::unique_ptr<PanelLayout> MediaPlaybackPanel::Create( + weld::Widget* pParent, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to MediaPlaybackPanel::Create", nullptr, 0); + if (pBindings == nullptr) + throw lang::IllegalArgumentException("no SfxBindings given to MediaPlaybackPanel::Create", nullptr, 2); + + return std::make_unique<MediaPlaybackPanel>(pParent, pBindings); +} + +void MediaPlaybackPanel::Initialize() +{ + InitializeWidgets(); + mxVolumeSlider->connect_value_changed(LINK(this, MediaPlaybackPanel, VolumeSlideHdl)); + mxPlayToolBox->connect_clicked(LINK(this, MediaPlaybackPanel, PlayToolBoxSelectHdl)); + mxMuteToolBox->connect_clicked(LINK(this, MediaPlaybackPanel, PlayToolBoxSelectHdl)); + mxTimeSlider->connect_value_changed(LINK(this, MediaPlaybackPanel, SeekHdl)); + + maIdle.SetPriority( TaskPriority::HIGHEST ); + maIdle.SetInvokeHandler( LINK( this, MediaPlaybackPanel, TimeoutHdl ) ); + maIdle.Start(); + mpBindings->Invalidate(SID_AVMEDIA_TOOLBOX); +} + +MediaPlaybackPanel::~MediaPlaybackPanel() +{ + disposeWidgets(); +} + +void MediaPlaybackPanel::NotifyItemUpdate( + const sal_uInt16 nSID, + const SfxItemState eState, + const SfxPoolItem* pState) +{ + if( nSID == SID_AVMEDIA_TOOLBOX ) + { + if(eState >= SfxItemState::DEFAULT) + { + mpMediaItem.reset(pState ? static_cast< MediaItem* >(pState->Clone()) : nullptr); + Update(); + } + } +} + +void MediaPlaybackPanel::UpdateToolBoxes(const MediaItem& rMediaItem) +{ + mxPlayToolBox->set_sensitive(false); + avmedia::MediaControlBase::UpdateToolBoxes(rMediaItem); +} + +void MediaPlaybackPanel::Update() +{ + if (mpMediaItem) + { + UpdateToolBoxes( *mpMediaItem ); + UpdateTimeSlider( *mpMediaItem ); + UpdateVolumeSlider( *mpMediaItem ); + UpdateTimeField( *mpMediaItem, mpMediaItem->getTime() ); + } +} + +IMPL_LINK_NOARG( MediaPlaybackPanel, VolumeSlideHdl, weld::Scale&, void) +{ + MediaItem aItem(SID_AVMEDIA_TOOLBOX); + aItem.setVolumeDB(mxVolumeSlider->get_value()); + mpBindings->GetDispatcher()->ExecuteList(SID_AVMEDIA_TOOLBOX, SfxCallMode::RECORD, { &aItem }); +} + +IMPL_LINK_NOARG( MediaPlaybackPanel, SeekHdl, weld::Scale&, void) +{ + MediaItem aItem(SID_AVMEDIA_TOOLBOX); + double nTime = 0; + if (mpMediaItem) + nTime = mxTimeSlider->get_value() * mpMediaItem->getDuration() / AVMEDIA_TIME_RANGE; + aItem.setTime(nTime); + mpBindings->GetDispatcher()->ExecuteList(SID_AVMEDIA_TOOLBOX, SfxCallMode::RECORD, { &aItem }); + mpBindings->Invalidate(SID_AVMEDIA_TOOLBOX); +} + +IMPL_LINK_NOARG( MediaPlaybackPanel, TimeoutHdl, Timer*, void) +{ + mpBindings->Invalidate(SID_AVMEDIA_TOOLBOX); +} + +IMPL_LINK( MediaPlaybackPanel, PlayToolBoxSelectHdl, const OUString&, rId, void) +{ + MediaItem aItem(SID_AVMEDIA_TOOLBOX); + + if (rId == "play") + { + aItem.setState( MediaState::Play ); + + if( !mpMediaItem || (mpMediaItem->getTime() == mpMediaItem->getDuration() )) + aItem.setTime( 0.0 ); + else + aItem.setTime( mpMediaItem->getTime()); + } + else if (rId == "pause") + { + aItem.setState( MediaState::Pause ); + } + else if (rId == "stop") + { + aItem.setState( MediaState::Stop ); + aItem.setTime( 0.0 ); + } + else if (rId == "mute") + { + aItem.setMute( mxMuteToolBox->get_item_active("mute") ); + } + else if (rId == "loop") + { + aItem.setLoop( mxPlayToolBox->get_item_active("loop") ); + } + + if(aItem.getMaskSet() != AVMediaSetMask::NONE) + { + mpBindings->GetDispatcher()->ExecuteList(SID_AVMEDIA_TOOLBOX, SfxCallMode::RECORD, { &aItem } ); + mpBindings->Invalidate(SID_AVMEDIA_TOOLBOX); + } +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/media/MediaPlaybackPanel.hxx b/svx/source/sidebar/media/MediaPlaybackPanel.hxx new file mode 100644 index 0000000000..b85f387920 --- /dev/null +++ b/svx/source/sidebar/media/MediaPlaybackPanel.hxx @@ -0,0 +1,80 @@ +/* -*- 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 . + */ +#pragma once + +#include <memory> + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <avmedia/mediaitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <avmedia/MediaControlBase.hxx> +#include <vcl/idle.hxx> + +using namespace css; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; + +namespace svx::sidebar { + +/** This panel provides media playback control in document +*/ +class MediaPlaybackPanel + : public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface, + public ::avmedia::MediaControlBase +{ +public: + MediaPlaybackPanel ( + weld::Widget* pParent, + SfxBindings* pBindings); + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + SfxBindings* pBindings); + virtual ~MediaPlaybackPanel() override; + +protected: + virtual void UpdateToolBoxes(const avmedia::MediaItem& rMediaItem) override; + +private: + std::unique_ptr< ::avmedia::MediaItem > mpMediaItem; + ::sfx2::sidebar::ControllerItem maMediaController; + Idle maIdle; + SfxBindings* mpBindings; + void Initialize(); + void Update(); + virtual void NotifyItemUpdate( const sal_uInt16 nSID, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + DECL_LINK(PlayToolBoxSelectHdl, const OUString&, void); + DECL_LINK(VolumeSlideHdl, weld::Scale&, void); + DECL_LINK(SeekHdl, weld::Scale&, void); + + DECL_LINK(TimeoutHdl, Timer*, void); +}; + + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/nbdtmg.cxx b/svx/source/sidebar/nbdtmg.cxx new file mode 100644 index 0000000000..b572d49f8a --- /dev/null +++ b/svx/source/sidebar/nbdtmg.cxx @@ -0,0 +1,920 @@ +/* -*- 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/nbdtmg.hxx> +#include <svx/svxids.hrc> +#include <vcl/svapp.hxx> +#include <svl/itemset.hxx> +#include <sfx2/request.hxx> +#include <svl/stritem.hxx> +#include <svtools/ctrltool.hxx> +#include <sfx2/objsh.hxx> +#include <editeng/flstitem.hxx> +#include <svl/itempool.hxx> +#include <vcl/outdev.hxx> +#include <editeng/brushitem.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <vcl/graph.hxx> +#include <vcl/settings.hxx> + +#include <i18nlangtag/languagetag.hxx> +#include <o3tl/temporary.hxx> +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/pathoptions.hxx> +#include <editeng/eeitem.hxx> + +#include <com/sun/star/text/VertOrientation.hpp> +#include <com/sun/star/style/NumberingType.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/text/DefaultNumberingProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <comphelper/processfactory.hxx> +#include <memory> + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::text; +using namespace com::sun::star::container; +using namespace com::sun::star::style; + +namespace svx::sidebar { + +namespace { + +const vcl::Font& lcl_GetDefaultBulletFont() +{ + static vcl::Font aDefBulletFont = []() + { + static vcl::Font tmp("OpenSymbol", "", Size(0, 14)); + tmp.SetCharSet( RTL_TEXTENCODING_SYMBOL ); + tmp.SetFamily( FAMILY_DONTKNOW ); + tmp.SetPitch( PITCH_DONTKNOW ); + tmp.SetWeight( WEIGHT_DONTKNOW ); + tmp.SetTransparent( true ); + return tmp; + }(); + return aDefBulletFont; +} + +const sal_Unicode aDefaultBulletTypes[] = +{ + 0x2022, + 0x25cf, + 0xe00c, + 0xe00a, + 0x2794, + 0x27a2, + 0x2717, + 0x2714 +}; + +NumSettings_Impl* lcl_CreateNumberingSettingsPtr(const Sequence<PropertyValue>& rLevelProps) +{ + NumSettings_Impl* pNew = new NumSettings_Impl; + for(const PropertyValue& rValue : rLevelProps) + { + if(rValue.Name == "NumberingType") + { + sal_Int16 nTmp; + if (rValue.Value >>= nTmp) + pNew->nNumberType = static_cast<SvxNumType>(nTmp); + } + else if(rValue.Name == "Prefix") + rValue.Value >>= pNew->sPrefix; + else if(rValue.Name == "Suffix") + rValue.Value >>= pNew->sSuffix; + else if (rValue.Name == "Adjust") + { + sal_Int16 nTmp; + if (rValue.Value >>= nTmp) + pNew->eNumAlign = static_cast<SvxAdjust>(nTmp); + } + else if(rValue.Name == "ParentNumbering") + rValue.Value >>= pNew->nParentNumbering; + else if(rValue.Name == "BulletChar") + rValue.Value >>= pNew->sBulletChar; + else if(rValue.Name == "BulletFontName") + rValue.Value >>= pNew->sBulletFont; + } + const sal_Unicode cLocalPrefix = pNew->sPrefix.getLength() ? pNew->sPrefix[0] : 0; + const sal_Unicode cLocalSuffix = pNew->sSuffix.getLength() ? pNew->sSuffix[0] : 0; + if( cLocalPrefix == ' ') pNew->sPrefix.clear(); + if( cLocalSuffix == ' ') pNew->sSuffix.clear(); + return pNew; +} + +} + +sal_uInt16 NBOTypeMgrBase:: IsSingleLevel(sal_uInt16 nCurLevel) +{ + sal_uInt16 nLv = sal_uInt16(0xFFFF); + sal_uInt16 nCount = 0; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < SVX_MAX_NUM; i++ ) + { + if(nCurLevel & nMask) + { + nCount++; + nLv=i; + } + nMask <<= 1 ; + } + + if ( nCount == 1) + return nLv; + else + return sal_uInt16(0xFFFF); +} + +void NBOTypeMgrBase::SetItems(const SfxItemSet* pArg) { + pSet = pArg; + if ( !pSet ) + return; + + SfxAllItemSet aSet(*pSet); + + const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false); + if (pBulletCharFmt) + aBulletCharFmtName = pBulletCharFmt->GetValue(); + + const SfxStringItem* pNumCharFmt = aSet.GetItem<SfxStringItem>(SID_NUM_CHAR_FMT, false); + if (pNumCharFmt) + aNumCharFmtName = pNumCharFmt->GetValue(); + + const SfxPoolItem* pItem; + SfxItemState eState = pSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem); + if(eState == SfxItemState::SET) + { + eCoreUnit = pSet->GetPool()->GetMetric(pSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE)); + } else { + //sd use different sid for numbering rule + eState = pSet->GetItemState(EE_PARA_NUMBULLET, false, &pItem); + if(eState == SfxItemState::SET) + { + eCoreUnit = pSet->GetPool()->GetMetric(pSet->GetPool()->GetWhich(EE_PARA_NUMBULLET)); + } + } +} + +void NBOTypeMgrBase::ImplLoad(std::u16string_view filename) +{ + bIsLoading = true; + MapUnit eOldCoreUnit=eCoreUnit; + eCoreUnit = MapUnit::Map100thMM; + INetURLObject aFile( SvtPathOptions().GetUserConfigPath() ); + aFile.Append( filename); + std::unique_ptr<SvStream> xIStm(::utl::UcbStreamHelper::CreateStream( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ )); + if( xIStm ) { + sal_uInt32 nVersion = 0; + sal_Int32 nNumIndex = 0; + xIStm->ReadUInt32( nVersion ); + if (nVersion==DEFAULT_NUMBERING_CACHE_FORMAT_VERSION) //first version + { + xIStm->ReadInt32( nNumIndex ); + while (nNumIndex>=0 && nNumIndex<DEFAULT_NUM_VALUSET_COUNT) { + SvxNumRule aNum(*xIStm); + //bullet color in font properties is not stored correctly. Need set transparency bits manually + for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++) + { + SvxNumberFormat aFmt(aNum.GetLevel(i)); + if (aFmt.GetBulletFont()) { + vcl::Font aFont(*aFmt.GetBulletFont()); + Color c=aFont.GetColor(); + c.SetAlpha(0); + aFont.SetColor(c); + aFmt.SetBulletFont(&aFont); + aNum.SetLevel(i, aFmt); + } + } + ReplaceNumRule(aNum,nNumIndex,0x1/*nLevel*/); + xIStm->ReadInt32( nNumIndex ); + } + } + } + eCoreUnit = eOldCoreUnit; + bIsLoading = false; +} +void NBOTypeMgrBase::ImplStore(std::u16string_view filename) +{ + if (bIsLoading) return; + MapUnit eOldCoreUnit=eCoreUnit; + eCoreUnit = MapUnit::Map100thMM; + INetURLObject aFile( SvtPathOptions().GetUserConfigPath() ); + aFile.Append( filename); + std::unique_ptr<SvStream> xOStm(::utl::UcbStreamHelper::CreateStream( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::WRITE )); + if( xOStm ) { + sal_uInt32 nVersion; + sal_Int32 nNumIndex; + nVersion = DEFAULT_NUMBERING_CACHE_FORMAT_VERSION; + xOStm->WriteUInt32( nVersion ); + for(sal_Int32 nItem = 0; nItem < DEFAULT_NUM_VALUSET_COUNT; nItem++ ) { + if (IsCustomized(nItem)) { + SvxNumRule aDefNumRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::CONTINUOUS | SvxNumRuleFlags::BULLET_COLOR, + 10, false, + SvxNumRuleType::NUMBERING, SvxNumberFormat::LABEL_ALIGNMENT); + xOStm->WriteInt32( nItem ); + ApplyNumRule(aDefNumRule,nItem,0x1/*nLevel*/,false,true); + aDefNumRule.Store(*xOStm); + } + } + nNumIndex = -1; + xOStm->WriteInt32( nNumIndex ); //write end flag + } + eCoreUnit = eOldCoreUnit; +} + +// Character Bullet Type lib +BulletsSettings* BulletsTypeMgr::pActualBullets[] ={nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}; +sal_Unicode BulletsTypeMgr::aDynamicBulletTypes[]={' ',' ',' ',' ',' ',' ',' ',' '}; +sal_Unicode BulletsTypeMgr::aDynamicRTLBulletTypes[]={' ',' ',' ',' ',' ',' ',' ',' '}; + +BulletsTypeMgr::BulletsTypeMgr() +{ + Init(); +} + +BulletsTypeMgr& BulletsTypeMgr::GetInstance() +{ + static BulletsTypeMgr theBulletsTypeMgr; + return theBulletsTypeMgr; +} + +void BulletsTypeMgr::Init() +{ + const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont(); + + for (sal_uInt16 i=0;i<DEFAULT_BULLET_TYPES;i++) + { + pActualBullets[i] = new BulletsSettings; + pActualBullets[i]->cBulletChar = aDefaultBulletTypes[i]; + pActualBullets[i]->aFont = rActBulletFont; + OString id = OString::Concat(RID_SVXSTR_BULLET_DESCRIPTION_0.getId()) + OString::number(i); + pActualBullets[i]->sDescription = SvxResId( TranslateId(RID_SVXSTR_BULLET_DESCRIPTION_0.mpContext, id.getStr()) ); + } +} +sal_uInt16 BulletsTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex) +{ + if ( mLevel == sal_uInt16(0xFFFF) || mLevel == 0) + return sal_uInt16(0xFFFF); + //if ( !lcl_IsNumFmtSet(pNR, mLevel) ) return (sal_uInt16)0xFFFF; + + sal_uInt16 nActLv = IsSingleLevel(mLevel); + + if ( nActLv == sal_uInt16(0xFFFF) ) + return sal_uInt16(0xFFFF); + + const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv)); + sal_UCS4 cChar = aFmt.GetBulletChar(); + for(sal_uInt16 i = nFromIndex; i < DEFAULT_BULLET_TYPES; i++) + { + if ( (cChar == pActualBullets[i]->cBulletChar) || + (cChar == 9830 && 57356 == pActualBullets[i]->cBulletChar) || + (cChar == 9632 && 57354 == pActualBullets[i]->cBulletChar) ) + { + return i+1; + } + } + + return sal_uInt16(0xFFFF); +} + +void BulletsTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel) +{ + if ( nIndex >= DEFAULT_BULLET_TYPES ) + return; + + if ( mLevel == sal_uInt16(0xFFFF) || mLevel == 0) + return; + + if ( GetNBOIndexForNumRule(aNum,mLevel) != sal_uInt16(0xFFFF) ) + return; + + sal_uInt16 nActLv = IsSingleLevel(mLevel); + + if ( nActLv == sal_uInt16(0xFFFF) ) + return; + + SvxNumberFormat aFmt(aNum.GetLevel(nActLv)); + sal_UCS4 cChar = aFmt.GetBulletChar(); + std::optional<vcl::Font> pFont = aFmt.GetBulletFont(); + + pActualBullets[nIndex]->cBulletChar = cChar; + if ( pFont ) + pActualBullets[nIndex]->aFont = *pFont; + pActualBullets[nIndex]->bIsCustomized = true; +} + +void BulletsTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool /*isDefault*/, bool isResetSize) +{ + if ( nIndex >= DEFAULT_BULLET_TYPES ) + return; + sal_UCS4 cChar = pActualBullets[nIndex]->cBulletChar; + const vcl::Font& rActBulletFont = pActualBullets[nIndex]->aFont; + + sal_uInt16 nMask = 1; + OUString sBulletCharFormatName = GetBulletCharFmtName(); + for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++) + { + if(mLevel & nMask) + { + SvxNumberFormat aFmt(aNum.GetLevel(i)); + aFmt.SetNumberingType( SVX_NUM_CHAR_SPECIAL ); + aFmt.SetBulletFont(&rActBulletFont); + aFmt.SetBulletChar(cChar); + aFmt.SetCharFormatName(sBulletCharFormatName); + aFmt.SetListFormat( "" ); + if (isResetSize) aFmt.SetBulletRelSize(45); + aNum.SetLevel(i, aFmt); + } + nMask <<= 1; + } +} + +OUString BulletsTypeMgr::GetDescription(sal_uInt16 nIndex, bool /*isDefault*/) +{ + OUString sRet; + + if ( nIndex >= DEFAULT_BULLET_TYPES ) + return sRet; + else + sRet = pActualBullets[nIndex]->sDescription; + + return sRet; +} + +bool BulletsTypeMgr::IsCustomized(sal_uInt16 nIndex) +{ + bool bRet = false; + + if ( nIndex >= DEFAULT_BULLET_TYPES ) + bRet = false; + else + bRet = pActualBullets[nIndex]->bIsCustomized; + + return bRet; +} + +// Numbering Type lib +NumberingTypeMgr::NumberingTypeMgr() +{ + Init(); + maDefaultNumberSettingsArr = maNumberSettingsArr; + ImplLoad(u"standard.syb"); +} + +NumberingTypeMgr::~NumberingTypeMgr() +{ +} + +const TranslateId RID_SVXSTR_SINGLENUM_DESCRIPTIONS[] = +{ + RID_SVXSTR_SINGLENUM_DESCRIPTION_0, + RID_SVXSTR_SINGLENUM_DESCRIPTION_1, + RID_SVXSTR_SINGLENUM_DESCRIPTION_2, + RID_SVXSTR_SINGLENUM_DESCRIPTION_3, + RID_SVXSTR_SINGLENUM_DESCRIPTION_4, + RID_SVXSTR_SINGLENUM_DESCRIPTION_5, + RID_SVXSTR_SINGLENUM_DESCRIPTION_6, + RID_SVXSTR_SINGLENUM_DESCRIPTION_7 +}; + +NumberingTypeMgr& NumberingTypeMgr::GetInstance() +{ + static NumberingTypeMgr theNumberingTypeMgr; + return theNumberingTypeMgr; +} + +void NumberingTypeMgr::Init() +{ + Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create( xContext ); + + Sequence< Sequence< PropertyValue > > aNumberings; + Locale aLocale(Application::GetSettings().GetLanguageTag().getLocale()); + try + { + aNumberings = xDefNum->getDefaultContinuousNumberingLevels( aLocale ); + + sal_Int32 nLength = aNumberings.getLength(); + + const Sequence<PropertyValue>* pValuesArr = aNumberings.getConstArray(); + for(sal_Int32 i = 0; i < nLength; i++) + { + NumSettings_Impl* pNew = lcl_CreateNumberingSettingsPtr(pValuesArr[i]); + std::shared_ptr<NumberSettings_Impl> pNumEntry = std::make_shared<NumberSettings_Impl>(); + pNumEntry->pNumSetting = pNew; + if ( i < 8 ) + pNumEntry->sDescription = SvxResId(RID_SVXSTR_SINGLENUM_DESCRIPTIONS[i]); + maNumberSettingsArr.push_back(pNumEntry); + } + } + catch(Exception&) + { + } +} + +sal_uInt16 NumberingTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 mLevel,sal_uInt16 nFromIndex) +{ + if ( mLevel == sal_uInt16(0xFFFF) || mLevel > aNum.GetLevelCount() || mLevel == 0) + return sal_uInt16(0xFFFF); + + sal_uInt16 nActLv = IsSingleLevel(mLevel); + + if ( nActLv == sal_uInt16(0xFFFF) ) + return sal_uInt16(0xFFFF); + + const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv)); + //sal_Unicode cPrefix = OUString(aFmt.GetPrefix())[0]; + //sal_Unicode cSuffix = :OUString(aFmt.GetSuffix())[0]; + const OUString& sPrefix = aFmt.GetPrefix(); + const OUString& sLclSuffix = aFmt.GetSuffix(); + sal_Int16 eNumType = aFmt.GetNumberingType(); + + sal_uInt16 nCount = maNumberSettingsArr.size(); + for(sal_uInt16 i = nFromIndex; i < nCount; ++i) + { + NumberSettings_Impl* _pSet = maNumberSettingsArr[i].get(); + sal_Int16 eNType = _pSet->pNumSetting->nNumberType; + OUString sLocalPrefix = _pSet->pNumSetting->sPrefix; + OUString sLocalSuffix = _pSet->pNumSetting->sSuffix; + if (sPrefix == sLocalPrefix && + sLclSuffix == sLocalSuffix && + eNumType == eNType ) + { + return i+1; + } + } + + + return sal_uInt16(0xFFFF); +} + +void NumberingTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel) +{ + sal_uInt16 nActLv = IsSingleLevel(mLevel); + + if ( nActLv == sal_uInt16(0xFFFF) ) + return; + + const SvxNumberFormat& aFmt(aNum.GetLevel(nActLv)); + SvxNumType eNumType = aFmt.GetNumberingType(); + + sal_uInt16 nCount = maNumberSettingsArr.size(); + if ( nIndex >= nCount ) + return; + + NumberSettings_Impl* _pSet = maNumberSettingsArr[nIndex].get(); + + _pSet->pNumSetting->sPrefix = aFmt.GetPrefix(); + _pSet->pNumSetting->sSuffix = aFmt.GetSuffix(); + _pSet->pNumSetting->nNumberType = eNumType; + _pSet->bIsCustomized = true; + + SvxNumRule aTmpRule1(aNum); + SvxNumRule aTmpRule2(aNum); + ApplyNumRule(aTmpRule1,nIndex,mLevel,true); + ApplyNumRule(aTmpRule2,nIndex,mLevel); + if (aTmpRule1==aTmpRule2) _pSet->bIsCustomized=false; + if (!_pSet->bIsCustomized) { + _pSet->sDescription = GetDescription(nIndex,true); + } + ImplStore(u"standard.syb"); +} + +void NumberingTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel, bool isDefault, bool isResetSize) +{ + if(maNumberSettingsArr.size() <= nIndex) + return; + NumberSettingsArr_Impl* pCurrentNumberSettingsArr = &maNumberSettingsArr; + if (isDefault) pCurrentNumberSettingsArr = &maDefaultNumberSettingsArr; + NumberSettings_Impl* _pSet = (*pCurrentNumberSettingsArr)[nIndex].get(); + SvxNumType eNewType = _pSet->pNumSetting->nNumberType; + + sal_uInt16 nMask = 1; + OUString sNumCharFmtName = GetNumCharFmtName(); + for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++) + { + if(mLevel & nMask) + { + SvxNumberFormat aFmt(aNum.GetLevel(i)); + if (eNewType!=aFmt.GetNumberingType()) isResetSize=true; + aFmt.SetNumberingType(eNewType); + aFmt.SetListFormat(_pSet->pNumSetting->sPrefix, _pSet->pNumSetting->sSuffix, i); + aFmt.SetCharFormatName(sNumCharFmtName); + if (isResetSize) aFmt.SetBulletRelSize(100); + aNum.SetLevel(i, aFmt); + } + nMask <<= 1 ; + } +} + +OUString NumberingTypeMgr::GetDescription(sal_uInt16 nIndex, bool isDefault) +{ + OUString sRet; + sal_uInt16 nLength = maNumberSettingsArr.size(); + + if ( nIndex >= nLength ) + return sRet; + else + sRet = maNumberSettingsArr[nIndex]->sDescription; + if (isDefault) sRet = maDefaultNumberSettingsArr[nIndex]->sDescription; + + return sRet; +} + +bool NumberingTypeMgr::IsCustomized(sal_uInt16 nIndex) +{ + bool bRet = false; + sal_uInt16 nLength = maNumberSettingsArr.size(); + + if ( nIndex >= nLength ) + bRet = false; + else + bRet = maNumberSettingsArr[nIndex]->bIsCustomized; + + return bRet; +} +// Multi-level /Outline Type lib +OutlineTypeMgr::OutlineTypeMgr() +{ + Init(); + for(sal_Int32 nItem = 0; nItem < DEFAULT_NUM_VALUSET_COUNT; nItem++ ) + { + pDefaultOutlineSettingsArrs[nItem] = pOutlineSettingsArrs[nItem]; + } + //Initial the first time to store the default value. Then do it again for customized value + Init(); + ImplLoad(u"standard.syc"); +} + +OutlineTypeMgr& OutlineTypeMgr::GetInstance() +{ + static OutlineTypeMgr theOutlineTypeMgr; + return theOutlineTypeMgr; +} + +void OutlineTypeMgr::Init() +{ + Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create( xContext ); + + Sequence<Reference<XIndexAccess> > aOutlineAccess; + Locale aLocale(Application::GetSettings().GetLanguageTag().getLocale()); + try + { + aOutlineAccess = xDefNum->getDefaultOutlineNumberings( aLocale ); + + SvxNumRule aDefNumRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::CONTINUOUS | SvxNumRuleFlags::BULLET_COLOR, + 10, false, + SvxNumRuleType::NUMBERING, SvxNumberFormat::LABEL_ALIGNMENT); + + auto nSize = std::min<sal_Int32>(aOutlineAccess.getLength(), DEFAULT_NUM_VALUSET_COUNT); + for(sal_Int32 nItem = 0; nItem < nSize; nItem++ ) + { + pOutlineSettingsArrs[ nItem ] = new OutlineSettings_Impl; + OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[ nItem ]; + OString id = OString::Concat(RID_SVXSTR_OUTLINENUM_DESCRIPTION_0.getId()) + OString::number(nItem); + pItemArr->sDescription = SvxResId( TranslateId(RID_SVXSTR_OUTLINENUM_DESCRIPTION_0.mpContext, id.getStr()) ); + pItemArr->pNumSettingsArr = new NumSettingsArr_Impl; + Reference<XIndexAccess> xLevel = aOutlineAccess.getConstArray()[nItem]; + for(sal_Int32 nLevel = 0; nLevel < SVX_MAX_NUM; nLevel++) + { + // use the last locale-defined level for all remaining levels. + sal_Int32 nLocaleLevel = std::min(nLevel, xLevel->getCount() - 1); + Sequence<PropertyValue> aLevelProps; + if (nLocaleLevel >= 0) + xLevel->getByIndex(nLocaleLevel) >>= aLevelProps; + + NumSettings_Impl* pNew = lcl_CreateNumberingSettingsPtr(aLevelProps); + const SvxNumberFormat& aNumFmt( aDefNumRule.GetLevel( nLevel) ); + assert(aNumFmt.GetNumAdjust() == SvxAdjust::Left && "new entry was previously defined by default, now defaults to Left"); + pNew->eLabelFollowedBy = aNumFmt.GetLabelFollowedBy(); + pNew->nTabValue = aNumFmt.GetListtabPos(); + if (pNew->eNumAlign == SvxAdjust::Right) + pNew->nNumAlignAt = -174; // number borrowed from RES_POOLNUMRULE_NUM4 + else + pNew->nNumAlignAt = aNumFmt.GetFirstLineIndent(); + pNew->nNumIndentAt = aNumFmt.GetIndentAt(); + pItemArr->pNumSettingsArr->push_back(std::shared_ptr<NumSettings_Impl>(pNew)); + } + } + } + catch(Exception&) + { + } +} + +sal_uInt16 OutlineTypeMgr::GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 /*mLevel*/,sal_uInt16 nFromIndex) +{ + sal_uInt16 const nLength = SAL_N_ELEMENTS(pOutlineSettingsArrs); + for(sal_uInt16 iDex = nFromIndex; iDex < nLength; iDex++) + { + bool bNotMatch = false; + OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[iDex]; + sal_uInt16 nCount = pItemArr ? pItemArr->pNumSettingsArr->size() : 0; + for (sal_uInt16 iLevel=0;iLevel < nCount;iLevel++) + { + NumSettings_Impl* _pSet = (*pItemArr->pNumSettingsArr)[iLevel].get(); + sal_Int16 eNType = _pSet->nNumberType; + + const SvxNumberFormat& aFmt(aNum.GetLevel(iLevel)); + const OUString& sPrefix = aFmt.GetPrefix(); + const OUString& sLclSuffix = aFmt.GetSuffix(); + sal_Int16 eNumType = aFmt.GetNumberingType(); + if( eNumType == SVX_NUM_CHAR_SPECIAL) + { + sal_UCS4 cChar = aFmt.GetBulletChar(); + + sal_UCS4 ccChar + = _pSet->sBulletChar.isEmpty() + ? 0 + : _pSet->sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0))); + + if ( !((cChar == ccChar) && + _pSet->eLabelFollowedBy == aFmt.GetLabelFollowedBy() && + _pSet->nTabValue == aFmt.GetListtabPos() && + _pSet->eNumAlign == aFmt.GetNumAdjust() && + _pSet->nNumAlignAt == aFmt.GetFirstLineIndent() && + _pSet->nNumIndentAt == aFmt.GetIndentAt())) + { + bNotMatch = true; + break; + } + } + else if ((eNumType&(~LINK_TOKEN)) == SVX_NUM_BITMAP ) + { + const SvxBrushItem* pBrsh1 = aFmt.GetBrush(); + const SvxBrushItem* pBrsh2 = _pSet->pBrushItem; + bool bIsMatch = false; + if (SfxPoolItem::areSame(pBrsh1,pBrsh2)) bIsMatch = true; + if (pBrsh1 && pBrsh2) { + const Graphic* pGrf1 = pBrsh1->GetGraphic(); + const Graphic* pGrf2 = pBrsh2->GetGraphic(); + if (pGrf1==pGrf2) bIsMatch = true; + if (pGrf1 && pGrf2) { + if ( pGrf1->GetBitmapEx() == pGrf2->GetBitmapEx() && + _pSet->aSize == aFmt.GetGraphicSize()) + bIsMatch = true; + } + } + if (!bIsMatch) { + bNotMatch = true; + break; + } + } + else + { + if (!(sPrefix == _pSet->sPrefix && + sLclSuffix == _pSet->sSuffix && + eNumType == eNType && + _pSet->eLabelFollowedBy == aFmt.GetLabelFollowedBy() && + _pSet->nTabValue == aFmt.GetListtabPos() && + _pSet->eNumAlign == aFmt.GetNumAdjust() && + _pSet->nNumAlignAt == aFmt.GetFirstLineIndent() && + _pSet->nNumIndentAt == aFmt.GetIndentAt())) + { + bNotMatch = true; + break; + } + } + } + if ( !bNotMatch ) + return iDex+1; + } + + + return sal_uInt16(0xFFFF); +} + +void OutlineTypeMgr::ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 mLevel) +{ + sal_uInt16 const nLength = SAL_N_ELEMENTS(pOutlineSettingsArrs); + if ( nIndex >= nLength ) + return; + + OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex]; + sal_uInt16 nCount = pItemArr->pNumSettingsArr->size(); + for (sal_uInt16 iLevel=0;iLevel < nCount;iLevel++) + { + const SvxNumberFormat& aFmt(aNum.GetLevel(iLevel)); + SvxNumType eNumType = aFmt.GetNumberingType(); + + NumSettings_Impl* _pSet = (*pItemArr->pNumSettingsArr)[iLevel].get(); + + _pSet->eLabelFollowedBy = aFmt.GetLabelFollowedBy(); + _pSet->nTabValue = aFmt.GetListtabPos(); + _pSet->eNumAlign = aFmt.GetNumAdjust(); + _pSet->nNumAlignAt = aFmt.GetFirstLineIndent(); + _pSet->nNumIndentAt = aFmt.GetIndentAt(); + + if( eNumType == SVX_NUM_CHAR_SPECIAL) + { + sal_UCS4 cChar = aFmt.GetBulletChar(); + OUString sChar(&cChar, 1); + _pSet->sBulletChar = sChar; + if ( aFmt.GetBulletFont() ) + _pSet->sBulletFont = aFmt.GetBulletFont()->GetFamilyName(); + _pSet->nNumberType = eNumType; + pItemArr->bIsCustomized = true; + }else if ((eNumType&(~LINK_TOKEN)) == SVX_NUM_BITMAP ) { + if (_pSet->pBrushItem) { + delete _pSet->pBrushItem; + _pSet->pBrushItem=nullptr; + } + if (aFmt.GetBrush()) + _pSet->pBrushItem = new SvxBrushItem(*aFmt.GetBrush()); + _pSet->aSize = aFmt.GetGraphicSize(); + _pSet->nNumberType = eNumType; + } else + { + _pSet->sPrefix = aFmt.GetPrefix(); + _pSet->sSuffix = aFmt.GetSuffix(); + _pSet->nNumberType = eNumType; + if ( aFmt.GetBulletFont() ) + _pSet->sBulletFont = aFmt.GetBulletFont()->GetFamilyName(); + pItemArr->bIsCustomized = true; + } + } + SvxNumRule aTmpRule1(aNum); + SvxNumRule aTmpRule2(aNum); + ApplyNumRule(aTmpRule1,nIndex,mLevel,true); + ApplyNumRule(aTmpRule2,nIndex,mLevel); + if (aTmpRule1==aTmpRule2) pItemArr->bIsCustomized=false; + if (!pItemArr->bIsCustomized) { + pItemArr->sDescription = GetDescription(nIndex,true); + } + ImplStore(u"standard.syc"); +} + +void OutlineTypeMgr::ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, sal_uInt16 /*mLevel*/, bool isDefault, bool isResetSize) +{ + DBG_ASSERT(DEFAULT_NUM_VALUSET_COUNT > nIndex, "wrong index"); + if(DEFAULT_NUM_VALUSET_COUNT <= nIndex) + return; + + const FontList* pList = nullptr; + + OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex]; + if (isDefault) pItemArr=pDefaultOutlineSettingsArrs[nIndex]; + + NumSettingsArr_Impl *pNumSettingsArr=pItemArr->pNumSettingsArr; + + NumSettings_Impl* pLevelSettings = nullptr; + for(sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++) + { + if(pNumSettingsArr->size() > i) + pLevelSettings = (*pNumSettingsArr)[i].get(); + + if(!pLevelSettings) + break; + + SvxNumberFormat aFmt(aNum.GetLevel(i)); + const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont(); + if (pLevelSettings->nNumberType !=aFmt.GetNumberingType()) isResetSize=true; + aFmt.SetNumberingType( pLevelSettings->nNumberType ); + sal_uInt16 nUpperLevelOrChar = static_cast<sal_uInt16>(pLevelSettings->nParentNumbering); + if(aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL) + { + if( pLevelSettings->sBulletFont.getLength() && + pLevelSettings->sBulletFont != rActBulletFont.GetFamilyName() ) + { + //search for the font + if(!pList) + { + if (SfxObjectShell* pCurDocShell = SfxObjectShell::Current()) + { + const SvxFontListItem* pFontListItem = static_cast<const SvxFontListItem*>(pCurDocShell->GetItem(SID_ATTR_CHAR_FONTLIST)); + pList = pFontListItem ? pFontListItem->GetFontList() : nullptr; + } + } + if(pList && pList->IsAvailable( pLevelSettings->sBulletFont ) ) + { + FontMetric aFontMetric = pList->Get(pLevelSettings->sBulletFont,WEIGHT_NORMAL, ITALIC_NONE); + vcl::Font aFont(aFontMetric); + aFmt.SetBulletFont(&aFont); + } + else + { + //if it cannot be found then create a new one + vcl::Font aCreateFont( pLevelSettings->sBulletFont, OUString(), Size( 0, 14 ) ); + aCreateFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW ); + aCreateFont.SetFamily( FAMILY_DONTKNOW ); + aCreateFont.SetPitch( PITCH_DONTKNOW ); + aCreateFont.SetWeight( WEIGHT_DONTKNOW ); + aCreateFont.SetTransparent( true ); + aFmt.SetBulletFont( &aCreateFont ); + } + }else + aFmt.SetBulletFont( &rActBulletFont ); + + sal_UCS4 cChar = 0; + if( !pLevelSettings->sBulletChar.isEmpty() ) + { + cChar + = pLevelSettings->sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0))); + } + if( AllSettings::GetLayoutRTL() ) + { + if( 0 == i && cChar == BulletsTypeMgr::aDynamicBulletTypes[5] ) + cChar = BulletsTypeMgr::aDynamicRTLBulletTypes[5]; + else if( 1 == i ) + { + const SvxNumberFormat& numberFmt = aNum.GetLevel(0); + if( numberFmt.GetBulletChar() == BulletsTypeMgr::aDynamicRTLBulletTypes[5] ) + cChar = BulletsTypeMgr::aDynamicRTLBulletTypes[4]; + } + } + + aFmt.SetBulletChar(cChar); + aFmt.SetCharFormatName( GetBulletCharFmtName() ); + if (isResetSize) aFmt.SetBulletRelSize(45); + }else if ((aFmt.GetNumberingType()&(~LINK_TOKEN)) == SVX_NUM_BITMAP ) { + if (pLevelSettings->pBrushItem) { + const Graphic* pGrf = pLevelSettings->pBrushItem->GetGraphic(); + Size aSize = pLevelSettings->aSize; + sal_Int16 eOrient = text::VertOrientation::LINE_CENTER; + if (!isResetSize && aFmt.GetGraphicSize()!=Size(0,0)) + aSize = aFmt.GetGraphicSize(); + else if (aSize.IsEmpty() && pGrf) + aSize = SvxNumberFormat::GetGraphicSizeMM100( pGrf ); + aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(GetMapUnit())); + aFmt.SetGraphicBrush( pLevelSettings->pBrushItem, &aSize, &eOrient ); + } + } else + { + aFmt.SetIncludeUpperLevels(sal::static_int_cast< sal_uInt8 >(0 != nUpperLevelOrChar ? aNum.GetLevelCount() : 1)); + aFmt.SetCharFormatName(GetNumCharFmtName()); + if (isResetSize) aFmt.SetBulletRelSize(100); + } + if(pNumSettingsArr->size() > i) { + aFmt.SetLabelFollowedBy(pLevelSettings->eLabelFollowedBy); + aFmt.SetListtabPos(pLevelSettings->nTabValue); + aFmt.SetNumAdjust(pLevelSettings->eNumAlign); + aFmt.SetFirstLineIndent(pLevelSettings->nNumAlignAt); + aFmt.SetIndentAt(pLevelSettings->nNumIndentAt); + } + aFmt.SetListFormat(pLevelSettings->sPrefix, pLevelSettings->sSuffix, i); + aNum.SetLevel(i, aFmt); + } +} + +OUString OutlineTypeMgr::GetDescription(sal_uInt16 nIndex, bool isDefault) +{ + OUString sRet; + + if ( nIndex >= SAL_N_ELEMENTS(pOutlineSettingsArrs) ) + return sRet; + else + { + OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex]; + if (isDefault) pItemArr = pDefaultOutlineSettingsArrs[nIndex]; + if ( pItemArr ) + { + sRet = pItemArr->sDescription; + } + } + return sRet; +} + +bool OutlineTypeMgr::IsCustomized(sal_uInt16 nIndex) +{ + bool bRet = false; + + if ( nIndex >= SAL_N_ELEMENTS(pOutlineSettingsArrs) ) + return bRet; + else + { + OutlineSettings_Impl* pItemArr = pOutlineSettingsArrs[nIndex]; + if ( pItemArr ) + { + bRet = pItemArr->bIsCustomized; + } + } + + return bRet; +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/nbdtmgfact.cxx b/svx/source/sidebar/nbdtmgfact.cxx new file mode 100644 index 0000000000..14dcd64c43 --- /dev/null +++ b/svx/source/sidebar/nbdtmgfact.cxx @@ -0,0 +1,42 @@ +/* -*- 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/nbdtmgfact.hxx> + +namespace svx::sidebar::NBOutlineTypeMgrFact +{ +NBOTypeMgrBase* CreateInstance(const NBOType aType) +{ + if (aType == NBOType::Bullets) + { + return &BulletsTypeMgr::GetInstance(); + } + else if (aType == NBOType::Numbering) + { + return &NumberingTypeMgr::GetInstance(); + } + else if (aType == NBOType::Outline) + { + return &OutlineTypeMgr::GetInstance(); + } + return nullptr; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/paragraph/ParaLineSpacingControl.cxx b/svx/source/sidebar/paragraph/ParaLineSpacingControl.cxx new file mode 100644 index 0000000000..bda7eb62e6 --- /dev/null +++ b/svx/source/sidebar/paragraph/ParaLineSpacingControl.cxx @@ -0,0 +1,447 @@ +/* -*- 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 "ParaLineSpacingControl.hxx" + +#include <editeng/editids.hrc> +#include <editeng/lspcitem.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/module.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/viewfrm.hxx> +#include <svtools/unitconv.hxx> + +#include <svl/intitem.hxx> +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> + +#include <ParaLineSpacingPopup.hxx> + +#include <vcl/commandinfoprovider.hxx> + +#define DEFAULT_LINE_SPACING 200 +#define FIX_DIST_DEF 283 +#define LINESPACE_1 100 +#define LINESPACE_15 150 +#define LINESPACE_2 200 +#define LINESPACE_115 115 + +// values of the mxLineDist listbox +#define LLINESPACE_1 0 +#define LLINESPACE_115 1 +#define LLINESPACE_15 2 +#define LLINESPACE_2 3 +#define LLINESPACE_PROP 4 +#define LLINESPACE_MIN 5 +#define LLINESPACE_DURCH 6 +#define LLINESPACE_FIX 7 + +#define MIN_FIXED_DISTANCE 28 + +using namespace svx; + +ParaLineSpacingControl::ParaLineSpacingControl(SvxLineSpacingToolBoxControl* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/paralinespacingcontrol.ui", "ParaLineSpacingControl") + , mxControl(pControl) + , meLNSpaceUnit(MapUnit::Map100thMM) + , mxSpacing1Button(m_xBuilder->weld_button("spacing_1")) + , mxSpacing115Button(m_xBuilder->weld_button("spacing_115")) + , mxSpacing15Button(m_xBuilder->weld_button("spacing_15")) + , mxSpacing2Button(m_xBuilder->weld_button("spacing_2")) + , mxLineDist(m_xBuilder->weld_combo_box("line_dist")) + , mxLineDistLabel(m_xBuilder->weld_label("value_label")) + , mxLineDistAtPercentBox(m_xBuilder->weld_metric_spin_button("percent_box", FieldUnit::PERCENT)) + , mxLineDistAtMetricBox(m_xBuilder->weld_metric_spin_button("metric_box", FieldUnit::CM)) + , mpActLineDistFld(mxLineDistAtPercentBox.get()) +{ + Link<weld::Button&,void> aLink = LINK(this, ParaLineSpacingControl, PredefinedValuesHandler); + mxSpacing1Button->connect_clicked(aLink); + mxSpacing115Button->connect_clicked(aLink); + mxSpacing15Button->connect_clicked(aLink); + mxSpacing2Button->connect_clicked(aLink); + + Link<weld::ComboBox&,void> aLink3 = LINK( this, ParaLineSpacingControl, LineSPDistHdl_Impl ); + mxLineDist->connect_changed(aLink3); + SelectEntryPos(LLINESPACE_1); + + Link<weld::MetricSpinButton&,void> aLink2 = LINK( this, ParaLineSpacingControl, LineSPDistAtHdl_Impl ); + mxLineDistAtPercentBox->connect_value_changed( aLink2 ); + mxLineDistAtMetricBox->connect_value_changed( aLink2 ); + + FieldUnit eUnit = FieldUnit::INCH; + SfxPoolItemHolder aResult; + SfxViewFrame* pCurrent(SfxViewFrame::Current()); + if (pCurrent && pCurrent->GetBindings().GetDispatcher()->QueryState(SID_ATTR_METRIC, aResult) >= SfxItemState::DEFAULT) + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(aResult.getItem())->GetValue()); + else + eUnit = SfxModule::GetCurrentFieldUnit(); + + SetFieldUnit(*mxLineDistAtMetricBox, eUnit); + + Initialize(); +} + +void ParaLineSpacingControl::GrabFocus() +{ + switch (mxLineDist->get_active()) + { + case LLINESPACE_1: + mxSpacing1Button->grab_focus(); + break; + case LLINESPACE_115: + mxSpacing115Button->grab_focus(); + break; + case LLINESPACE_15: + mxSpacing15Button->grab_focus(); + break; + case LLINESPACE_2: + mxSpacing2Button->grab_focus(); + break; + default: + mxLineDist->grab_focus(); + break; + } +} + +ParaLineSpacingControl::~ParaLineSpacingControl() +{ +} + +void ParaLineSpacingControl::Initialize() +{ + SfxPoolItemHolder aResult; + SfxViewFrame* pCurrent = SfxViewFrame::Current(); + const bool bItemStateSet(nullptr != pCurrent); + const SfxItemState eState(bItemStateSet + ? pCurrent->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PARA_LINESPACE, aResult) + : SfxItemState::DEFAULT); + + mxLineDist->set_sensitive(true); + + if( bItemStateSet && (eState == SfxItemState::DEFAULT || eState == SfxItemState::SET) ) + { + const SvxLineSpacingItem* currSPItem(static_cast<const SvxLineSpacingItem*>(aResult.getItem())); + // It seems draw/impress and writer require different MapUnit values for fixed line spacing + // metric values to be correctly calculated. + MapUnit eUnit = MapUnit::Map100thMM; // works for draw/impress + if (vcl::CommandInfoProvider::GetModuleIdentifier(pCurrent->GetFrame().GetFrameInterface()) + == "com.sun.star.text.TextDocument") + eUnit = MapUnit::MapTwip; // works for writer + meLNSpaceUnit = eUnit; + + switch( currSPItem->GetLineSpaceRule() ) + { + case SvxLineSpaceRule::Auto: + { + SvxInterLineSpaceRule eInter = currSPItem->GetInterLineSpaceRule(); + + switch( eInter ) + { + case SvxInterLineSpaceRule::Off: + SelectEntryPos(LLINESPACE_1); + break; + + case SvxInterLineSpaceRule::Prop: + { + if ( LINESPACE_1 == currSPItem->GetPropLineSpace() ) + { + SelectEntryPos(LLINESPACE_1); + } + else if ( LINESPACE_115 == currSPItem->GetPropLineSpace() ) + { + SelectEntryPos(LLINESPACE_115); + } + else if ( LINESPACE_15 == currSPItem->GetPropLineSpace() ) + { + SelectEntryPos(LLINESPACE_15); + } + else if ( LINESPACE_2 == currSPItem->GetPropLineSpace() ) + { + SelectEntryPos(LLINESPACE_2); + } + else + { + SelectEntryPos(LLINESPACE_PROP); + mxLineDistAtPercentBox->set_value(mxLineDistAtPercentBox->normalize(currSPItem->GetPropLineSpace()), FieldUnit::PERCENT); + } + } + break; + + case SvxInterLineSpaceRule::Fix: + { + SelectEntryPos(LLINESPACE_DURCH); + SetMetricValue(*mxLineDistAtMetricBox, currSPItem->GetInterLineSpace(), eUnit); + } + break; + default: + break; + } + } + break; + case SvxLineSpaceRule::Fix: + { + SelectEntryPos(LLINESPACE_FIX); + SetMetricValue(*mxLineDistAtMetricBox, currSPItem->GetLineHeight(), eUnit); + } + break; + + case SvxLineSpaceRule::Min: + { + SelectEntryPos(LLINESPACE_MIN); + SetMetricValue(*mxLineDistAtMetricBox, currSPItem->GetLineHeight(), eUnit); + } + break; + default: + break; + } + } + else if( bItemStateSet && eState == SfxItemState::DISABLED ) + { + mxLineDist->set_sensitive(false); + mxLineDistLabel->set_sensitive(false); + mpActLineDistFld->set_sensitive(false); + mpActLineDistFld->set_text(""); + + } + else // !bItemStateSet || eState == SfxItemState::DONTCARE || eState == SfxItemState::UNKNOWN + { + mxLineDistLabel->set_sensitive(false); + mpActLineDistFld->set_sensitive(false); + mpActLineDistFld->set_text(""); + mxLineDist->set_active(-1); + } + + mxLineDist->save_value(); +} + +void ParaLineSpacingControl::UpdateMetricFields() +{ + switch (mxLineDist->get_active()) + { + case LLINESPACE_1: + case LLINESPACE_115: + case LLINESPACE_15: + case LLINESPACE_2: + if (mpActLineDistFld == mxLineDistAtPercentBox.get()) + mxLineDistAtMetricBox->hide(); + else + mxLineDistAtPercentBox->hide(); + + mxLineDistLabel->set_sensitive(false); + mpActLineDistFld->show(); + mpActLineDistFld->set_sensitive(false); + mpActLineDistFld->set_text(""); + break; + + case LLINESPACE_DURCH: + mxLineDistAtPercentBox->hide(); + + mpActLineDistFld = mxLineDistAtMetricBox.get(); + mxLineDistAtMetricBox->set_min(0, FieldUnit::NONE); + + if (mxLineDistAtMetricBox->get_text().isEmpty()) + mxLineDistAtMetricBox->set_value(mxLineDistAtMetricBox->normalize(0), FieldUnit::NONE); + + mxLineDistLabel->set_sensitive(true); + mpActLineDistFld->show(); + mpActLineDistFld->set_sensitive(true); + break; + + case LLINESPACE_MIN: + mxLineDistAtPercentBox->hide(); + + mpActLineDistFld = mxLineDistAtMetricBox.get(); + mxLineDistAtMetricBox->set_min(0, FieldUnit::NONE); + + if (mxLineDistAtMetricBox->get_text().isEmpty()) + mxLineDistAtMetricBox->set_value(mxLineDistAtMetricBox->normalize(0), FieldUnit::TWIP); + + mxLineDistLabel->set_sensitive(true); + mpActLineDistFld->show(); + mpActLineDistFld->set_sensitive(true); + break; + + case LLINESPACE_PROP: + mxLineDistAtMetricBox->hide(); + + mpActLineDistFld = mxLineDistAtPercentBox.get(); + + if (mxLineDistAtPercentBox->get_text().isEmpty()) + mxLineDistAtPercentBox->set_value(mxLineDistAtPercentBox->normalize(100), FieldUnit::TWIP); + + mxLineDistLabel->set_sensitive(true); + mpActLineDistFld->show(); + mpActLineDistFld->set_sensitive(true); + break; + + case LLINESPACE_FIX: + mxLineDistAtPercentBox->hide(); + + mpActLineDistFld = mxLineDistAtMetricBox.get(); + sal_Int64 nTemp = mxLineDistAtMetricBox->get_value(FieldUnit::NONE); + mxLineDistAtMetricBox->set_min(mxLineDistAtMetricBox->normalize(MIN_FIXED_DISTANCE), FieldUnit::TWIP); + + if (mxLineDistAtMetricBox->get_value(FieldUnit::NONE) != nTemp) + SetMetricValue(*mxLineDistAtMetricBox, FIX_DIST_DEF, MapUnit::MapTwip); + + mxLineDistLabel->set_sensitive(true); + mpActLineDistFld->show(); + mpActLineDistFld->set_sensitive(true); + break; + } +} + +void ParaLineSpacingControl::SelectEntryPos(sal_Int32 nPos) +{ + mxLineDist->set_active(nPos); + UpdateMetricFields(); +} + +IMPL_LINK_NOARG(ParaLineSpacingControl, LineSPDistHdl_Impl, weld::ComboBox&, void) +{ + UpdateMetricFields(); + ExecuteLineSpace(); +} + +IMPL_LINK_NOARG( ParaLineSpacingControl, LineSPDistAtHdl_Impl, weld::MetricSpinButton&, void ) +{ + ExecuteLineSpace(); +} + +void ParaLineSpacingControl::ExecuteLineSpace() +{ + mxLineDist->save_value(); + + SvxLineSpacingItem aSpacing(DEFAULT_LINE_SPACING, SID_ATTR_PARA_LINESPACE); + const sal_Int32 nPos = mxLineDist->get_active(); + + switch ( nPos ) + { + case LLINESPACE_1: + case LLINESPACE_115: + case LLINESPACE_15: + case LLINESPACE_2: + SetLineSpace(aSpacing, nPos); + break; + + case LLINESPACE_PROP: + SetLineSpace(aSpacing, nPos, mxLineDistAtPercentBox->denormalize(static_cast<tools::Long>(mxLineDistAtPercentBox->get_value(FieldUnit::PERCENT)))); + break; + + case LLINESPACE_MIN: + case LLINESPACE_DURCH: + case LLINESPACE_FIX: + SetLineSpace(aSpacing, nPos, GetCoreValue(*mxLineDistAtMetricBox, meLNSpaceUnit)); + break; + + default: + break; + } + + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + pViewFrm->GetBindings().GetDispatcher()->ExecuteList( + SID_ATTR_PARA_LINESPACE, SfxCallMode::RECORD, { &aSpacing }); + } +} + +void ParaLineSpacingControl::SetLineSpace(SvxLineSpacingItem& rLineSpace, sal_Int32 eSpace, tools::Long lValue) +{ + switch ( eSpace ) + { + case LLINESPACE_1: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + + case LLINESPACE_115: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( LINESPACE_115 ); + break; + + case LLINESPACE_15: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( LINESPACE_15 ); + break; + + case LLINESPACE_2: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( LINESPACE_2 ); + break; + + case LLINESPACE_PROP: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( static_cast<sal_uInt16>(lValue) ); + break; + + case LLINESPACE_MIN: + rLineSpace.SetLineHeight( static_cast<sal_uInt16>(lValue) ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + + case LLINESPACE_DURCH: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetInterLineSpace( static_cast<sal_uInt16>(lValue) ); + break; + + case LLINESPACE_FIX: + rLineSpace.SetLineHeight(static_cast<sal_uInt16>(lValue)); + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Fix ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + } +} + +IMPL_LINK(ParaLineSpacingControl, PredefinedValuesHandler, weld::Button&, rControl, void) +{ + if (&rControl == mxSpacing1Button.get()) + { + ExecuteLineSpacing(LLINESPACE_1); + } + else if (&rControl == mxSpacing115Button.get()) + { + ExecuteLineSpacing(LLINESPACE_115); + } + else if (&rControl == mxSpacing15Button.get()) + { + ExecuteLineSpacing(LLINESPACE_15); + } + else if (&rControl == mxSpacing2Button.get()) + { + ExecuteLineSpacing(LLINESPACE_2); + } +} + +void ParaLineSpacingControl::ExecuteLineSpacing(sal_Int32 nEntry) +{ + SvxLineSpacingItem aSpacing(DEFAULT_LINE_SPACING, SID_ATTR_PARA_LINESPACE); + + SetLineSpace(aSpacing, nEntry); + + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + pViewFrm->GetBindings().GetDispatcher()->ExecuteList( + SID_ATTR_PARA_LINESPACE, SfxCallMode::RECORD, { &aSpacing }); + } + + // close when the user used the buttons + mxControl->EndPopupMode(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/paragraph/ParaLineSpacingControl.hxx b/svx/source/sidebar/paragraph/ParaLineSpacingControl.hxx new file mode 100644 index 0000000000..e49556f16c --- /dev/null +++ b/svx/source/sidebar/paragraph/ParaLineSpacingControl.hxx @@ -0,0 +1,80 @@ +/* -*- 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 . + */ +#pragma once + +#include <svtools/toolbarmenu.hxx> + +class SvxLineSpacingItem; + +namespace svx +{ +class SvxLineSpacingToolBoxControl; + +class ParaLineSpacingControl : public WeldToolbarPopup +{ +public: + explicit ParaLineSpacingControl(SvxLineSpacingToolBoxControl* pControl, weld::Widget* pParent); + virtual ~ParaLineSpacingControl() override; + + /// Setup the widgets with values from the document. + void Initialize(); + + virtual void GrabFocus() override; + +private: + rtl::Reference<SvxLineSpacingToolBoxControl> mxControl; + + MapUnit meLNSpaceUnit; + + std::unique_ptr<weld::Button> mxSpacing1Button; + std::unique_ptr<weld::Button> mxSpacing115Button; + std::unique_ptr<weld::Button> mxSpacing15Button; + std::unique_ptr<weld::Button> mxSpacing2Button; + + std::unique_ptr<weld::ComboBox> mxLineDist; + + std::unique_ptr<weld::Label> mxLineDistLabel; + std::unique_ptr<weld::MetricSpinButton> mxLineDistAtPercentBox; + std::unique_ptr<weld::MetricSpinButton> mxLineDistAtMetricBox; + weld::MetricSpinButton* mpActLineDistFld; + +private: + /// Take the values from the widgets, and update the paragraph accordingly. + void ExecuteLineSpace(); + + /// Set one particular value. + static void SetLineSpace(SvxLineSpacingItem& rLineSpace, sal_Int32 eSpace, + tools::Long lValue = 0); + + /// For the buttons - set the values, and close the popup. + void ExecuteLineSpacing(sal_Int32 aEntry); + + /// Set mpActlineDistFld and visibility of mpLineDist* fields according to what is just selected. + void UpdateMetricFields(); + + /// Set the entry and update the metric fields. + void SelectEntryPos(sal_Int32 nPos); + + DECL_LINK(LineSPDistHdl_Impl, weld::ComboBox&, void); + DECL_LINK(LineSPDistAtHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(PredefinedValuesHandler, weld::Button&, void); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/paragraph/ParaLineSpacingPopup.cxx b/svx/source/sidebar/paragraph/ParaLineSpacingPopup.cxx new file mode 100644 index 0000000000..c6476185a6 --- /dev/null +++ b/svx/source/sidebar/paragraph/ParaLineSpacingPopup.cxx @@ -0,0 +1,99 @@ +/* -*- 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 "ParaLineSpacingControl.hxx" + +#include <ParaLineSpacingPopup.hxx> +#include <vcl/toolbox.hxx> + +using namespace svx; + +SvxLineSpacingToolBoxControl::SvxLineSpacingToolBoxControl( + const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +SvxLineSpacingToolBoxControl::~SvxLineSpacingToolBoxControl() {} + +void SvxLineSpacingToolBoxControl::initialize(const css::uno::Sequence<css::uno::Any>& rArguments) +{ + PopupWindowController::initialize(rArguments); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel()); + } + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +void SAL_CALL SvxLineSpacingToolBoxControl::execute(sal_Int16 /*KeyModifier*/) +{ + if (m_pToolbar) + { + // Toggle the popup also when toolbutton is activated + m_pToolbar->set_menu_item_active(m_aCommandURL, + !m_pToolbar->get_menu_item_active(m_aCommandURL)); + } + else + { + // Open the popup also when Enter key is pressed. + createPopupWindow(); + } +} + +std::unique_ptr<WeldToolbarPopup> SvxLineSpacingToolBoxControl::weldPopupWindow() +{ + return std::make_unique<ParaLineSpacingControl>(this, m_pToolbar); +} + +VclPtr<vcl::Window> SvxLineSpacingToolBoxControl::createVclPopupWindow(vcl::Window* pParent) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create( + getFrameInterface(), pParent, + std::make_unique<ParaLineSpacingControl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString SvxLineSpacingToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.LineSpacingToolBoxControl"; +} + +css::uno::Sequence<OUString> SvxLineSpacingToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_LineSpacingToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SvxLineSpacingToolBoxControl(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/paragraph/ParaPropertyPanel.cxx b/svx/source/sidebar/paragraph/ParaPropertyPanel.cxx new file mode 100644 index 0000000000..20e05096d6 --- /dev/null +++ b/svx/source/sidebar/paragraph/ParaPropertyPanel.cxx @@ -0,0 +1,492 @@ +/* -*- 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 "ParaPropertyPanel.hxx" +#include <sfx2/dispatch.hxx> +#include <sfx2/module.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/weldutils.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <svx/dlgctrl.hxx> +#include <svx/svxids.hrc> +#include <svl/intitem.hxx> +#include <sfx2/objsh.hxx> +#include <svtools/unitconv.hxx> +#include <sal/log.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <utility> + +using namespace css; +using namespace css::uno; + +namespace svx::sidebar { +#define DEFAULT_VALUE 0 + +#define MAX_DURCH 31680 // tdf#68335: 1584 pt for UX interoperability with Word + +#define MAX_SW 1709400 +#define MAX_SC_SD 116220200 +#define NEGA_MAXVALUE -10000000 + +std::unique_ptr<PanelLayout> ParaPropertyPanel::Create ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings, + const css::uno::Reference<css::ui::XSidebar>& rxSidebar) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to ParaPropertyPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to ParaPropertyPanel::Create", nullptr, 1); + if (pBindings == nullptr) + throw lang::IllegalArgumentException("no SfxBindings given to ParaPropertyPanel::Create", nullptr, 2); + + return std::make_unique<ParaPropertyPanel>(pParent, rxFrame, pBindings, rxSidebar); +} + +void ParaPropertyPanel::HandleContextChange ( + const vcl::EnumContext& rContext) +{ + if (maContext == rContext) + { + // Nothing to do. + return; + } + + maContext = rContext; + switch (maContext.GetCombinedContext_DI()) + { + case CombinedEnumContext(Application::Calc, Context::DrawText): + case CombinedEnumContext(Application::WriterVariants, Context::DrawText): + mxTBxVertAlign->show(); + mxTBxBackColor->hide(); + mxTBxNumBullet->hide(); + ReSize(); + break; + + case CombinedEnumContext(Application::DrawImpress, Context::Draw): + case CombinedEnumContext(Application::DrawImpress, Context::TextObject): + case CombinedEnumContext(Application::DrawImpress, Context::Graphic): + case CombinedEnumContext(Application::DrawImpress, Context::DrawText): + case CombinedEnumContext(Application::DrawImpress, Context::Table): + mxTBxVertAlign->show(); + mxTBxBackColor->hide(); + mxTBxNumBullet->hide(); + ReSize(); + break; + + case CombinedEnumContext(Application::WriterVariants, Context::Default): + case CombinedEnumContext(Application::WriterVariants, Context::Text): + mxTBxVertAlign->hide(); + mxTBxBackColor->show(); + mxTBxNumBullet->show(); + ReSize(); + break; + + case CombinedEnumContext(Application::WriterVariants, Context::Table): + mxTBxVertAlign->show(); + mxTBxBackColor->show(); + mxTBxNumBullet->show(); + ReSize(); + break; + + case CombinedEnumContext(Application::WriterVariants, Context::Annotation): + mxTBxVertAlign->hide(); + mxTBxBackColor->hide(); + mxTBxNumBullet->hide(); + ReSize(); + break; + + case CombinedEnumContext(Application::Calc, Context::EditCell): + case CombinedEnumContext(Application::Calc, Context::Cell): + case CombinedEnumContext(Application::Calc, Context::Pivot): + case CombinedEnumContext(Application::Calc, Context::Sparkline): + case CombinedEnumContext(Application::DrawImpress, Context::Text): + case CombinedEnumContext(Application::DrawImpress, Context::OutlineText): + break; + + default: + break; + } +} + +void ParaPropertyPanel::ReSize() +{ + if (mxSidebar.is()) + mxSidebar->requestLayout(); +} + +void ParaPropertyPanel::InitToolBoxIndent() +{ + Link<weld::MetricSpinButton&,void> aLink = LINK( this, ParaPropertyPanel, ModifyIndentHdl_Impl ); + mxLeftIndent->connect_value_changed( aLink ); + mxRightIndent->connect_value_changed( aLink ); + mxFLineIndent->connect_value_changed( aLink ); + + m_eLRSpaceUnit = maLRSpaceControl.GetCoreMetric(); +} + +void ParaPropertyPanel::InitToolBoxSpacing() +{ + Link<weld::MetricSpinButton&,void> aLink = LINK( this, ParaPropertyPanel, ULSpaceHdl_Impl ); + mxTopDist->connect_value_changed(aLink); + mxBottomDist->connect_value_changed( aLink ); + + m_eULSpaceUnit = maULSpaceControl.GetCoreMetric(); +} + +void ParaPropertyPanel::initial() +{ + limitMetricWidths(); + + //toolbox + InitToolBoxIndent(); + InitToolBoxSpacing(); +} + +// for Paragraph Indent +IMPL_LINK_NOARG( ParaPropertyPanel, ModifyIndentHdl_Impl, weld::MetricSpinButton&, void) +{ + SvxLRSpaceItem aMargin( SID_ATTR_PARA_LRSPACE ); + aMargin.SetTextLeft(mxLeftIndent->GetCoreValue(m_eLRSpaceUnit)); + aMargin.SetRight(mxRightIndent->GetCoreValue(m_eLRSpaceUnit)); + aMargin.SetTextFirstLineOffset(static_cast<short>(mxFLineIndent->GetCoreValue(m_eLRSpaceUnit))); + + GetBindings()->GetDispatcher()->ExecuteList( + SID_ATTR_PARA_LRSPACE, SfxCallMode::RECORD, { &aMargin }); +} + + +// for Paragraph Spacing +IMPL_LINK_NOARG( ParaPropertyPanel, ULSpaceHdl_Impl, weld::MetricSpinButton&, void) +{ + SvxULSpaceItem aMargin( SID_ATTR_PARA_ULSPACE ); + aMargin.SetUpper( static_cast<sal_uInt16>(mxTopDist->GetCoreValue(m_eULSpaceUnit))); + aMargin.SetLower( static_cast<sal_uInt16>(mxBottomDist->GetCoreValue(m_eULSpaceUnit))); + + GetBindings()->GetDispatcher()->ExecuteList( + SID_ATTR_PARA_ULSPACE, SfxCallMode::RECORD, { &aMargin }); +} + +// for Paragraph State change +void ParaPropertyPanel::NotifyItemUpdate( + sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState) +{ + switch (nSID) + { + case SID_ATTR_METRIC: + { + m_eMetricUnit = GetCurrentUnit(eState,pState); + if( m_eMetricUnit!=m_last_eMetricUnit ) + { + mxLeftIndent->SetFieldUnit(m_eMetricUnit); + mxRightIndent->SetFieldUnit(m_eMetricUnit); + mxFLineIndent->SetFieldUnit(m_eMetricUnit); + mxTopDist->SetFieldUnit(m_eMetricUnit); + mxBottomDist->SetFieldUnit(m_eMetricUnit); + + limitMetricWidths(); + } + m_last_eMetricUnit = m_eMetricUnit; + } + break; + + case SID_ATTR_PARA_LRSPACE: + StateChangedIndentImpl( eState, pState ); + break; + + case SID_ATTR_PARA_ULSPACE: + StateChangedULImpl( eState, pState ); + break; + } +} + +void ParaPropertyPanel::StateChangedIndentImpl( SfxItemState eState, const SfxPoolItem* pState ) +{ + switch (maContext.GetCombinedContext_DI()) + { + + case CombinedEnumContext(Application::WriterVariants, Context::DrawText): + case CombinedEnumContext(Application::WriterVariants, Context::Annotation): + case CombinedEnumContext(Application::Calc, Context::DrawText): + case CombinedEnumContext(Application::DrawImpress, Context::DrawText): + case CombinedEnumContext(Application::DrawImpress, Context::Draw): + case CombinedEnumContext(Application::DrawImpress, Context::TextObject): + case CombinedEnumContext(Application::DrawImpress, Context::Graphic): + case CombinedEnumContext(Application::DrawImpress, Context::Table): + { + mxLeftIndent->set_min( DEFAULT_VALUE, FieldUnit::NONE ); + mxRightIndent->set_min( DEFAULT_VALUE, FieldUnit::NONE ); + mxFLineIndent->set_min( DEFAULT_VALUE, FieldUnit::NONE ); + } + break; + case CombinedEnumContext(Application::WriterVariants, Context::Default): + case CombinedEnumContext(Application::WriterVariants, Context::Text): + case CombinedEnumContext(Application::WriterVariants, Context::Table): + { + mxLeftIndent->set_min( NEGA_MAXVALUE, FieldUnit::MM_100TH ); + mxRightIndent->set_min( NEGA_MAXVALUE, FieldUnit::MM_100TH ); + mxFLineIndent->set_min( NEGA_MAXVALUE, FieldUnit::MM_100TH ); + } + break; + } + + bool bDisabled = eState == SfxItemState::DISABLED; + mxLeftIndent->set_sensitive(!bDisabled); + mxRightIndent->set_sensitive(!bDisabled); + mxFLineIndent->set_sensitive(!bDisabled); + + if (pState && eState >= SfxItemState::DEFAULT) + { + const SvxLRSpaceItem* pSpace = static_cast<const SvxLRSpaceItem*>(pState); + maTxtLeft = pSpace->GetTextLeft(); + maTxtLeft = OutputDevice::LogicToLogic(maTxtLeft, m_eLRSpaceUnit, MapUnit::MapTwip); + + tools::Long aTxtRight = pSpace->GetRight(); + aTxtRight = OutputDevice::LogicToLogic(aTxtRight, m_eLRSpaceUnit, MapUnit::MapTwip); + + tools::Long aTxtFirstLineOfst = pSpace->GetTextFirstLineOffset(); + aTxtFirstLineOfst = OutputDevice::LogicToLogic( aTxtFirstLineOfst, m_eLRSpaceUnit, MapUnit::MapTwip ); + + tools::Long nVal = o3tl::convert(maTxtLeft, o3tl::Length::twip, o3tl::Length::mm100); + nVal = static_cast<tools::Long>(mxLeftIndent->normalize( nVal )); + + if ( maContext.GetCombinedContext_DI() != CombinedEnumContext(Application::WriterVariants, Context::Text) + && maContext.GetCombinedContext_DI() != CombinedEnumContext(Application::WriterVariants, Context::Default) + && maContext.GetCombinedContext_DI() != CombinedEnumContext(Application::WriterVariants, Context::Table)) + { + mxFLineIndent->set_min( nVal*-1, FieldUnit::MM_100TH ); + } + + tools::Long nrVal = o3tl::convert(aTxtRight, o3tl::Length::twip, o3tl::Length::mm100); + nrVal = static_cast<tools::Long>(mxRightIndent->normalize( nrVal )); + + switch (maContext.GetCombinedContext_DI()) + { + case CombinedEnumContext(Application::WriterVariants, Context::DrawText): + case CombinedEnumContext(Application::WriterVariants, Context::Text): + case CombinedEnumContext(Application::WriterVariants, Context::Default): + case CombinedEnumContext(Application::WriterVariants, Context::Table): + case CombinedEnumContext(Application::WriterVariants, Context::Annotation): + { + mxLeftIndent->set_max( MAX_SW - nrVal, FieldUnit::MM_100TH ); + mxRightIndent->set_max( MAX_SW - nVal, FieldUnit::MM_100TH ); + mxFLineIndent->set_max( MAX_SW - nVal - nrVal, FieldUnit::MM_100TH ); + } + break; + case CombinedEnumContext(Application::DrawImpress, Context::DrawText): + case CombinedEnumContext(Application::DrawImpress, Context::Draw): + case CombinedEnumContext(Application::DrawImpress, Context::Table): + case CombinedEnumContext(Application::DrawImpress, Context::TextObject): + case CombinedEnumContext(Application::DrawImpress, Context::Graphic): + { + mxLeftIndent->set_max( MAX_SC_SD - nrVal, FieldUnit::MM_100TH ); + mxRightIndent->set_max( MAX_SC_SD - nVal, FieldUnit::MM_100TH ); + mxFLineIndent->set_max( MAX_SC_SD - nVal - nrVal, FieldUnit::MM_100TH ); + } + } + + mxLeftIndent->set_value( nVal, FieldUnit::MM_100TH ); + mxRightIndent->set_value( nrVal, FieldUnit::MM_100TH ); + + tools::Long nfVal = o3tl::convert(aTxtFirstLineOfst, o3tl::Length::twip, o3tl::Length::mm100); + nfVal = static_cast<tools::Long>(mxFLineIndent->normalize( nfVal )); + mxFLineIndent->set_value( nfVal, FieldUnit::MM_100TH ); + } + else if (eState != SfxItemState::DISABLED ) + { + mxLeftIndent->set_text(""); + mxRightIndent->set_text(""); + mxFLineIndent->set_text(""); + } + + limitMetricWidths(); +} + +void ParaPropertyPanel::StateChangedULImpl( SfxItemState eState, const SfxPoolItem* pState ) +{ + mxTopDist->set_max( mxTopDist->normalize( MAX_DURCH ), MapToFieldUnit(m_eULSpaceUnit) ); + mxBottomDist->set_max( mxBottomDist->normalize( MAX_DURCH ), MapToFieldUnit(m_eULSpaceUnit) ); + + bool bDisabled = eState == SfxItemState::DISABLED; + mxTopDist->set_sensitive(!bDisabled); + mxBottomDist->set_sensitive(!bDisabled); + + if( pState && eState >= SfxItemState::DEFAULT ) + { + const SvxULSpaceItem* pOldItem = static_cast<const SvxULSpaceItem*>(pState); + + maUpper = pOldItem->GetUpper(); + maUpper = OutputDevice::LogicToLogic(maUpper, m_eULSpaceUnit, MapUnit::MapTwip); + + maLower = pOldItem->GetLower(); + maLower = OutputDevice::LogicToLogic(maLower, m_eULSpaceUnit, MapUnit::MapTwip); + + sal_Int64 nVal = o3tl::convert(maUpper, o3tl::Length::twip, o3tl::Length::mm100); + nVal = mxTopDist->normalize( nVal ); + mxTopDist->set_value( nVal, FieldUnit::MM_100TH ); + + nVal = o3tl::convert(maLower, o3tl::Length::twip, o3tl::Length::mm100); + nVal = mxBottomDist->normalize( nVal ); + mxBottomDist->set_value( nVal, FieldUnit::MM_100TH ); + } + else if (eState != SfxItemState::DISABLED ) + { + mxTopDist->set_text(""); + mxBottomDist->set_text(""); + } + limitMetricWidths(); +} + +FieldUnit ParaPropertyPanel::GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState ) +{ + FieldUnit eUnit = FieldUnit::NONE; + + if ( pState && eState >= SfxItemState::DEFAULT ) + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue()); + else + { + SfxViewFrame* pFrame = SfxViewFrame::Current(); + SfxObjectShell* pSh = nullptr; + if ( pFrame ) + pSh = pFrame->GetObjectShell(); + if ( pSh ) //the object shell is not always available during reload + { + SfxModule* pModule = pSh->GetModule(); + if ( pModule ) + { + const SfxPoolItem* pItem = pModule->GetItem( SID_ATTR_METRIC ); + if ( pItem ) + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + } + else + { + SAL_WARN("svx.sidebar", "GetModuleFieldUnit(): no module found"); + } + } + } + + return eUnit; +} + +ParaPropertyPanel::ParaPropertyPanel(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings, + css::uno::Reference<css::ui::XSidebar> xSidebar) + : PanelLayout(pParent, "ParaPropertyPanel", "svx/ui/sidebarparagraph.ui"), + //Alignment + mxTBxHorzAlign(m_xBuilder->weld_toolbar("horizontalalignment")), + mxHorzAlignDispatch(new ToolbarUnoDispatcher(*mxTBxHorzAlign, *m_xBuilder, rxFrame)), + mxTBxVertAlign(m_xBuilder->weld_toolbar("verticalalignment")), + mxVertAlignDispatch(new ToolbarUnoDispatcher(*mxTBxVertAlign, *m_xBuilder, rxFrame)), + //NumBullet&Backcolor + mxTBxNumBullet(m_xBuilder->weld_toolbar("numberbullet")), + mxNumBulletDispatch(new ToolbarUnoDispatcher(*mxTBxNumBullet, *m_xBuilder, rxFrame)), + mxTBxBackColor(m_xBuilder->weld_toolbar("backgroundcolor")), + mxBackColorDispatch(new ToolbarUnoDispatcher(*mxTBxBackColor, *m_xBuilder, rxFrame)), + mxTBxWriteDirection(m_xBuilder->weld_toolbar("writedirection")), + mxWriteDirectionDispatch(new ToolbarUnoDispatcher(*mxTBxWriteDirection, *m_xBuilder, rxFrame)), + mxTBxParaSpacing(m_xBuilder->weld_toolbar("paraspacing")), + mxParaSpacingDispatch(new ToolbarUnoDispatcher(*mxTBxParaSpacing, *m_xBuilder, rxFrame)), + mxTBxLineSpacing(m_xBuilder->weld_toolbar("linespacing")), + mxLineSpacingDispatch(new ToolbarUnoDispatcher(*mxTBxLineSpacing, *m_xBuilder, rxFrame)), + mxTBxIndent(m_xBuilder->weld_toolbar("indent")), + mxIndentDispatch(new ToolbarUnoDispatcher(*mxTBxIndent, *m_xBuilder, rxFrame)), + //Paragraph spacing + mxTopDist(m_xBuilder->weld_metric_spin_button("aboveparaspacing", FieldUnit::CM)), + mxBottomDist(m_xBuilder->weld_metric_spin_button("belowparaspacing", FieldUnit::CM)), + mxLeftIndent(m_xBuilder->weld_metric_spin_button("beforetextindent", FieldUnit::CM)), + mxRightIndent(m_xBuilder->weld_metric_spin_button("aftertextindent", FieldUnit::CM)), + mxFLineIndent(m_xBuilder->weld_metric_spin_button("firstlineindent", FieldUnit::CM)), + maTxtLeft (0), + maUpper (0), + maLower (0), + m_eMetricUnit(FieldUnit::NONE), + m_last_eMetricUnit(FieldUnit::NONE), + m_eLRSpaceUnit(), + m_eULSpaceUnit(), + maLRSpaceControl (SID_ATTR_PARA_LRSPACE,*pBindings,*this), + maULSpaceControl (SID_ATTR_PARA_ULSPACE, *pBindings,*this), + m_aMetricCtl (SID_ATTR_METRIC, *pBindings,*this), + mpBindings(pBindings), + mxSidebar(std::move(xSidebar)) +{ + // tdf#130197 We want to give this toolbar a width as if it had 5 entries + // (the parent grid has homogeneous width set so both columns will have the + // same width). This ParaPropertyPanel is a default panel in writer, so + // subsequent panels, e.g. the TableEditPanel panel can have up to 5 + // entries in each of its column and remain in alignment with this panel + padWidthForSidebar(*mxTBxIndent, rxFrame); + + initial(); + m_aMetricCtl.RequestUpdate(); +} + +void ParaPropertyPanel::limitMetricWidths() +{ + limitWidthForSidebar(*mxTopDist); + limitWidthForSidebar(*mxBottomDist); + limitWidthForSidebar(*mxLeftIndent); + limitWidthForSidebar(*mxRightIndent); + limitWidthForSidebar(*mxFLineIndent); +} + +ParaPropertyPanel::~ParaPropertyPanel() +{ + mxHorzAlignDispatch.reset(); + mxTBxHorzAlign.reset(); + + mxVertAlignDispatch.reset(); + mxTBxVertAlign.reset(); + + mxNumBulletDispatch.reset(); + mxTBxNumBullet.reset(); + + mxBackColorDispatch.reset(); + mxTBxBackColor.reset(); + + mxWriteDirectionDispatch.reset(); + mxTBxWriteDirection.reset(); + + mxParaSpacingDispatch.reset(); + mxTBxParaSpacing.reset(); + + mxLineSpacingDispatch.reset(); + mxTBxLineSpacing.reset(); + + mxIndentDispatch.reset(); + mxTBxIndent.reset(); + + mxTopDist.reset(); + mxBottomDist.reset(); + mxLeftIndent.reset(); + mxRightIndent.reset(); + mxFLineIndent.reset(); + + maLRSpaceControl.dispose(); + maULSpaceControl.dispose(); + m_aMetricCtl.dispose(); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/paragraph/ParaPropertyPanel.hxx b/svx/source/sidebar/paragraph/ParaPropertyPanel.hxx new file mode 100644 index 0000000000..04bbf90653 --- /dev/null +++ b/svx/source/sidebar/paragraph/ParaPropertyPanel.hxx @@ -0,0 +1,135 @@ +/* -*- 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 . + */ +#pragma once + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/IContextChangeReceiver.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> +#include <svx/relfld.hxx> + +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/ui/XSidebar.hpp> + +#include <svl/poolitem.hxx> +#include <tools/fldunit.hxx> +#include <vcl/EnumContext.hxx> + +class ToolbarUnoDispatcher; + +namespace svx::sidebar { + +class ParaPropertyPanel + : public PanelLayout, + public ::sfx2::sidebar::IContextChangeReceiver, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + virtual ~ParaPropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings, + const css::uno::Reference<css::ui::XSidebar>& rxSidebar); + + SfxBindings* GetBindings() { return mpBindings;} + + virtual void HandleContextChange ( + const vcl::EnumContext& rContext) override; + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + static FieldUnit GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState ); + + ParaPropertyPanel ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings, + css::uno::Reference<css::ui::XSidebar> xSidebar); + +private: + // UI controls + //Alignment + std::unique_ptr<weld::Toolbar> mxTBxHorzAlign; + std::unique_ptr<ToolbarUnoDispatcher> mxHorzAlignDispatch; + std::unique_ptr<weld::Toolbar> mxTBxVertAlign; + std::unique_ptr<ToolbarUnoDispatcher> mxVertAlignDispatch; + //NumBullet&Backcolor + std::unique_ptr<weld::Toolbar> mxTBxNumBullet; + std::unique_ptr<ToolbarUnoDispatcher> mxNumBulletDispatch; + std::unique_ptr<weld::Toolbar> mxTBxBackColor; + std::unique_ptr<ToolbarUnoDispatcher> mxBackColorDispatch; + + std::unique_ptr<weld::Toolbar> mxTBxWriteDirection; + std::unique_ptr<ToolbarUnoDispatcher> mxWriteDirectionDispatch; + std::unique_ptr<weld::Toolbar> mxTBxParaSpacing; + std::unique_ptr<ToolbarUnoDispatcher> mxParaSpacingDispatch; + std::unique_ptr<weld::Toolbar> mxTBxLineSpacing; + std::unique_ptr<ToolbarUnoDispatcher> mxLineSpacingDispatch; + std::unique_ptr<weld::Toolbar> mxTBxIndent; + std::unique_ptr<ToolbarUnoDispatcher> mxIndentDispatch; + + //Paragraph spacing + std::optional<SvxRelativeField> mxTopDist; + std::optional<SvxRelativeField> mxBottomDist; + std::optional<SvxRelativeField> mxLeftIndent; + std::optional<SvxRelativeField> mxRightIndent; + std::optional<SvxRelativeField> mxFLineIndent; + + // Data Member + tools::Long maTxtLeft; + tools::Long maUpper; + tools::Long maLower; + + FieldUnit m_eMetricUnit; + FieldUnit m_last_eMetricUnit; + MapUnit m_eLRSpaceUnit; + MapUnit m_eULSpaceUnit; + // Control Items + ::sfx2::sidebar::ControllerItem maLRSpaceControl; + ::sfx2::sidebar::ControllerItem maULSpaceControl; + ::sfx2::sidebar::ControllerItem m_aMetricCtl; + + vcl::EnumContext maContext; + SfxBindings* mpBindings; + css::uno::Reference<css::ui::XSidebar> mxSidebar; + + DECL_LINK(ModifyIndentHdl_Impl, weld::MetricSpinButton&, void); + DECL_LINK(ULSpaceHdl_Impl, weld::MetricSpinButton&, void); + + void StateChangedIndentImpl( SfxItemState eState, const SfxPoolItem* pState ); + void StateChangedULImpl( SfxItemState eState, const SfxPoolItem* pState ); + + void initial(); + void ReSize(); + void InitToolBoxIndent(); + void InitToolBoxSpacing(); + void limitMetricWidths(); +}; + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/paragraph/ParaSpacingControl.cxx b/svx/source/sidebar/paragraph/ParaSpacingControl.cxx new file mode 100644 index 0000000000..5b4c409698 --- /dev/null +++ b/svx/source/sidebar/paragraph/ParaSpacingControl.cxx @@ -0,0 +1,257 @@ +/* -*- 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 "ParaSpacingWindow.hxx" + +#include <cppuhelper/queryinterface.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/editids.hrc> +#include <svx/ParaSpacingControl.hxx> +#include <vcl/toolbox.hxx> +#include <sfx2/sfxsids.hrc> +#include <svl/intitem.hxx> +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp> +#include <com/sun/star/ui/XContextChangeEventMultiplexer.hpp> + +using namespace svx; + +SFX_IMPL_TOOLBOX_CONTROL(ParaAboveSpacingControl, SvxULSpaceItem); +SFX_IMPL_TOOLBOX_CONTROL(ParaBelowSpacingControl, SvxULSpaceItem); + +SFX_IMPL_TOOLBOX_CONTROL(ParaLeftSpacingControl, SvxLRSpaceItem); +SFX_IMPL_TOOLBOX_CONTROL(ParaRightSpacingControl, SvxLRSpaceItem); +SFX_IMPL_TOOLBOX_CONTROL(ParaFirstLineSpacingControl, SvxLRSpaceItem); + +ParaULSpacingControl::ParaULSpacingControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx) + : SfxToolBoxControl(nSlotId, nId, rTbx) +{ + addStatusListener(".uno:MetricUnit"); +} + +ParaULSpacingControl::~ParaULSpacingControl() +{ +} + +void ParaULSpacingControl::StateChangedAtToolBoxControl(sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState) +{ + ToolBoxItemId nId = GetId(); + ToolBox& rTbx = GetToolBox(); + ParaULSpacingWindow* pWindow = static_cast<ParaULSpacingWindow*>(rTbx.GetItemWindow(nId)); + + DBG_ASSERT( pWindow, "Control not found!" ); + + if(SfxItemState::DISABLED == eState) + pWindow->Disable(); + else + pWindow->Enable(); + + rTbx.EnableItem(nId, SfxItemState::DISABLED != eState); + + if(nSID == SID_ATTR_METRIC && pState && eState >= SfxItemState::DEFAULT) + { + const SfxUInt16Item* pMetricItem = static_cast<const SfxUInt16Item*>(pState); + pWindow->SetUnit(static_cast<FieldUnit>(pMetricItem->GetValue())); + } + else if((nSID == SID_ATTR_PARA_ULSPACE + || nSID == SID_ATTR_PARA_ABOVESPACE + || nSID == SID_ATTR_PARA_BELOWSPACE ) + && pState && eState >= SfxItemState::DEFAULT) + pWindow->SetValue(static_cast<const SvxULSpaceItem*>(pState)); +} + +// ParaAboveSpacingControl + +ParaAboveSpacingControl::ParaAboveSpacingControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx) + : ParaULSpacingControl(nSlotId, nId, rTbx) +{ +} + +VclPtr<InterimItemWindow> ParaAboveSpacingControl::CreateItemWindow(vcl::Window* pParent) +{ + VclPtr<ParaAboveSpacingWindow> pWindow = VclPtr<ParaAboveSpacingWindow>::Create(pParent); + pWindow->Show(); + + return pWindow; +} + +// ParaBelowSpacingControl + +ParaBelowSpacingControl::ParaBelowSpacingControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx) + : ParaULSpacingControl(nSlotId, nId, rTbx) +{ +} + +VclPtr<InterimItemWindow> ParaBelowSpacingControl::CreateItemWindow(vcl::Window* pParent) +{ + VclPtr<ParaBelowSpacingWindow> pWindow = VclPtr<ParaBelowSpacingWindow>::Create(pParent); + pWindow->Show(); + + return pWindow; +} + +// ParaLRSpacingControl + +ParaLRSpacingControl::ParaLRSpacingControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx) + : SfxToolBoxControl(nSlotId, nId, rTbx) +{ + addStatusListener(".uno:MetricUnit"); +} + +ParaLRSpacingControl::~ParaLRSpacingControl() +{ +} + +void SAL_CALL ParaLRSpacingControl::dispose() +{ + if(m_xMultiplexer.is()) + { + m_xMultiplexer->removeAllContextChangeEventListeners(this); + m_xMultiplexer.clear(); + } + + SfxToolBoxControl::dispose(); +} + +void ParaLRSpacingControl::StateChangedAtToolBoxControl(sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState) +{ + ToolBoxItemId nId = GetId(); + ToolBox& rTbx = GetToolBox(); + ParaLRSpacingWindow* pWindow = static_cast<ParaLRSpacingWindow*>(rTbx.GetItemWindow(nId)); + + DBG_ASSERT( pWindow, "Control not found!" ); + + if(SfxItemState::DISABLED == eState) + pWindow->Disable(); + else + pWindow->Enable(); + + if(!m_xMultiplexer.is() && m_xFrame.is()) + { + m_xMultiplexer = css::ui::ContextChangeEventMultiplexer::get( + ::comphelper::getProcessComponentContext()); + + m_xMultiplexer->addContextChangeEventListener(this, m_xFrame->getController()); + } + + if(nSID == SID_ATTR_METRIC && pState && eState >= SfxItemState::DEFAULT) + { + const SfxUInt16Item* pMetricItem = static_cast<const SfxUInt16Item*>(pState); + pWindow->SetUnit(static_cast<FieldUnit>(pMetricItem->GetValue())); + } + else if(nSID == SID_ATTR_PARA_LRSPACE + || nSID == SID_ATTR_PARA_LEFTSPACE + || nSID == SID_ATTR_PARA_RIGHTSPACE + || nSID == SID_ATTR_PARA_FIRSTLINESPACE + ) + { + pWindow->SetValue(eState, pState); + } +} + +void SAL_CALL ParaLRSpacingControl::notifyContextChangeEvent(const css::ui::ContextChangeEventObject& rEvent) +{ + ToolBoxItemId nId = GetId(); + ToolBox& rTbx = GetToolBox(); + ParaLRSpacingWindow* pWindow = static_cast<ParaLRSpacingWindow*>(rTbx.GetItemWindow(nId)); + + if(pWindow) + { + vcl::EnumContext eContext( + vcl::EnumContext::GetApplicationEnum(rEvent.ApplicationName), + vcl::EnumContext::GetContextEnum(rEvent.ContextName)); + pWindow->SetContext(eContext); + } +} + +::css::uno::Any SAL_CALL ParaLRSpacingControl::queryInterface(const ::css::uno::Type& aType) +{ + ::css::uno::Any a(SfxToolBoxControl::queryInterface(aType)); + if (a.hasValue()) + return a; + + return ::cppu::queryInterface(aType, static_cast<css::ui::XContextChangeEventListener*>(this)); +} + +void SAL_CALL ParaLRSpacingControl::acquire() noexcept +{ + SfxToolBoxControl::acquire(); +} + +void SAL_CALL ParaLRSpacingControl::disposing(const ::css::lang::EventObject&) +{ + SfxToolBoxControl::disposing(); +} + +void SAL_CALL ParaLRSpacingControl::release() noexcept +{ + SfxToolBoxControl::release(); +} + +// ParaLeftSpacingControl + +ParaLeftSpacingControl::ParaLeftSpacingControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx) +: ParaLRSpacingControl(nSlotId, nId, rTbx) +{ +} + +VclPtr<InterimItemWindow> ParaLeftSpacingControl::CreateItemWindow(vcl::Window* pParent) +{ + VclPtr<ParaLeftSpacingWindow> pWindow = VclPtr<ParaLeftSpacingWindow>::Create(pParent); + pWindow->Show(); + + return pWindow; +} + +// ParaRightSpacingControl + +ParaRightSpacingControl::ParaRightSpacingControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx) +: ParaLRSpacingControl(nSlotId, nId, rTbx) +{ +} + +VclPtr<InterimItemWindow> ParaRightSpacingControl::CreateItemWindow(vcl::Window* pParent) +{ + VclPtr<ParaRightSpacingWindow> pWindow = VclPtr<ParaRightSpacingWindow>::Create(pParent); + pWindow->Show(); + + return pWindow; +} + +// ParaFirstLineSpacingControl + +ParaFirstLineSpacingControl::ParaFirstLineSpacingControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox& rTbx) +: ParaLRSpacingControl(nSlotId, nId, rTbx) +{ +} + +VclPtr<InterimItemWindow> ParaFirstLineSpacingControl::CreateItemWindow(vcl::Window* pParent) +{ + VclPtr<ParaFirstLineSpacingWindow> pWindow = VclPtr<ParaFirstLineSpacingWindow>::Create(pParent); + pWindow->Show(); + + return pWindow; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx b/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx new file mode 100644 index 0000000000..ac8749b3b3 --- /dev/null +++ b/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx @@ -0,0 +1,342 @@ +/* -*- 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 "ParaSpacingWindow.hxx" +#include <editeng/editids.hrc> +#include <editeng/lrspitem.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/app.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> + +using namespace svx; + +#define DEFAULT_VALUE 0 +#define MAX_DURCH 31680 // tdf#68335: 1584 pt for UX interoperability with Word +#define MAX_SW 1709400 +#define MAX_SC_SD 116220200 +#define NEGA_MAXVALUE -10000000 + +// ParaULSpacingWindow + +ParaULSpacingWindow::ParaULSpacingWindow(vcl::Window* pParent) + : InterimItemWindow(pParent, "svx/ui/paraulspacing.ui", "ParaULSpacingWindow") + , m_eUnit(MapUnit::MapTwip) +{ + m_xAboveSpacing.emplace(m_xBuilder->weld_metric_spin_button("aboveparaspacing", FieldUnit::CM)); + m_xBelowSpacing.emplace(m_xBuilder->weld_metric_spin_button("belowparaspacing", FieldUnit::CM)); + m_xAboveContainer = m_xBuilder->weld_container("above"); + m_xBelowContainer = m_xBuilder->weld_container("below"); + + Link<weld::MetricSpinButton&,void> aLink = LINK(this, ParaULSpacingWindow, ModifySpacingHdl); + m_xAboveSpacing->connect_value_changed(aLink); + m_xBelowSpacing->connect_value_changed(aLink); + + /// set the initial values of max width + m_xAboveSpacing->set_max(m_xAboveSpacing->normalize(MAX_DURCH), FieldUnit::CM); + m_xBelowSpacing->set_max(m_xBelowSpacing->normalize(MAX_DURCH), FieldUnit::CM); +} + +ParaULSpacingWindow::~ParaULSpacingWindow() +{ + disposeOnce(); +} + +void ParaULSpacingWindow::dispose() +{ + m_xAboveSpacing.reset(); + m_xBelowSpacing.reset(); + m_xAboveContainer.reset(); + m_xBelowContainer.reset(); + + InterimItemWindow::dispose(); +} + +void ParaULSpacingWindow::SetUnit(FieldUnit eUnit) +{ + m_xAboveSpacing->SetFieldUnit(eUnit); + m_xBelowSpacing->SetFieldUnit(eUnit); + + SfxItemPool &rPool = SfxGetpApp()->GetPool(); + m_eUnit = rPool.GetMetric(SID_ATTR_PARA_ULSPACE); + + m_xAboveSpacing->set_max(m_xAboveSpacing->normalize(MAX_DURCH), MapToFieldUnit(m_eUnit)); + m_xBelowSpacing->set_max(m_xBelowSpacing->normalize(MAX_DURCH), MapToFieldUnit(m_eUnit)); +} + +void ParaULSpacingWindow::SetValue(const SvxULSpaceItem* pItem) +{ + sal_Int64 nVal = pItem->GetUpper(); + nVal = m_xAboveSpacing->normalize(nVal); + m_xAboveSpacing->set_value(nVal, FieldUnit::MM_100TH); + + nVal = pItem->GetLower(); + nVal = m_xBelowSpacing->normalize(nVal); + m_xBelowSpacing->set_value(nVal, FieldUnit::MM_100TH); +} + +IMPL_LINK_NOARG(ParaULSpacingWindow, ModifySpacingHdl, weld::MetricSpinButton&, void) +{ + SfxViewFrame* pFrame = SfxViewFrame::Current(); + if (!pFrame) + return; + SfxDispatcher* pDisp = pFrame->GetBindings().GetDispatcher(); + if(pDisp) + { + SvxULSpaceItem aMargin(SID_ATTR_PARA_ULSPACE); + aMargin.SetUpper(m_xAboveSpacing->GetCoreValue(m_eUnit)); + aMargin.SetLower(m_xBelowSpacing->GetCoreValue(m_eUnit)); + pDisp->ExecuteList(SID_ATTR_PARA_ULSPACE, SfxCallMode::RECORD, {&aMargin}); + } +} + +// ParaAboveSpacingWindow +ParaAboveSpacingWindow::ParaAboveSpacingWindow(vcl::Window* pParent) + : ParaULSpacingWindow(pParent) +{ + InitControlBase(&m_xAboveSpacing->get_widget()); + + m_xAboveContainer->show(); + m_xBelowContainer->hide(); + + SetSizePixel(get_preferred_size()); +} + +// ParaBelowSpacingWindow +ParaBelowSpacingWindow::ParaBelowSpacingWindow(vcl::Window* pParent) + : ParaULSpacingWindow(pParent) +{ + InitControlBase(&m_xBelowSpacing->get_widget()); + + m_xAboveContainer->hide(); + m_xBelowContainer->show(); + + SetSizePixel(get_preferred_size()); +} + +// ParaLRSpacingWindow +ParaLRSpacingWindow::ParaLRSpacingWindow(vcl::Window* pParent) + : InterimItemWindow(pParent, "svx/ui/paralrspacing.ui", "ParaLRSpacingWindow") + , m_eUnit(MapUnit::MapTwip) +{ + m_xBeforeSpacing.emplace(m_xBuilder->weld_metric_spin_button("beforetextindent", FieldUnit::CM)); + m_xAfterSpacing.emplace(m_xBuilder->weld_metric_spin_button("aftertextindent", FieldUnit::CM)); + m_xFLSpacing.emplace(m_xBuilder->weld_metric_spin_button("firstlineindent", FieldUnit::CM)); + m_xBeforeContainer = m_xBuilder->weld_container("before"); + m_xAfterContainer = m_xBuilder->weld_container("after"); + m_xFirstLineContainer = m_xBuilder->weld_container("firstline"); + + Link<weld::MetricSpinButton&,void> aLink = LINK(this, ParaLRSpacingWindow, ModifySpacingHdl); + m_xBeforeSpacing->connect_value_changed(aLink); + m_xAfterSpacing->connect_value_changed(aLink); + m_xFLSpacing->connect_value_changed(aLink); + + /// set the initial values of max width + m_xBeforeSpacing->set_min(NEGA_MAXVALUE, FieldUnit::MM_100TH); + m_xAfterSpacing->set_min(NEGA_MAXVALUE, FieldUnit::MM_100TH); + m_xFLSpacing->set_min(NEGA_MAXVALUE, FieldUnit::MM_100TH); +} + +ParaLRSpacingWindow::~ParaLRSpacingWindow() +{ + disposeOnce(); +} + +void ParaLRSpacingWindow::dispose() +{ + m_xBeforeSpacing.reset(); + m_xAfterSpacing.reset(); + m_xFLSpacing.reset(); + m_xBeforeContainer.reset(); + m_xAfterContainer.reset(); + m_xFirstLineContainer.reset(); + + InterimItemWindow::dispose(); +} + +void ParaLRSpacingWindow::SetContext(const vcl::EnumContext& eContext) +{ + m_aContext = eContext; +} + +void ParaLRSpacingWindow::SetValue(SfxItemState eState, const SfxPoolItem* pState) +{ + switch(m_aContext.GetCombinedContext_DI()) + { + + case CombinedEnumContext(Application::WriterVariants, Context::DrawText): + case CombinedEnumContext(Application::WriterVariants, Context::Annotation): + case CombinedEnumContext(Application::Calc, Context::DrawText): + case CombinedEnumContext(Application::DrawImpress, Context::DrawText): + case CombinedEnumContext(Application::DrawImpress, Context::Draw): + case CombinedEnumContext(Application::DrawImpress, Context::TextObject): + case CombinedEnumContext(Application::DrawImpress, Context::Graphic): + case CombinedEnumContext(Application::DrawImpress, Context::Table): + { + m_xBeforeSpacing->set_min(DEFAULT_VALUE, FieldUnit::NONE); + m_xAfterSpacing->set_min(DEFAULT_VALUE, FieldUnit::NONE); + m_xFLSpacing->set_min(DEFAULT_VALUE, FieldUnit::NONE); + } + break; + case CombinedEnumContext(Application::WriterVariants, Context::Default): + case CombinedEnumContext(Application::WriterVariants, Context::Text): + case CombinedEnumContext(Application::WriterVariants, Context::Table): + { + m_xBeforeSpacing->set_min(NEGA_MAXVALUE, FieldUnit::MM_100TH); + m_xAfterSpacing->set_min(NEGA_MAXVALUE, FieldUnit::MM_100TH); + m_xFLSpacing->set_min(NEGA_MAXVALUE, FieldUnit::MM_100TH); + } + break; + } + + if(pState && eState >= SfxItemState::DEFAULT) + { + m_xBeforeSpacing->set_sensitive(true); + m_xAfterSpacing->set_sensitive(true); + m_xFLSpacing->set_sensitive(true); + + const SvxLRSpaceItem* pSpace = static_cast<const SvxLRSpaceItem*>(pState); + tools::Long aTxtLeft = pSpace->GetTextLeft(); + tools::Long aTxtRight = pSpace->GetRight(); + tools::Long aTxtFirstLineOfst = pSpace->GetTextFirstLineOffset(); + + aTxtLeft = m_xBeforeSpacing->normalize(aTxtLeft); + + if(m_aContext.GetCombinedContext_DI() != CombinedEnumContext(Application::WriterVariants, Context::Text) + && m_aContext.GetCombinedContext_DI() != CombinedEnumContext(Application::WriterVariants, Context::Default) + && m_aContext.GetCombinedContext_DI() != CombinedEnumContext(Application::WriterVariants, Context::Table)) + { + m_xFLSpacing->set_min(aTxtLeft*-1, FieldUnit::MM_100TH); + } + + aTxtRight = m_xAfterSpacing->normalize(aTxtRight); + + switch(m_aContext.GetCombinedContext_DI()) + { + case CombinedEnumContext(Application::WriterVariants, Context::DrawText): + case CombinedEnumContext(Application::WriterVariants, Context::Text): + case CombinedEnumContext(Application::WriterVariants, Context::Default): + case CombinedEnumContext(Application::WriterVariants, Context::Table): + case CombinedEnumContext(Application::WriterVariants, Context::Annotation): + { + m_xBeforeSpacing->set_max(MAX_SW - aTxtRight, FieldUnit::MM_100TH); + m_xAfterSpacing->set_max(MAX_SW - aTxtLeft, FieldUnit::MM_100TH); + m_xFLSpacing->set_max(MAX_SW - aTxtLeft - aTxtRight, FieldUnit::MM_100TH); + } + break; + case CombinedEnumContext(Application::DrawImpress, Context::DrawText): + case CombinedEnumContext(Application::DrawImpress, Context::Draw): + case CombinedEnumContext(Application::DrawImpress, Context::Table): + case CombinedEnumContext(Application::DrawImpress, Context::TextObject): + case CombinedEnumContext(Application::DrawImpress, Context::Graphic): + { + m_xBeforeSpacing->set_max(MAX_SC_SD - aTxtRight, FieldUnit::MM_100TH); + m_xAfterSpacing->set_max(MAX_SC_SD - aTxtLeft, FieldUnit::MM_100TH); + m_xFLSpacing->set_max(MAX_SC_SD - aTxtLeft - aTxtRight, FieldUnit::MM_100TH); + } + } + + m_xBeforeSpacing->set_value(aTxtLeft, FieldUnit::MM_100TH); + m_xAfterSpacing->set_value(aTxtRight, FieldUnit::MM_100TH); + + aTxtFirstLineOfst = m_xFLSpacing->normalize(aTxtFirstLineOfst); + m_xFLSpacing->set_value(aTxtFirstLineOfst, FieldUnit::MM_100TH); + } + else if(eState == SfxItemState::DISABLED) + { + m_xBeforeSpacing->set_sensitive(false); + m_xAfterSpacing->set_sensitive(false); + m_xFLSpacing->set_sensitive(false); + } + else + { + m_xBeforeSpacing->set_text(""); + m_xAfterSpacing->set_text(""); + m_xFLSpacing->set_text(""); + } +} + +void ParaLRSpacingWindow::SetUnit(FieldUnit eUnit) +{ + m_xBeforeSpacing->SetFieldUnit(eUnit); + m_xAfterSpacing->SetFieldUnit(eUnit); + m_xFLSpacing->SetFieldUnit(eUnit); + + SfxItemPool &rPool = SfxGetpApp()->GetPool(); + m_eUnit = rPool.GetMetric(SID_ATTR_PARA_LRSPACE); +} + +IMPL_LINK_NOARG(ParaLRSpacingWindow, ModifySpacingHdl, weld::MetricSpinButton&, void) +{ + SfxViewFrame* pFrame = SfxViewFrame::Current(); + if (!pFrame) + return; + SfxDispatcher* pDisp = pFrame->GetBindings().GetDispatcher(); + if(pDisp) + { + SvxLRSpaceItem aMargin(SID_ATTR_PARA_LRSPACE); + aMargin.SetTextLeft(m_xBeforeSpacing->GetCoreValue(m_eUnit)); + aMargin.SetRight(m_xAfterSpacing->GetCoreValue(m_eUnit)); + aMargin.SetTextFirstLineOffset(m_xFLSpacing->GetCoreValue(m_eUnit)); + + pDisp->ExecuteList(SID_ATTR_PARA_LRSPACE, SfxCallMode::RECORD, {&aMargin}); + } +} + +// ParaLeftSpacingWindow +ParaLeftSpacingWindow::ParaLeftSpacingWindow(vcl::Window* pParent) + : ParaLRSpacingWindow(pParent) +{ + InitControlBase(&m_xBeforeSpacing->get_widget()); + + m_xBeforeContainer->show(); + m_xAfterContainer->hide(); + m_xFirstLineContainer->hide(); + + SetSizePixel(get_preferred_size()); +} + +// ParaRightSpacingWindow +ParaRightSpacingWindow::ParaRightSpacingWindow(vcl::Window* pParent) + : ParaLRSpacingWindow(pParent) +{ + InitControlBase(&m_xAfterSpacing->get_widget()); + + m_xBeforeContainer->hide(); + m_xAfterContainer->show(); + m_xFirstLineContainer->hide(); + + SetSizePixel(get_preferred_size()); +} + +// ParaFirstLineSpacingWindow +ParaFirstLineSpacingWindow::ParaFirstLineSpacingWindow(vcl::Window* pParent) + : ParaLRSpacingWindow(pParent) +{ + InitControlBase(&m_xFLSpacing->get_widget()); + + m_xBeforeContainer->hide(); + m_xAfterContainer->hide(); + m_xFirstLineContainer->show(); + + SetSizePixel(get_preferred_size()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx b/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx new file mode 100644 index 0000000000..139ae1b8f0 --- /dev/null +++ b/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx @@ -0,0 +1,110 @@ +/* -*- 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 . + */ +#pragma once + +#include <editeng/ulspitem.hxx> +#include <vcl/EnumContext.hxx> +#include <vcl/InterimItemWindow.hxx> +#include <svx/relfld.hxx> + +using namespace com::sun::star; + +namespace svx +{ +class ParaULSpacingWindow : public InterimItemWindow +{ +public: + virtual ~ParaULSpacingWindow() override; + virtual void dispose() override; + + void SetValue(const SvxULSpaceItem* pItem); + void SetUnit(FieldUnit eUnit); + +protected: + ParaULSpacingWindow(vcl::Window* pParent); + + std::optional<SvxRelativeField> m_xAboveSpacing; + std::optional<SvxRelativeField> m_xBelowSpacing; + std::unique_ptr<weld::Container> m_xAboveContainer; + std::unique_ptr<weld::Container> m_xBelowContainer; + + MapUnit m_eUnit; + + DECL_LINK(ModifySpacingHdl, weld::MetricSpinButton&, void); +}; + +class ParaAboveSpacingWindow : public ParaULSpacingWindow +{ +public: + explicit ParaAboveSpacingWindow(vcl::Window* pParent); +}; + +class ParaBelowSpacingWindow : public ParaULSpacingWindow +{ +public: + explicit ParaBelowSpacingWindow(vcl::Window* pParent); +}; + +class ParaLRSpacingWindow : public InterimItemWindow +{ +public: + virtual ~ParaLRSpacingWindow() override; + virtual void dispose() override; + + void SetValue(SfxItemState eState, const SfxPoolItem* pState); + void SetUnit(FieldUnit eUnit); + void SetContext(const vcl::EnumContext& eContext); + +protected: + ParaLRSpacingWindow(vcl::Window* pParent); + + std::optional<SvxRelativeField> m_xBeforeSpacing; + std::optional<SvxRelativeField> m_xAfterSpacing; + std::optional<SvxRelativeField> m_xFLSpacing; + std::unique_ptr<weld::Container> m_xBeforeContainer; + std::unique_ptr<weld::Container> m_xAfterContainer; + std::unique_ptr<weld::Container> m_xFirstLineContainer; + + MapUnit m_eUnit; + + vcl::EnumContext m_aContext; + + DECL_LINK(ModifySpacingHdl, weld::MetricSpinButton&, void); +}; + +class ParaLeftSpacingWindow : public ParaLRSpacingWindow +{ +public: + explicit ParaLeftSpacingWindow(vcl::Window* pParent); +}; + +class ParaRightSpacingWindow : public ParaLRSpacingWindow +{ +public: + explicit ParaRightSpacingWindow(vcl::Window* pParent); +}; + +class ParaFirstLineSpacingWindow : public ParaLRSpacingWindow +{ +public: + explicit ParaFirstLineSpacingWindow(vcl::Window* pParent); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/possize/PosSizePropertyPanel.cxx b/svx/source/sidebar/possize/PosSizePropertyPanel.cxx new file mode 100644 index 0000000000..18abfa1160 --- /dev/null +++ b/svx/source/sidebar/possize/PosSizePropertyPanel.cxx @@ -0,0 +1,1087 @@ +/* -*- 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 <algorithm> + +#include "PosSizePropertyPanel.hxx" +#include <sal/log.hxx> +#include <svx/svxids.hrc> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/module.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/weldutils.hxx> +#include <svx/dialcontrol.hxx> +#include <svx/dialmgr.hxx> +#include <svx/rectenum.hxx> +#include <svx/sdangitm.hxx> +#include <unotools/viewoptions.hxx> +#include <unotools/localedatawrapper.hxx> +#include <utility> +#include <vcl/canvastools.hxx> +#include <vcl/fieldvalues.hxx> +#include <svl/intitem.hxx> +#include <svx/strings.hrc> +#include <svx/svdpagv.hxx> +#include <svx/svdview.hxx> +#include <svx/transfrmhelper.hxx> +#include <boost/property_tree/ptree.hpp> + +#include <svtools/unitconv.hxx> + +using namespace css; +using namespace css::uno; + +constexpr OUString USERITEM_NAME = u"FitItem"_ustr; + +namespace svx::sidebar { + +PosSizePropertyPanel::PosSizePropertyPanel( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings, + css::uno::Reference<css::ui::XSidebar> xSidebar) +: PanelLayout(pParent, "PosSizePropertyPanel", "svx/ui/sidebarpossize.ui"), + mxFtPosX(m_xBuilder->weld_label("horizontallabel")), + mxMtrPosX(m_xBuilder->weld_metric_spin_button("horizontalpos", FieldUnit::CM)), + mxFtPosY(m_xBuilder->weld_label("verticallabel")), + mxMtrPosY(m_xBuilder->weld_metric_spin_button("verticalpos", FieldUnit::CM)), + mxFtWidth(m_xBuilder->weld_label("widthlabel")), + mxMtrWidth(m_xBuilder->weld_metric_spin_button("selectwidth", FieldUnit::CM)), + mxFtHeight(m_xBuilder->weld_label("heightlabel")), + mxMtrHeight(m_xBuilder->weld_metric_spin_button("selectheight", FieldUnit::CM)), + mxCbxScale(m_xBuilder->weld_check_button("ratio")), + mxFtAngle(m_xBuilder->weld_label("rotationlabel")), + mxMtrAngle(m_xBuilder->weld_metric_spin_button("rotation", FieldUnit::DEGREE)), + mxCtrlDial(new DialControl), + mxDial(new weld::CustomWeld(*m_xBuilder, "orientationcontrol", *mxCtrlDial)), + mxFtFlip(m_xBuilder->weld_label("fliplabel")), + mxFlipTbx(m_xBuilder->weld_toolbar("selectrotationtype")), + mxFlipDispatch(new ToolbarUnoDispatcher(*mxFlipTbx, *m_xBuilder, rxFrame)), + mxArrangeTbx(m_xBuilder->weld_toolbar("arrangetoolbar")), + mxArrangeDispatch(new ToolbarUnoDispatcher(*mxArrangeTbx, *m_xBuilder, rxFrame)), + mxArrangeTbx2(m_xBuilder->weld_toolbar("arrangetoolbar2")), + mxArrangeDispatch2(new ToolbarUnoDispatcher(*mxArrangeTbx2, *m_xBuilder, rxFrame)), + mxAlignTbx(m_xBuilder->weld_toolbar("aligntoolbar")), + mxAlignDispatch(new ToolbarUnoDispatcher(*mxAlignTbx, *m_xBuilder, rxFrame)), + mxAlignTbx2(m_xBuilder->weld_toolbar("aligntoolbar2")), + mxAlignDispatch2(new ToolbarUnoDispatcher(*mxAlignTbx2, *m_xBuilder, rxFrame)), + mxBtnEditOLEObject(m_xBuilder->weld_button("btnEditObject")), + mpView(nullptr), + mlOldWidth(1), + mlOldHeight(1), + mlRotX(0), + mlRotY(0), + mePoolUnit(), + meDlgUnit(FieldUnit::INCH), // #i124409# init with fallback default + mbFieldMetricOutDated(true), + maTransfPosXControl(SID_ATTR_TRANSFORM_POS_X, *pBindings, *this), + maTransfPosYControl(SID_ATTR_TRANSFORM_POS_Y, *pBindings, *this), + maTransfWidthControl(SID_ATTR_TRANSFORM_WIDTH, *pBindings, *this), + maTransfHeightControl(SID_ATTR_TRANSFORM_HEIGHT, *pBindings, *this), + maSvxAngleControl( SID_ATTR_TRANSFORM_ANGLE, *pBindings, *this), + maRotXControl(SID_ATTR_TRANSFORM_ROT_X, *pBindings, *this), + maRotYControl(SID_ATTR_TRANSFORM_ROT_Y, *pBindings, *this), + maProPosControl(SID_ATTR_TRANSFORM_PROTECT_POS, *pBindings, *this), + maProSizeControl(SID_ATTR_TRANSFORM_PROTECT_SIZE, *pBindings, *this), + maAutoWidthControl(SID_ATTR_TRANSFORM_AUTOWIDTH, *pBindings, *this), + maAutoHeightControl(SID_ATTR_TRANSFORM_AUTOHEIGHT, *pBindings, *this), + m_aMetricCtl(SID_ATTR_METRIC, *pBindings, *this), + mpBindings(pBindings), + mbSizeProtected(false), + mbPositionProtected(false), + mbAutoWidth(false), + mbAutoHeight(false), + mbAdjustEnabled(false), + mxSidebar(std::move(xSidebar)) +{ + Initialize(); + + // A guesstimate of the longest label in the various sidebar panes to use + // to get this pane's contents to align with them, for lack of a better + // solution + auto nWidth = mxFtWidth->get_preferred_size().Width(); + OUString sLabel = mxFtWidth->get_label(); + mxFtWidth->set_label(SvxResId(RID_SVXSTR_TRANSPARENCY)); + nWidth = std::max(nWidth, mxFtWidth->get_preferred_size().Width());; + mxFtWidth->set_label(sLabel); + mxFtWidth->set_size_request(nWidth, -1); + + mpBindings->Update( SID_ATTR_METRIC ); + mpBindings->Update( SID_ATTR_TRANSFORM_WIDTH ); + mpBindings->Update( SID_ATTR_TRANSFORM_HEIGHT ); + mpBindings->Update( SID_ATTR_TRANSFORM_PROTECT_SIZE ); +} + +PosSizePropertyPanel::~PosSizePropertyPanel() +{ + mxFtPosX.reset(); + mxMtrPosX.reset(); + mxFtPosY.reset(); + mxMtrPosY.reset(); + mxFtWidth.reset(); + mxMtrWidth.reset(); + mxFtHeight.reset(); + mxMtrHeight.reset(); + mxCbxScale.reset(); + mxFtAngle.reset(); + mxMtrAngle.reset(); + mxDial.reset(); + mxCtrlDial.reset(); + mxFtFlip.reset(); + mxFlipDispatch.reset(); + mxFlipTbx.reset(); + mxAlignDispatch.reset(); + mxAlignDispatch2.reset(); + mxAlignTbx.reset(); + mxAlignTbx2.reset(); + mxArrangeDispatch.reset(); + mxArrangeDispatch2.reset(); + mxArrangeTbx.reset(); + mxArrangeTbx2.reset(); + mxBtnEditOLEObject.reset(); + + maTransfPosXControl.dispose(); + maTransfPosYControl.dispose(); + maTransfWidthControl.dispose(); + maTransfHeightControl.dispose(); + + maSvxAngleControl.dispose(); + maRotXControl.dispose(); + maRotYControl.dispose(); + maProPosControl.dispose(); + maProSizeControl.dispose(); + maAutoWidthControl.dispose(); + maAutoHeightControl.dispose(); + m_aMetricCtl.dispose(); +} + +namespace +{ + bool hasText(const SdrView& rSdrView) + { + const SdrMarkList& rMarkList = rSdrView.GetMarkedObjectList(); + + if(1 == rMarkList.GetMarkCount()) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + const SdrObjKind eKind(pObj->GetObjIdentifier()); + + if((pObj->GetObjInventor() == SdrInventor::Default) && (SdrObjKind::Text == eKind || SdrObjKind::TitleText == eKind || SdrObjKind::OutlineText == eKind)) + { + const SdrTextObj* pSdrTextObj = DynCastSdrTextObj(pObj); + + if(pSdrTextObj && pSdrTextObj->HasText()) + { + return true; + } + } + } + + return false; + } +} // end of anonymous namespace + + +void PosSizePropertyPanel::Initialize() +{ + //Position : Horizontal / Vertical + mxMtrPosX->connect_value_changed( LINK( this, PosSizePropertyPanel, ChangePosXHdl ) ); + mxMtrPosY->connect_value_changed( LINK( this, PosSizePropertyPanel, ChangePosYHdl ) ); + + //Size : Width / Height + mxMtrWidth->connect_value_changed( LINK( this, PosSizePropertyPanel, ChangeWidthHdl ) ); + mxMtrHeight->connect_value_changed( LINK( this, PosSizePropertyPanel, ChangeHeightHdl ) ); + + //Size : Keep ratio + mxCbxScale->connect_toggled( LINK( this, PosSizePropertyPanel, ClickAutoHdl ) ); + + //rotation control + mxCtrlDial->SetLinkedField(mxMtrAngle.get(), 2); + mxCtrlDial->SetModifyHdl(LINK( this, PosSizePropertyPanel, RotationHdl)); + + //use same logic as DialControl_Impl::SetSize + weld::DrawingArea* pDrawingArea = mxCtrlDial->GetDrawingArea(); + int nDim = (std::min<int>(pDrawingArea->get_approximate_digit_width() * 6, + pDrawingArea->get_text_height() * 3) - 1) | 1; + Size aSize(nDim, nDim); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + mxCtrlDial->Init(aSize); + + mxBtnEditOLEObject->connect_clicked( LINK( this, PosSizePropertyPanel, ClickObjectEditHdl ) ); + + SfxViewShell* pCurSh = SfxViewShell::Current(); + if ( pCurSh ) + mpView = pCurSh->GetDrawView(); + else + mpView = nullptr; + + if ( mpView != nullptr ) + { + maUIScale = mpView->GetModel().GetUIScale(); + mbAdjustEnabled = hasText(*mpView); + } + + mePoolUnit = maTransfWidthControl.GetCoreMetric(); +} + +std::unique_ptr<PanelLayout> PosSizePropertyPanel::Create ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings, + const css::uno::Reference<css::ui::XSidebar>& rxSidebar) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to PosSizePropertyPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to PosSizePropertyPanel::Create", nullptr, 1); + if (pBindings == nullptr) + throw lang::IllegalArgumentException("no SfxBindings given to PosSizePropertyPanel::Create", nullptr, 2); + + return std::make_unique<PosSizePropertyPanel>(pParent, rxFrame, pBindings, rxSidebar); +} + +void PosSizePropertyPanel::HandleContextChange( + const vcl::EnumContext& rContext) +{ + if (maContext == rContext) + { + // Nothing to do. + return; + } + + maContext = rContext; + + bool bShowPosition = false; + bool bShowAngle = false; + bool bShowFlip = false; + bool bShowEditObject = false; + bool bShowArrangeTbx2 = false; + + switch (maContext.GetCombinedContext_DI()) + { + case CombinedEnumContext(Application::WriterVariants, Context::Draw): + bShowAngle = true; + bShowFlip = true; + bShowArrangeTbx2 = true; + break; + + case CombinedEnumContext(Application::WriterVariants, Context::Graphic): + bShowFlip = true; + bShowAngle = true; // RotGrfFlyFrame: Writer FlyFrames for Graphics now support angle + break; + + case CombinedEnumContext(Application::Calc, Context::Draw): + case CombinedEnumContext(Application::Calc, Context::DrawLine): + case CombinedEnumContext(Application::Calc, Context::Graphic): + case CombinedEnumContext(Application::DrawImpress, Context::Draw): + case CombinedEnumContext(Application::DrawImpress, Context::DrawLine): + case CombinedEnumContext(Application::DrawImpress, Context::TextObject): + case CombinedEnumContext(Application::DrawImpress, Context::Graphic): + bShowPosition = true; + bShowAngle = true; + bShowFlip = true; + break; + + case CombinedEnumContext(Application::WriterVariants, Context::OLE): + bShowEditObject = true; + break; + + case CombinedEnumContext(Application::Calc, Context::OLE): + case CombinedEnumContext(Application::DrawImpress, Context::OLE): + bShowPosition = true; + bShowEditObject = true; + break; + + case CombinedEnumContext(Application::Calc, Context::Chart): + case CombinedEnumContext(Application::Calc, Context::Form): + case CombinedEnumContext(Application::Calc, Context::Media): + case CombinedEnumContext(Application::Calc, Context::MultiObject): + case CombinedEnumContext(Application::DrawImpress, Context::Media): + case CombinedEnumContext(Application::DrawImpress, Context::Form): + case CombinedEnumContext(Application::DrawImpress, Context::ThreeDObject): + case CombinedEnumContext(Application::DrawImpress, Context::MultiObject): + bShowPosition = true; + break; + } + + // Position + mxFtPosX->set_visible(bShowPosition); + mxMtrPosX->set_visible(bShowPosition); + mxFtPosY->set_visible(bShowPosition); + mxMtrPosY->set_visible(bShowPosition); + + // Rotation + mxFtAngle->set_visible(bShowAngle); + mxMtrAngle->set_visible(bShowAngle); + mxCtrlDial->set_visible(bShowAngle); + + // Flip + mxFtFlip->set_visible(bShowFlip); + mxFlipTbx->set_visible(bShowFlip); + + // Edit Object + mxBtnEditOLEObject->set_visible(bShowEditObject); + + // Arrange tool bar 2 + mxArrangeTbx2->set_visible(bShowArrangeTbx2); + + if (mxSidebar.is()) + mxSidebar->requestLayout(); +} + + +IMPL_LINK_NOARG( PosSizePropertyPanel, ChangeWidthHdl, weld::MetricSpinButton&, void ) +{ + if( mxCbxScale->get_active() && + mxCbxScale->get_sensitive() ) + { + tools::Long nHeight = static_cast<tools::Long>( (static_cast<double>(mlOldHeight) * static_cast<double>(mxMtrWidth->get_value(FieldUnit::NONE))) / static_cast<double>(mlOldWidth) ); + if( nHeight <= mxMtrHeight->get_max( FieldUnit::NONE ) ) + { + mxMtrHeight->set_value( nHeight, FieldUnit::NONE ); + } + else + { + nHeight = static_cast<tools::Long>(mxMtrHeight->get_max( FieldUnit::NONE )); + mxMtrHeight->set_value(nHeight, FieldUnit::NONE); + const tools::Long nWidth = static_cast<tools::Long>( (static_cast<double>(mlOldWidth) * static_cast<double>(nHeight)) / static_cast<double>(mlOldHeight) ); + mxMtrWidth->set_value( nWidth, FieldUnit::NONE ); + } + } + executeSize(); +} + + +IMPL_LINK_NOARG( PosSizePropertyPanel, ChangeHeightHdl, weld::MetricSpinButton&, void ) +{ + if( mxCbxScale->get_active() && + mxCbxScale->get_sensitive() ) + { + tools::Long nWidth = static_cast<tools::Long>( (static_cast<double>(mlOldWidth) * static_cast<double>(mxMtrHeight->get_value(FieldUnit::NONE))) / static_cast<double>(mlOldHeight) ); + if( nWidth <= mxMtrWidth->get_max( FieldUnit::NONE ) ) + { + mxMtrWidth->set_value( nWidth, FieldUnit::NONE ); + } + else + { + nWidth = static_cast<tools::Long>(mxMtrWidth->get_max( FieldUnit::NONE )); + mxMtrWidth->set_value( nWidth, FieldUnit::NONE ); + const tools::Long nHeight = static_cast<tools::Long>( (static_cast<double>(mlOldHeight) * static_cast<double>(nWidth)) / static_cast<double>(mlOldWidth) ); + mxMtrHeight->set_value( nHeight, FieldUnit::NONE ); + } + } + executeSize(); +} + + +IMPL_LINK_NOARG( PosSizePropertyPanel, ChangePosXHdl, weld::MetricSpinButton&, void ) +{ + if ( mxMtrPosX->get_value_changed_from_saved()) + { + tools::Long lX = GetCoreValue( *mxMtrPosX, mePoolUnit ); + + Fraction aUIScale = mpView->GetModel().GetUIScale(); + lX = tools::Long( lX * aUIScale ); + + SfxInt32Item aPosXItem( SID_ATTR_TRANSFORM_POS_X,static_cast<sal_uInt32>(lX)); + + GetBindings()->GetDispatcher()->ExecuteList( + SID_ATTR_TRANSFORM, SfxCallMode::RECORD, { &aPosXItem }); + } +} + +IMPL_LINK_NOARG( PosSizePropertyPanel, ChangePosYHdl, weld::MetricSpinButton&, void ) +{ + if ( mxMtrPosY->get_value_changed_from_saved() ) + { + tools::Long lY = GetCoreValue( *mxMtrPosY, mePoolUnit ); + + Fraction aUIScale = mpView->GetModel().GetUIScale(); + lY = tools::Long( lY * aUIScale ); + + SfxInt32Item aPosYItem( SID_ATTR_TRANSFORM_POS_Y,static_cast<sal_uInt32>(lY)); + + GetBindings()->GetDispatcher()->ExecuteList( + SID_ATTR_TRANSFORM, SfxCallMode::RECORD, { &aPosYItem }); + } +} + +IMPL_LINK_NOARG( PosSizePropertyPanel, ClickAutoHdl, weld::Toggleable&, void ) +{ + if ( mxCbxScale->get_active() ) + { + mlOldWidth = std::max(GetCoreValue(*mxMtrWidth, mePoolUnit), SAL_CONST_INT64(1)); + mlOldHeight = std::max(GetCoreValue(*mxMtrHeight, mePoolUnit), SAL_CONST_INT64(1)); + } + + // mxCbxScale must synchronized with that on Position and Size tabpage on Shape Properties dialog + SvtViewOptions aPageOpt(EViewType::TabPage, "cui/ui/possizetabpage/PositionAndSize"); + aPageOpt.SetUserItem( USERITEM_NAME, css::uno::Any( OUString::number( int(mxCbxScale->get_active()) ) ) ); +} + +IMPL_LINK_NOARG( PosSizePropertyPanel, RotationHdl, DialControl&, void ) +{ + Degree100 nTmp = mxCtrlDial->GetRotation(); + + // #i123993# Need to take UIScale into account when executing rotations + const double fUIScale(mpView ? double(mpView->GetModel().GetUIScale()) : 1.0); + SdrAngleItem aAngleItem( SID_ATTR_TRANSFORM_ANGLE, nTmp); + SfxInt32Item aRotXItem( SID_ATTR_TRANSFORM_ROT_X, basegfx::fround(mlRotX * fUIScale)); + SfxInt32Item aRotYItem( SID_ATTR_TRANSFORM_ROT_Y, basegfx::fround(mlRotY * fUIScale)); + + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM, + SfxCallMode::RECORD, { &aAngleItem, &aRotXItem, &aRotYItem }); +} + +IMPL_STATIC_LINK_NOARG( PosSizePropertyPanel, ClickObjectEditHdl, weld::Button&, void ) +{ + SfxViewShell* pCurSh = SfxViewShell::Current(); + if ( pCurSh) + { + pCurSh->DoVerb( -1 ); + } +} + +namespace +{ + void limitWidth(weld::MetricSpinButton& rMetricSpinButton) + { + // space is limited in the sidebar, so limit MetricSpinButtons to a width of 7 digits + const int nMaxDigits = 7; + + weld::SpinButton& rSpinButton = rMetricSpinButton.get_widget(); + rSpinButton.set_width_chars(std::min(rSpinButton.get_width_chars(), nMaxDigits)); + } +} + +void PosSizePropertyPanel::NotifyItemUpdate( + sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState) +{ + mxFtAngle->set_sensitive(true); + mxMtrAngle->set_sensitive(true); + mxDial->set_sensitive(true); + mxFtFlip->set_sensitive(true); + mxFlipTbx->set_sensitive(true); + + const SfxUInt32Item* pWidthItem; + const SfxUInt32Item* pHeightItem; + + SfxViewShell* pCurSh = SfxViewShell::Current(); + if ( pCurSh ) + mpView = pCurSh->GetDrawView(); + else + mpView = nullptr; + + if ( mpView == nullptr ) + return; + + mbAdjustEnabled = hasText(*mpView); + + // Pool unit and dialog unit may have changed, make sure that we + // have the current values. + mePoolUnit = maTransfWidthControl.GetCoreMetric(); + + switch (nSID) + { + case SID_ATTR_TRANSFORM_WIDTH: + if ( SfxItemState::DEFAULT == eState ) + { + pWidthItem = dynamic_cast< const SfxUInt32Item* >(pState); + + if(pWidthItem) + { + tools::Long lOldWidth1 = tools::Long( pWidthItem->GetValue() / maUIScale ); + SetFieldUnit( *mxMtrWidth, meDlgUnit, true ); + SetMetricValue( *mxMtrWidth, lOldWidth1, mePoolUnit ); + limitWidth(*mxMtrWidth); + mlOldWidth = lOldWidth1; + mxMtrWidth->save_value(); + break; + } + } + + mxMtrWidth->set_text( "" ); + break; + + case SID_ATTR_TRANSFORM_HEIGHT: + if ( SfxItemState::DEFAULT == eState ) + { + pHeightItem = dynamic_cast< const SfxUInt32Item* >(pState); + + if(pHeightItem) + { + tools::Long nTmp = tools::Long( pHeightItem->GetValue() / maUIScale); + SetFieldUnit( *mxMtrHeight, meDlgUnit, true ); + SetMetricValue( *mxMtrHeight, nTmp, mePoolUnit ); + limitWidth(*mxMtrHeight); + mlOldHeight = nTmp; + mxMtrHeight->save_value(); + break; + } + } + + mxMtrHeight->set_text( ""); + break; + + case SID_ATTR_TRANSFORM_POS_X: + if(SfxItemState::DEFAULT == eState) + { + const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState); + + if(pItem) + { + tools::Long nTmp = tools::Long(pItem->GetValue() / maUIScale); + SetFieldUnit( *mxMtrPosX, meDlgUnit, true ); + SetMetricValue( *mxMtrPosX, nTmp, mePoolUnit ); + limitWidth(*mxMtrPosX); + mxMtrPosX->save_value(); + break; + } + } + + mxMtrPosX->set_text( "" ); + break; + + case SID_ATTR_TRANSFORM_POS_Y: + if(SfxItemState::DEFAULT == eState) + { + const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState); + + if(pItem) + { + tools::Long nTmp = tools::Long(pItem->GetValue() / maUIScale); + SetFieldUnit( *mxMtrPosY, meDlgUnit, true ); + SetMetricValue( *mxMtrPosY, nTmp, mePoolUnit ); + limitWidth(*mxMtrPosY); + mxMtrPosY->save_value(); + break; + } + } + + mxMtrPosY->set_text( "" ); + break; + + case SID_ATTR_TRANSFORM_ROT_X: + if (SfxItemState::DEFAULT == eState) + { + const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState); + + if(pItem) + { + mlRotX = pItem->GetValue(); + mlRotX = tools::Long( mlRotX / maUIScale ); + } + } + break; + + case SID_ATTR_TRANSFORM_ROT_Y: + if (SfxItemState::DEFAULT == eState) + { + const SfxInt32Item* pItem = dynamic_cast< const SfxInt32Item* >(pState); + + if(pItem) + { + mlRotY = pItem->GetValue(); + mlRotY = tools::Long( mlRotY / maUIScale ); + } + } + break; + + case SID_ATTR_TRANSFORM_PROTECT_POS: + if(SfxItemState::DEFAULT == eState) + { + const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState); + + if(pItem) + { + // record the state of position protect + mbPositionProtected = pItem->GetValue(); + break; + } + } + + mbPositionProtected = false; + break; + + case SID_ATTR_TRANSFORM_PROTECT_SIZE: + if(SfxItemState::DEFAULT == eState) + { + const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState); + + if(pItem) + { + // record the state of size protect + mbSizeProtected = pItem->GetValue(); + break; + } + } + + mbSizeProtected = false; + break; + + case SID_ATTR_TRANSFORM_AUTOWIDTH: + if(SfxItemState::DEFAULT == eState) + { + const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState); + + if(pItem) + { + mbAutoWidth = pItem->GetValue(); + } + } + break; + + case SID_ATTR_TRANSFORM_AUTOHEIGHT: + if(SfxItemState::DEFAULT == eState) + { + const SfxBoolItem* pItem = dynamic_cast< const SfxBoolItem* >(pState); + + if(pItem) + { + mbAutoHeight = pItem->GetValue(); + } + } + break; + + case SID_ATTR_TRANSFORM_ANGLE: + if (eState >= SfxItemState::DEFAULT) + { + const SdrAngleItem* pItem = dynamic_cast< const SdrAngleItem* >(pState); + + if(pItem) + { + Degree100 nTmp = NormAngle36000(pItem->GetValue()); + + mxMtrAngle->set_value(nTmp.get(), FieldUnit::DEGREE); + mxCtrlDial->SetRotation(nTmp); + + break; + } + } + + mxMtrAngle->set_text( "" ); + mxCtrlDial->SetRotation( 0_deg100 ); + break; + + case SID_ATTR_METRIC: + { + const Fraction aUIScale(mpView->GetModel().GetUIScale()); + MetricState(eState, pState, aUIScale); + UpdateUIScale(aUIScale); + mbFieldMetricOutDated = false; + break; + } + default: + break; + } + + const sal_Int32 nCombinedContext(maContext.GetCombinedContext_DI()); + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + switch (rMarkList.GetMarkCount()) + { + case 0: + break; + + case 1: + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + const SdrObjKind eKind(pObj->GetObjIdentifier()); + + if(((nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::Draw) + || nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject) + ) && SdrObjKind::Edge == eKind) + || SdrObjKind::Caption == eKind) + { + mxFtAngle->set_sensitive(false); + mxMtrAngle->set_sensitive(false); + mxDial->set_sensitive(false); + mxFlipTbx->set_sensitive(false); + mxFtFlip->set_sensitive(false); + } + break; + } + + default: + { + sal_uInt16 nMarkObj = 0; + bool isNoEdge = true; + + while(isNoEdge && rMarkList.GetMark(nMarkObj)) + { + const SdrObject* pObj = rMarkList.GetMark(nMarkObj)->GetMarkedSdrObj(); + const SdrObjKind eKind(pObj->GetObjIdentifier()); + + if(((nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::Draw) + || nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject) + ) && SdrObjKind::Edge == eKind) + || SdrObjKind::Caption == eKind) + { + isNoEdge = false; + break; + } + nMarkObj++; + } + + if(!isNoEdge) + { + mxFtAngle->set_sensitive(false); + mxMtrAngle->set_sensitive(false); + mxDial->set_sensitive(false); + mxFlipTbx->set_sensitive(false); + mxFtFlip->set_sensitive(false); + } + break; + } + } + + if(nCombinedContext == CombinedEnumContext(Application::DrawImpress, Context::TextObject)) + { + mxFlipTbx->set_sensitive(false); + mxFtFlip->set_sensitive(false); + } + + DisableControls(); + + // mxCbxScale must synchronized with that on Position and Size tabpage on Shape Properties dialog + SvtViewOptions aPageOpt(EViewType::TabPage, "cui/ui/possizetabpage/PositionAndSize"); + OUString sUserData; + css::uno::Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME ); + OUString aTemp; + if ( aUserItem >>= aTemp ) + sUserData = aTemp; + mxCbxScale->set_active(static_cast<bool>(sUserData.toInt32())); +} + +void PosSizePropertyPanel::GetControlState(const sal_uInt16 nSID, boost::property_tree::ptree& rState) +{ + weld::MetricSpinButton* pControl = nullptr; + switch (nSID) + { + case SID_ATTR_TRANSFORM_POS_X: + pControl = mxMtrPosX.get(); + break; + case SID_ATTR_TRANSFORM_POS_Y: + pControl = mxMtrPosY.get(); + break; + case SID_ATTR_TRANSFORM_WIDTH: + pControl = mxMtrWidth.get(); + break; + case SID_ATTR_TRANSFORM_HEIGHT: + pControl = mxMtrHeight.get(); + break; + } + + if (pControl && !pControl->get_text().isEmpty()) + { + OUString sValue = Application::GetSettings().GetNeutralLocaleDataWrapper(). + getNum(pControl->get_value(pControl->get_unit()), pControl->get_digits(), false, false); + rState.put(pControl->get_buildable_name().toUtf8().getStr(), sValue.toUtf8().getStr()); + } +} + +void PosSizePropertyPanel::executeSize() +{ + if ( !mxMtrWidth->get_value_changed_from_saved() && !mxMtrHeight->get_value_changed_from_saved()) + return; + + Fraction aUIScale = mpView->GetModel().GetUIScale(); + + // get Width + double nWidth = static_cast<double>(mxMtrWidth->get_value(FieldUnit::MM_100TH)); + tools::Long lWidth = tools::Long(nWidth * static_cast<double>(aUIScale)); + lWidth = OutputDevice::LogicToLogic( lWidth, MapUnit::Map100thMM, mePoolUnit ); + lWidth = static_cast<tools::Long>(mxMtrWidth->denormalize( lWidth )); + + // get Height + double nHeight = static_cast<double>(mxMtrHeight->get_value(FieldUnit::MM_100TH)); + tools::Long lHeight = tools::Long(nHeight * static_cast<double>(aUIScale)); + lHeight = OutputDevice::LogicToLogic( lHeight, MapUnit::Map100thMM, mePoolUnit ); + lHeight = static_cast<tools::Long>(mxMtrHeight->denormalize( lHeight )); + + // put Width & Height to itemset + SfxUInt32Item aWidthItem( SID_ATTR_TRANSFORM_WIDTH, static_cast<sal_uInt32>(lWidth)); + SfxUInt32Item aHeightItem( SID_ATTR_TRANSFORM_HEIGHT, static_cast<sal_uInt32>(lHeight)); + SfxUInt16Item aPointItem (SID_ATTR_TRANSFORM_SIZE_POINT, sal_uInt16(RectPoint::LT)); + const sal_Int32 nCombinedContext(maContext.GetCombinedContext_DI()); + + if( nCombinedContext == CombinedEnumContext(Application::WriterVariants, Context::Graphic) + || nCombinedContext == CombinedEnumContext(Application::WriterVariants, Context::OLE) + ) + { + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM, + SfxCallMode::RECORD, { &aWidthItem, &aHeightItem, &aPointItem }); + } + else + { + if ( (mxMtrWidth->get_value_changed_from_saved()) && (mxMtrHeight->get_value_changed_from_saved())) + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM, + SfxCallMode::RECORD, { &aWidthItem, &aHeightItem, &aPointItem }); + else if( mxMtrWidth->get_value_changed_from_saved()) + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM, + SfxCallMode::RECORD, { &aWidthItem, &aPointItem }); + else if ( mxMtrHeight->get_value_changed_from_saved()) + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM, + SfxCallMode::RECORD, { &aHeightItem, &aPointItem }); + } +} + +void PosSizePropertyPanel::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) +{ + if (meDlgUnit != GetCurrentUnit(SfxItemState::DEFAULT, nullptr)) + { + mpBindings->Update( SID_ATTR_METRIC ); + } + + PanelLayout::DumpAsPropertyTree(rJsonWriter); +} + +void PosSizePropertyPanel::MetricState(SfxItemState eState, const SfxPoolItem* pState, const Fraction& rUIScale) +{ + bool bPosXBlank = false; + bool bPosYBlank = false; + bool bWidthBlank = false; + bool bHeightBlank = false; + + // #i124409# use the given Item to get the correct UI unit and initialize it + // and the Fields using it + FieldUnit eDlgUnit = GetCurrentUnit(eState, pState); + mbFieldMetricOutDated |= (eDlgUnit != meDlgUnit || maUIScale != rUIScale); + if (!mbFieldMetricOutDated) + return; + meDlgUnit = eDlgUnit; + + if (mxMtrPosX->get_text().isEmpty()) + bPosXBlank = true; + SetFieldUnit( *mxMtrPosX, meDlgUnit, true ); + if(bPosXBlank) + mxMtrPosX->set_text(OUString()); + + if (mxMtrPosY->get_text().isEmpty()) + bPosYBlank = true; + SetFieldUnit( *mxMtrPosY, meDlgUnit, true ); + if(bPosYBlank) + mxMtrPosY->set_text(OUString()); + + SetPosSizeMinMax(rUIScale); + + if (mxMtrWidth->get_text().isEmpty()) + bWidthBlank = true; + SetFieldUnit( *mxMtrWidth, meDlgUnit, true ); + if(bWidthBlank) + mxMtrWidth->set_text(OUString()); + + if (mxMtrHeight->get_text().isEmpty()) + bHeightBlank = true; + SetFieldUnit( *mxMtrHeight, meDlgUnit, true ); + if(bHeightBlank) + mxMtrHeight->set_text(OUString()); +} + + +FieldUnit PosSizePropertyPanel::GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState ) +{ + FieldUnit eUnit = FieldUnit::NONE; + + if ( pState && eState >= SfxItemState::DEFAULT ) + { + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue()); + } + else + { + SfxViewFrame* pFrame = SfxViewFrame::Current(); + SfxObjectShell* pSh = nullptr; + if ( pFrame ) + pSh = pFrame->GetObjectShell(); + if ( pSh ) + { + SfxModule* pModule = pSh->GetModule(); + if ( pModule ) + { + const SfxPoolItem* pItem = pModule->GetItem( SID_ATTR_METRIC ); + if ( pItem ) + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + } + else + { + SAL_WARN("svx.sidebar", "GetModuleFieldUnit(): no module found"); + } + } + } + + return eUnit; +} + + +void PosSizePropertyPanel::DisableControls() +{ + if( mbPositionProtected ) + { + // the position is protected("Position protect" option in modal dialog is checked), + // disable all the Position controls in sidebar + mxFtPosX->set_sensitive(false); + mxMtrPosX->set_sensitive(false); + mxFtPosY->set_sensitive(false); + mxMtrPosY->set_sensitive(false); + mxFtAngle->set_sensitive(false); + mxMtrAngle->set_sensitive(false); + mxDial->set_sensitive(false); + mxFtFlip->set_sensitive(false); + mxFlipTbx->set_sensitive(false); + + mxFtWidth->set_sensitive(false); + mxMtrWidth->set_sensitive(false); + mxFtHeight->set_sensitive(false); + mxMtrHeight->set_sensitive(false); + mxCbxScale->set_sensitive(false); + } + else + { + mxFtPosX->set_sensitive(true); + mxMtrPosX->set_sensitive(true); + mxFtPosY->set_sensitive(true); + mxMtrPosY->set_sensitive(true); + + if( mbSizeProtected ) + { + mxFtWidth->set_sensitive(false); + mxMtrWidth->set_sensitive(false); + mxFtHeight->set_sensitive(false); + mxMtrHeight->set_sensitive(false); + mxCbxScale->set_sensitive(false); + } + else + { + if( mbAdjustEnabled ) + { + if( mbAutoWidth ) + { + mxFtWidth->set_sensitive(false); + mxMtrWidth->set_sensitive(false); + mxCbxScale->set_sensitive(false); + } + else + { + mxFtWidth->set_sensitive(true); + mxMtrWidth->set_sensitive(true); + } + if( mbAutoHeight ) + { + mxFtHeight->set_sensitive(false); + mxMtrHeight->set_sensitive(false); + mxCbxScale->set_sensitive(false); + } + else + { + mxFtHeight->set_sensitive(true); + mxMtrHeight->set_sensitive(true); + } + if( !mbAutoWidth && !mbAutoHeight ) + mxCbxScale->set_sensitive(true); + } + else + { + mxFtWidth->set_sensitive(true); + mxMtrWidth->set_sensitive(true); + mxFtHeight->set_sensitive(true); + mxMtrHeight->set_sensitive(true); + mxCbxScale->set_sensitive(true); + } + } + } +} + +void PosSizePropertyPanel::SetPosSizeMinMax(const Fraction& rUIScale) +{ + SdrPageView* pPV = mpView->GetSdrPageView(); + if (!pPV) + return; + tools::Rectangle aTmpRect(mpView->GetAllMarkedRect()); + pPV->LogicToPagePos(aTmpRect); + maRect = vcl::unotools::b2DRectangleFromRectangle(aTmpRect); + + tools::Rectangle aTmpRect2(mpView->GetWorkArea()); + pPV->LogicToPagePos(aTmpRect2); + maWorkArea = vcl::unotools::b2DRectangleFromRectangle(aTmpRect2); + + TransfrmHelper::ScaleRect(maWorkArea, rUIScale); + TransfrmHelper::ScaleRect(maRect, rUIScale); + + const sal_uInt16 nDigits(mxMtrPosX->get_digits()); + TransfrmHelper::ConvertRect( maWorkArea, nDigits, mePoolUnit, meDlgUnit ); + TransfrmHelper::ConvertRect( maRect, nDigits, mePoolUnit, meDlgUnit ); + + double fLeft(maWorkArea.getMinX()); + double fTop(maWorkArea.getMinY()); + double fRight(maWorkArea.getMaxX()); + double fBottom(maWorkArea.getMaxY()); + + // seems that sidebar defaults to top left reference point + // and there's no way to set it to something else + fRight -= maRect.getWidth(); + fBottom -= maRect.getHeight(); + + const double fMaxLong(static_cast<double>(vcl::ConvertValue( LONG_MAX, 0, MapUnit::Map100thMM, meDlgUnit ) - 1)); + fLeft = std::clamp(fLeft, -fMaxLong, fMaxLong); + fRight = std::clamp(fRight, -fMaxLong, fMaxLong); + fTop = std::clamp(fTop, - fMaxLong, fMaxLong); + fBottom = std::clamp(fBottom, -fMaxLong, fMaxLong); + + mxMtrPosX->set_range(basegfx::fround64(fLeft), basegfx::fround64(fRight), FieldUnit::NONE); + limitWidth(*mxMtrPosX); + mxMtrPosY->set_range(basegfx::fround64(fTop), basegfx::fround64(fBottom), FieldUnit::NONE); + limitWidth(*mxMtrPosY); + + double fMaxWidth = maWorkArea.getWidth() - (maRect.getWidth() - fLeft); + double fMaxHeight = maWorkArea.getHeight() - (maRect.getHeight() - fTop); + mxMtrWidth->set_max(std::min<sal_Int64>(INT_MAX, basegfx::fround64(fMaxWidth*100)), FieldUnit::NONE); + limitWidth(*mxMtrWidth); + mxMtrHeight->set_max(std::min<sal_Int64>(INT_MAX, basegfx::fround64(fMaxHeight*100)), FieldUnit::NONE); + limitWidth(*mxMtrHeight); +} + +void PosSizePropertyPanel::UpdateUIScale(const Fraction& rUIScale) +{ + if (maUIScale == rUIScale) + return; + + // UI scale has changed. + + // Remember the new UI scale. + maUIScale = rUIScale; + + // The content of the position and size boxes is only updated when item changes are notified. + // Request such notifications without changing the actual item values. + GetBindings()->Invalidate(SID_ATTR_TRANSFORM_POS_X, true); + GetBindings()->Invalidate(SID_ATTR_TRANSFORM_POS_Y, true); + GetBindings()->Invalidate(SID_ATTR_TRANSFORM_WIDTH, true); + GetBindings()->Invalidate(SID_ATTR_TRANSFORM_HEIGHT, true); +} + + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/possize/PosSizePropertyPanel.hxx b/svx/source/sidebar/possize/PosSizePropertyPanel.hxx new file mode 100644 index 0000000000..b57d0bcf7d --- /dev/null +++ b/svx/source/sidebar/possize/PosSizePropertyPanel.hxx @@ -0,0 +1,194 @@ +/* -*- 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_SIDEBAR_POSSIZE_POSSIZEPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_POSSIZE_POSSIZEPROPERTYPANEL_HXX + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/IContextChangeReceiver.hxx> +#include <sfx2/weldutils.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> +#include <svl/poolitem.hxx> +#include <tools/fldunit.hxx> +#include <tools/fract.hxx> +#include <com/sun/star/ui/XSidebar.hpp> +#include <basegfx/range/b2drange.hxx> +#include <vcl/EnumContext.hxx> +#include <vcl/customweld.hxx> +#include <vcl/weld.hxx> + +class SdrView; + +namespace svx { +class DialControl; +}; + +namespace svx::sidebar { + +class PosSizePropertyPanel +: public PanelLayout, + public ::sfx2::sidebar::IContextChangeReceiver, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + virtual ~PosSizePropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings, + const css::uno::Reference<css::ui::XSidebar>& rxSidebar); + + virtual void HandleContextChange( + const vcl::EnumContext& rContext) override; + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void DumpAsPropertyTree(tools::JsonWriter&) override; + + SfxBindings* GetBindings() { return mpBindings;} + + // constructor/destructor + PosSizePropertyPanel( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings, + css::uno::Reference<css::ui::XSidebar> xSidebar); + + virtual void GetControlState( + const sal_uInt16 nSId, + boost::property_tree::ptree& rState) override; + +private: + //Position + std::unique_ptr<weld::Label> mxFtPosX; + std::unique_ptr<weld::MetricSpinButton> mxMtrPosX; + std::unique_ptr<weld::Label> mxFtPosY; + std::unique_ptr<weld::MetricSpinButton> mxMtrPosY; + + // size + std::unique_ptr<weld::Label> mxFtWidth; + std::unique_ptr<weld::MetricSpinButton> mxMtrWidth; + std::unique_ptr<weld::Label> mxFtHeight; + std::unique_ptr<weld::MetricSpinButton> mxMtrHeight; + std::unique_ptr<weld::CheckButton> mxCbxScale; + + //rotation + std::unique_ptr<weld::Label> mxFtAngle; + std::unique_ptr<weld::MetricSpinButton> mxMtrAngle; + + //rotation control + std::unique_ptr<svx::DialControl> mxCtrlDial; + std::unique_ptr<weld::CustomWeld> mxDial; + + //flip + std::unique_ptr<weld::Label> mxFtFlip; + std::unique_ptr<weld::Toolbar> mxFlipTbx; + std::unique_ptr<ToolbarUnoDispatcher> mxFlipDispatch; + + std::unique_ptr<weld::Toolbar> mxArrangeTbx; + std::unique_ptr<ToolbarUnoDispatcher> mxArrangeDispatch; + std::unique_ptr<weld::Toolbar> mxArrangeTbx2; + std::unique_ptr<ToolbarUnoDispatcher> mxArrangeDispatch2; + + std::unique_ptr<weld::Toolbar> mxAlignTbx; + std::unique_ptr<ToolbarUnoDispatcher> mxAlignDispatch; + std::unique_ptr<weld::Toolbar> mxAlignTbx2; + std::unique_ptr<ToolbarUnoDispatcher> mxAlignDispatch2; + + //edit objects button for online's mobile view + std::unique_ptr<weld::Button> mxBtnEditOLEObject; + + // Internal variables + basegfx::B2DRange maRect; + basegfx::B2DRange maWorkArea; + const SdrView* mpView; + sal_uInt32 mlOldWidth; + sal_uInt32 mlOldHeight; + tools::Long mlRotX; + tools::Long mlRotY; + Fraction maUIScale; + MapUnit mePoolUnit; + FieldUnit meDlgUnit; + bool mbFieldMetricOutDated; + + // Controller Items + ::sfx2::sidebar::ControllerItem maTransfPosXControl; + ::sfx2::sidebar::ControllerItem maTransfPosYControl; + ::sfx2::sidebar::ControllerItem maTransfWidthControl; + ::sfx2::sidebar::ControllerItem maTransfHeightControl; + + ::sfx2::sidebar::ControllerItem maSvxAngleControl; + ::sfx2::sidebar::ControllerItem maRotXControl; + ::sfx2::sidebar::ControllerItem maRotYControl; + ::sfx2::sidebar::ControllerItem maProPosControl; + ::sfx2::sidebar::ControllerItem maProSizeControl; + ::sfx2::sidebar::ControllerItem maAutoWidthControl; + ::sfx2::sidebar::ControllerItem maAutoHeightControl; + ::sfx2::sidebar::ControllerItem m_aMetricCtl; + + vcl::EnumContext maContext; + SfxBindings* mpBindings; + + bool mbSizeProtected : 1; + bool mbPositionProtected : 1; + bool mbAutoWidth : 1; + bool mbAutoHeight : 1; + bool mbAdjustEnabled : 1; + + css::uno::Reference<css::ui::XSidebar> mxSidebar; + + DECL_LINK( ChangePosXHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ChangePosYHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ChangeWidthHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ChangeHeightHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ClickAutoHdl, weld::Toggleable&, void ); + DECL_LINK( RotationHdl, svx::DialControl&, void ); + DECL_STATIC_LINK( PosSizePropertyPanel, ClickObjectEditHdl, weld::Button&, void ); + + void Initialize(); + void executeSize(); + + void MetricState(SfxItemState eState, const SfxPoolItem* pState, const Fraction& rUIScale); + static FieldUnit GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState ); + void DisableControls(); + void SetPosSizeMinMax(const Fraction& rUIScale); + + /** Check if the UI scale has changed and handle such a change. + UI scale is an SD only feature. The UI scale is represented by items + ATTR_OPTIONS_SCALE_X and + ATTR_OPTIONS_SCALE_Y. + As we have no direct access (there is no dependency of svx on sd) we have to + use a small trick (aka hack): + a) call this method whenever a change of the metric item is notified, + b) check if the UI scale has changed (strangely, the UI scale value is available at the SdrModel. + c) invalidate the items for position and size to trigger notifications of their current values. + */ + void UpdateUIScale(const Fraction& rUIScale); +}; + + +} // end of namespace svx::sidebar + + +#endif // INCLUDED_SVX_SOURCE_SIDEBAR_POSSIZE_POSSIZEPROPERTYPANEL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/shadow/ShadowPropertyPanel.cxx b/svx/source/sidebar/shadow/ShadowPropertyPanel.cxx new file mode 100644 index 0000000000..36b0d780d9 --- /dev/null +++ b/svx/source/sidebar/shadow/ShadowPropertyPanel.cxx @@ -0,0 +1,363 @@ +/* -*- 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/. + */ + +#include "ShadowPropertyPanel.hxx" +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <svx/colorbox.hxx> +#include <svx/svxids.hrc> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <unotools/localedatawrapper.hxx> +#include <svx/sdooitm.hxx> +#include <svx/sdshitm.hxx> +#include <svx/sdshtitm.hxx> +#include <svx/sdprcitm.hxx> +#include <svx/sdsxyitm.hxx> +#include <svx/sdshcitm.hxx> +#include <comphelper/lok.hxx> +#include <svl/itemset.hxx> + +using namespace css; +using namespace css::uno; + +namespace svx::sidebar { + +ShadowPropertyPanel::ShadowPropertyPanel( + weld::Widget* pParent, + SfxBindings* pBindings) +: PanelLayout(pParent, "ShadowPropertyPanel", "svx/ui/sidebarshadow.ui"), + maShadowController(SID_ATTR_FILL_SHADOW, *pBindings, *this), + maShadowTransController(SID_ATTR_SHADOW_TRANSPARENCE, *pBindings, *this), + maShadowBlurController(SID_ATTR_SHADOW_BLUR, *pBindings, *this), + maShadowColorController(SID_ATTR_SHADOW_COLOR, *pBindings, *this), + maShadowXDistanceController(SID_ATTR_SHADOW_XDISTANCE, *pBindings, *this), + maShadowYDistanceController(SID_ATTR_SHADOW_YDISTANCE, *pBindings, *this), + mpBindings(pBindings), + nX(0), + nY(0), + nXY(0), + mxShowShadow(m_xBuilder->weld_check_button("SHOW_SHADOW")), + mxShadowDistance(m_xBuilder->weld_metric_spin_button("LB_DISTANCE", FieldUnit::POINT)), + mxLBShadowColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_SHADOW_COLOR"), [this]{ return GetFrameWeld(); })), + mxShadowAngle(m_xBuilder->weld_combo_box("LB_ANGLE")), + mxFTAngle(m_xBuilder->weld_label("angle")), + mxFTDistance(m_xBuilder->weld_label("distance")), + mxFTTransparency(m_xBuilder->weld_label("transparency_label")), + mxFTBlur(m_xBuilder->weld_label("blur_label")), + mxFTColor(m_xBuilder->weld_label("shadowcolorlabel")), + mxShadowTransSlider(m_xBuilder->weld_scale("transparency_slider")), + mxShadowTransMetric(m_xBuilder->weld_metric_spin_button("FIELD_TRANSPARENCY", FieldUnit::PERCENT)), + mxShadowBlurMetric(m_xBuilder->weld_metric_spin_button("LB_SHADOW_BLUR", FieldUnit::POINT)) +{ + Initialize(); +} + +ShadowPropertyPanel::~ShadowPropertyPanel() +{ + mxShowShadow.reset(); + mxFTAngle.reset(); + mxShadowAngle.reset(); + mxFTDistance.reset(); + mxShadowDistance.reset(); + mxFTTransparency.reset(); + mxShadowTransSlider.reset(); + mxShadowTransMetric.reset(); + mxShadowBlurMetric.reset(); + mxFTBlur.reset(); + mxFTColor.reset(); + mxLBShadowColor.reset(); + + maShadowController.dispose(); + maShadowTransController.dispose(); + maShadowBlurController.dispose(); + maShadowColorController.dispose(); + maShadowXDistanceController.dispose(); + maShadowYDistanceController.dispose(); +} + +void ShadowPropertyPanel::Initialize() +{ + mxShowShadow->set_state( TRISTATE_FALSE ); + mxShowShadow->connect_toggled( LINK(this, ShadowPropertyPanel, ClickShadowHdl ) ); + mxShadowTransMetric->connect_value_changed( LINK(this, ShadowPropertyPanel, ModifyShadowTransMetricHdl) ); + mxLBShadowColor->SetSelectHdl( LINK( this, ShadowPropertyPanel, ModifyShadowColorHdl ) ); + mxShadowAngle->connect_changed( LINK(this, ShadowPropertyPanel, ModifyShadowAngleHdl) ); + mxShadowDistance->connect_value_changed( LINK(this, ShadowPropertyPanel, ModifyShadowDistanceHdl) ); + mxShadowTransSlider->set_range(0, 100); + mxShadowTransSlider->connect_value_changed( LINK(this, ShadowPropertyPanel, ModifyShadowTransSliderHdl) ); + mxShadowBlurMetric->set_range(0, 150, FieldUnit::POINT); + mxShadowBlurMetric->connect_value_changed(LINK(this, ShadowPropertyPanel, ModifyShadowBlurMetricHdl)); + InsertAngleValues(); +} + +IMPL_LINK_NOARG(ShadowPropertyPanel, ClickShadowHdl, weld::Toggleable&, void) +{ + if( mxShowShadow->get_state() == TRISTATE_FALSE ) + { + SdrOnOffItem aItem(makeSdrShadowItem(false)); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_SHADOW, + SfxCallMode::RECORD, { &aItem }); + + if (comphelper::LibreOfficeKit::isActive()) + { + mxShowShadow->set_state( TRISTATE_FALSE ); + UpdateControls(); + } + } + else + { + SdrOnOffItem aItem(makeSdrShadowItem(true)); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_FILL_SHADOW, + SfxCallMode::RECORD, { &aItem }); + + if (mxShadowDistance->get_value(FieldUnit::POINT) == 0) + mxShadowDistance->set_value( 8, FieldUnit::POINT ); + + if (comphelper::LibreOfficeKit::isActive()) + { + mxShowShadow->set_state( TRISTATE_TRUE ); + UpdateControls(); + } + } +} + +IMPL_LINK_NOARG(ShadowPropertyPanel, ModifyShadowColorHdl, ColorListBox&, void) +{ + XColorItem aItem(makeSdrShadowColorItem(mxLBShadowColor->GetSelectEntryColor())); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_SHADOW_COLOR, + SfxCallMode::RECORD, { &aItem }); +} + +IMPL_LINK_NOARG(ShadowPropertyPanel, ModifyShadowTransMetricHdl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nVal = mxShadowTransMetric->get_value(FieldUnit::PERCENT); + SetTransparencyValue(nVal); + SdrPercentItem aItem( makeSdrShadowTransparenceItem(nVal) ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_SHADOW_TRANSPARENCE, + SfxCallMode::RECORD, { &aItem }); +} + +IMPL_LINK_NOARG(ShadowPropertyPanel, ModifyShadowBlurMetricHdl, weld::MetricSpinButton&, void) +{ + SdrMetricItem aItem(SDRATTR_SHADOWBLUR, mxShadowBlurMetric->get_value(FieldUnit::MM_100TH)); + + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_SHADOW_BLUR, SfxCallMode::RECORD, { &aItem }); +} + +IMPL_LINK_NOARG(ShadowPropertyPanel, ModifyShadowTransSliderHdl, weld::Scale&, void) +{ + sal_uInt16 nVal = mxShadowTransSlider->get_value(); + SetTransparencyValue(nVal); + SdrPercentItem aItem( makeSdrShadowTransparenceItem(nVal) ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_SHADOW_TRANSPARENCE, + SfxCallMode::RECORD, { &aItem }); +} + +IMPL_LINK_NOARG(ShadowPropertyPanel, ModifyShadowAngleHdl, weld::ComboBox&, void) +{ + ModifyShadowDistance(); +} + +IMPL_LINK_NOARG(ShadowPropertyPanel, ModifyShadowDistanceHdl, weld::MetricSpinButton&, void) +{ + ModifyShadowDistance(); +} + +void ShadowPropertyPanel::ModifyShadowDistance() +{ + auto nAngle = mxShadowAngle->get_active_id().toInt32(); + nXY = mxShadowDistance->get_value(FieldUnit::MM_100TH); + switch (nAngle) + { + case 0: nX = nXY; nY = 0; break; + case 45: nX = nXY; nY = -nXY; break; + case 90: nX = 0; nY = - nXY; break; + case 135: nX = nY = -nXY; break; + case 180: nX = -nXY; nY = 0; break; + case 225: nX = -nXY; nY = nXY; break; + case 270: nX = 0; nY = nXY; break; + case 315: nX = nY = nXY; break; + } + SdrMetricItem aXItem(makeSdrShadowXDistItem(nX)); + SdrMetricItem aYItem(makeSdrShadowYDistItem(nY)); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_SHADOW_XDISTANCE, + SfxCallMode::RECORD, { &aXItem }); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_SHADOW_YDISTANCE, + SfxCallMode::RECORD, { &aYItem }); +} + +void ShadowPropertyPanel::UpdateControls() +{ + if (mxShowShadow->get_state() == TRISTATE_FALSE) + { + mxShadowDistance->set_sensitive(false); + mxLBShadowColor->set_sensitive(false); + mxShadowAngle->set_sensitive(false); + mxFTAngle->set_sensitive(false); + mxFTDistance->set_sensitive(false); + mxFTTransparency->set_sensitive(false); + mxFTBlur->set_sensitive(false); + mxFTColor->set_sensitive(false); + mxShadowTransSlider->set_sensitive(false); + mxShadowTransMetric->set_sensitive(false); + mxShadowBlurMetric->set_sensitive(false); + + return; + } + else + { + mxShadowDistance->set_sensitive(true); + mxLBShadowColor->set_sensitive(true); + mxShadowAngle->set_sensitive(true); + mxFTAngle->set_sensitive(true); + mxFTDistance->set_sensitive(true); + mxFTTransparency->set_sensitive(true); + mxFTBlur->set_sensitive(true); + mxFTColor->set_sensitive(true); + mxShadowTransSlider->set_sensitive(true); + mxShadowTransMetric->set_sensitive(true); + mxShadowBlurMetric->set_sensitive(true); + } + + if(nX > 0 && nY == 0) { mxShadowAngle->set_active(0); nXY = nX; } + else if( nX > 0 && nY < 0 ) { mxShadowAngle->set_active(1); nXY = nX; } + else if( nX == 0 && nY < 0 ) { mxShadowAngle->set_active(2); nXY = -nY; } + else if( nX < 0 && nY < 0 ) { mxShadowAngle->set_active(3); nXY = -nY; } + else if( nX < 0 && nY == 0 ) { mxShadowAngle->set_active(4); nXY = -nX; } + else if( nX < 0 && nY > 0 ) { mxShadowAngle->set_active(5); nXY = nY; } + else if( nX == 0 && nY > 0 ) { mxShadowAngle->set_active(6); nXY = nY; } + else if( nX > 0 && nY > 0 ) { mxShadowAngle->set_active(7); nXY = nX; } + else { nXY = 0; } + mxShadowDistance->set_value(nXY, FieldUnit::MM_100TH); +} + +void ShadowPropertyPanel::SetTransparencyValue(tools::Long nVal) +{ + mxShadowTransSlider->set_value(nVal); + mxShadowTransMetric->set_value(nVal, FieldUnit::PERCENT); +} + +void ShadowPropertyPanel::InsertAngleValues() +{ + OUString sSuffix = weld::MetricSpinButton::MetricToString(FieldUnit::DEGREE); + + const LocaleDataWrapper& rLocaleData = Application::GetSettings().GetLocaleDataWrapper(); + + mxShadowAngle->append(OUString::number(0), rLocaleData.getNum(0, 0, true, true) + sSuffix); + mxShadowAngle->append(OUString::number(45), rLocaleData.getNum(45, 0, true, true) + sSuffix); + mxShadowAngle->append(OUString::number(90), rLocaleData.getNum(90, 0, true, true) + sSuffix); + mxShadowAngle->append(OUString::number(135), rLocaleData.getNum(135, 0, true, true) + sSuffix); + mxShadowAngle->append(OUString::number(180), rLocaleData.getNum(180, 0, true, true) + sSuffix); + mxShadowAngle->append(OUString::number(225), rLocaleData.getNum(225, 0, true, true) + sSuffix); + mxShadowAngle->append(OUString::number(270), rLocaleData.getNum(270, 0, true, true) + sSuffix); + mxShadowAngle->append(OUString::number(315), rLocaleData.getNum(315, 0, true, true) + sSuffix); +} + +void ShadowPropertyPanel::NotifyItemUpdate( + sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState) +{ + switch(nSID) + { + case SID_ATTR_FILL_SHADOW: + { + if(eState >= SfxItemState::DEFAULT) + { + const SdrOnOffItem* pItem = dynamic_cast< const SdrOnOffItem* >(pState); + if (pItem && pItem->GetValue()) + mxShowShadow->set_state(TRISTATE_TRUE); + else + mxShowShadow->set_state(TRISTATE_FALSE); + } + } + break; + + case SID_ATTR_SHADOW_TRANSPARENCE: + { + if(eState >= SfxItemState::DEFAULT) + { + const SdrPercentItem* pTransparencyItem = dynamic_cast< const SdrPercentItem* >(pState); + if(pTransparencyItem) + { + const sal_uInt16 nVal = pTransparencyItem->GetValue(); + SetTransparencyValue(nVal); + } + else + SetTransparencyValue(0); + } + } + break; + case SID_ATTR_SHADOW_BLUR: + { + if (eState >= SfxItemState::DEFAULT) + { + const SdrMetricItem* pRadiusItem = dynamic_cast<const SdrMetricItem*>(pState); + if (pRadiusItem) + { + mxShadowBlurMetric->set_value(pRadiusItem->GetValue(), FieldUnit::MM_100TH); + } + } + } + break; + case SID_ATTR_SHADOW_COLOR: + { + if(eState >= SfxItemState::DEFAULT) + { + const XColorItem* pColorItem = dynamic_cast< const XColorItem* >(pState); + if(pColorItem) + { + mxLBShadowColor->SelectEntry(pColorItem->GetColorValue()); + } + } + } + break; + case SID_ATTR_SHADOW_XDISTANCE: + { + if(eState >= SfxItemState::DEFAULT) + { + const SdrMetricItem* pXDistItem = dynamic_cast< const SdrMetricItem* >(pState); + if(pXDistItem) + { + nX = pXDistItem->GetValue(); + } + } + } + break; + case SID_ATTR_SHADOW_YDISTANCE: + { + if(eState >= SfxItemState::DEFAULT) + { + const SdrMetricItem* pYDistItem = dynamic_cast< const SdrMetricItem* >(pState); + if(pYDistItem) + { + nY = pYDistItem->GetValue(); + } + } + } + break; + } + UpdateControls(); +} + +std::unique_ptr<PanelLayout> ShadowPropertyPanel::Create ( + weld::Widget* pParent, + SfxBindings* pBindings) +{ + if(pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to ShadowPropertyPanel::Create", nullptr, 0); + if(pBindings == nullptr) + throw lang::IllegalArgumentException("no SfxBindings given to ShadowPropertyPanel::Create", nullptr, 2); + + return std::make_unique<ShadowPropertyPanel>(pParent, pBindings); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/shadow/ShadowPropertyPanel.hxx b/svx/source/sidebar/shadow/ShadowPropertyPanel.hxx new file mode 100644 index 0000000000..a68405eb0c --- /dev/null +++ b/svx/source/sidebar/shadow/ShadowPropertyPanel.hxx @@ -0,0 +1,89 @@ +/* -*- 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/. + */ +#ifndef INCLUDED_SVX_SOURCE_SIDEBAR_AREA_SHADOWPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_AREA_SHADOWPROPERTYPANEL_HXX + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> + +class ColorListBox; + +namespace svx::sidebar { + +class ShadowPropertyPanel +: public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + virtual ~ShadowPropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + SfxBindings* pBindings); + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + SfxBindings* GetBindings() { return mpBindings;} + + void Initialize(); + + ShadowPropertyPanel( + weld::Widget* pParent, + SfxBindings* pBindings); + +private: + ::sfx2::sidebar::ControllerItem maShadowController; + ::sfx2::sidebar::ControllerItem maShadowTransController; + ::sfx2::sidebar::ControllerItem maShadowBlurController; + ::sfx2::sidebar::ControllerItem maShadowColorController; + ::sfx2::sidebar::ControllerItem maShadowXDistanceController; + ::sfx2::sidebar::ControllerItem maShadowYDistanceController; + + SfxBindings* mpBindings; + tools::Long nX,nY,nXY; + + std::unique_ptr<weld::CheckButton> mxShowShadow; + std::unique_ptr<weld::MetricSpinButton> mxShadowDistance; + std::unique_ptr<ColorListBox> mxLBShadowColor; + std::unique_ptr<weld::ComboBox> mxShadowAngle; + std::unique_ptr<weld::Label> mxFTAngle; + std::unique_ptr<weld::Label> mxFTDistance; + std::unique_ptr<weld::Label> mxFTTransparency; + std::unique_ptr<weld::Label> mxFTBlur; + std::unique_ptr<weld::Label> mxFTColor; + std::unique_ptr<weld::Scale> mxShadowTransSlider; + std::unique_ptr<weld::MetricSpinButton> mxShadowTransMetric; + std::unique_ptr<weld::MetricSpinButton> mxShadowBlurMetric; + + void InsertAngleValues(); + void SetTransparencyValue(tools::Long); + void UpdateControls(); + void ModifyShadowDistance(); + + DECL_LINK(ClickShadowHdl, weld::Toggleable&, void); + DECL_LINK(ModifyShadowColorHdl, ColorListBox&, void); + DECL_LINK(ModifyShadowTransMetricHdl, weld::MetricSpinButton&, void); + DECL_LINK(ModifyShadowAngleHdl, weld::ComboBox&, void); + DECL_LINK(ModifyShadowDistanceHdl, weld::MetricSpinButton&, void); + DECL_LINK(ModifyShadowTransSliderHdl, weld::Scale&, void); + DECL_LINK(ModifyShadowBlurMetricHdl, weld::MetricSpinButton&, void); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/shapes/DefaultShapesPanel.cxx b/svx/source/sidebar/shapes/DefaultShapesPanel.cxx new file mode 100644 index 0000000000..1b62cdedba --- /dev/null +++ b/svx/source/sidebar/shapes/DefaultShapesPanel.cxx @@ -0,0 +1,156 @@ +/* -*- 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 <DefaultShapesPanel.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <comphelper/dispatchcommand.hxx> +#include <utility> +#include <vcl/commandinfoprovider.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +namespace svx::sidebar { + +DefaultShapesPanel::DefaultShapesPanel ( + weld::Widget* pParent, + css::uno::Reference<css::frame::XFrame> xFrame) + : PanelLayout(pParent, "DefaultShapesPanel", "svx/ui/defaultshapespanel.ui") + , mxLineArrowSet(new ValueSet(nullptr)) + , mxLineArrowSetWin(new weld::CustomWeld(*m_xBuilder, "LinesArrows", *mxLineArrowSet)) + , mxCurveSet(new ValueSet(nullptr)) + , mxCurveSetWin(new weld::CustomWeld(*m_xBuilder, "Curves", *mxCurveSet)) + , mxConnectorSet(new ValueSet(nullptr)) + , mxConnectorSetWin(new weld::CustomWeld(*m_xBuilder, "Connectors", *mxConnectorSet)) + , mxBasicShapeSet(new ValueSet(nullptr)) + , mxBasicShapeSetWin(new weld::CustomWeld(*m_xBuilder, "BasicShapes", *mxBasicShapeSet)) + , mxSymbolShapeSet(new ValueSet(nullptr)) + , mxSymbolShapeSetWin(new weld::CustomWeld(*m_xBuilder, "SymbolShapes", *mxSymbolShapeSet)) + , mxBlockArrowSet(new ValueSet(nullptr)) + , mxBlockArrowSetWin(new weld::CustomWeld(*m_xBuilder, "BlockArrows", *mxBlockArrowSet)) + , mxFlowchartSet(new ValueSet(nullptr)) + , mxFlowchartSetWin(new weld::CustomWeld(*m_xBuilder, "Flowcharts", *mxFlowchartSet)) + , mxCalloutSet(new ValueSet(nullptr)) + , mxCalloutSetWin(new weld::CustomWeld(*m_xBuilder, "Callouts", *mxCalloutSet)) + , mxStarSet(new ValueSet(nullptr)) + , mxStarSetWin(new weld::CustomWeld(*m_xBuilder, "Stars", *mxStarSet)) + , mx3DObjectSet(new ValueSet(nullptr)) + , mx3DObjectSetWin(new weld::CustomWeld(*m_xBuilder, "3DObjects", *mx3DObjectSet)) + , mxFrame(std::move(xFrame)) +{ + Initialize(); + pParent->set_size_request(pParent->get_approximate_digit_width() * 20, -1); + m_xContainer->set_size_request(m_xContainer->get_approximate_digit_width() * 25, -1); +} + +std::unique_ptr<PanelLayout> DefaultShapesPanel::Create( + weld::Widget* pParent, + const Reference< XFrame >& rxFrame) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to DefaultShapesPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to DefaultShapesPanel::Create", nullptr, 1); + + return std::make_unique<DefaultShapesPanel>(pParent, rxFrame); +} + +void DefaultShapesPanel::Initialize() +{ + mpShapesSetMap = decltype(mpShapesSetMap){ + { mxLineArrowSet.get(), mpLineShapes }, + { mxCurveSet.get(), mpCurveShapes }, + { mxConnectorSet.get(), mpConnectorShapes }, + { mxBasicShapeSet.get(), mpBasicShapes }, + { mxSymbolShapeSet.get(), mpSymbolShapes }, + { mxBlockArrowSet.get(), mpBlockArrowShapes }, + { mxFlowchartSet.get(), mpFlowchartShapes }, + { mxCalloutSet.get(), mpCalloutShapes }, + { mxStarSet.get(), mpStarShapes }, + { mx3DObjectSet.get(), mp3DShapes } + }; + populateShapes(); + for(auto& aSetMap: mpShapesSetMap) + { + aSetMap.first->SetColor(Application::GetSettings().GetStyleSettings().GetDialogColor()); + aSetMap.first->SetSelectHdl(LINK(this, DefaultShapesPanel, ShapeSelectHdl)); + } +} + +DefaultShapesPanel::~DefaultShapesPanel() +{ + mpShapesSetMap.clear(); + mxLineArrowSetWin.reset(); + mxLineArrowSet.reset(); + mxCurveSetWin.reset(); + mxCurveSet.reset(); + mxConnectorSetWin.reset(); + mxConnectorSet.reset(); + mxBasicShapeSetWin.reset(); + mxBasicShapeSet.reset(); + mxSymbolShapeSetWin.reset(); + mxSymbolShapeSet.reset(); + mxBlockArrowSetWin.reset(); + mxBlockArrowSet.reset(); + mxFlowchartSetWin.reset(); + mxFlowchartSet.reset(); + mxCalloutSetWin.reset(); + mxCalloutSet.reset(); + mxStarSetWin.reset(); + mxStarSet.reset(); + mx3DObjectSetWin.reset(); + mx3DObjectSet.reset(); +} + +IMPL_LINK(DefaultShapesPanel, ShapeSelectHdl, ValueSet*, rValueSet, void) +{ + for(auto& aSetMap : mpShapesSetMap) + { + if(rValueSet == aSetMap.first) + { + sal_uInt16 nSelectionId = aSetMap.first->GetSelectedItemId(); + comphelper::dispatchCommand(aSetMap.second[nSelectionId - 1], {}); + } + else + aSetMap.first->SetNoSelection(); + } +} + +void DefaultShapesPanel::populateShapes() +{ + OUString sSlotStr, sLabel; + Image aSlotImage; + for(auto& aSet : mpShapesSetMap) + { + aSet.first->SetColCount(6); + for(std::map<sal_uInt16, OUString>::size_type i = 0; i < aSet.second.size(); i++) + { + sSlotStr = aSet.second[i]; + aSlotImage = vcl::CommandInfoProvider::GetImageForCommand(sSlotStr, mxFrame); + auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(sSlotStr, + vcl::CommandInfoProvider::GetModuleIdentifier(mxFrame)); + sLabel = vcl::CommandInfoProvider::GetTooltipForCommand(sSlotStr, aProperties, mxFrame); + sal_uInt16 nSelectionId = i + 1; // tdf#142767 id 0 is reserved for nothing-selected + aSet.first->InsertItem(nSelectionId, aSlotImage, sLabel); + } + } +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/shapes/ShapesUtil.cxx b/svx/source/sidebar/shapes/ShapesUtil.cxx new file mode 100644 index 0000000000..ffd1acb629 --- /dev/null +++ b/svx/source/sidebar/shapes/ShapesUtil.cxx @@ -0,0 +1,212 @@ +/* -*- 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 <ShapesUtil.hxx> +#include <map> +#include <rtl/ustring.hxx> + +namespace svx::sidebar{ +SvxShapeCommandsMap::SvxShapeCommandsMap() +{ + mpLineShapes = decltype(mpLineShapes){ + {0, ".uno:Line"}, + {1, ".uno:LineArrowEnd"}, + {2, ".uno:LineCircleArrow"}, + {3, ".uno:LineSquareArrow"}, + {4, ".uno:LineArrows"}, + {5, ".uno:LineArrowStart"}, + {6, ".uno:LineArrowCircle"}, + {7, ".uno:LineArrowSquare"}, + {8, ".uno:MeasureLine"}, + {9, ".uno:Line_Diagonal"} + }; + + mpCurveShapes = decltype(mpCurveShapes){ + {0, ".uno:Freeline_Unfilled"}, + {1, ".uno:Bezier_Unfilled"}, + {2, ".uno:Polygon_Unfilled"}, + {3, ".uno:Polygon_Diagonal_Unfilled"}, + {4, ".uno:Freeline"}, + {5, ".uno:BezierFill"}, + {6, ".uno:Polygon"}, + {7, ".uno:Polygon_Diagonal"} + }; + + mpConnectorShapes = decltype(mpConnectorShapes){ + {0, ".uno:ConnectorArrowEnd"}, + {1, ".uno:ConnectorLineArrowEnd"}, + {2, ".uno:ConnectorCurveArrowEnd"}, + {3, ".uno:ConnectorLinesArrowEnd"}, + {4, ".uno:Connector"}, + {5, ".uno:ConnectorLine"}, + {6, ".uno:ConnectorCurve"}, + {7, ".uno:ConnectorLines"}, + {8, ".uno:ConnectorArrows"}, + {9, ".uno:ConnectorLineArrows"}, + {10, ".uno:ConnectorCurveArrows"}, + {11, ".uno:ConnectorLinesArrows"} + }; + + mpBasicShapes = decltype(mpBasicShapes){ + {0, ".uno:BasicShapes.rectangle"}, + {1, ".uno:BasicShapes.round-rectangle"}, + {2, ".uno:BasicShapes.quadrat"}, + {3, ".uno:BasicShapes.round-quadrat"}, + {4, ".uno:BasicShapes.parallelogram"}, + {5, ".uno:BasicShapes.trapezoid"}, + {6, ".uno:BasicShapes.ellipse"}, + {7, ".uno:BasicShapes.circle"}, + {8, ".uno:BasicShapes.circle-pie"}, + {9, ".uno:CircleCut"}, + {10, ".uno:Arc"}, + {11, ".uno:BasicShapes.block-arc"}, + {12, ".uno:BasicShapes.isosceles-triangle"}, + {13, ".uno:BasicShapes.right-triangle"}, + {14, ".uno:BasicShapes.diamond"}, + {15, ".uno:BasicShapes.pentagon"}, + {16, ".uno:BasicShapes.hexagon"}, + {17, ".uno:BasicShapes.octagon"}, + {18, ".uno:BasicShapes.cross"}, + {19, ".uno:BasicShapes.can"}, + {20, ".uno:BasicShapes.cube"}, + {21, ".uno:BasicShapes.paper"}, + {22, ".uno:BasicShapes.frame"}, + {23, ".uno:BasicShapes.ring"} + }; + + mpSymbolShapes = decltype(mpSymbolShapes){ + {0, ".uno:SymbolShapes.smiley"}, + {1, ".uno:SymbolShapes.sun"}, + {2, ".uno:SymbolShapes.moon"}, + {3, ".uno:SymbolShapes.lightning"}, + {4, ".uno:SymbolShapes.heart"}, + {5, ".uno:SymbolShapes.flower"}, + {6, ".uno:SymbolShapes.cloud"}, + {7, ".uno:SymbolShapes.forbidden"}, + {8, ".uno:SymbolShapes.puzzle"}, + {9, ".uno:SymbolShapes.bracket-pair"}, + {10, ".uno:SymbolShapes.left-bracket"}, + {11, ".uno:SymbolShapes.right-bracket"}, + {12, ".uno:SymbolShapes.brace-pair"}, + {13, ".uno:SymbolShapes.left-brace"}, + {14, ".uno:SymbolShapes.right-brace"}, + {15, ".uno:SymbolShapes.quad-bevel"}, + {16, ".uno:SymbolShapes.octagon-bevel"}, + {17, ".uno:SymbolShapes.diamond-bevel"} + }; + + mpBlockArrowShapes = decltype(mpBlockArrowShapes){ + {0, ".uno:ArrowShapes.left-arrow"}, + {1, ".uno:ArrowShapes.right-arrow"}, + {2, ".uno:ArrowShapes.up-arrow"}, + {3, ".uno:ArrowShapes.down-arrow"}, + {4, ".uno:ArrowShapes.left-right-arrow"}, + {5, ".uno:ArrowShapes.up-down-arrow"}, + {6, ".uno:ArrowShapes.up-right-arrow"}, + {7, ".uno:ArrowShapes.up-right-down-arrow"}, + {8, ".uno:ArrowShapes.quad-arrow"}, + {9, ".uno:ArrowShapes.corner-right-arrow"}, + {10, ".uno:ArrowShapes.split-arrow"}, + {11, ".uno:ArrowShapes.striped-right-arrow"}, + {12, ".uno:ArrowShapes.notched-right-arrow"}, + {13, ".uno:ArrowShapes.pentagon-right"}, + {14, ".uno:ArrowShapes.chevron"}, + {15, ".uno:ArrowShapes.right-arrow-callout"}, + {16, ".uno:ArrowShapes.left-arrow-callout"}, + {17, ".uno:ArrowShapes.up-arrow-callout"}, + {18, ".uno:ArrowShapes.left-right-arrow-callout"}, + {19, ".uno:ArrowShapes.up-down-arrow-callout"}, + {20, ".uno:ArrowShapes.up-right-arrow-callout"}, + {21, ".uno:ArrowShapes.quad-arrow-callout"}, + {22, ".uno:ArrowShapes.circular-arrow"}, + {23, ".uno:ArrowShapes.down-arrow-callout"}, + {24, ".uno:ArrowShapes.split-round-arrow"}, + {25, ".uno:ArrowShapes.s-sharped-arrow"} + }; + + mpFlowchartShapes = decltype(mpFlowchartShapes){ + {0, ".uno:FlowChartShapes.flowchart-process"}, + {1, ".uno:FlowChartShapes.flowchart-alternate-process"}, + {2, ".uno:FlowChartShapes.flowchart-decision"}, + {3, ".uno:FlowChartShapes.flowchart-data"}, + {4, ".uno:FlowChartShapes.flowchart-predefined-process"}, + {5, ".uno:FlowChartShapes.flowchart-internal-storage"}, + {6, ".uno:FlowChartShapes.flowchart-document"}, + {7, ".uno:FlowChartShapes.flowchart-multidocument"}, + {8, ".uno:FlowChartShapes.flowchart-terminator"}, + {9, ".uno:FlowChartShapes.flowchart-preparation"}, + {10, ".uno:FlowChartShapes.flowchart-manual-input"}, + {11, ".uno:FlowChartShapes.flowchart-manual-operation"}, + {12, ".uno:FlowChartShapes.flowchart-connector"}, + {13, ".uno:FlowChartShapes.flowchart-off-page-connector"}, + {14, ".uno:FlowChartShapes.flowchart-card"}, + {15, ".uno:FlowChartShapes.flowchart-punched-tape"}, + {16, ".uno:FlowChartShapes.flowchart-summing-junction"}, + {17, ".uno:FlowChartShapes.flowchart-or"}, + {18, ".uno:FlowChartShapes.flowchart-collate"}, + {19, ".uno:FlowChartShapes.flowchart-sort"}, + {20, ".uno:FlowChartShapes.flowchart-extract"}, + {21, ".uno:FlowChartShapes.flowchart-merge"}, + {22, ".uno:FlowChartShapes.flowchart-stored-data"}, + {23, ".uno:FlowChartShapes.flowchart-delay"}, + {24, ".uno:FlowChartShapes.flowchart-sequential-access"}, + {25, ".uno:FlowChartShapes.flowchart-magnetic-disk"}, + {26, ".uno:FlowChartShapes.flowchart-direct-access-storage"}, + {27, ".uno:FlowChartShapes.flowchart-display"} + }; + + mpCalloutShapes = decltype(mpCalloutShapes){ + {0, ".uno:CalloutShapes.rectangular-callout"}, + {1, ".uno:CalloutShapes.round-rectangular-callout"}, + {2, ".uno:CalloutShapes.round-callout"}, + {3, ".uno:CalloutShapes.cloud-callout"}, + {4, ".uno:CalloutShapes.line-callout-1"}, + {5, ".uno:CalloutShapes.line-callout-2"}, + {6, ".uno:CalloutShapes.line-callout-3"} + }; + + mpStarShapes = decltype(mpStarShapes){ + {0, ".uno:StarShapes.star4"}, + {1, ".uno:StarShapes.star5"}, + {2, ".uno:StarShapes.star6"}, + {3, ".uno:StarShapes.star8"}, + {4, ".uno:StarShapes.star12"}, + {5, ".uno:StarShapes.star24"}, + {6, ".uno:StarShapes.bang"}, + {7, ".uno:StarShapes.vertical-scroll"}, + {8, ".uno:StarShapes.horizontal-scroll"}, + {9, ".uno:StarShapes.signet"}, + {10, ".uno:StarShapes.doorplate"}, + {11, ".uno:StarShapes.concave-star6"} + }; + + mp3DShapes = decltype(mp3DShapes){ + {0, ".uno:Cube"}, + {1, ".uno:Sphere"}, + {2, ".uno:Cylinder"}, + {3, ".uno:Cone"}, + {4, ".uno:Cyramid"}, + {5, ".uno:Torus"}, + {6, ".uno:Shell3D"}, + {7, ".uno:HalfSphere"} + }; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file diff --git a/svx/source/sidebar/styles/StylesPropertyPanel.cxx b/svx/source/sidebar/styles/StylesPropertyPanel.cxx new file mode 100644 index 0000000000..4e6b2235d1 --- /dev/null +++ b/svx/source/sidebar/styles/StylesPropertyPanel.cxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ +#include <sal/config.h> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include "StylesPropertyPanel.hxx" + +using namespace css; +using namespace css::uno; + +namespace svx::sidebar { + +std::unique_ptr<PanelLayout> StylesPropertyPanel::Create ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to StylesPropertyPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to StylesPropertyPanel::Create", nullptr, 1); + + return std::make_unique<StylesPropertyPanel>(pParent, rxFrame); +} + +StylesPropertyPanel::StylesPropertyPanel(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame) + : PanelLayout(pParent, "SidebarStylesPanel", "svx/ui/sidebarstylespanel.ui") + , m_xFontStyle(m_xBuilder->weld_toolbar("fontstyletoolbox")) + , m_xFontStyleDispatch(new ToolbarUnoDispatcher(*m_xFontStyle, *m_xBuilder, rxFrame)) + , m_xStyle(m_xBuilder->weld_toolbar("style")) + , m_xStyleDispatch(new ToolbarUnoDispatcher(*m_xStyle, *m_xBuilder, rxFrame)) +{ +} + +StylesPropertyPanel::~StylesPropertyPanel() +{ + m_xStyleDispatch.reset(); + m_xStyle.reset(); + m_xFontStyleDispatch.reset(); + m_xFontStyle.reset(); +} + +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/svx/source/sidebar/styles/StylesPropertyPanel.hxx b/svx/source/sidebar/styles/StylesPropertyPanel.hxx new file mode 100644 index 0000000000..66f773ae95 --- /dev/null +++ b/svx/source/sidebar/styles/StylesPropertyPanel.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ +#pragma once + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/weldutils.hxx> + +namespace svx::sidebar{ + +class StylesPropertyPanel : public PanelLayout +{ +private: + std::unique_ptr<weld::Toolbar> m_xFontStyle; + std::unique_ptr<ToolbarUnoDispatcher> m_xFontStyleDispatch; + + std::unique_ptr<weld::Toolbar> m_xStyle; + std::unique_ptr<ToolbarUnoDispatcher> m_xStyleDispatch; + +public: + virtual ~StylesPropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame); + + StylesPropertyPanel( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame); +}; + +} //end of namespace svx::sidebar +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/svx/source/sidebar/text/TextCharacterSpacingControl.cxx b/svx/source/sidebar/text/TextCharacterSpacingControl.cxx new file mode 100644 index 0000000000..28eb699d2d --- /dev/null +++ b/svx/source/sidebar/text/TextCharacterSpacingControl.cxx @@ -0,0 +1,225 @@ +/* -*- 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 <sfx2/bindings.hxx> +#include "TextCharacterSpacingControl.hxx" +#include <unotools/viewoptions.hxx> +#include <editeng/editids.hrc> +#include <editeng/kernitem.hxx> +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <TextCharacterSpacingPopup.hxx> +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <helpids.h> + +#include <com/sun/star/beans/NamedValue.hpp> + +#define SPACING_VERY_TIGHT -30 +#define SPACING_TIGHT -15 +#define SPACING_NORMAL 0 +#define SPACING_LOOSE 30 +#define SPACING_VERY_LOOSE 60 + +namespace svx { + +TextCharacterSpacingControl::TextCharacterSpacingControl(TextCharacterSpacingPopup* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/textcharacterspacingcontrol.ui", "TextCharacterSpacingControl") + , mnCustomKern(0) + , mnLastCus(SPACING_NOCUSTOM) + , mxEditKerning(m_xBuilder->weld_metric_spin_button("kerning", FieldUnit::POINT)) + , mxTight(m_xBuilder->weld_button("tight")) + , mxVeryTight(m_xBuilder->weld_button("very_tight")) + , mxNormal(m_xBuilder->weld_button("normal")) + , mxLoose(m_xBuilder->weld_button("loose")) + , mxVeryLoose(m_xBuilder->weld_button("very_loose")) + , mxLastCustom(m_xBuilder->weld_button("last_custom")) + , mxControl(pControl) +{ + mxEditKerning->connect_value_changed(LINK(this, TextCharacterSpacingControl, KerningModifyHdl)); + mxEditKerning->set_help_id(HID_SPACING_MB_KERN); + + Link<weld::Button&,void> aLink = LINK(this, TextCharacterSpacingControl, PredefinedValuesHdl); + mxNormal->connect_clicked(aLink); + mxVeryTight->connect_clicked(aLink); + mxTight->connect_clicked(aLink); + mxVeryLoose->connect_clicked(aLink); + mxLoose->connect_clicked(aLink); + mxLastCustom->connect_clicked(aLink); + + Initialize(); +} + +void TextCharacterSpacingControl::GrabFocus() +{ + tools::Long nKerning = mxEditKerning->get_value(FieldUnit::NONE); + switch (nKerning) + { + case SPACING_VERY_TIGHT: + mxVeryTight->grab_focus(); + break; + case SPACING_TIGHT: + mxTight->grab_focus(); + break; + case SPACING_NORMAL: + mxNormal->grab_focus(); + break; + case SPACING_LOOSE: + mxLoose->grab_focus(); + break; + case SPACING_VERY_LOOSE: + mxVeryLoose->grab_focus(); + break; + default: + if (nKerning == mnCustomKern) + mxLastCustom->grab_focus(); + else + mxEditKerning->grab_focus(); + } +} + +TextCharacterSpacingControl::~TextCharacterSpacingControl() +{ + if (mnLastCus == SPACING_CLOSE_BY_CUS_EDIT) + { + SvtViewOptions aWinOpt(EViewType::Window, SIDEBAR_SPACING_GLOBAL_VALUE); + css::uno::Sequence<css::beans::NamedValue> aSeq + { { "Spacing", css::uno::Any(OUString::number(mnCustomKern)) } }; + aWinOpt.SetUserData(aSeq); + } +} + +void TextCharacterSpacingControl::Initialize() +{ + SfxPoolItemHolder aResult; + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + const SfxItemState eState(pViewFrm ? pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_CHAR_KERNING, aResult) : SfxItemState::UNKNOWN); + const SvxKerningItem* pKerningItem(static_cast<const SvxKerningItem*>(aResult.getItem())); + tools::Long nKerning = 0; + + if (pKerningItem) + nKerning = pKerningItem->GetValue(); + + SvtViewOptions aWinOpt(EViewType::Window, SIDEBAR_SPACING_GLOBAL_VALUE); + if(aWinOpt.Exists()) + { + css::uno::Sequence<css::beans::NamedValue> aSeq = aWinOpt.GetUserData(); + OUString aTmp; + if(aSeq.hasElements()) + aSeq[0].Value >>= aTmp; + + OUString aWinData(aTmp); + mnCustomKern = aWinData.toInt32(); + mnLastCus = SPACING_CLOSE_BY_CUS_EDIT; + } + else + { + mnLastCus = SPACING_NOCUSTOM; + } + + if(eState >= SfxItemState::DEFAULT) + { + MapUnit eUnit = GetCoreMetric(); + MapUnit eOrgUnit = eUnit; + tools::Long nBig = mxEditKerning->normalize(nKerning); + nKerning = OutputDevice::LogicToLogic(nBig, eOrgUnit, MapUnit::MapPoint); + mxEditKerning->set_value(nKerning, FieldUnit::NONE); + } + else if(SfxItemState::DISABLED == eState) + { + mxEditKerning->set_text(OUString()); + mxEditKerning->set_sensitive(false); + } + else + { + mxEditKerning->set_text(OUString()); + mxEditKerning->set_sensitive(false); + } +} + +void TextCharacterSpacingControl::ExecuteCharacterSpacing(tools::Long nValue, bool bClose) +{ + MapUnit eUnit = GetCoreMetric(); + + tools::Long nSign = (nValue < 0) ? -1 : 1; + nValue = nValue * nSign; + + tools::Long nVal = OutputDevice::LogicToLogic(nValue, MapUnit::MapPoint, eUnit); + short nKern = (nValue == 0) ? 0 : static_cast<short>(mxEditKerning->denormalize(nVal)); + + SvxKerningItem aKernItem(nSign * nKern, SID_ATTR_CHAR_KERNING); + + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + pViewFrm->GetBindings().GetDispatcher()->ExecuteList(SID_ATTR_CHAR_KERNING, + SfxCallMode::RECORD, { &aKernItem }); + } + + if (bClose) + mxControl->EndPopupMode(); +} + +IMPL_LINK(TextCharacterSpacingControl, PredefinedValuesHdl, weld::Button&, rControl, void) +{ + mnLastCus = SPACING_CLOSE_BY_CLICK_ICON; + + if (&rControl == mxNormal.get()) + { + ExecuteCharacterSpacing(SPACING_NORMAL); + } + else if (&rControl == mxVeryTight.get()) + { + ExecuteCharacterSpacing(SPACING_VERY_TIGHT); + } + else if (&rControl == mxTight.get()) + { + ExecuteCharacterSpacing(SPACING_TIGHT); + } + else if (&rControl == mxVeryLoose.get()) + { + ExecuteCharacterSpacing(SPACING_VERY_LOOSE); + } + else if (&rControl == mxLoose.get()) + { + ExecuteCharacterSpacing(SPACING_LOOSE); + } + else if (&rControl == mxLastCustom.get()) + { + ExecuteCharacterSpacing(mnCustomKern); + } +} + +IMPL_LINK_NOARG(TextCharacterSpacingControl, KerningModifyHdl, weld::MetricSpinButton&, void) +{ + mnLastCus = SPACING_CLOSE_BY_CUS_EDIT; + mnCustomKern = mxEditKerning->get_value(FieldUnit::NONE); + + ExecuteCharacterSpacing(mnCustomKern, false); +} + +MapUnit TextCharacterSpacingControl::GetCoreMetric() +{ + SfxItemPool &rPool = SfxGetpApp()->GetPool(); + sal_uInt16 nWhich = rPool.GetWhich(SID_ATTR_CHAR_KERNING); + return rPool.GetMetric(nWhich); +} + +} // end of namespace svx + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/text/TextCharacterSpacingControl.hxx b/svx/source/sidebar/text/TextCharacterSpacingControl.hxx new file mode 100644 index 0000000000..dc7312f0ea --- /dev/null +++ b/svx/source/sidebar/text/TextCharacterSpacingControl.hxx @@ -0,0 +1,69 @@ +/* -*- 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_SIDEBAR_TEXT_TEXTCHARACTERSPACINGCONTROL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_TEXT_TEXTCHARACTERSPACINGCONTROL_HXX + +#include <svtools/toolbarmenu.hxx> + +namespace svx { +#define SPACING_NOCUSTOM 0 +#define SPACING_CLOSE_BY_CLICK_ICON -1 +#define SPACING_CLOSE_BY_CUS_EDIT 1 + +inline constexpr OUString SIDEBAR_SPACING_GLOBAL_VALUE = u"PopupPanel_Spacing"_ustr; + +class TextCharacterSpacingPopup; + +class TextCharacterSpacingControl final : public WeldToolbarPopup +{ +public: + explicit TextCharacterSpacingControl(TextCharacterSpacingPopup* pControl, weld::Widget* pParent); + + virtual void GrabFocus() override; + + virtual ~TextCharacterSpacingControl() override; + +private: + tools::Long mnCustomKern; + short mnLastCus; + + std::unique_ptr<weld::MetricSpinButton> mxEditKerning; + std::unique_ptr<weld::Button> mxTight; + std::unique_ptr<weld::Button> mxVeryTight; + std::unique_ptr<weld::Button> mxNormal; + std::unique_ptr<weld::Button> mxLoose; + std::unique_ptr<weld::Button> mxVeryLoose; + std::unique_ptr<weld::Button> mxLastCustom; + + rtl::Reference<TextCharacterSpacingPopup> mxControl; + + void Initialize(); + void ExecuteCharacterSpacing(tools::Long nValue, bool bClose = true); + + DECL_LINK(PredefinedValuesHdl, weld::Button&, void); + DECL_LINK(KerningModifyHdl, weld::MetricSpinButton&, void); + + static MapUnit GetCoreMetric(); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/text/TextCharacterSpacingPopup.cxx b/svx/source/sidebar/text/TextCharacterSpacingPopup.cxx new file mode 100644 index 0000000000..62a1a6e369 --- /dev/null +++ b/svx/source/sidebar/text/TextCharacterSpacingPopup.cxx @@ -0,0 +1,82 @@ +/* -*- 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 <TextCharacterSpacingPopup.hxx> +#include "TextCharacterSpacingControl.hxx" +#include <vcl/toolbox.hxx> + +using namespace svx; + +TextCharacterSpacingPopup::TextCharacterSpacingPopup( + const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void TextCharacterSpacingPopup::initialize(const css::uno::Sequence<css::uno::Any>& rArguments) +{ + PopupWindowController::initialize(rArguments); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel()); + } + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +TextCharacterSpacingPopup::~TextCharacterSpacingPopup() {} + +std::unique_ptr<WeldToolbarPopup> TextCharacterSpacingPopup::weldPopupWindow() +{ + return std::make_unique<TextCharacterSpacingControl>(this, m_pToolbar); +} + +VclPtr<vcl::Window> TextCharacterSpacingPopup::createVclPopupWindow(vcl::Window* pParent) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create( + getFrameInterface(), pParent, + std::make_unique<TextCharacterSpacingControl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString TextCharacterSpacingPopup::getImplementationName() +{ + return "com.sun.star.comp.svx.CharacterSpacingToolBoxControl"; +} + +css::uno::Sequence<OUString> TextCharacterSpacingPopup::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_CharacterSpacingToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new TextCharacterSpacingPopup(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/text/TextPropertyPanel.cxx b/svx/source/sidebar/text/TextPropertyPanel.cxx new file mode 100644 index 0000000000..5b4e907cd8 --- /dev/null +++ b/svx/source/sidebar/text/TextPropertyPanel.cxx @@ -0,0 +1,149 @@ +/* -*- 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 "TextPropertyPanel.hxx" + +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <comphelper/lok.hxx> +#include <sfx2/viewsh.hxx> + +using namespace css; + +namespace svx::sidebar { + +std::unique_ptr<PanelLayout> TextPropertyPanel::Create ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to TextPropertyPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to TextPropertyPanel::Create", nullptr, 1); + + return std::make_unique<TextPropertyPanel>(pParent, rxFrame); +} + +TextPropertyPanel::TextPropertyPanel(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame) + : PanelLayout(pParent, "SidebarTextPanel", "svx/ui/sidebartextpanel.ui") + , mxFont(m_xBuilder->weld_toolbar("font")) + , mxFontDispatch(new ToolbarUnoDispatcher(*mxFont, *m_xBuilder, rxFrame)) + , mxFontHeight(m_xBuilder->weld_toolbar("fontheight")) + , mxFontHeightDispatch(new ToolbarUnoDispatcher(*mxFontHeight, *m_xBuilder, rxFrame)) + , mxFontEffects(m_xBuilder->weld_toolbar("fonteffects")) + , mxFontEffectsDispatch(new ToolbarUnoDispatcher(*mxFontEffects, *m_xBuilder, rxFrame)) + , mxFontAdjust(m_xBuilder->weld_toolbar("fontadjust")) + , mxFontAdjustDispatch(new ToolbarUnoDispatcher(*mxFontAdjust, *m_xBuilder, rxFrame)) + , mxToolBoxFontColor(m_xBuilder->weld_toolbar("colorbar")) + , mxToolBoxFontColorDispatch(new ToolbarUnoDispatcher(*mxToolBoxFontColor, *m_xBuilder, rxFrame)) + , mxToolBoxBackgroundColor(m_xBuilder->weld_toolbar("colorbar_background")) + , mxToolBoxBackgroundColorDispatch(new ToolbarUnoDispatcher(*mxToolBoxBackgroundColor, *m_xBuilder, rxFrame)) + , mxResetBar(m_xBuilder->weld_toolbar("resetattr")) + , mxResetBarDispatch(new ToolbarUnoDispatcher(*mxResetBar, *m_xBuilder, rxFrame)) + , mxDefaultBar(m_xBuilder->weld_toolbar("defaultattr")) + , mxDefaultBarDispatch(new ToolbarUnoDispatcher(*mxDefaultBar, *m_xBuilder, rxFrame)) + , mxPositionBar(m_xBuilder->weld_toolbar("position")) + , mxPositionBarDispatch(new ToolbarUnoDispatcher(*mxPositionBar, *m_xBuilder, rxFrame)) + , mxSpacingBar(m_xBuilder->weld_toolbar("spacingbar")) + , mxSpacingBarDispatch(new ToolbarUnoDispatcher(*mxSpacingBar, *m_xBuilder, rxFrame)) +{ + bool isMobilePhone = false; + const SfxViewShell* pViewShell = SfxViewShell::Current(); + if (comphelper::LibreOfficeKit::isActive() && + pViewShell && pViewShell->isLOKMobilePhone()) + isMobilePhone = true; + mxSpacingBar->set_visible(!isMobilePhone); +} + +TextPropertyPanel::~TextPropertyPanel() +{ + mxResetBarDispatch.reset(); + mxDefaultBarDispatch.reset(); + mxPositionBarDispatch.reset(); + mxSpacingBarDispatch.reset(); + mxToolBoxFontColorDispatch.reset(); + mxToolBoxBackgroundColorDispatch.reset(); + mxFontAdjustDispatch.reset(); + mxFontEffectsDispatch.reset(); + mxFontHeightDispatch.reset(); + mxFontDispatch.reset(); + + mxResetBar.reset(); + mxDefaultBar.reset(); + mxPositionBar.reset(); + mxSpacingBar.reset(); + mxToolBoxFontColor.reset(); + mxToolBoxBackgroundColor.reset(); + mxFontAdjust.reset(); + mxFontEffects.reset(); + mxFontHeight.reset(); + mxFont.reset(); +} + +void TextPropertyPanel::HandleContextChange ( + const vcl::EnumContext& rContext) +{ + if (maContext == rContext) + return; + + maContext = rContext; + + bool bWriterText = false; + bool bDrawText = false; + bool bCalcText = false; + + switch (maContext.GetCombinedContext_DI()) + { + case CombinedEnumContext(Application::Calc, Context::DrawText): + case CombinedEnumContext(Application::WriterVariants, Context::DrawText): + case CombinedEnumContext(Application::WriterVariants, Context::Annotation): + case CombinedEnumContext(Application::DrawImpress, Context::DrawText): + case CombinedEnumContext(Application::DrawImpress, Context::Text): + case CombinedEnumContext(Application::DrawImpress, Context::Table): + case CombinedEnumContext(Application::DrawImpress, Context::OutlineText): + case CombinedEnumContext(Application::DrawImpress, Context::Draw): + case CombinedEnumContext(Application::DrawImpress, Context::TextObject): + case CombinedEnumContext(Application::DrawImpress, Context::Graphic): + bDrawText = true; + break; + + case CombinedEnumContext(Application::WriterVariants, Context::Text): + case CombinedEnumContext(Application::WriterVariants, Context::Table): + bWriterText = true; + break; + + case CombinedEnumContext(Application::Calc, Context::Text): + case CombinedEnumContext(Application::Calc, Context::Table): + case CombinedEnumContext(Application::Calc, Context::Cell): + case CombinedEnumContext(Application::Calc, Context::EditCell): + case CombinedEnumContext(Application::Calc, Context::Grid): + bCalcText = true; + break; + + default: + break; + } + + mxToolBoxBackgroundColor->set_visible(bWriterText || bDrawText); + mxResetBar->set_visible(bWriterText || bCalcText); + mxDefaultBar->set_visible(bDrawText); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/text/TextPropertyPanel.hxx b/svx/source/sidebar/text/TextPropertyPanel.hxx new file mode 100644 index 0000000000..c383ef1bd8 --- /dev/null +++ b/svx/source/sidebar/text/TextPropertyPanel.hxx @@ -0,0 +1,76 @@ +/* -*- 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_SIDEBAR_TEXT_TEXTPROPERTYPANEL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_TEXT_TEXTPROPERTYPANEL_HXX + +#include <sfx2/sidebar/IContextChangeReceiver.hxx> +#include <sfx2/weldutils.hxx> +#include <vcl/EnumContext.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> + +namespace svx::sidebar { + +class TextPropertyPanel + : public PanelLayout, + public ::sfx2::sidebar::IContextChangeReceiver +{ +public: + virtual ~TextPropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame); + + virtual void HandleContextChange ( + const vcl::EnumContext& rContext) override; + + TextPropertyPanel ( + weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame); + +private: + std::unique_ptr<weld::Toolbar> mxFont; + std::unique_ptr<ToolbarUnoDispatcher> mxFontDispatch; + std::unique_ptr<weld::Toolbar> mxFontHeight; + std::unique_ptr<ToolbarUnoDispatcher> mxFontHeightDispatch; + std::unique_ptr<weld::Toolbar> mxFontEffects; + std::unique_ptr<ToolbarUnoDispatcher> mxFontEffectsDispatch; + std::unique_ptr<weld::Toolbar> mxFontAdjust; + std::unique_ptr<ToolbarUnoDispatcher> mxFontAdjustDispatch; + std::unique_ptr<weld::Toolbar> mxToolBoxFontColor; + std::unique_ptr<ToolbarUnoDispatcher> mxToolBoxFontColorDispatch; + std::unique_ptr<weld::Toolbar> mxToolBoxBackgroundColor; + std::unique_ptr<ToolbarUnoDispatcher> mxToolBoxBackgroundColorDispatch; + std::unique_ptr<weld::Toolbar> mxResetBar; + std::unique_ptr<ToolbarUnoDispatcher> mxResetBarDispatch; + std::unique_ptr<weld::Toolbar> mxDefaultBar; + std::unique_ptr<ToolbarUnoDispatcher> mxDefaultBarDispatch; + std::unique_ptr<weld::Toolbar> mxPositionBar; + std::unique_ptr<ToolbarUnoDispatcher> mxPositionBarDispatch; + std::unique_ptr<weld::Toolbar> mxSpacingBar; + std::unique_ptr<ToolbarUnoDispatcher> mxSpacingBarDispatch; + + vcl::EnumContext maContext; +}; + +} // end of namespace svx::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/text/TextUnderlineControl.cxx b/svx/source/sidebar/text/TextUnderlineControl.cxx new file mode 100644 index 0000000000..34c22b9428 --- /dev/null +++ b/svx/source/sidebar/text/TextUnderlineControl.cxx @@ -0,0 +1,143 @@ +/* -*- 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 "TextUnderlineControl.hxx" +#include <svx/svxids.hrc> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <TextUnderlinePopup.hxx> +#include <editeng/editids.hrc> +#include <editeng/udlnitem.hxx> +#include <svl/itemset.hxx> +#include <helpids.h> + +namespace svx { + +TextUnderlineControl::TextUnderlineControl(TextUnderlinePopup* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/textunderlinecontrol.ui", "TextUnderlineControl") + , mxNone(m_xBuilder->weld_button("none")) + , mxSingle(m_xBuilder->weld_button("single")) + , mxDouble(m_xBuilder->weld_button("double")) + , mxBold(m_xBuilder->weld_button("bold")) + , mxDot(m_xBuilder->weld_button("dot")) + , mxDotBold(m_xBuilder->weld_button("dotbold")) + , mxDash(m_xBuilder->weld_button("dash")) + , mxDashLong(m_xBuilder->weld_button("dashlong")) + , mxDashDot(m_xBuilder->weld_button("dashdot")) + , mxDashDotDot(m_xBuilder->weld_button("dashdotdot")) + , mxWave(m_xBuilder->weld_button("wave")) + , mxMoreOptions(m_xBuilder->weld_button("moreoptions")) + , mxControl(pControl) +{ + mxMoreOptions->set_help_id(HID_UNDERLINE_BTN); + + Link<weld::Button&,void> aLink = LINK(this, TextUnderlineControl, PBClickHdl); + mxNone->connect_clicked(aLink); + mxSingle->connect_clicked(aLink); + mxDouble->connect_clicked(aLink); + mxBold->connect_clicked(aLink); + mxDot->connect_clicked(aLink); + mxDotBold->connect_clicked(aLink); + mxDash->connect_clicked(aLink); + mxDashLong->connect_clicked(aLink); + mxDashDot->connect_clicked(aLink); + mxDashDotDot->connect_clicked(aLink); + mxWave->connect_clicked(aLink); + mxMoreOptions->connect_clicked(aLink); +} + +void TextUnderlineControl::GrabFocus() +{ + mxNone->grab_focus(); +} + +TextUnderlineControl::~TextUnderlineControl() +{ +} + +FontLineStyle TextUnderlineControl::getLineStyle(const weld::Button& rButton) const +{ + if (&rButton == mxSingle.get()) + return LINESTYLE_SINGLE; + else if (&rButton == mxDouble.get()) + return LINESTYLE_DOUBLE; + else if (&rButton == mxBold.get()) + return LINESTYLE_BOLD; + else if (&rButton == mxDot.get()) + return LINESTYLE_DOTTED; + else if (&rButton == mxDotBold.get()) + return LINESTYLE_BOLDDOTTED; + else if (&rButton == mxDash.get()) + return LINESTYLE_DASH; + else if (&rButton == mxDashLong.get()) + return LINESTYLE_LONGDASH; + else if (&rButton == mxDashDot.get()) + return LINESTYLE_DASHDOT; + else if (&rButton == mxDashDotDot.get()) + return LINESTYLE_DASHDOTDOT; + else if (&rButton == mxWave.get()) + return LINESTYLE_WAVE; + + return LINESTYLE_NONE; +} + +namespace { + +Color GetUnderlineColor() +{ + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SfxPoolItemHolder aResult; + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_CHAR_UNDERLINE, aResult); + const SvxUnderlineItem* pUnderlineItem(static_cast<const SvxUnderlineItem*>(aResult.getItem())); + + if (pUnderlineItem) + return pUnderlineItem->GetColor(); + } + + return COL_AUTO; +} + +} + +IMPL_LINK(TextUnderlineControl, PBClickHdl, weld::Button&, rButton, void) +{ + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + if (&rButton == mxMoreOptions.get()) + { + SfxDispatcher* pDisp = pViewFrm->GetBindings().GetDispatcher(); + pDisp->Execute(SID_CHAR_DLG_EFFECT, SfxCallMode::ASYNCHRON); + } + else + { + const FontLineStyle eUnderline = getLineStyle(rButton); + + SvxUnderlineItem aLineItem(eUnderline, SID_ATTR_CHAR_UNDERLINE); + aLineItem.SetColor(GetUnderlineColor()); + + pViewFrm->GetBindings().GetDispatcher()->ExecuteList(SID_ATTR_CHAR_UNDERLINE, + SfxCallMode::RECORD, { &aLineItem }); + } + } + mxControl->EndPopupMode(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/text/TextUnderlineControl.hxx b/svx/source/sidebar/text/TextUnderlineControl.hxx new file mode 100644 index 0000000000..cc1a19c679 --- /dev/null +++ b/svx/source/sidebar/text/TextUnderlineControl.hxx @@ -0,0 +1,60 @@ +/* -*- 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_SIDEBAR_TEXT_TEXTUNDERLINECONTROL_HXX +#define INCLUDED_SVX_SOURCE_SIDEBAR_TEXT_TEXTUNDERLINECONTROL_HXX + +#include <svtools/toolbarmenu.hxx> + +namespace svx +{ +class TextUnderlinePopup; + +class TextUnderlineControl final : public WeldToolbarPopup +{ +public: + explicit TextUnderlineControl(TextUnderlinePopup* pControl, weld::Widget* pParent); + virtual void GrabFocus() override; + virtual ~TextUnderlineControl() override; + +private: + std::unique_ptr<weld::Button> mxNone; + std::unique_ptr<weld::Button> mxSingle; + std::unique_ptr<weld::Button> mxDouble; + std::unique_ptr<weld::Button> mxBold; + std::unique_ptr<weld::Button> mxDot; + std::unique_ptr<weld::Button> mxDotBold; + std::unique_ptr<weld::Button> mxDash; + std::unique_ptr<weld::Button> mxDashLong; + std::unique_ptr<weld::Button> mxDashDot; + std::unique_ptr<weld::Button> mxDashDotDot; + std::unique_ptr<weld::Button> mxWave; + std::unique_ptr<weld::Button> mxMoreOptions; + + rtl::Reference<TextUnderlinePopup> mxControl; + + FontLineStyle getLineStyle(const weld::Button& rButton) const; + + DECL_LINK(PBClickHdl, weld::Button&, void); +}; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/text/TextUnderlinePopup.cxx b/svx/source/sidebar/text/TextUnderlinePopup.cxx new file mode 100644 index 0000000000..befa2b80dc --- /dev/null +++ b/svx/source/sidebar/text/TextUnderlinePopup.cxx @@ -0,0 +1,82 @@ +/* -*- 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 <TextUnderlinePopup.hxx> +#include "TextUnderlineControl.hxx" +#include <vcl/toolbox.hxx> + +using namespace svx; + +TextUnderlinePopup::TextUnderlinePopup( + const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +TextUnderlinePopup::~TextUnderlinePopup() {} + +void TextUnderlinePopup::initialize(const css::uno::Sequence<css::uno::Any>& rArguments) +{ + PopupWindowController::initialize(rArguments); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel()); + } + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWN | pToolBox->GetItemBits(nId)); +} + +std::unique_ptr<WeldToolbarPopup> TextUnderlinePopup::weldPopupWindow() +{ + return std::make_unique<TextUnderlineControl>(this, m_pToolbar); +} + +VclPtr<vcl::Window> TextUnderlinePopup::createVclPopupWindow(vcl::Window* pParent) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create( + getFrameInterface(), pParent, + std::make_unique<TextUnderlineControl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString TextUnderlinePopup::getImplementationName() +{ + return "com.sun.star.comp.svx.UnderlineToolBoxControl"; +} + +css::uno::Sequence<OUString> TextUnderlinePopup::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_UnderlineToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new TextUnderlinePopup(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/sidebar/textcolumns/TextColumnsPropertyPanel.cxx b/svx/source/sidebar/textcolumns/TextColumnsPropertyPanel.cxx new file mode 100644 index 0000000000..0d9916b5a9 --- /dev/null +++ b/svx/source/sidebar/textcolumns/TextColumnsPropertyPanel.cxx @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include "TextColumnsPropertyPanel.hxx" + +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/objsh.hxx> +#include <svl/itempool.hxx> +#include <svtools/unitconv.hxx> +#include <svx/sdmetitm.hxx> +#include <svx/svddef.hxx> +#include <svx/svxids.hrc> +#include <svl/itemset.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +namespace +{ +MapUnit GetUnit(const SfxBindings* pBindings, sal_uInt16 nWhich) +{ + assert(pBindings); + + SfxObjectShell* pSh = nullptr; + if (auto pShell = pBindings->GetDispatcher()->GetShell(0)) + pSh = pShell->GetObjectShell(); + if (!pSh) + pSh = SfxObjectShell::Current(); + SfxItemPool& rPool = pSh ? pSh->GetPool() : SfxGetpApp()->GetPool(); + return rPool.GetMetric(nWhich); +} +} + +namespace svx::sidebar +{ +TextColumnsPropertyPanel::TextColumnsPropertyPanel(weld::Widget* pParent, SfxBindings* pBindings) + : PanelLayout(pParent, "TextColumnsPropertyPanel", "svx/ui/sidebartextcolumnspanel.ui") + , mpBindings(pBindings) + , m_xColumnsNumber(m_xBuilder->weld_spin_button("FLD_COL_NUMBER")) + , m_xColumnsSpacing(m_xBuilder->weld_metric_spin_button("MTR_FLD_COL_SPACING", FieldUnit::CM)) + , maColumnsNumberController(SID_ATTR_TEXTCOLUMNS_NUMBER, *pBindings, *this) + , maColumnsSpacingController(SID_ATTR_TEXTCOLUMNS_SPACING, *pBindings, *this) +{ + m_xColumnsNumber->connect_value_changed( + LINK(this, TextColumnsPropertyPanel, ModifyColumnsNumberHdl)); + m_xColumnsSpacing->connect_value_changed( + LINK(this, TextColumnsPropertyPanel, ModifyColumnsSpacingHdl)); +} + +TextColumnsPropertyPanel::~TextColumnsPropertyPanel() +{ + maColumnsSpacingController.dispose(); + maColumnsNumberController.dispose(); + + m_xColumnsSpacing.reset(); + m_xColumnsNumber.reset(); +} + +IMPL_LINK_NOARG(TextColumnsPropertyPanel, ModifyColumnsNumberHdl, weld::SpinButton&, void) +{ + SfxInt16Item aItem(SDRATTR_TEXTCOLUMNS_NUMBER, m_xColumnsNumber->get_value()); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_TEXTCOLUMNS_NUMBER, SfxCallMode::RECORD, + { &aItem }); +} + +IMPL_LINK_NOARG(TextColumnsPropertyPanel, ModifyColumnsSpacingHdl, weld::MetricSpinButton&, void) +{ + const MapUnit aUnit = GetUnit(mpBindings, SDRATTR_TEXTCOLUMNS_SPACING); + SdrMetricItem aItem(SDRATTR_TEXTCOLUMNS_SPACING, GetCoreValue(*m_xColumnsSpacing, aUnit)); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_TEXTCOLUMNS_SPACING, SfxCallMode::RECORD, + { &aItem }); +} + +void TextColumnsPropertyPanel::NotifyItemUpdate(sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState) +{ + switch (nSID) + { + case SID_ATTR_TEXTCOLUMNS_NUMBER: + if (eState >= SfxItemState::DEFAULT) + { + if (const auto pItem = dynamic_cast<const SfxInt16Item*>(pState)) + m_xColumnsNumber->set_value(pItem->GetValue()); + } + break; + case SID_ATTR_TEXTCOLUMNS_SPACING: + if (eState >= SfxItemState::DEFAULT) + { + const MapUnit aUnit = GetUnit(mpBindings, SDRATTR_TEXTCOLUMNS_SPACING); + if (const auto pItem = dynamic_cast<const SdrMetricItem*>(pState)) + SetMetricValue(*m_xColumnsSpacing, pItem->GetValue(), aUnit); + } + break; + } +} + +std::unique_ptr<PanelLayout> TextColumnsPropertyPanel::Create(weld::Widget* pParent, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw css::lang::IllegalArgumentException( + "no parent Window given to TextColumnsPropertyPanel::Create", nullptr, 0); + if (pBindings == nullptr) + throw css::lang::IllegalArgumentException( + "no SfxBindings given to TextColumnsPropertyPanel::Create", nullptr, 2); + + return std::make_unique<TextColumnsPropertyPanel>(pParent, pBindings); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/svx/source/sidebar/textcolumns/TextColumnsPropertyPanel.hxx b/svx/source/sidebar/textcolumns/TextColumnsPropertyPanel.hxx new file mode 100644 index 0000000000..e9c27fcc6c --- /dev/null +++ b/svx/source/sidebar/textcolumns/TextColumnsPropertyPanel.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> + +class ColorListBox; + +namespace svx::sidebar +{ +class TextColumnsPropertyPanel : public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + TextColumnsPropertyPanel(weld::Widget* pParent, SfxBindings* pBindings); + virtual ~TextColumnsPropertyPanel() override; + + static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent, SfxBindings* pBindings); + + virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState(const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override{}; + +private: + SfxBindings* mpBindings; + + std::unique_ptr<weld::SpinButton> m_xColumnsNumber; + std::unique_ptr<weld::MetricSpinButton> m_xColumnsSpacing; + + sfx2::sidebar::ControllerItem maColumnsNumberController; + sfx2::sidebar::ControllerItem maColumnsSpacingController; + + DECL_LINK(ModifyColumnsNumberHdl, weld::SpinButton&, void); + DECL_LINK(ModifyColumnsSpacingHdl, weld::MetricSpinButton&, void); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/svx/source/sidebar/tools/ValueSetWithTextControl.cxx b/svx/source/sidebar/tools/ValueSetWithTextControl.cxx new file mode 100644 index 0000000000..91cea51325 --- /dev/null +++ b/svx/source/sidebar/tools/ValueSetWithTextControl.cxx @@ -0,0 +1,130 @@ +/* -*- 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/sidebar/ValueSetWithTextControl.hxx> +#include <sfx2/sidebar/Theme.hxx> + +#include <i18nlangtag/mslangid.hxx> +#include <svtools/valueset.hxx> +#include <vcl/event.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +namespace svx::sidebar { + +ValueSetWithTextControl::ValueSetWithTextControl() + : ValueSet(nullptr) +{ +} + +void ValueSetWithTextControl::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + ValueSet::SetDrawingArea(pDrawingArea); + + Size aSize(250, 300); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + SetOutputSizePixel(aSize); + + SetColCount(); +} + +void ValueSetWithTextControl::SetOptimalDrawingAreaHeight() +{ + const vcl::Font aFont(Application::GetSettings().GetStyleSettings().GetLabelFont()); + const sal_Int32 nRowHeight = aFont.GetFontSize().Height() * 9 / 4; // see UserDraw() + const Size aSize(GetOutputSizePixel().Width(), nRowHeight * maItems.size()); + GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); + SetOutputSizePixel(aSize); +} + +void ValueSetWithTextControl::AddItem( + const OUString& rItemText, + const OUString& rItemText2 ) +{ + ValueSetWithTextItem aItem; + aItem.maItemText = rItemText; + aItem.maItemText2 = rItemText2; + + maItems.push_back( aItem ); + + InsertItem( maItems.size() ); + SetItemText( maItems.size(), rItemText ); +} + +void ValueSetWithTextControl::UserDraw( const UserDrawEvent& rUDEvt ) +{ + const tools::Rectangle aRect = rUDEvt.GetRect(); + vcl::RenderContext* pDev = rUDEvt.GetRenderContext(); + pDev->Push(); + const sal_uInt16 nItemId = rUDEvt.GetItemId(); + + const tools::Long nRectHeight = aRect.GetHeight(); + + vcl::Font aFont(Application::GetSettings().GetStyleSettings().GetLabelFont()); + { + Size aSize = aFont.GetFontSize(); + aSize.setHeight( (nRectHeight*4)/9 ); + aFont.SetFontSize( aSize ); + } + + { + //draw background + if ( GetSelectedItemId() == nItemId ) + { + tools::Rectangle aBackRect = aRect; + aBackRect.AdjustTop(3 ); + aBackRect.AdjustBottom( -2 ); + pDev->SetFillColor( sfx2::sidebar::Theme::GetColor( sfx2::sidebar::Theme::Color_Highlight ) ); + pDev->DrawRect(aBackRect); + } + else + { + pDev->SetFillColor( COL_TRANSPARENT ); + pDev->DrawRect(aRect); + } + + if ( GetSelectedItemId() == nItemId ) + { + aFont.SetColor( sfx2::sidebar::Theme::GetColor( sfx2::sidebar::Theme::Color_HighlightText ) ); + } + else + { + aFont.SetColor( Application::GetSettings().GetStyleSettings().GetFieldTextColor() ); + } + + tools::Rectangle aStrRect = aRect; + aStrRect.AdjustTop(nRectHeight/4 ); + aStrRect.AdjustBottom( -(nRectHeight/4) ); + + const tools::Long nRectWidth = aRect.GetWidth(); + aStrRect.AdjustLeft(8 ); + aStrRect.AdjustRight( -((nRectWidth*2)/3) ); + pDev->SetFont(aFont); + pDev->DrawText(aStrRect, maItems[nItemId-1].maItemText, DrawTextFlags::EndEllipsis); + aStrRect.AdjustLeft(nRectWidth/3 ); + aStrRect.AdjustRight((nRectWidth*2)/3 ); + pDev->DrawText(aStrRect, maItems[nItemId-1].maItemText2, DrawTextFlags::EndEllipsis); + } + + Invalidate( aRect ); + pDev->Pop(); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |