Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : */
9 :
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>
19 :
20 : namespace writerfilter
21 : {
22 : namespace dmapper
23 : {
24 :
25 : using namespace ::com::sun::star;
26 :
27 : /// w:sdt's w:dropDownList doesn't have width, so guess the size based on the longest string.
28 34 : awt::Size lcl_getOptimalWidth(StyleSheetTablePtr pStyleSheet, OUString& rDefault, std::vector<OUString>& rItems)
29 : {
30 34 : OUString aLongest = rDefault;
31 34 : sal_Int32 nHeight = 0;
32 96 : for (size_t i = 0; i < rItems.size(); ++i)
33 62 : if (rItems[i].getLength() > aLongest.getLength())
34 3 : aLongest = rItems[i];
35 :
36 68 : MapMode aMap(MAP_100TH_MM);
37 34 : OutputDevice* pOut = Application::GetDefaultDevice();
38 34 : pOut->Push(PushFlags::FONT | PushFlags::MAPMODE);
39 :
40 68 : PropertyMapPtr pDefaultCharProps = pStyleSheet->GetDefaultCharProps();
41 68 : vcl::Font aFont(pOut->GetFont());
42 68 : boost::optional<PropertyMap::Property> aFontName = pDefaultCharProps->getProperty(PROP_CHAR_FONT_NAME);
43 34 : if (aFontName)
44 34 : aFont.SetName(aFontName->second.get<OUString>());
45 68 : boost::optional<PropertyMap::Property> aHeight = pDefaultCharProps->getProperty(PROP_CHAR_HEIGHT);
46 34 : if (aHeight)
47 : {
48 34 : nHeight = aHeight->second.get<double>() * 35; // points -> mm100
49 34 : aFont.SetSize(Size(0, nHeight));
50 : }
51 34 : pOut->SetFont(aFont);
52 34 : pOut->SetMapMode(aMap);
53 34 : sal_Int32 nWidth = pOut->GetTextWidth(aLongest);
54 :
55 34 : pOut->Pop();
56 :
57 : // Border: see PDFWriterImpl::drawFieldBorder(), border size is font height / 4,
58 : // so additional width / height needed is height / 2.
59 34 : sal_Int32 nBorder = nHeight / 2;
60 :
61 : // Width: space for the text + the square having the dropdown arrow.
62 68 : return awt::Size(nWidth + nBorder + nHeight, nHeight + nBorder);
63 : }
64 :
65 1984 : SdtHelper::SdtHelper(DomainMapper_Impl& rDM_Impl)
66 : : m_rDM_Impl(rDM_Impl)
67 : , m_bHasElements(false)
68 1984 : , m_bOutsideAParagraph(false)
69 : {
70 1984 : }
71 :
72 3968 : SdtHelper::~SdtHelper()
73 : {
74 3968 : }
75 :
76 16 : void SdtHelper::createDropDownControl()
77 : {
78 16 : OUString aDefaultText = m_aSdtTexts.makeStringAndClear();
79 32 : uno::Reference<awt::XControlModel> xControlModel(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.form.component.ComboBox"), uno::UNO_QUERY);
80 32 : uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY);
81 16 : xPropertySet->setPropertyValue("DefaultText", uno::makeAny(aDefaultText));
82 16 : xPropertySet->setPropertyValue("Dropdown", uno::makeAny(sal_True));
83 32 : uno::Sequence<OUString> aItems(m_aDropDownItems.size());
84 78 : for (size_t i = 0; i < m_aDropDownItems.size(); ++i)
85 62 : aItems[i] = m_aDropDownItems[i];
86 16 : xPropertySet->setPropertyValue("StringItemList", uno::makeAny(aItems));
87 :
88 16 : createControlShape(lcl_getOptimalWidth(m_rDM_Impl.GetStyleSheetTable(), aDefaultText, m_aDropDownItems), xControlModel);
89 32 : m_aDropDownItems.clear();
90 16 : }
91 :
92 18 : void SdtHelper::createDateControl(OUString& rContentText, const beans::PropertyValue& rCharFormat)
93 : {
94 18 : uno::Reference<awt::XControlModel> xControlModel;
95 : try
96 : {
97 18 : xControlModel.set(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.form.component.DateField"), uno::UNO_QUERY_THROW);
98 : }
99 0 : catch (css::uno::RuntimeException&)
100 : {
101 0 : throw;
102 : }
103 0 : catch (css::uno::Exception& e)
104 : {
105 0 : css::uno::Any a(cppu::getCaughtException());
106 0 : throw css::lang::WrappedTargetRuntimeException("wrapped " + a.getValueTypeName() + ": " + e.Message, css::uno::Reference<css::uno::XInterface>(), a);
107 : }
108 : uno::Reference<beans::XPropertySet> xPropertySet(
109 36 : xControlModel, uno::UNO_QUERY_THROW);
110 :
111 18 : xPropertySet->setPropertyValue("Dropdown", uno::makeAny(sal_True));
112 :
113 : // See com/sun/star/awt/UnoControlDateFieldModel.idl, DateFormat; sadly there are no constants
114 18 : sal_Int16 nDateFormat = 0;
115 36 : OUString sDateFormat = m_sDateFormat.makeStringAndClear();
116 18 : if (sDateFormat == "M/d/yyyy" || sDateFormat == "M.d.yyyy")
117 : // Approximate with MM.dd.yyy
118 15 : nDateFormat = 8;
119 : else
120 : // Set default format, so at least the date picker is created.
121 : SAL_WARN("writerfilter", "unhandled w:dateFormat value");
122 18 : xPropertySet->setPropertyValue("DateFormat", uno::makeAny(nDateFormat));
123 :
124 18 : util::Date aDate;
125 18 : util::DateTime aDateTime;
126 18 : if (utl::ISO8601parseDateTime(m_sDate.makeStringAndClear(), aDateTime))
127 : {
128 9 : utl::extractDate(aDateTime, aDate);
129 9 : xPropertySet->setPropertyValue("Date", uno::makeAny(aDate));
130 : }
131 : else
132 9 : xPropertySet->setPropertyValue("HelpText", uno::makeAny(rContentText));
133 :
134 : // append date format to grab bag
135 36 : comphelper::SequenceAsHashMap aGrabBag;
136 18 : aGrabBag["OriginalDate"] <<= aDate;
137 18 : aGrabBag["OriginalContent"] <<= rContentText;
138 18 : aGrabBag["DateFormat"] <<= sDateFormat;
139 18 : aGrabBag["Locale"] <<= m_sLocale.makeStringAndClear();
140 18 : aGrabBag["CharFormat"] <<= rCharFormat.Value;
141 : // merge in properties like ooxml:CT_SdtPr_alias and friends.
142 18 : 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
144 18 : m_aGrabBag.clear();
145 :
146 36 : std::vector<OUString> aItems;
147 36 : createControlShape(lcl_getOptimalWidth(m_rDM_Impl.GetStyleSheetTable(), rContentText, aItems), xControlModel, aGrabBag.getAsConstPropertyValueList());
148 18 : }
149 :
150 16 : void SdtHelper::createControlShape(awt::Size aSize, uno::Reference<awt::XControlModel> const& xControlModel)
151 : {
152 16 : createControlShape(aSize, xControlModel, uno::Sequence<beans::PropertyValue>());
153 16 : }
154 :
155 34 : void SdtHelper::createControlShape(awt::Size aSize, uno::Reference<awt::XControlModel> const& xControlModel, const uno::Sequence<beans::PropertyValue>& rGrabBag)
156 : {
157 34 : uno::Reference<drawing::XControlShape> xControlShape(m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.drawing.ControlShape"), uno::UNO_QUERY);
158 34 : xControlShape->setSize(aSize);
159 34 : xControlShape->setControl(xControlModel);
160 :
161 68 : uno::Reference<beans::XPropertySet> xPropertySet(xControlShape, uno::UNO_QUERY);
162 34 : xPropertySet->setPropertyValue("VertOrient", uno::makeAny(text::VertOrientation::CENTER));
163 :
164 34 : if (rGrabBag.hasElements())
165 18 : xPropertySet->setPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG, uno::makeAny(rGrabBag));
166 :
167 68 : uno::Reference<text::XTextContent> xTextContent(xControlShape, uno::UNO_QUERY);
168 34 : m_rDM_Impl.appendTextContent(xTextContent, uno::Sequence< beans::PropertyValue >());
169 68 : m_bHasElements = true;
170 34 : }
171 :
172 961 : void SdtHelper::appendToInteropGrabBag(const beans::PropertyValue& rValue)
173 : {
174 961 : m_aGrabBag.push_back(rValue);
175 961 : }
176 :
177 568 : uno::Sequence<beans::PropertyValue> SdtHelper::getInteropGrabBagAndClear()
178 : {
179 568 : uno::Sequence<beans::PropertyValue> aRet = comphelper::containerToSequence(m_aGrabBag);
180 568 : m_aGrabBag.clear();
181 568 : return aRet;
182 : }
183 :
184 81132 : bool SdtHelper::isInteropGrabBagEmpty()
185 : {
186 81132 : return m_aGrabBag.empty();
187 : }
188 :
189 183 : sal_Int32 SdtHelper::getInteropGrabBagSize()
190 : {
191 183 : return m_aGrabBag.size();
192 : }
193 :
194 1582 : bool SdtHelper::containedInInteropGrabBag(const OUString& rValueName)
195 : {
196 4222 : for (size_t i=0; i < m_aGrabBag.size(); ++i)
197 3026 : if (m_aGrabBag[i].Name == rValueName)
198 386 : return true;
199 :
200 1196 : return false;
201 : }
202 :
203 : } // namespace dmapper
204 : } // namespace writerfilter
205 :
206 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|