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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <com/sun/star/awt/XControlModel.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/container/XIndexContainer.hpp>
25 #include <com/sun/star/container/XNamed.hpp>
26 #include <com/sun/star/drawing/XControlShape.hpp>
27 #include <com/sun/star/drawing/XDrawPage.hpp>
28 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
29 #include <com/sun/star/form/XForm.hpp>
30 #include <com/sun/star/form/XFormComponent.hpp>
31 #include <com/sun/star/form/XFormsSupplier.hpp>
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/text/TextContentAnchorType.hpp>
34 #include <com/sun/star/text/VertOrientation.hpp>
35 #include <com/sun/star/uno/Any.hxx>
37 #include "FormControlHelper.hxx"
38 #include <xmloff/odffields.hxx>
39 #include <comphelper/sequence.hxx>
40 #include <tools/diagnose_ex.h>
42 namespace writerfilter
{
45 using namespace ::com::sun::star
;
47 struct FormControlHelper::FormControlHelper_Impl
: public virtual SvRefBase
51 uno::Reference
<drawing::XDrawPage
> rDrawPage
;
52 uno::Reference
<form::XForm
> rForm
;
53 uno::Reference
<form::XFormComponent
> rFormComponent
;
54 uno::Reference
<lang::XMultiServiceFactory
> rServiceFactory
;
55 uno::Reference
<text::XTextDocument
> rTextDocument
;
57 uno::Reference
<drawing::XDrawPage
> const & getDrawPage();
58 uno::Reference
<lang::XMultiServiceFactory
> const & getServiceFactory();
59 uno::Reference
<form::XForm
> const & getForm();
60 uno::Reference
<container::XIndexContainer
> getFormComps();
63 uno::Reference
<drawing::XDrawPage
> const & FormControlHelper::FormControlHelper_Impl::getDrawPage()
67 uno::Reference
<drawing::XDrawPageSupplier
>
68 xDrawPageSupplier(rTextDocument
, uno::UNO_QUERY
);
69 if (xDrawPageSupplier
.is())
70 rDrawPage
= xDrawPageSupplier
->getDrawPage();
76 uno::Reference
<lang::XMultiServiceFactory
> const & FormControlHelper::FormControlHelper_Impl::getServiceFactory()
78 if (! rServiceFactory
.is())
79 rServiceFactory
.set(rTextDocument
, uno::UNO_QUERY
);
81 return rServiceFactory
;
84 uno::Reference
<form::XForm
> const & FormControlHelper::FormControlHelper_Impl::getForm()
88 uno::Reference
<form::XFormsSupplier
> xFormsSupplier(getDrawPage(), uno::UNO_QUERY
);
90 if (xFormsSupplier
.is())
92 uno::Reference
<container::XNameContainer
> xFormsNamedContainer(xFormsSupplier
->getForms());
93 static const char sDOCXForm
[] = "DOCX-Standard";
95 OUString
sFormName(sDOCXForm
);
96 sal_uInt16 nUnique
= 0;
98 while (xFormsNamedContainer
->hasByName(sFormName
))
101 sFormName
= sDOCXForm
+ OUString::number(nUnique
);
104 uno::Reference
<uno::XInterface
> xForm(getServiceFactory()->createInstance("com.sun.star.form.component.Form"));
107 uno::Reference
<beans::XPropertySet
>
108 xFormProperties(xForm
, uno::UNO_QUERY
);
109 uno::Any
aAny(sFormName
);
110 xFormProperties
->setPropertyValue("Name", aAny
);
113 rForm
.set(xForm
, uno::UNO_QUERY
);
115 uno::Reference
<container::XIndexContainer
> xForms(xFormsNamedContainer
, uno::UNO_QUERY
);
116 uno::Any
aAny(xForm
);
117 xForms
->insertByIndex(xForms
->getCount(), aAny
);
124 uno::Reference
<container::XIndexContainer
> FormControlHelper::FormControlHelper_Impl::getFormComps()
126 uno::Reference
<container::XIndexContainer
> xIndexContainer(getForm(), uno::UNO_QUERY
);
128 return xIndexContainer
;
131 FormControlHelper::FormControlHelper(FieldId eFieldId
,
132 uno::Reference
<text::XTextDocument
> const& xTextDocument
,
133 FFDataHandler::Pointer_t
const & pFFData
)
134 : m_pFFData(pFFData
), m_pImpl(new FormControlHelper_Impl
)
136 m_pImpl
->m_eFieldId
= eFieldId
;
137 m_pImpl
->rTextDocument
= xTextDocument
;
140 FormControlHelper::~FormControlHelper()
144 bool FormControlHelper::createCheckbox(uno::Reference
<text::XTextRange
> const& xTextRange
,
145 const OUString
& rControlName
)
149 uno::Reference
<lang::XMultiServiceFactory
>
150 xServiceFactory(m_pImpl
->getServiceFactory());
152 if (! xServiceFactory
.is())
155 uno::Reference
<uno::XInterface
> xInterface
= xServiceFactory
->createInstance("com.sun.star.form.component.CheckBox");
157 if (!xInterface
.is())
160 m_pImpl
->rFormComponent
.set(xInterface
, uno::UNO_QUERY
);
161 if (!m_pImpl
->rFormComponent
.is())
164 uno::Reference
<beans::XPropertySet
> xPropSet(xInterface
, uno::UNO_QUERY
);
166 sal_uInt32 nCheckBoxHeight
= 16 * m_pFFData
->getCheckboxHeight();
168 if (m_pFFData
->getCheckboxAutoHeight())
170 uno::Reference
<beans::XPropertySet
> xTextRangeProps(xTextRange
, uno::UNO_QUERY
);
174 float fCheckBoxHeight
= 0.0;
175 xTextRangeProps
->getPropertyValue("CharHeight") >>= fCheckBoxHeight
;
176 nCheckBoxHeight
= static_cast<sal_uInt32
>(floor(fCheckBoxHeight
* 35.3));
178 catch (beans::UnknownPropertyException
&)
183 m_pImpl
->aSize
.Width
= nCheckBoxHeight
;
184 m_pImpl
->aSize
.Height
= m_pImpl
->aSize
.Width
;
186 if (!m_pFFData
->getStatusText().isEmpty())
188 xPropSet
->setPropertyValue("HelpText", uno::Any(m_pFFData
->getStatusText()));
191 xPropSet
->setPropertyValue("DefaultState", uno::Any(m_pFFData
->getCheckboxChecked()));
193 if (!m_pFFData
->getHelpText().isEmpty())
195 xPropSet
->setPropertyValue("HelpF1Text", uno::Any(m_pFFData
->getHelpText()));
198 xPropSet
->setPropertyValue("Name", uno::Any(rControlName
));
203 void FormControlHelper::processField(uno::Reference
<text::XFormField
> const& xFormField
)
205 // Set field type first before adding parameters.
206 if (m_pImpl
->m_eFieldId
== FIELD_FORMTEXT
)
208 xFormField
->setFieldType(ODF_FORMTEXT
);
210 else if (m_pImpl
->m_eFieldId
== FIELD_FORMCHECKBOX
)
212 xFormField
->setFieldType(ODF_FORMCHECKBOX
);
214 else if (m_pImpl
->m_eFieldId
== FIELD_FORMDROPDOWN
)
216 xFormField
->setFieldType(ODF_FORMDROPDOWN
);
219 uno::Reference
<container::XNameContainer
> xNameCont
= xFormField
->getParameters();
220 uno::Reference
<container::XNamed
> xNamed( xFormField
, uno::UNO_QUERY
);
221 if ( m_pFFData
&& xNamed
.is() && xNameCont
.is() )
223 OUString sTmp
= m_pFFData
->getEntryMacro();
224 if ( !sTmp
.isEmpty() )
225 xNameCont
->insertByName( "EntryMacro", uno::makeAny(sTmp
) );
226 sTmp
= m_pFFData
->getExitMacro();
227 if ( !sTmp
.isEmpty() )
228 xNameCont
->insertByName( "ExitMacro", uno::makeAny(sTmp
) );
230 sTmp
= m_pFFData
->getHelpText();
231 if ( !sTmp
.isEmpty() )
232 xNameCont
->insertByName( "Help", uno::makeAny(sTmp
) );
234 sTmp
= m_pFFData
->getStatusText();
235 if ( !sTmp
.isEmpty() )
236 xNameCont
->insertByName( "Hint", uno::makeAny(sTmp
) );
238 if (m_pImpl
->m_eFieldId
== FIELD_FORMTEXT
)
240 sTmp
= m_pFFData
->getName();
243 if ( !sTmp
.isEmpty() )
244 xNamed
->setName( sTmp
);
246 catch ( uno::Exception
& )
248 DBG_UNHANDLED_EXCEPTION("writerfilter","Set Formfield name failed");
251 sTmp
= m_pFFData
->getTextType();
252 if ( !sTmp
.isEmpty() )
253 xNameCont
->insertByName( "Type", uno::makeAny(sTmp
) );
255 const sal_uInt16 nMaxLength
= m_pFFData
->getTextMaxLength();
258 xNameCont
->insertByName( "MaxLength", uno::makeAny(nMaxLength
) );
261 sTmp
= m_pFFData
->getTextDefault();
262 if ( !sTmp
.isEmpty() )
263 xNameCont
->insertByName( "Content", uno::makeAny(sTmp
) );
265 sTmp
= m_pFFData
->getTextFormat();
266 if ( !sTmp
.isEmpty() )
267 xNameCont
->insertByName( "Format", uno::makeAny(sTmp
) );
269 else if (m_pImpl
->m_eFieldId
== FIELD_FORMCHECKBOX
)
271 uno::Reference
<beans::XPropertySet
> xPropSet(xFormField
, uno::UNO_QUERY
);
273 aAny
<<= m_pFFData
->getCheckboxChecked();
275 xPropSet
->setPropertyValue("Checked", aAny
);
277 else if (m_pImpl
->m_eFieldId
== FIELD_FORMDROPDOWN
)
279 const FFDataHandler::DropDownEntries_t
& rEntries
= m_pFFData
->getDropDownEntries();
280 if (!rEntries
.empty())
282 if ( xNameCont
->hasByName(ODF_FORMDROPDOWN_LISTENTRY
) )
283 xNameCont
->replaceByName(ODF_FORMDROPDOWN_LISTENTRY
, uno::makeAny(comphelper::containerToSequence(rEntries
)));
285 xNameCont
->insertByName(ODF_FORMDROPDOWN_LISTENTRY
, uno::makeAny(comphelper::containerToSequence(rEntries
)));
287 sal_Int32 nResult
= m_pFFData
->getDropDownResult().toInt32();
290 if ( xNameCont
->hasByName(ODF_FORMDROPDOWN_RESULT
) )
291 xNameCont
->replaceByName(ODF_FORMDROPDOWN_RESULT
, uno::makeAny( nResult
) );
293 xNameCont
->insertByName(ODF_FORMDROPDOWN_RESULT
, uno::makeAny( nResult
) );
300 void FormControlHelper::insertControl(uno::Reference
<text::XTextRange
> const& xTextRange
)
302 bool bCreated
= false;
305 uno::Reference
<container::XNameContainer
> xFormCompsByName(m_pImpl
->getForm(), uno::UNO_QUERY
);
306 uno::Reference
<container::XIndexContainer
> xFormComps(m_pImpl
->getFormComps());
307 if (! xFormComps
.is())
310 sal_Int32 nControl
= 0;
312 OUString sControlName
;
316 OUString sTmp
= "Control" + OUString::number(nControl
);
319 if (! xFormCompsByName
->hasByName(sTmp
))
327 switch (m_pImpl
->m_eFieldId
)
329 case FIELD_FORMCHECKBOX
:
330 bCreated
= createCheckbox(xTextRange
, sControlName
);
339 uno::Any
aAny(m_pImpl
->rFormComponent
);
340 xFormComps
->insertByIndex(xFormComps
->getCount(), aAny
);
342 if (! m_pImpl
->getServiceFactory().is())
345 uno::Reference
<uno::XInterface
> xInterface
= m_pImpl
->getServiceFactory()->createInstance("com.sun.star.drawing.ControlShape");
347 if (! xInterface
.is())
350 uno::Reference
<drawing::XShape
> xShape(xInterface
, uno::UNO_QUERY
);
355 xShape
->setSize(m_pImpl
->aSize
);
357 uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY
);
359 sal_uInt16 nTmp
= sal_uInt16(text::TextContentAnchorType_AS_CHARACTER
);
360 xShapeProps
->setPropertyValue("AnchorType", uno::makeAny
<sal_uInt16
>(nTmp
));
362 nTmp
= text::VertOrientation::CENTER
;
363 xShapeProps
->setPropertyValue("VertOrient", uno::makeAny
<sal_uInt16
>(nTmp
));
365 xShapeProps
->setPropertyValue("TextRange", uno::Any(xTextRange
));
367 uno::Reference
<drawing::XControlShape
> xControlShape(xShape
, uno::UNO_QUERY
);
368 uno::Reference
<awt::XControlModel
> xControlModel(m_pImpl
->rFormComponent
, uno::UNO_QUERY
);
369 xControlShape
->setControl(xControlModel
);
371 m_pImpl
->getDrawPage()->add(xShape
);
376 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */