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         }
189     }
190 
191     m_pImpl->aSize.Width = nCheckBoxHeight;
192     m_pImpl->aSize.Height = m_pImpl->aSize.Width;
193 
194     uno::Any aAny;
195     if (m_pFFData->getStatusText().getLength())
196     {
197         aAny <<= m_pFFData->getStatusText();
198 
199         xPropSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpText")), aAny);
200     }
201 
202     aAny <<= m_pFFData->getCheckboxChecked();
203     xPropSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultState")), aAny);
204 
205     if (m_pFFData->getHelpText().getLength())
206     {
207         aAny <<= m_pFFData->getHelpText();
208         xPropSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpF1Text")), aAny);
209     }
210 
211     aAny <<= rControlName;
212     xPropSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), aAny);
213 
214     return true;
215 }
216 
insertControl(uno::Reference<text::XTextRange> xTextRange)217 bool FormControlHelper::insertControl(uno::Reference<text::XTextRange> xTextRange)
218 {
219     bool bCreated = false;
220 
221     uno::Reference<container::XNameContainer> xFormCompsByName(m_pImpl->getForm(), uno::UNO_QUERY);
222     uno::Reference<container::XIndexContainer> xFormComps(m_pImpl->getFormComps());
223     if (! xFormComps.is())
224         return false;
225 
226     static ::rtl::OUString sControl(RTL_CONSTASCII_USTRINGPARAM("Control"));
227 
228     sal_Int32 nControl = 0;
229     bool bDone = false;
230     ::rtl::OUString sControlName;
231 
232     do
233     {
234         ::rtl::OUString sTmp(sControl);
235         sTmp += ::rtl::OUString::valueOf(nControl);
236 
237         nControl++;
238         if (! xFormCompsByName->hasByName(sTmp))
239         {
240             sControlName = sTmp;
241             bDone = true;
242         }
243     }
244     while (! bDone);
245 
246     switch (m_pImpl->m_eFieldId)
247     {
248     case FIELD_FORMCHECKBOX:
249         bCreated = createCheckbox(xTextRange, sControlName);
250         break;
251     default:
252         break;
253     }
254 
255     if (!bCreated)
256         return false;
257 
258     uno::Any aAny(m_pImpl->rFormComponent);
259     xFormComps->insertByIndex(xFormComps->getCount(), aAny);
260 
261     if (! m_pImpl->getServiceFactory().is())
262         return false;
263 
264     uno::Reference<uno::XInterface> xInterface =
265         m_pImpl->getServiceFactory()->createInstance
266         (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.ControlShape")));
267 
268     if (! xInterface.is())
269         return false;
270 
271     uno::Reference<drawing::XShape> xShape(xInterface, uno::UNO_QUERY);
272 
273     if (! xShape.is())
274         return false;
275 
276     xShape->setSize(m_pImpl->aSize);
277 
278     uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
279 
280     sal_uInt16 nTmp = text::TextContentAnchorType_AS_CHARACTER;
281     aAny <<= nTmp;
282 
283     static const ::rtl::OUString sAnchorType(RTL_CONSTASCII_USTRINGPARAM("AnchorType"));
284     xShapeProps->setPropertyValue(sAnchorType, aAny);
285 
286     static const ::rtl::OUString sVertOrient(RTL_CONSTASCII_USTRINGPARAM("VertOrient"));
287     nTmp = text::VertOrientation::CENTER;
288     aAny <<= nTmp;
289     xShapeProps->setPropertyValue(sVertOrient, aAny);
290 
291     aAny <<= xTextRange;
292 
293     static const ::rtl::OUString sTextRange(RTL_CONSTASCII_USTRINGPARAM("TextRange"));
294     xShapeProps->setPropertyValue(sTextRange, aAny);
295 
296     uno::Reference<drawing::XControlShape> xControlShape(xShape, uno::UNO_QUERY);
297     uno::Reference<awt::XControlModel> xControlModel(m_pImpl->rFormComponent, uno::UNO_QUERY);
298     xControlShape->setControl(xControlModel);
299 
300     m_pImpl->getDrawPage()->add(xShape);
301 
302     return true;
303 }
304 
305 }}
306