1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <SdtHelper.hxx>
11 #include <com/sun/star/drawing/XControlShape.hpp>
12 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
13 #include <com/sun/star/text/VertOrientation.hpp>
14 #include <cppuhelper/exc_hlp.hxx>
15 #include <editeng/unoprnms.hxx>
16 #include <vcl/svapp.hxx>
17 #include <unotools/datetime.hxx>
18 #include <comphelper/sequence.hxx>
20 namespace writerfilter
25 using namespace ::com::sun::star
;
27 /// w:sdt's w:dropDownList doesn't have width, so guess the size based on the longest string.
28 awt::Size
lcl_getOptimalWidth(StyleSheetTablePtr pStyleSheet
, OUString
& rDefault
, std::vector
<OUString
>& rItems
)
30 OUString aLongest
= rDefault
;
31 sal_Int32 nHeight
= 0;
32 for (size_t i
= 0; i
< rItems
.size(); ++i
)
33 if (rItems
[i
].getLength() > aLongest
.getLength())
36 MapMode
aMap(MAP_100TH_MM
);
37 OutputDevice
* pOut
= Application::GetDefaultDevice();
38 pOut
->Push(PushFlags::FONT
| PushFlags::MAPMODE
);
40 PropertyMapPtr pDefaultCharProps
= pStyleSheet
->GetDefaultCharProps();
41 vcl::Font
aFont(pOut
->GetFont());
42 boost::optional
<PropertyMap::Property
> aFontName
= pDefaultCharProps
->getProperty(PROP_CHAR_FONT_NAME
);
44 aFont
.SetName(aFontName
->second
.get
<OUString
>());
45 boost::optional
<PropertyMap::Property
> aHeight
= pDefaultCharProps
->getProperty(PROP_CHAR_HEIGHT
);
48 nHeight
= aHeight
->second
.get
<double>() * 35; // points -> mm100
49 aFont
.SetSize(Size(0, nHeight
));
52 pOut
->SetMapMode(aMap
);
53 sal_Int32 nWidth
= pOut
->GetTextWidth(aLongest
);
57 // Border: see PDFWriterImpl::drawFieldBorder(), border size is font height / 4,
58 // so additional width / height needed is height / 2.
59 sal_Int32 nBorder
= nHeight
/ 2;
61 // Width: space for the text + the square having the dropdown arrow.
62 return awt::Size(nWidth
+ nBorder
+ nHeight
, nHeight
+ nBorder
);
65 SdtHelper::SdtHelper(DomainMapper_Impl
& rDM_Impl
)
66 : m_rDM_Impl(rDM_Impl
)
67 , m_bHasElements(false)
68 , m_bOutsideAParagraph(false)
72 SdtHelper::~SdtHelper()
76 void SdtHelper::createDropDownControl()
78 OUString aDefaultText
= m_aSdtTexts
.makeStringAndClear();
79 uno::Reference
<awt::XControlModel
> xControlModel(m_rDM_Impl
.GetTextFactory()->createInstance("com.sun.star.form.component.ComboBox"), uno::UNO_QUERY
);
80 uno::Reference
<beans::XPropertySet
> xPropertySet(xControlModel
, uno::UNO_QUERY
);
81 xPropertySet
->setPropertyValue("DefaultText", uno::makeAny(aDefaultText
));
82 xPropertySet
->setPropertyValue("Dropdown", uno::makeAny(sal_True
));
83 uno::Sequence
<OUString
> aItems(m_aDropDownItems
.size());
84 for (size_t i
= 0; i
< m_aDropDownItems
.size(); ++i
)
85 aItems
[i
] = m_aDropDownItems
[i
];
86 xPropertySet
->setPropertyValue("StringItemList", uno::makeAny(aItems
));
88 createControlShape(lcl_getOptimalWidth(m_rDM_Impl
.GetStyleSheetTable(), aDefaultText
, m_aDropDownItems
), xControlModel
);
89 m_aDropDownItems
.clear();
92 void SdtHelper::createDateControl(OUString
& rContentText
, const beans::PropertyValue
& rCharFormat
)
94 uno::Reference
<awt::XControlModel
> xControlModel
;
97 xControlModel
.set(m_rDM_Impl
.GetTextFactory()->createInstance("com.sun.star.form.component.DateField"), uno::UNO_QUERY_THROW
);
99 catch (css::uno::RuntimeException
&)
103 catch (css::uno::Exception
& e
)
105 css::uno::Any
a(cppu::getCaughtException());
106 throw css::lang::WrappedTargetRuntimeException("wrapped " + a
.getValueTypeName() + ": " + e
.Message
, css::uno::Reference
<css::uno::XInterface
>(), a
);
108 uno::Reference
<beans::XPropertySet
> xPropertySet(
109 xControlModel
, uno::UNO_QUERY_THROW
);
111 xPropertySet
->setPropertyValue("Dropdown", uno::makeAny(sal_True
));
113 // See com/sun/star/awt/UnoControlDateFieldModel.idl, DateFormat; sadly there are no constants
114 sal_Int16 nDateFormat
= 0;
115 OUString sDateFormat
= m_sDateFormat
.makeStringAndClear();
116 if (sDateFormat
== "M/d/yyyy" || sDateFormat
== "M.d.yyyy")
117 // Approximate with MM.dd.yyy
120 // Set default format, so at least the date picker is created.
121 SAL_WARN("writerfilter", "unhandled w:dateFormat value");
122 xPropertySet
->setPropertyValue("DateFormat", uno::makeAny(nDateFormat
));
125 util::DateTime aDateTime
;
126 if (utl::ISO8601parseDateTime(m_sDate
.makeStringAndClear(), aDateTime
))
128 utl::extractDate(aDateTime
, aDate
);
129 xPropertySet
->setPropertyValue("Date", uno::makeAny(aDate
));
132 xPropertySet
->setPropertyValue("HelpText", uno::makeAny(rContentText
));
134 // append date format to grab bag
135 comphelper::SequenceAsHashMap aGrabBag
;
136 aGrabBag
["OriginalDate"] <<= aDate
;
137 aGrabBag
["OriginalContent"] <<= rContentText
;
138 aGrabBag
["DateFormat"] <<= sDateFormat
;
139 aGrabBag
["Locale"] <<= m_sLocale
.makeStringAndClear();
140 aGrabBag
["CharFormat"] <<= rCharFormat
.Value
;
141 // merge in properties like ooxml:CT_SdtPr_alias and friends.
142 aGrabBag
.update(comphelper::SequenceAsHashMap(comphelper::containerToSequence(m_aGrabBag
)));
143 // and empty the property list, so they won't end up on the next sdt as well
146 std::vector
<OUString
> aItems
;
147 createControlShape(lcl_getOptimalWidth(m_rDM_Impl
.GetStyleSheetTable(), rContentText
, aItems
), xControlModel
, aGrabBag
.getAsConstPropertyValueList());
150 void SdtHelper::createControlShape(awt::Size aSize
, uno::Reference
<awt::XControlModel
> const& xControlModel
)
152 createControlShape(aSize
, xControlModel
, uno::Sequence
<beans::PropertyValue
>());
155 void SdtHelper::createControlShape(awt::Size aSize
, uno::Reference
<awt::XControlModel
> const& xControlModel
, const uno::Sequence
<beans::PropertyValue
>& rGrabBag
)
157 uno::Reference
<drawing::XControlShape
> xControlShape(m_rDM_Impl
.GetTextFactory()->createInstance("com.sun.star.drawing.ControlShape"), uno::UNO_QUERY
);
158 xControlShape
->setSize(aSize
);
159 xControlShape
->setControl(xControlModel
);
161 uno::Reference
<beans::XPropertySet
> xPropertySet(xControlShape
, uno::UNO_QUERY
);
162 xPropertySet
->setPropertyValue("VertOrient", uno::makeAny(text::VertOrientation::CENTER
));
164 if (rGrabBag
.hasElements())
165 xPropertySet
->setPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG
, uno::makeAny(rGrabBag
));
167 uno::Reference
<text::XTextContent
> xTextContent(xControlShape
, uno::UNO_QUERY
);
168 m_rDM_Impl
.appendTextContent(xTextContent
, uno::Sequence
< beans::PropertyValue
>());
169 m_bHasElements
= true;
172 void SdtHelper::appendToInteropGrabBag(const beans::PropertyValue
& rValue
)
174 m_aGrabBag
.push_back(rValue
);
177 uno::Sequence
<beans::PropertyValue
> SdtHelper::getInteropGrabBagAndClear()
179 uno::Sequence
<beans::PropertyValue
> aRet
= comphelper::containerToSequence(m_aGrabBag
);
184 bool SdtHelper::isInteropGrabBagEmpty()
186 return m_aGrabBag
.empty();
189 sal_Int32
SdtHelper::getInteropGrabBagSize()
191 return m_aGrabBag
.size();
194 bool SdtHelper::containedInInteropGrabBag(const OUString
& rValueName
)
196 for (size_t i
=0; i
< m_aGrabBag
.size(); ++i
)
197 if (m_aGrabBag
[i
].Name
== rValueName
)
203 } // namespace dmapper
204 } // namespace writerfilter
206 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */