From 3ec2d26dc2017ac4a27483febfc63328632f352d Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 30 Apr 2013 17:26:36 +0200 Subject: bnc#779630 initial DOCX import of w:sdt's w:date Also factor out the w:sdt-related methods to a helper class to avoid DomainMapper_Impl become a God object. Change-Id: Ic1a388940bce89688e8558818f92ce9ac997609c --- writerfilter/Library_writerfilter.mk | 1 + writerfilter/source/dmapper/DomainMapper.cxx | 41 ++++++- writerfilter/source/dmapper/DomainMapper_Impl.cxx | 63 +---------- writerfilter/source/dmapper/DomainMapper_Impl.hxx | 8 +- writerfilter/source/dmapper/SdtHelper.cxx | 129 ++++++++++++++++++++++ writerfilter/source/dmapper/SdtHelper.hxx | 68 ++++++++++++ writerfilter/source/ooxml/model.xml | 3 + 7 files changed, 246 insertions(+), 67 deletions(-) create mode 100644 writerfilter/source/dmapper/SdtHelper.cxx create mode 100644 writerfilter/source/dmapper/SdtHelper.hxx (limited to 'writerfilter') diff --git a/writerfilter/Library_writerfilter.mk b/writerfilter/Library_writerfilter.mk index fdde17f7ddab..81d7df296b19 100644 --- a/writerfilter/Library_writerfilter.mk +++ b/writerfilter/Library_writerfilter.mk @@ -106,6 +106,7 @@ $(eval $(call gb_Library_add_exception_objects,writerfilter,\ writerfilter/source/dmapper/PropertyIds \ writerfilter/source/dmapper/PropertyMap \ writerfilter/source/dmapper/PropertyMapHelper \ + writerfilter/source/dmapper/SdtHelper \ writerfilter/source/dmapper/SectionColumnHandler \ writerfilter/source/dmapper/SettingsTable \ writerfilter/source/dmapper/StyleSheetTable \ diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 4d6f9055fb98..16ac29cd8866 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -19,6 +19,7 @@ #include "PageBordersHandler.hxx" #include +#include #include #include #include @@ -1435,14 +1436,14 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) break; case NS_ooxml::LN_CT_SdtBlock_sdtEndContent: m_pImpl->SetSdt(false); - if (!m_pImpl->m_aDropDownItems.empty()) - m_pImpl->createDropDownControl(); + if (!m_pImpl->m_pSdtHelper->getDropDownItems().empty()) + m_pImpl->m_pSdtHelper->createDropDownControl(); break; case NS_ooxml::LN_CT_SdtListItem_displayText: // TODO handle when this is != value break; case NS_ooxml::LN_CT_SdtListItem_value: - m_pImpl->m_aDropDownItems.push_back(sStringValue); + m_pImpl->m_pSdtHelper->getDropDownItems().push_back(sStringValue); break; default: { @@ -3311,6 +3312,26 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, PropertyMapPtr rContext, SprmType pProperties->resolve(*this); } break; + case NS_ooxml::LN_CT_SdtPr_date: + { + writerfilter::Reference::Pointer_t pProperties = rSprm.getProps(); + if (pProperties.get() != NULL) + pProperties->resolve(*this); + } + break; + case NS_ooxml::LN_CT_SdtDate_dateFormat: + { + if (sStringValue == "M/d/yyyy") + // See com/sun/star/awt/UnoControlDateFieldModel.idl, DateFormat; sadly there are no constants for this. + m_pImpl->m_pSdtHelper->getDateFormat().reset(8); + else + { + // Set default format, so at least the date picker is created. + m_pImpl->m_pSdtHelper->getDateFormat().reset(0); + SAL_WARN("writerfilter", "unhandled w:dateFormat value"); + } + } + break; default: { #ifdef DEBUG_DOMAINMAPPER @@ -3602,9 +3623,19 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len) aBuffer.append( (const sal_Unicode *) data_, len); sText = aBuffer.makeStringAndClear(); - if (!m_pImpl->m_aDropDownItems.empty()) + if (!m_pImpl->m_pSdtHelper->getDropDownItems().empty()) { - m_pImpl->m_aSdtTexts.append(sText); + m_pImpl->m_pSdtHelper->getSdtTexts().append(sText); + return; + } + else if (m_pImpl->m_pSdtHelper->getDateFormat()) + { + /* + * Here we assume w:sdt only contains a single text token. We need to + * create the control early, as in Writer, it's part of the cell, but + * in OOXML, the sdt contains the cell. + */ + m_pImpl->m_pSdtHelper->createDateControl(sText); return; } diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 854179f51436..b5a5baab6599 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -186,7 +187,8 @@ DomainMapper_Impl::DomainMapper_Impl( m_bSdt(false), m_xInsertTextRange(xInsertTextRange), m_bIsNewDoc(bIsNewDoc), - m_bInTableStyleRunProps(false) + m_bInTableStyleRunProps(false), + m_pSdtHelper(0) { appendTableManager( ); GetBodyText(); @@ -203,6 +205,7 @@ DomainMapper_Impl::DomainMapper_Impl( getTableManager( ).startLevel(); m_bUsingEnhancedFields = lcl_IsUsingEnhancedFields( m_xComponentContext ); + m_pSdtHelper = new SdtHelper(*this); } @@ -211,6 +214,7 @@ DomainMapper_Impl::~DomainMapper_Impl() RemoveLastParagraph( ); getTableManager( ).endLevel(); popTableManager( ); + delete m_pSdtHelper; } @@ -3937,63 +3941,6 @@ bool DomainMapper_Impl::IsNewDoc() return m_bIsNewDoc; } -/// w:sdt's w:dropDownList doesn't have width, so guess the size based on the longest string. -awt::Size lcl_getOptimalWidth(StyleSheetTablePtr pStyleSheet, OUString& rDefault, std::vector& rItems) -{ - OUString aLongest = rDefault; - sal_Int32 nHeight = 0; - for (size_t i = 0; i < rItems.size(); ++i) - if (rItems[i].getLength() > aLongest.getLength()) - aLongest = rItems[i]; - - MapMode aMap(MAP_100TH_MM); - OutputDevice* pOut = Application::GetDefaultDevice(); - pOut->Push(PUSH_FONT | PUSH_MAPMODE); - - PropertyMapPtr pDefaultCharProps = pStyleSheet->GetDefaultCharProps(); - Font aFont(pOut->GetFont()); - PropertyMap::iterator aFontName = pDefaultCharProps->find(PropertyDefinition(PROP_CHAR_FONT_NAME, false)); - if (aFontName != pDefaultCharProps->end()) - aFont.SetName(aFontName->second.get()); - PropertyMap::iterator aHeight = pDefaultCharProps->find(PropertyDefinition(PROP_CHAR_HEIGHT, false)); - if (aHeight != pDefaultCharProps->end()) - { - nHeight = aHeight->second.get() * 35; // points -> mm100 - aFont.SetSize(Size(0, nHeight)); - } - pOut->SetFont(aFont); - pOut->SetMapMode(aMap); - sal_Int32 nWidth = pOut->GetTextWidth(aLongest); - - pOut->Pop(); - // Width: space for the text + the square having the dropdown arrow. - return awt::Size(nWidth + nHeight, nHeight); -} - -void DomainMapper_Impl::createDropDownControl() -{ - OUString aDefaultText = m_aSdtTexts.makeStringAndClear(); - uno::Reference xControlModel(m_xTextFactory->createInstance("com.sun.star.form.component.ComboBox"), uno::UNO_QUERY); - uno::Reference xPropertySet(xControlModel, uno::UNO_QUERY); - xPropertySet->setPropertyValue("DefaultText", uno::makeAny(aDefaultText)); - xPropertySet->setPropertyValue("Dropdown", uno::makeAny(sal_True)); - uno::Sequence aItems(m_aDropDownItems.size()); - for (size_t i = 0; i < m_aDropDownItems.size(); ++i) - aItems[i] = m_aDropDownItems[i]; - xPropertySet->setPropertyValue("StringItemList", uno::makeAny(aItems)); - - uno::Reference xControlShape(m_xTextFactory->createInstance("com.sun.star.drawing.ControlShape"), uno::UNO_QUERY); - xControlShape->setSize(lcl_getOptimalWidth(GetStyleSheetTable(), aDefaultText, m_aDropDownItems)); - m_aDropDownItems.clear(); - xControlShape->setControl(xControlModel); - - xPropertySet.set(xControlShape, uno::UNO_QUERY); - xPropertySet->setPropertyValue("VertOrient", uno::makeAny(text::VertOrientation::CENTER)); - - uno::Reference xTextContent(xControlShape, uno::UNO_QUERY); - appendTextContent(xTextContent, uno::Sequence< beans::PropertyValue >()); -} - }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 68fe0aeac626..60faa83be428 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -29,6 +29,7 @@ #include #include #include +#include #ifndef INCLUDED_RESOURCESIDS #include @@ -71,6 +72,8 @@ namespace dmapper { using namespace com::sun::star; +class SdtHelper; + struct _PageMar { sal_Int32 top; @@ -679,10 +682,7 @@ public: /// If we're inside , inside bool m_bInTableStyleRunProps; - std::vector m_aDropDownItems; - OUStringBuffer m_aSdtTexts; - /// Create drop-down control from w:sdt's w:dropDownList. - void createDropDownControl(); + SdtHelper* m_pSdtHelper; }; } //namespace dmapper } //namespace writerfilter diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx new file mode 100644 index 000000000000..a1b215b3efaa --- /dev/null +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -0,0 +1,129 @@ +/* -*- 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 +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace writerfilter { +namespace dmapper { + +using namespace ::com::sun::star; + +/// w:sdt's w:dropDownList doesn't have width, so guess the size based on the longest string. +awt::Size lcl_getOptimalWidth(StyleSheetTablePtr pStyleSheet, OUString& rDefault, std::vector& rItems) +{ + OUString aLongest = rDefault; + sal_Int32 nHeight = 0; + for (size_t i = 0; i < rItems.size(); ++i) + if (rItems[i].getLength() > aLongest.getLength()) + aLongest = rItems[i]; + + MapMode aMap(MAP_100TH_MM); + OutputDevice* pOut = Application::GetDefaultDevice(); + pOut->Push(PUSH_FONT | PUSH_MAPMODE); + + PropertyMapPtr pDefaultCharProps = pStyleSheet->GetDefaultCharProps(); + Font aFont(pOut->GetFont()); + PropertyMap::iterator aFontName = pDefaultCharProps->find(PropertyDefinition(PROP_CHAR_FONT_NAME, false)); + if (aFontName != pDefaultCharProps->end()) + aFont.SetName(aFontName->second.get()); + PropertyMap::iterator aHeight = pDefaultCharProps->find(PropertyDefinition(PROP_CHAR_HEIGHT, false)); + if (aHeight != pDefaultCharProps->end()) + { + nHeight = aHeight->second.get() * 35; // points -> mm100 + aFont.SetSize(Size(0, nHeight)); + } + pOut->SetFont(aFont); + pOut->SetMapMode(aMap); + sal_Int32 nWidth = pOut->GetTextWidth(aLongest); + + pOut->Pop(); + // Width: space for the text + the square having the dropdown arrow. + return awt::Size(nWidth + nHeight, nHeight); +} + +SdtHelper::SdtHelper(DomainMapper_Impl& rDM_Impl): + m_rDM_Impl(rDM_Impl) +{ +} + +SdtHelper::~SdtHelper() +{ +} + +void SdtHelper::createDropDownControl() +{ + OUString aDefaultText = m_aSdtTexts.makeStringAndClear(); + uno::Reference xControlModel(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.form.component.ComboBox"), uno::UNO_QUERY); + uno::Reference xPropertySet(xControlModel, uno::UNO_QUERY); + xPropertySet->setPropertyValue("DefaultText", uno::makeAny(aDefaultText)); + xPropertySet->setPropertyValue("Dropdown", uno::makeAny(sal_True)); + uno::Sequence aItems(m_aDropDownItems.size()); + for (size_t i = 0; i < m_aDropDownItems.size(); ++i) + aItems[i] = m_aDropDownItems[i]; + xPropertySet->setPropertyValue("StringItemList", uno::makeAny(aItems)); + + createControlShape(lcl_getOptimalWidth(m_rDM_Impl.GetStyleSheetTable(), aDefaultText, m_aDropDownItems), xControlModel); + m_aDropDownItems.clear(); +} + +void SdtHelper::createDateControl(OUString& rDefaultText) +{ + uno::Reference xControlModel(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.form.component.DateField"), uno::UNO_QUERY); + uno::Reference xPropertySet(xControlModel, uno::UNO_QUERY); + xPropertySet->setPropertyValue("HelpText", uno::makeAny(rDefaultText)); + xPropertySet->setPropertyValue("Dropdown", uno::makeAny(sal_True)); + xPropertySet->setPropertyValue("DateFormat", uno::makeAny(*m_oDateFormat)); + m_oDateFormat.reset(); + + std::vector aItems; + createControlShape(lcl_getOptimalWidth(m_rDM_Impl.GetStyleSheetTable(), rDefaultText, aItems), xControlModel); +} + +void SdtHelper::createControlShape(awt::Size aSize, uno::Reference xControlModel) +{ + uno::Reference xControlShape(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.drawing.ControlShape"), uno::UNO_QUERY); + xControlShape->setSize(aSize); + xControlShape->setControl(xControlModel); + + uno::Reference xPropertySet(xControlShape, uno::UNO_QUERY); + xPropertySet->setPropertyValue("VertOrient", uno::makeAny(text::VertOrientation::CENTER)); + + uno::Reference xTextContent(xControlShape, uno::UNO_QUERY); + m_rDM_Impl.appendTextContent(xTextContent, uno::Sequence< beans::PropertyValue >()); +} + +std::vector& SdtHelper::getDropDownItems() +{ + return m_aDropDownItems; +} + +OUStringBuffer& SdtHelper::getSdtTexts() +{ + return m_aSdtTexts; +} + +boost::optional& SdtHelper::getDateFormat() +{ + return m_oDateFormat; +} + +} // namespace dmapper +} // namespace writerfilter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx new file mode 100644 index 000000000000..d2ce37220fc4 --- /dev/null +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -0,0 +1,68 @@ +/* -*- 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_SDTHELPER_HXX +#define INCLUDED_SDTHELPER_HXX + +#include + +#include +#include + +#include + +namespace com { namespace sun { namespace star { + namespace awt{ + struct Size; + class XControlModel; + } +}}} + +namespace writerfilter { + namespace dmapper { + + /** + * Helper to create form controls from w:sdt tokens. + * + * w:sdt tokens can't be imported as form fields, as w:sdt supports + * e.g. date picking as well. + */ + class SdtHelper + { + DomainMapper_Impl& m_rDM_Impl; + + /// Items of the drop-down control. + std::vector m_aDropDownItems; + /// Pieces of the default text -- currently used only by the dropdown control. + OUStringBuffer m_aSdtTexts; + /// Date format, see com/sun/star/awt/UnoControlDateFieldModel.idl + boost::optional m_oDateFormat; + + /// Create and append the drawing::XControlShape, containing the various models. + void createControlShape(com::sun::star::awt::Size aSize, com::sun::star::uno::Reference); + public: + SdtHelper(DomainMapper_Impl& rDM_Impl); + virtual ~SdtHelper(); + + std::vector& getDropDownItems(); + OUStringBuffer& getSdtTexts(); + boost::optional& getDateFormat(); + + /// Create drop-down control from w:sdt's w:dropDownList. + void createDropDownControl(); + /// Create date control from w:sdt's w:date. + void createDateControl(OUString& rDefaultText); + }; + + } // namespace dmapper +} // namespace writerfilter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 458e26adbc72..0e11017cc142 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -22772,6 +22772,9 @@ + + + -- cgit