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
This commit is contained in:
Miklos Vajna
2013-05-02 12:14:47 +02:00
parent 3af051aa4a
commit 3ec2d26dc2
9 changed files with 252 additions and 68 deletions
+2
View File
@@ -53,6 +53,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_ooxmlimport,\
embeddedobj/util/embobj \
fileaccess/source/fileacc \
filter/source/config/cache/filterconfig1 \
forms/util/frm \
framework/util/fwk \
i18npool/util/i18npool \
linguistic/source/lng \
@@ -66,6 +67,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_ooxmlimport,\
sw/util/msword \
sfx2/util/sfx \
svl/source/fsstor/fsstorage \
svl/util/svl \
svtools/util/svt \
toolkit/util/tk \
ucb/source/core/ucb1 \
+4 -1
View File
@@ -901,7 +901,10 @@ void Test::testN779627()
*/
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xShapeProperties( xDraws->getByIndex(2), uno::UNO_QUERY );
uno::Reference<beans::XPropertySet> xShapeProperties( xDraws->getByIndex(3), uno::UNO_QUERY );
uno::Reference<drawing::XShapeDescriptor> xShapeDescriptor(xShapeProperties, uno::UNO_QUERY);
// If this goes wrong, probably the index of the shape is changed and the test should be adjusted.
CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.RectangleShape"), xShapeDescriptor->getShapeType());
sal_Int16 nValue;
xShapeProperties->getPropertyValue("HoriOrient") >>= nValue;
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not centered horizontally", text::HoriOrientation::CENTER, nValue);
+1
View File
@@ -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 \
+36 -5
View File
@@ -19,6 +19,7 @@
#include "PageBordersHandler.hxx"
#include <resourcemodel/ResourceModelHelper.hxx>
#include <SdtHelper.hxx>
#include <DomainMapper_Impl.hxx>
#include <ConversionHelper.hxx>
#include <ModelEventListener.hxx>
@@ -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<Properties>::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;
}
@@ -19,6 +19,7 @@
#include <DomainMapper_Impl.hxx>
#include <ConversionHelper.hxx>
#include <SdtHelper.hxx>
#include <DomainMapperTableHandler.hxx>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
@@ -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<OUString>& 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<OUString>());
PropertyMap::iterator aHeight = pDefaultCharProps->find(PropertyDefinition(PROP_CHAR_HEIGHT, false));
if (aHeight != pDefaultCharProps->end())
{
nHeight = aHeight->second.get<double>() * 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<awt::XControlModel> xControlModel(m_xTextFactory->createInstance("com.sun.star.form.component.ComboBox"), uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY);
xPropertySet->setPropertyValue("DefaultText", uno::makeAny(aDefaultText));
xPropertySet->setPropertyValue("Dropdown", uno::makeAny(sal_True));
uno::Sequence<OUString> 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<drawing::XControlShape> 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<text::XTextContent> xTextContent(xControlShape, uno::UNO_QUERY);
appendTextContent(xTextContent, uno::Sequence< beans::PropertyValue >());
}
}}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -29,6 +29,7 @@
#include <com/sun/star/container/XNameContainer.hpp>
#include <vector>
#include <stack>
#include <boost/optional.hpp>
#ifndef INCLUDED_RESOURCESIDS
#include <doctok/resourceids.hxx>
@@ -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 <w:rPr>, inside <w:style w:type="table">
bool m_bInTableStyleRunProps;
std::vector<OUString> m_aDropDownItems;
OUStringBuffer m_aSdtTexts;
/// Create drop-down control from w:sdt's w:dropDownList.
void createDropDownControl();
SdtHelper* m_pSdtHelper;
};
} //namespace dmapper
} //namespace writerfilter
+129
View File
@@ -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 <com/sun/star/awt/Size.hpp>
#include <com/sun/star/awt/XControlModel.hpp>
#include <com/sun/star/drawing/XControlShape.hpp>
#include <com/sun/star/text/VertOrientation.hpp>
#include <vcl/outdev.hxx>
#include <vcl/svapp.hxx>
#include <DomainMapper_Impl.hxx>
#include <StyleSheetTable.hxx>
#include <SdtHelper.hxx>
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<OUString>& 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<OUString>());
PropertyMap::iterator aHeight = pDefaultCharProps->find(PropertyDefinition(PROP_CHAR_HEIGHT, false));
if (aHeight != pDefaultCharProps->end())
{
nHeight = aHeight->second.get<double>() * 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<awt::XControlModel> xControlModel(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.form.component.ComboBox"), uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY);
xPropertySet->setPropertyValue("DefaultText", uno::makeAny(aDefaultText));
xPropertySet->setPropertyValue("Dropdown", uno::makeAny(sal_True));
uno::Sequence<OUString> 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<awt::XControlModel> xControlModel(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.form.component.DateField"), uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> 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<OUString> aItems;
createControlShape(lcl_getOptimalWidth(m_rDM_Impl.GetStyleSheetTable(), rDefaultText, aItems), xControlModel);
}
void SdtHelper::createControlShape(awt::Size aSize, uno::Reference<awt::XControlModel> xControlModel)
{
uno::Reference<drawing::XControlShape> xControlShape(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.drawing.ControlShape"), uno::UNO_QUERY);
xControlShape->setSize(aSize);
xControlShape->setControl(xControlModel);
uno::Reference<beans::XPropertySet> xPropertySet(xControlShape, uno::UNO_QUERY);
xPropertySet->setPropertyValue("VertOrient", uno::makeAny(text::VertOrientation::CENTER));
uno::Reference<text::XTextContent> xTextContent(xControlShape, uno::UNO_QUERY);
m_rDM_Impl.appendTextContent(xTextContent, uno::Sequence< beans::PropertyValue >());
}
std::vector<OUString>& SdtHelper::getDropDownItems()
{
return m_aDropDownItems;
}
OUStringBuffer& SdtHelper::getSdtTexts()
{
return m_aSdtTexts;
}
boost::optional<sal_Int16>& SdtHelper::getDateFormat()
{
return m_oDateFormat;
}
} // namespace dmapper
} // namespace writerfilter
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+68
View File
@@ -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 <boost/optional.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <rtl/ustrbuf.hxx>
#include <WriterFilterDllApi.hxx>
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<OUString> 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<sal_Int16> 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<com::sun::star::awt::XControlModel>);
public:
SdtHelper(DomainMapper_Impl& rDM_Impl);
virtual ~SdtHelper();
std::vector<OUString>& getDropDownItems();
OUStringBuffer& getSdtTexts();
boost::optional<sal_Int16>& 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: */
+3
View File
@@ -22772,6 +22772,9 @@
<resource name="CT_SdtDropDownList" resource="Properties" tag="field">
<element name="listItem" tokenid="ooxml:CT_SdtDropDownList_listItem"/>
</resource>
<resource name="CT_SdtDate" resource="Properties" tag="field">
<element name="dateFormat" tokenid="ooxml:CT_SdtDate_dateFormat"/>
</resource>
<resource name="CT_SdtListItem" resource="Properties" tag="field">
<attribute name="displayText" tokenid="ooxml:CT_SdtListItem_displayText"/>
<attribute name="value" tokenid="ooxml:CT_SdtListItem_value"/>