1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <math.h>
25 
26 #include <com/sun/star/awt/XControlModel.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/container/XIndexContainer.hpp>
29 #include <com/sun/star/drawing/XControlShape.hpp>
30 #include <com/sun/star/drawing/XDrawPage.hpp>
31 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
32 #include <com/sun/star/form/XForm.hpp>
33 #include <com/sun/star/form/XFormComponent.hpp>
34 #include <com/sun/star/form/XFormsSupplier.hpp>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/text/TextContentAnchorType.hpp>
37 #include <com/sun/star/text/VertOrientation.hpp>
38 #include <com/sun/star/uno/Any.hxx>
39 #include <com/sun/star/uno/Type.hxx>
40 
41 #include "FormControlHelper.hxx"
42 
43 namespace writerfilter {
44 namespace dmapper {
45 
46 using namespace ::com::sun::star;
47 
48 struct FormControlHelper::FormControlHelper_Impl
49 {
50     FieldId m_eFieldId;
51     awt::Size aSize;
52     uno::Reference<drawing::XDrawPage> rDrawPage;
53     uno::Reference<form::XForm> rForm;
54     uno::Reference<form::XFormComponent> rFormComponent;
55     uno::Reference<lang::XMultiServiceFactory> rServiceFactory;
56     uno::Reference<text::XTextDocument> rTextDocument;
57 
58     uno::Reference<drawing::XDrawPage> getDrawPage();
59     uno::Reference<lang::XMultiServiceFactory> getServiceFactory();
60     uno::Reference<form::XForm> getForm();
61     uno::Reference<container::XIndexContainer> getFormComps();
62 };
63 
getDrawPage()64 uno::Reference<drawing::XDrawPage> FormControlHelper::FormControlHelper_Impl::getDrawPage()
65 {
66     if (! rDrawPage.is())
67     {
68         uno::Reference<drawing::XDrawPageSupplier>
69             xDrawPageSupplier(rTextDocument, uno::UNO_QUERY);
70         if (xDrawPageSupplier.is())
71             rDrawPage = xDrawPageSupplier->getDrawPage();
72     }
73 
74     return rDrawPage;
75 }
76 
getServiceFactory()77 uno::Reference<lang::XMultiServiceFactory> FormControlHelper::FormControlHelper_Impl::getServiceFactory()
78 {
79     if (! rServiceFactory.is())
80         rServiceFactory = uno::Reference<lang::XMultiServiceFactory>(rTextDocument, uno::UNO_QUERY);
81 
82     return rServiceFactory;
83 }
84 
getForm()85 uno::Reference<form::XForm> FormControlHelper::FormControlHelper_Impl::getForm()
86 {
87     if (! rForm.is())
88     {
89         uno::Reference<form::XFormsSupplier> xFormsSupplier(getDrawPage(), uno::UNO_QUERY);
90 
91         if (xFormsSupplier.is())
92         {
93             uno::Reference<container::XNameContainer> xFormsNamedContainer(xFormsSupplier->getForms());
94             static ::rtl::OUString sDOCXForm(RTL_CONSTASCII_USTRINGPARAM("DOCX-Standard"));
95 
96             ::rtl::OUString sFormName(sDOCXForm);
97             sal_uInt16 nUnique = 0;
98 
99             while (xFormsNamedContainer->hasByName(sFormName))
100             {
101                 ++nUnique;
102                 sFormName = sDOCXForm;
103                 sFormName += ::rtl::OUString::valueOf(nUnique);
104             }
105 
106             uno::Reference<uno::XInterface>
107                 xForm(getServiceFactory()->createInstance
108                       (::rtl::OUString
109                        (RTL_CONSTASCII_USTRINGPARAM
110                         ("com.sun.star.form.component.Form"))));
111             if (xForm.is())
112             {
113                 uno::Reference<beans::XPropertySet>
114                     xFormProperties(xForm, uno::UNO_QUERY);
115                 uno::Any aAny(sFormName);
116                 static ::rtl::OUString sName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")));
117                 xFormProperties->setPropertyValue(sName, aAny);
118             }
119 
120             rForm = uno::Reference<form::XForm>(xForm, uno::UNO_QUERY);
121 
122             uno::Reference<container::XIndexContainer> xForms(xFormsNamedContainer, uno::UNO_QUERY);
123             uno::Any aAny(xForm);
124             xForms->insertByIndex(xForms->getCount(), aAny);
125         }
126     }
127 
128     return rForm;
129 }
130 
getFormComps()131 uno::Reference<container::XIndexContainer> FormControlHelper::FormControlHelper_Impl::getFormComps()
132 {
133     uno::Reference<container::XIndexContainer> xIndexContainer(getForm(), uno::UNO_QUERY);
134 
135     return xIndexContainer;
136 }
137 
FormControlHelper(FieldId eFieldId,uno::Reference<text::XTextDocument> rTextDocument,FFDataHandler::Pointer_t pFFData)138 FormControlHelper::FormControlHelper(FieldId eFieldId,
139                                      uno::Reference<text::XTextDocument> rTextDocument,
140                                      FFDataHandler::Pointer_t pFFData)
141     : m_pFFData(pFFData), m_pImpl(new FormControlHelper_Impl)
142 {
143     m_pImpl->m_eFieldId = eFieldId;
144     m_pImpl->rTextDocument = rTextDocument;
145 }
146 
~FormControlHelper()147 FormControlHelper::~FormControlHelper()
148 {
149 }
150 
createCheckbox(uno::Reference<text::XTextRange> xTextRange,const::rtl::OUString & rControlName)151 bool FormControlHelper::createCheckbox(uno::Reference<text::XTextRange> xTextRange,
152                                        const ::rtl::OUString & rControlName)
153 {
154     uno::Reference<lang::XMultiServiceFactory>
155         xServiceFactory(m_pImpl->getServiceFactory());
156 
157     if (! xServiceFactory.is())
158         return false;
159 
160     uno::Reference<uno::XInterface> xInterface =
161         xServiceFactory->createInstance
162         (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.component.CheckBox")));
163 
164     if (!xInterface.is())
165         return false;
166 
167     m_pImpl->rFormComponent = uno::Reference<form::XFormComponent>(xInterface, uno::UNO_QUERY);
168     if (!m_pImpl->rFormComponent.is())
169         return false;
170 
171     uno::Reference<beans::XPropertySet> xPropSet(xInterface, uno::UNO_QUERY);
172 
173     sal_uInt32 nCheckBoxHeight = 16 * m_pFFData->getCheckboxHeight();
174 
175     if (m_pFFData->getCheckboxAutoHeight())
176     {
177         uno::Reference<beans::XPropertySet> xTextRangeProps(xTextRange, uno::UNO_QUERY);
178 
179         try
180         {
181             static ::rtl::OUString sCharHeight(RTL_CONSTASCII_USTRINGPARAM("CharHeight"));
182             float fCheckBoxHeight = 0.0;
183             xTextRangeProps->getPropertyValue(sCharHeight) >>= fCheckBoxHeight;
184             nCheckBoxHeight = floor(fCheckBoxHeight * 35.3);
185         }
186         catch (beans::UnknownPropertyException & rException)
187         {
188             (void) rException;
189         }
190     }
191 
192     m_pImpl->aSize.Width = nCheckBoxHeight;
193     m_pImpl->aSize.Height = m_pImpl->aSize.Width;
194 
195     uno::Any aAny;
196     if (m_pFFData->getStatusText().getLength())
197     {
198         aAny <<= m_pFFData->getStatusText();
199 
200         xPropSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpText")), aAny);
201     }
202 
203     aAny <<= m_pFFData->getCheckboxChecked();
204     xPropSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultState")), aAny);
205 
206     if (m_pFFData->getHelpText().getLength())
207     {
208         aAny <<= m_pFFData->getHelpText();
209         xPropSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpF1Text")), aAny);
210     }
211 
212     aAny <<= rControlName;
213     xPropSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), aAny);
214 
215     return true;
216 }
217 
insertControl(uno::Reference<text::XTextRange> xTextRange)218 bool FormControlHelper::insertControl(uno::Reference<text::XTextRange> xTextRange)
219 {
220     bool bCreated = false;
221 
222     uno::Reference<container::XNameContainer> xFormCompsByName(m_pImpl->getForm(), uno::UNO_QUERY);
223     uno::Reference<container::XIndexContainer> xFormComps(m_pImpl->getFormComps());
224     if (! xFormComps.is())
225         return false;
226 
227     static ::rtl::OUString sControl(RTL_CONSTASCII_USTRINGPARAM("Control"));
228 
229     sal_Int32 nControl = 0;
230     bool bDone = false;
231     ::rtl::OUString sControlName;
232 
233     do
234     {
235         ::rtl::OUString sTmp(sControl);
236         sTmp += ::rtl::OUString::valueOf(nControl);
237 
238         nControl++;
239         if (! xFormCompsByName->hasByName(sTmp))
240         {
241             sControlName = sTmp;
242             bDone = true;
243         }
244     }
245     while (! bDone);
246 
247     switch (m_pImpl->m_eFieldId)
248     {
249     case FIELD_FORMCHECKBOX:
250         bCreated = createCheckbox(xTextRange, sControlName);
251         break;
252     default:
253         break;
254     }
255 
256     if (!bCreated)
257         return false;
258 
259     uno::Any aAny(m_pImpl->rFormComponent);
260     xFormComps->insertByIndex(xFormComps->getCount(), aAny);
261 
262     if (! m_pImpl->getServiceFactory().is())
263         return false;
264 
265     uno::Reference<uno::XInterface> xInterface =
266         m_pImpl->getServiceFactory()->createInstance
267         (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.ControlShape")));
268 
269     if (! xInterface.is())
270         return false;
271 
272     uno::Reference<drawing::XShape> xShape(xInterface, uno::UNO_QUERY);
273 
274     if (! xShape.is())
275         return false;
276 
277     xShape->setSize(m_pImpl->aSize);
278 
279     uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
280 
281     sal_uInt16 nTmp = text::TextContentAnchorType_AS_CHARACTER;
282     aAny <<= nTmp;
283 
284     static const ::rtl::OUString sAnchorType(RTL_CONSTASCII_USTRINGPARAM("AnchorType"));
285     xShapeProps->setPropertyValue(sAnchorType, aAny);
286 
287     static const ::rtl::OUString sVertOrient(RTL_CONSTASCII_USTRINGPARAM("VertOrient"));
288     nTmp = text::VertOrientation::CENTER;
289     aAny <<= nTmp;
290     xShapeProps->setPropertyValue(sVertOrient, aAny);
291 
292     aAny <<= xTextRange;
293 
294     static const ::rtl::OUString sTextRange(RTL_CONSTASCII_USTRINGPARAM("TextRange"));
295     xShapeProps->setPropertyValue(sTextRange, aAny);
296 
297     uno::Reference<drawing::XControlShape> xControlShape(xShape, uno::UNO_QUERY);
298     uno::Reference<awt::XControlModel> xControlModel(m_pImpl->rFormComponent, uno::UNO_QUERY);
299     xControlShape->setControl(xControlModel);
300 
301     m_pImpl->getDrawPage()->add(xShape);
302 
303     return true;
304 }
305 
306 }}
307