From 95ebd24a629b4c8cd62cc20c0701683512cc8fa0 Mon Sep 17 00:00:00 2001 From: Mike Kaganski Date: Thu, 27 May 2021 13:00:10 +0300 Subject: editengine-columns: ODF support [API CHANGE] This uses existing ODF markup, as used by Writer's text frame: style::columns child element of style:graphic-properties, its fo:column-count and fo:column-gap attributes. No ODF extension is required. Since currently only columns with same width and spacing are implemented, without additional settings, style:column child elements are exported, but ignored on import. This adds new property to css::drawing::TextProperties service: TextColumns (of type css::text::XTextColumns). Change-Id: I7e63293e5814b281ceec8a9632e696322d3629e8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116035 Tested-by: Jenkins Reviewed-by: Mike Kaganski --- svx/Library_svxcore.mk | 1 + svx/source/svdraw/svdotext.cxx | 20 ++ svx/source/unodraw/SvxXTextColumns.cxx | 325 +++++++++++++++++++++++++++++++++ svx/source/unodraw/unomod.cxx | 5 + svx/source/unodraw/unopool.cxx | 7 + svx/source/unodraw/unoshape.cxx | 39 ++++ 6 files changed, 397 insertions(+) create mode 100644 svx/source/unodraw/SvxXTextColumns.cxx (limited to 'svx') diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk index 20915ae573c9..8e596acd4605 100644 --- a/svx/Library_svxcore.mk +++ b/svx/Library_svxcore.mk @@ -390,6 +390,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\ svx/source/toolbars/fontworkbar \ svx/source/unodraw/gluepts \ svx/source/unodraw/shapepropertynotifier \ + svx/source/unodraw/SvxXTextColumns \ svx/source/unodraw/tableshape \ svx/source/unodraw/unobrushitemhelper \ svx/source/unodraw/unobtabl \ diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx index a5d9939a6103..27b514dc4ea9 100644 --- a/svx/source/svdraw/svdotext.cxx +++ b/svx/source/svdraw/svdotext.cxx @@ -1724,16 +1724,36 @@ SdrTextAniDirection SdrTextObj::GetTextAniDirection() const return GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION).GetValue(); } +bool SdrTextObj::HasTextColumnsNumber() const +{ + return GetObjectItemSet().HasItem(SDRATTR_TEXTCOLUMNS_NUMBER); +} + sal_Int16 SdrTextObj::GetTextColumnsNumber() const { return GetObjectItemSet().Get(SDRATTR_TEXTCOLUMNS_NUMBER).GetValue(); } +void SdrTextObj::SetTextColumnsNumber(sal_Int16 nColumns) +{ + SetObjectItem(SfxInt16Item(SDRATTR_TEXTCOLUMNS_NUMBER, nColumns)); +} + +bool SdrTextObj::HasTextColumnsSpacing() const +{ + return GetObjectItemSet().HasItem(SDRATTR_TEXTCOLUMNS_SPACING); +} + sal_Int32 SdrTextObj::GetTextColumnsSpacing() const { return GetObjectItemSet().Get(SDRATTR_TEXTCOLUMNS_SPACING).GetValue(); } +void SdrTextObj::SetTextColumnsSpacing(sal_Int32 nSpacing) +{ + SetObjectItem(SdrMetricItem(SDRATTR_TEXTCOLUMNS_SPACING, nSpacing)); +} + // Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a // painting rectangle. Rotation is excluded from the returned values. GDIMetaFile* SdrTextObj::GetTextScrollMetaFileAndRectangle( diff --git a/svx/source/unodraw/SvxXTextColumns.cxx b/svx/source/unodraw/SvxXTextColumns.cxx new file mode 100644 index 000000000000..d245f071391b --- /dev/null +++ b/svx/source/unodraw/SvxXTextColumns.cxx @@ -0,0 +1,325 @@ +/* -*- 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/. + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace +{ +enum : sal_uInt16 +{ + WID_TXTCOL_IS_AUTOMATIC, + WID_TXTCOL_AUTO_DISTANCE, + WID_TXTCOL_LINE_WIDTH, + WID_TXTCOL_LINE_COLOR, + WID_TXTCOL_LINE_REL_HGT, + WID_TXTCOL_LINE_ALIGN, + WID_TXTCOL_LINE_IS_ON, + WID_TXTCOL_LINE_STYLE, +}; + +SfxItemPropertyMapEntry const saTextColumns_Impl[] = { + { u"IsAutomatic", WID_TXTCOL_IS_AUTOMATIC, cppu::UnoType::get(), + css::beans::PropertyAttribute::READONLY, 0 }, + { u"AutomaticDistance", WID_TXTCOL_AUTO_DISTANCE, cppu::UnoType::get(), 0, 0 }, + { u"SeparatorLineWidth", WID_TXTCOL_LINE_WIDTH, cppu::UnoType::get(), 0, 0 }, + { u"SeparatorLineColor", WID_TXTCOL_LINE_COLOR, + cppu::UnoType::get(), 0, 0 }, + { u"SeparatorLineRelativeHeight", WID_TXTCOL_LINE_REL_HGT, cppu::UnoType::get(), 0, + 0 }, + { u"SeparatorLineVerticalAlignment", WID_TXTCOL_LINE_ALIGN, + cppu::UnoType::get(), 0, 0 }, + { u"SeparatorLineIsOn", WID_TXTCOL_LINE_IS_ON, cppu::UnoType::get(), 0, 0 }, + { u"SeparatorLineStyle", WID_TXTCOL_LINE_STYLE, cppu::UnoType::get(), 0, 0 }, + { u"", 0, css::uno::Type(), 0, 0 }, +}; + +class SvxXTextColumns final + : public cppu::WeakImplHelper +{ +public: + SvxXTextColumns() = default; + + // XTextColumns + virtual sal_Int32 SAL_CALL getReferenceValue() override; + virtual sal_Int16 SAL_CALL getColumnCount() override; + virtual void SAL_CALL setColumnCount(sal_Int16 nColumns) override; + virtual css::uno::Sequence SAL_CALL getColumns() override; + virtual void SAL_CALL + setColumns(const css::uno::Sequence& Columns) override; + + // XPropertySet + virtual css::uno::Reference + SAL_CALL getPropertySetInfo() override; + virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, + const css::uno::Any& aValue) override; + virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& PropertyName) override; + virtual void SAL_CALL addPropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& xListener) override; + virtual void SAL_CALL removePropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& aListener) override; + virtual void SAL_CALL addVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + virtual void SAL_CALL removeVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + +private: + sal_Int32 m_nReference = USHRT_MAX; + css::uno::Sequence m_aTextColumns; + bool m_bIsAutomaticWidth = true; + sal_Int32 m_nAutoDistance = 0; + + const SfxItemPropertySet m_aPropSet = { saTextColumns_Impl }; + + //separator line + sal_Int32 m_nSepLineWidth = 0; + com::sun::star::util::Color m_nSepLineColor = 0; // black + sal_Int32 m_nSepLineHeightRelative = 100; // full height + css::style::VerticalAlignment m_nSepLineVertAlign = css::style::VerticalAlignment_MIDDLE; + bool m_bSepLineIsOn = false; + sal_Int16 m_nSepLineStyle = css::text::ColumnSeparatorStyle::NONE; +}; + +OUString SvxXTextColumns::getImplementationName() { return "SvxXTextColumns"; } + +sal_Bool SvxXTextColumns::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence SvxXTextColumns::getSupportedServiceNames() +{ + return { "com.sun.star.text.TextColumns" }; +} + +sal_Int32 SvxXTextColumns::getReferenceValue() +{ + SolarMutexGuard aGuard; + return m_nReference; +} + +sal_Int16 SvxXTextColumns::getColumnCount() +{ + SolarMutexGuard aGuard; + return o3tl::narrowing(m_aTextColumns.getLength()); +} + +void SvxXTextColumns::setColumnCount(sal_Int16 nColumns) +{ + SolarMutexGuard aGuard; + if (nColumns <= 0) + throw css::uno::RuntimeException(); + m_bIsAutomaticWidth = true; + m_aTextColumns.realloc(nColumns); + css::text::TextColumn* pCols = m_aTextColumns.getArray(); + m_nReference = USHRT_MAX; + sal_Int32 nWidth = m_nReference / nColumns; + sal_Int32 nDiff = m_nReference - nWidth * nColumns; + sal_Int32 nDist = m_nAutoDistance / 2; + for (sal_Int16 i = 0; i < nColumns; i++) + { + pCols[i].Width = nWidth; + pCols[i].LeftMargin = i == 0 ? 0 : nDist; + pCols[i].RightMargin = i == nColumns - 1 ? 0 : nDist; + } + pCols[nColumns - 1].Width += nDiff; +} + +css::uno::Sequence SvxXTextColumns::getColumns() +{ + SolarMutexGuard aGuard; + return m_aTextColumns; +} + +void SvxXTextColumns::setColumns(const css::uno::Sequence& rColumns) +{ + SolarMutexGuard aGuard; + sal_Int32 nReferenceTemp = std::accumulate( + rColumns.begin(), rColumns.end(), sal_Int32(0), + [](const sal_Int32 nSum, const css::text::TextColumn& rCol) { return nSum + rCol.Width; }); + m_bIsAutomaticWidth = false; + m_nReference = !nReferenceTemp ? USHRT_MAX : nReferenceTemp; + m_aTextColumns = rColumns; +} + +css::uno::Reference SvxXTextColumns::getPropertySetInfo() +{ + return m_aPropSet.getPropertySetInfo(); +} + +void SvxXTextColumns::setPropertyValue(const OUString& rPropertyName, const css::uno::Any& aValue) +{ + const SfxItemPropertyMapEntry* pEntry = m_aPropSet.getPropertyMap().getByName(rPropertyName); + if (!pEntry) + throw css::beans::UnknownPropertyException("Unknown property: " + rPropertyName, + static_cast(this)); + if (pEntry->nFlags & css::beans::PropertyAttribute::READONLY) + throw css::beans::PropertyVetoException("Property is read-only: " + rPropertyName, + static_cast(this)); + + switch (pEntry->nWID) + { + case WID_TXTCOL_LINE_WIDTH: + if (sal_Int32 nTmp; !(aValue >>= nTmp) || nTmp < 0) + throw css::lang::IllegalArgumentException(); + else + m_nSepLineWidth = convertMm100ToTwip(nTmp); + break; + case WID_TXTCOL_LINE_COLOR: + if (!(aValue >>= m_nSepLineColor)) + throw css::lang::IllegalArgumentException(); + break; + case WID_TXTCOL_LINE_STYLE: + if (!(aValue >>= m_nSepLineStyle)) + throw css::lang::IllegalArgumentException(); + break; + case WID_TXTCOL_LINE_REL_HGT: + if (sal_Int32 nTmp; !(aValue >>= nTmp) || nTmp < 0) + throw css::lang::IllegalArgumentException(); + else + m_nSepLineHeightRelative = nTmp; + break; + case WID_TXTCOL_LINE_ALIGN: + if (css::style::VerticalAlignment eAlign; aValue >>= eAlign) + m_nSepLineVertAlign = eAlign; + else if (sal_Int8 nTmp; aValue >>= nTmp) + m_nSepLineVertAlign = static_cast(nTmp); + else + throw css::lang::IllegalArgumentException(); + break; + case WID_TXTCOL_LINE_IS_ON: + if (!(aValue >>= m_bSepLineIsOn)) + throw css::lang::IllegalArgumentException(); + break; + case WID_TXTCOL_AUTO_DISTANCE: + if (sal_Int32 nTmp; !(aValue >>= nTmp) || nTmp < 0 || nTmp >= m_nReference) + throw css::lang::IllegalArgumentException(); + else + { + m_nAutoDistance = nTmp; + sal_Int32 nColumns = m_aTextColumns.getLength(); + css::text::TextColumn* pCols = m_aTextColumns.getArray(); + sal_Int32 nDist = m_nAutoDistance / 2; + for (sal_Int32 i = 0; i < nColumns; i++) + { + pCols[i].LeftMargin = i == 0 ? 0 : nDist; + pCols[i].RightMargin = i == nColumns - 1 ? 0 : nDist; + } + } + break; + } +} + +css::uno::Any SvxXTextColumns::getPropertyValue(const OUString& rPropertyName) +{ + const SfxItemPropertyMapEntry* pEntry = m_aPropSet.getPropertyMap().getByName(rPropertyName); + if (!pEntry) + throw css::beans::UnknownPropertyException("Unknown property: " + rPropertyName, + static_cast(this)); + + css::uno::Any aRet; + switch (pEntry->nWID) + { + case WID_TXTCOL_LINE_WIDTH: + aRet <<= o3tl::narrowing(convertTwipToMm100(m_nSepLineWidth)); + break; + case WID_TXTCOL_LINE_COLOR: + aRet <<= m_nSepLineColor; + break; + case WID_TXTCOL_LINE_STYLE: + aRet <<= m_nSepLineStyle; + break; + case WID_TXTCOL_LINE_REL_HGT: + aRet <<= m_nSepLineHeightRelative; + break; + case WID_TXTCOL_LINE_ALIGN: + aRet <<= m_nSepLineVertAlign; + break; + case WID_TXTCOL_LINE_IS_ON: + aRet <<= m_bSepLineIsOn; + break; + case WID_TXTCOL_IS_AUTOMATIC: + aRet <<= m_bIsAutomaticWidth; + break; + case WID_TXTCOL_AUTO_DISTANCE: + aRet <<= m_nAutoDistance; + break; + } + return aRet; +} + +void SvxXTextColumns::addPropertyChangeListener( + const OUString& /*rPropertyName*/, + const css::uno::Reference& /*xListener*/) +{ +} + +void SvxXTextColumns::removePropertyChangeListener( + const OUString& /*rPropertyName*/, + const css::uno::Reference& /*xListener*/) +{ +} + +void SvxXTextColumns::addVetoableChangeListener( + const OUString& /*rPropertyName*/, + const css::uno::Reference& /*xListener*/) +{ +} + +void SvxXTextColumns::removeVetoableChangeListener( + const OUString& /*rPropertyName*/, + const css::uno::Reference& /*xListener*/) +{ +} +} + +css::uno::Reference SvxXTextColumns_createInstance() noexcept +{ + return static_cast(new SvxXTextColumns); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/svx/source/unodraw/unomod.cxx b/svx/source/unodraw/unomod.cxx index 5980da82d73d..25b6016dd419 100644 --- a/svx/source/unodraw/unomod.cxx +++ b/svx/source/unodraw/unomod.cxx @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -182,6 +183,10 @@ css::uno::Reference create( uno::Reference< uno::XInterface> xRet( static_cast< ::cppu::OWeakObject* >( pGraphicHelper.get() ) ); return xRet; } + else if (rServiceSpecifier == "com.sun.star.text.TextColumns") + { + return SvxXTextColumns_createInstance(); + } uno::Reference< uno::XInterface > xRet( SvxUnoDrawMSFactory::createTextField( rServiceSpecifier ) ); if( !xRet.is() ) diff --git a/svx/source/unodraw/unopool.cxx b/svx/source/unodraw/unopool.cxx index 5931087349c3..59c19c70262d 100644 --- a/svx/source/unodraw/unopool.cxx +++ b/svx/source/unodraw/unopool.cxx @@ -241,6 +241,13 @@ void SvxUnoDrawPool::_getPropertyStates( const comphelper::PropertyMapEntry** pp } } break; + case OWN_ATTR_TEXTCOLUMNS: + if (IsStaticDefaultItem(&pPool->GetDefaultItem(sal_uInt16(SDRATTR_TEXTCOLUMNS_NUMBER))) + && IsStaticDefaultItem(&pPool->GetDefaultItem(sal_uInt16(SDRATTR_TEXTCOLUMNS_SPACING)))) + *pStates = beans::PropertyState_DEFAULT_VALUE; + else + *pStates = beans::PropertyState_DIRECT_VALUE; + break; default: //#i18732# - correction: // use method instead of using probably diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx index fd5296007a1d..32e3a5c6768a 100644 --- a/svx/source/unodraw/unoshape.cxx +++ b/svx/source/unodraw/unoshape.cxx @@ -86,6 +86,7 @@ #include #include #include +#include #include #include @@ -2494,6 +2495,27 @@ bool SvxShape::setPropertyValueImpl( const OUString&, const SfxItemPropertyMapEn return false; } } + + case OWN_ATTR_TEXTCOLUMNS: + { + if (auto pTextObj = dynamic_cast(GetSdrObject())) + { + css::uno::Reference xTextColumns; + if (rValue >>= xTextColumns) + { + pTextObj->SetTextColumnsNumber(xTextColumns->getColumnCount()); + if (css::uno::Reference xPropSet{ xTextColumns, + css::uno::UNO_QUERY }) + { + auto aVal = xPropSet->getPropertyValue("AutomaticDistance"); + if (sal_Int32 nSpacing; aVal >>= nSpacing) + pTextObj->SetTextColumnsSpacing(nSpacing); + } + } + } + return true; + } + default: { return false; @@ -2897,6 +2919,23 @@ bool SvxShape::getPropertyValueImpl( const OUString&, const SfxItemPropertyMapEn break; } + case OWN_ATTR_TEXTCOLUMNS: + { + if (auto pTextObj = dynamic_cast(GetSdrObject())) + { + if (pTextObj->HasTextColumnsNumber() || pTextObj->HasTextColumnsSpacing()) + { + auto xIf = SvxXTextColumns_createInstance(); + css::uno::Reference xCols(xIf, css::uno::UNO_QUERY_THROW); + xCols->setColumnCount(pTextObj->GetTextColumnsNumber()); + css::uno::Reference xProp(xIf, css::uno::UNO_QUERY_THROW); + xProp->setPropertyValue("AutomaticDistance", + css::uno::Any(pTextObj->GetTextColumnsSpacing())); + rValue <<= xIf; + } + } + break; + } default: return false; -- cgit