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 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <toolkit/helper/formpdfexport.hxx>
22 :
23 : #include <com/sun/star/container/XIndexAccess.hpp>
24 : #include <com/sun/star/container/XNameAccess.hpp>
25 : #include <com/sun/star/container/XNameContainer.hpp>
26 : #include <com/sun/star/form/XForm.hpp>
27 : #include <com/sun/star/container/XChild.hpp>
28 : #include <com/sun/star/lang/XServiceInfo.hpp>
29 : #include <com/sun/star/beans/XPropertySet.hpp>
30 : #include <com/sun/star/form/FormComponentType.hpp>
31 : #include <com/sun/star/awt/TextAlign.hpp>
32 : #include <com/sun/star/style/VerticalAlignment.hpp>
33 : #include <com/sun/star/form/FormButtonType.hpp>
34 : #include <com/sun/star/form/FormSubmitMethod.hpp>
35 :
36 : #include <toolkit/helper/vclunohelper.hxx>
37 : #include <vcl/pdfextoutdevdata.hxx>
38 : #include <vcl/outdev.hxx>
39 :
40 : #include <functional>
41 : #include <algorithm>
42 :
43 :
44 : namespace toolkitform
45 : {
46 :
47 :
48 : using namespace ::com::sun::star;
49 : using namespace ::com::sun::star::uno;
50 : using namespace ::com::sun::star::awt;
51 : using namespace ::com::sun::star::style;
52 : using namespace ::com::sun::star::beans;
53 : using namespace ::com::sun::star::form;
54 : using namespace ::com::sun::star::lang;
55 : using namespace ::com::sun::star::container;
56 :
57 : static const char FM_PROP_NAME[] = "Name";
58 :
59 : namespace
60 : {
61 :
62 : /** determines the FormComponentType of a form control
63 : */
64 0 : sal_Int16 classifyFormControl( const Reference< XPropertySet >& _rxModel )
65 : {
66 : static const char FM_PROP_CLASSID[] = "ClassId";
67 0 : sal_Int16 nControlType = FormComponentType::CONTROL;
68 :
69 0 : Reference< XPropertySetInfo > xPSI;
70 0 : if ( _rxModel.is() )
71 0 : xPSI = _rxModel->getPropertySetInfo();
72 0 : if ( xPSI.is() && xPSI->hasPropertyByName( FM_PROP_CLASSID ) )
73 : {
74 0 : OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_CLASSID ) >>= nControlType );
75 : }
76 :
77 0 : return nControlType;
78 : }
79 :
80 :
81 : /** (default-)creates a PDF widget according to a given FormComponentType
82 : */
83 0 : vcl::PDFWriter::AnyWidget* createDefaultWidget( sal_Int16 _nFormComponentType )
84 : {
85 0 : switch ( _nFormComponentType )
86 : {
87 : case FormComponentType::COMMANDBUTTON:
88 0 : return new vcl::PDFWriter::PushButtonWidget;
89 : case FormComponentType::CHECKBOX:
90 0 : return new vcl::PDFWriter::CheckBoxWidget;
91 : case FormComponentType::RADIOBUTTON:
92 0 : return new vcl::PDFWriter::RadioButtonWidget;
93 : case FormComponentType::LISTBOX:
94 0 : return new vcl::PDFWriter::ListBoxWidget;
95 : case FormComponentType::COMBOBOX:
96 0 : return new vcl::PDFWriter::ComboBoxWidget;
97 :
98 : case FormComponentType::TEXTFIELD:
99 : case FormComponentType::FILECONTROL:
100 : case FormComponentType::DATEFIELD:
101 : case FormComponentType::TIMEFIELD:
102 : case FormComponentType::NUMERICFIELD:
103 : case FormComponentType::CURRENCYFIELD:
104 : case FormComponentType::PATTERNFIELD:
105 0 : return new vcl::PDFWriter::EditWidget;
106 : }
107 0 : return NULL;
108 : }
109 :
110 :
111 : /** determines a unique number for the radio group which the given radio
112 : button model belongs to
113 :
114 : The number is guaranteed to be
115 : <ul><li>unique within the document in which the button lives</li>
116 : <li>the same for subsequent calls with other radio button models,
117 : which live in the same document, and belong to the same group</li>
118 : </ul>
119 :
120 : @precond
121 : the model must be part of the form component hierarchy in a document
122 : */
123 0 : sal_Int32 determineRadioGroupId( const Reference< XPropertySet >& _rxRadioModel )
124 : {
125 : OSL_ENSURE( classifyFormControl( _rxRadioModel ) == FormComponentType::RADIOBUTTON,
126 : "determineRadioGroupId: this *is* no radio button model!" );
127 : // The fact that radio button groups need to be unique within the complete
128 : // host document makes it somewhat difficult ...
129 : // Problem is that two form radio buttons belong to the same group if
130 : // - they have the same parent
131 : // - AND they have the same name
132 : // This implies that we need some knowledge about (potentially) *all* radio button
133 : // groups in the document.
134 :
135 : // get the root-level container
136 0 : Reference< XChild > xChild( _rxRadioModel, UNO_QUERY );
137 0 : Reference< XForm > xParentForm( xChild.is() ? xChild->getParent() : Reference< XInterface >(), UNO_QUERY );
138 : OSL_ENSURE( xParentForm.is(), "determineRadioGroupId: no parent form -> group id!" );
139 0 : if ( !xParentForm.is() )
140 0 : return -1;
141 :
142 0 : while ( xParentForm.is() )
143 : {
144 0 : xChild = xParentForm.get();
145 0 : xParentForm.set(xChild->getParent(), css::uno::UNO_QUERY);
146 : }
147 0 : Reference< XIndexAccess > xRoot( xChild->getParent(), UNO_QUERY );
148 : OSL_ENSURE( xRoot.is(), "determineRadioGroupId: unable to determine the root of the form component hierarchy!" );
149 0 : if ( !xRoot.is() )
150 0 : return -1;
151 :
152 : // count the leafs in the hierarchy, until we encounter radio button
153 0 : ::std::vector< Reference< XIndexAccess > > aAncestors;
154 0 : ::std::vector< sal_Int32 > aPath;
155 :
156 0 : Reference< XInterface > xNormalizedLookup( _rxRadioModel, UNO_QUERY );
157 0 : OUString sRadioGroupName;
158 0 : OSL_VERIFY( _rxRadioModel->getPropertyValue( OUString(FM_PROP_NAME) ) >>= sRadioGroupName );
159 :
160 0 : Reference< XIndexAccess > xCurrentContainer( xRoot );
161 0 : sal_Int32 nStartWithChild = 0;
162 0 : sal_Int32 nGroupsEncountered = 0;
163 : do
164 : {
165 0 : Reference< XNameAccess > xElementNameAccess( xCurrentContainer, UNO_QUERY );
166 : OSL_ENSURE( xElementNameAccess.is(), "determineRadioGroupId: no name container?" );
167 0 : if ( !xElementNameAccess.is() )
168 0 : return -1;
169 :
170 0 : if ( nStartWithChild == 0 )
171 : { // we encounter this container the first time. In particular, we did not
172 : // just step up
173 0 : nGroupsEncountered += xElementNameAccess->getElementNames().getLength();
174 : // this is way too much: Not all of the elements in the current container
175 : // may form groups, especially if they're forms. But anyway, this number is
176 : // sufficient for our purpose. Finally, the container contains *at most*
177 : // that much groups
178 : }
179 :
180 0 : sal_Int32 nCount = xCurrentContainer->getCount();
181 : sal_Int32 i;
182 0 : for ( i = nStartWithChild; i < nCount; ++i )
183 : {
184 0 : Reference< XInterface > xElement( xCurrentContainer->getByIndex( i ), UNO_QUERY );
185 0 : if ( !xElement.is() )
186 : {
187 : OSL_FAIL( "determineRadioGroupId: very suspicious!" );
188 0 : continue;
189 : }
190 :
191 0 : Reference< XIndexAccess > xNewContainer( xElement, UNO_QUERY );
192 0 : if ( xNewContainer.is() )
193 : {
194 : // step down the hierarchy
195 0 : aAncestors.push_back( xCurrentContainer );
196 0 : xCurrentContainer = xNewContainer;
197 0 : aPath.push_back( i );
198 0 : nStartWithChild = 0;
199 0 : break;
200 : // out of the inner loop, but continue with the outer loop
201 : }
202 :
203 0 : if ( xElement.get() == xNormalizedLookup.get() )
204 : {
205 : // look up the name of the radio group in the list of all element names
206 0 : Sequence< OUString > aElementNames( xElementNameAccess->getElementNames() );
207 0 : const OUString* pElementNames = aElementNames.getConstArray();
208 0 : const OUString* pElementNamesEnd = pElementNames + aElementNames.getLength();
209 0 : while ( pElementNames != pElementNamesEnd )
210 : {
211 0 : if ( *pElementNames == sRadioGroupName )
212 : {
213 0 : sal_Int32 nLocalGroupIndex = pElementNames - aElementNames.getConstArray();
214 : OSL_ENSURE( nLocalGroupIndex < xElementNameAccess->getElementNames().getLength(),
215 : "determineRadioGroupId: inconsistency!" );
216 :
217 0 : sal_Int32 nGlobalGroupId = nGroupsEncountered - xElementNameAccess->getElementNames().getLength() + nLocalGroupIndex;
218 0 : return nGlobalGroupId;
219 : }
220 0 : ++pElementNames;
221 : }
222 0 : OSL_FAIL( "determineRadioGroupId: did not find the radios element name!" );
223 : }
224 0 : }
225 :
226 0 : if ( !( i < nCount ) )
227 : {
228 : // the loop terminated because there were no more elements
229 : // -> step up, if possible
230 0 : if ( aAncestors.empty() )
231 0 : break;
232 :
233 0 : xCurrentContainer = aAncestors.back(); aAncestors.pop_back();
234 0 : nStartWithChild = aPath.back() + 1; aPath.pop_back();
235 0 : }
236 : }
237 : while ( true );
238 0 : return -1;
239 : }
240 :
241 :
242 : /** copies a StringItemList to a PDF widget's list
243 : */
244 0 : void getStringItemVector( const Reference< XPropertySet >& _rxModel, ::std::vector< OUString >& _rVector )
245 : {
246 : static const char FM_PROP_STRINGITEMLIST[] = "StringItemList";
247 0 : Sequence< OUString > aListEntries;
248 0 : OSL_VERIFY( _rxModel->getPropertyValue( FM_PROP_STRINGITEMLIST ) >>= aListEntries );
249 : ::std::copy( aListEntries.begin(), aListEntries.end(),
250 0 : ::std::back_insert_iterator< ::std::vector< OUString > >( _rVector ) );
251 0 : }
252 : }
253 :
254 :
255 : /** creates a PDF compatible control descriptor for the given control
256 : */
257 0 : std::unique_ptr<vcl::PDFWriter::AnyWidget> describePDFControl( const Reference< XControl >& _rxControl,
258 : vcl::PDFExtOutDevData& i_pdfExportData )
259 : {
260 0 : std::unique_ptr<vcl::PDFWriter::AnyWidget> Descriptor;
261 : OSL_ENSURE( _rxControl.is(), "describePDFControl: invalid (NULL) control!" );
262 0 : if ( !_rxControl.is() )
263 0 : return Descriptor;
264 :
265 : try
266 : {
267 0 : Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
268 0 : sal_Int16 nControlType = classifyFormControl( xModelProps );
269 0 : Descriptor.reset( createDefaultWidget( nControlType ) );
270 0 : if ( !Descriptor.get() )
271 : // no PDF widget available for this
272 0 : return Descriptor;
273 :
274 0 : Reference< XPropertySetInfo > xPSI( xModelProps->getPropertySetInfo() );
275 0 : Reference< XServiceInfo > xSI( xModelProps, UNO_QUERY );
276 : OSL_ENSURE( xSI.is(), "describePDFControl: no service info!" );
277 : // if we survived classifyFormControl, then it's a real form control, and they all have
278 : // service infos
279 :
280 :
281 : // set the common widget properties
282 :
283 :
284 : // Name, Description, Text
285 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_NAME ) >>= Descriptor->Name );
286 : static const char FM_PROP_HELPTEXT[] = "HelpText";
287 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_HELPTEXT ) >>= Descriptor->Description );
288 0 : Any aText;
289 : static const char FM_PROP_TEXT[] = "Text";
290 : static const char FM_PROP_LABEL[] = "Label";
291 0 : if ( xPSI->hasPropertyByName( FM_PROP_TEXT ) )
292 0 : aText = xModelProps->getPropertyValue( FM_PROP_TEXT );
293 0 : else if ( xPSI->hasPropertyByName( FM_PROP_LABEL ) )
294 0 : aText = xModelProps->getPropertyValue( FM_PROP_LABEL );
295 0 : if ( aText.hasValue() )
296 0 : OSL_VERIFY( aText >>= Descriptor->Text );
297 :
298 :
299 : // readonly
300 : static const char FM_PROP_READONLY[] = "ReadOnly";
301 0 : if ( xPSI->hasPropertyByName( FM_PROP_READONLY ) )
302 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_READONLY ) >>= Descriptor->ReadOnly );
303 :
304 :
305 : // border
306 : {
307 : static const char FM_PROP_BORDER[] = "Border";
308 0 : if ( xPSI->hasPropertyByName( FM_PROP_BORDER ) )
309 : {
310 0 : sal_Int16 nBorderType = 0;
311 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_BORDER ) >>= nBorderType );
312 0 : Descriptor->Border = ( nBorderType != 0 );
313 :
314 0 : OUString sBorderColorPropertyName( "BorderColor" );
315 0 : if ( xPSI->hasPropertyByName( sBorderColorPropertyName ) )
316 : {
317 0 : sal_Int32 nBoderColor = COL_TRANSPARENT;
318 0 : if ( xModelProps->getPropertyValue( sBorderColorPropertyName ) >>= nBoderColor )
319 0 : Descriptor->BorderColor = Color( nBoderColor );
320 : else
321 0 : Descriptor->BorderColor = Color( COL_BLACK );
322 0 : }
323 : }
324 : }
325 :
326 :
327 : // background color
328 : static const char FM_PROP_BACKGROUNDCOLOR[] = "BackgroundColor";
329 0 : if ( xPSI->hasPropertyByName( FM_PROP_BACKGROUNDCOLOR ) )
330 : {
331 0 : sal_Int32 nBackColor = COL_TRANSPARENT;
332 0 : xModelProps->getPropertyValue( FM_PROP_BACKGROUNDCOLOR ) >>= nBackColor;
333 0 : Descriptor->Background = true;
334 0 : Descriptor->BackgroundColor = Color( nBackColor );
335 : }
336 :
337 :
338 : // text color
339 : static const char FM_PROP_TEXTCOLOR[] = "TextColor";
340 0 : if ( xPSI->hasPropertyByName( FM_PROP_TEXTCOLOR ) )
341 : {
342 0 : sal_Int32 nTextColor = COL_TRANSPARENT;
343 0 : xModelProps->getPropertyValue( FM_PROP_TEXTCOLOR ) >>= nTextColor;
344 0 : Descriptor->TextColor = Color( nTextColor );
345 : }
346 :
347 :
348 : // text style
349 0 : Descriptor->TextStyle = DrawTextFlags::NONE;
350 :
351 : // multi line and word break
352 : // The MultiLine property of the control is mapped to both the "MULTILINE" and
353 : // "WORDBREAK" style flags
354 : static const char FM_PROP_MULTILINE[] = "MultiLine";
355 0 : if ( xPSI->hasPropertyByName( FM_PROP_MULTILINE ) )
356 : {
357 0 : bool bMultiLine = false;
358 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_MULTILINE ) >>= bMultiLine );
359 0 : if ( bMultiLine )
360 0 : Descriptor->TextStyle |= DrawTextFlags::MultiLine | DrawTextFlags::WordBreak;
361 : }
362 :
363 : // horizontal alignment
364 : static const char FM_PROP_ALIGN[] = "Align";
365 0 : if ( xPSI->hasPropertyByName( FM_PROP_ALIGN ) )
366 : {
367 0 : sal_Int16 nAlign = awt::TextAlign::LEFT;
368 0 : xModelProps->getPropertyValue( FM_PROP_ALIGN ) >>= nAlign;
369 : // TODO: when the property is VOID - are there situations/UIs where this
370 : // means something else than LEFT?
371 0 : switch ( nAlign )
372 : {
373 0 : case awt::TextAlign::LEFT: Descriptor->TextStyle |= DrawTextFlags::Left; break;
374 0 : case awt::TextAlign::CENTER: Descriptor->TextStyle |= DrawTextFlags::Center; break;
375 0 : case awt::TextAlign::RIGHT: Descriptor->TextStyle |= DrawTextFlags::Right; break;
376 : default:
377 : OSL_FAIL( "describePDFControl: invalid text align!" );
378 : }
379 : }
380 :
381 : // vertical alignment
382 : {
383 0 : OUString sVertAlignPropertyName( "VerticalAlign" );
384 0 : if ( xPSI->hasPropertyByName( sVertAlignPropertyName ) )
385 : {
386 0 : sal_Int16 nAlign = VerticalAlignment_MIDDLE;
387 0 : xModelProps->getPropertyValue( sVertAlignPropertyName ) >>= nAlign;
388 0 : switch ( nAlign )
389 : {
390 0 : case VerticalAlignment_TOP: Descriptor->TextStyle |= DrawTextFlags::Top; break;
391 0 : case VerticalAlignment_MIDDLE: Descriptor->TextStyle |= DrawTextFlags::VCenter; break;
392 0 : case VerticalAlignment_BOTTOM: Descriptor->TextStyle |= DrawTextFlags::Bottom; break;
393 : default:
394 : OSL_FAIL( "describePDFControl: invalid vertical text align!" );
395 : }
396 0 : }
397 : }
398 :
399 : // font
400 : static const char FM_PROP_FONT[] = "FontDescriptor";
401 0 : if ( xPSI->hasPropertyByName( FM_PROP_FONT ) )
402 : {
403 0 : FontDescriptor aUNOFont;
404 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_FONT ) >>= aUNOFont );
405 0 : Descriptor->TextFont = VCLUnoHelper::CreateFont( aUNOFont, vcl::Font() );
406 : }
407 :
408 : // tab order
409 0 : OUString aTabIndexString( "TabIndex" );
410 0 : if ( xPSI->hasPropertyByName( aTabIndexString ) )
411 : {
412 0 : sal_Int16 nIndex = -1;
413 0 : OSL_VERIFY( xModelProps->getPropertyValue( aTabIndexString ) >>= nIndex );
414 0 : Descriptor->TabOrder = nIndex;
415 : }
416 :
417 :
418 : // special widget properties
419 :
420 : // edits
421 0 : if ( Descriptor->getType() == vcl::PDFWriter::Edit )
422 : {
423 0 : vcl::PDFWriter::EditWidget* pEditWidget = static_cast< vcl::PDFWriter::EditWidget* >( Descriptor.get() );
424 :
425 : // multiline (already flagged in the TextStyle)
426 0 : pEditWidget->MultiLine = bool( Descriptor->TextStyle & DrawTextFlags::MultiLine );
427 :
428 : // password input
429 0 : OUString sEchoCharPropName( "EchoChar" );
430 0 : if ( xPSI->hasPropertyByName( sEchoCharPropName ) )
431 : {
432 0 : sal_Int16 nEchoChar = 0;
433 0 : if ( ( xModelProps->getPropertyValue( sEchoCharPropName ) >>= nEchoChar ) && ( nEchoChar != 0 ) )
434 0 : pEditWidget->Password = true;
435 : }
436 :
437 : // file select
438 : static const char FM_SUN_COMPONENT_FILECONTROL[] = "com.sun.star.form.component.FileControl";
439 0 : if ( xSI->supportsService( FM_SUN_COMPONENT_FILECONTROL ) )
440 0 : pEditWidget->FileSelect = true;
441 :
442 : // maximum text length
443 : static const char FM_PROP_MAXTEXTLEN[] = "MaxTextLen";
444 0 : if ( xPSI->hasPropertyByName( FM_PROP_MAXTEXTLEN ) )
445 : {
446 0 : sal_Int16 nMaxTextLength = 0;
447 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_MAXTEXTLEN ) >>= nMaxTextLength );
448 0 : if ( nMaxTextLength <= 0 )
449 : // "-1" has a special meaning for database-bound controls
450 0 : nMaxTextLength = 0;
451 0 : pEditWidget->MaxLen = nMaxTextLength;
452 0 : }
453 : }
454 :
455 :
456 : // buttons
457 0 : if ( Descriptor->getType() == vcl::PDFWriter::PushButton )
458 : {
459 0 : vcl::PDFWriter::PushButtonWidget* pButtonWidget = static_cast< vcl::PDFWriter::PushButtonWidget* >( Descriptor.get() );
460 0 : FormButtonType eButtonType = FormButtonType_PUSH;
461 0 : OSL_VERIFY( xModelProps->getPropertyValue("ButtonType") >>= eButtonType );
462 : static const char FM_PROP_TARGET_URL[] = "TargetURL";
463 0 : if ( eButtonType == FormButtonType_SUBMIT )
464 : {
465 : // if a button is a submit button, then it uses the URL at its parent form
466 0 : Reference< XChild > xChild( xModelProps, UNO_QUERY );
467 0 : Reference < XPropertySet > xParentProps;
468 0 : if ( xChild.is() )
469 0 : xParentProps.set(xChild->getParent(), css::uno::UNO_QUERY);
470 0 : if ( xParentProps.is() )
471 : {
472 0 : Reference< XServiceInfo > xParentSI( xParentProps, UNO_QUERY );
473 0 : if ( xParentSI.is() && xParentSI->supportsService("com.sun.star.form.component.HTMLForm") )
474 : {
475 0 : OSL_VERIFY( xParentProps->getPropertyValue( FM_PROP_TARGET_URL ) >>= pButtonWidget->URL );
476 0 : pButtonWidget->Submit = true;
477 0 : FormSubmitMethod eMethod = FormSubmitMethod_POST;
478 0 : OSL_VERIFY( xParentProps->getPropertyValue("SubmitMethod") >>= eMethod );
479 0 : pButtonWidget->SubmitGet = (eMethod == FormSubmitMethod_GET);
480 0 : }
481 0 : }
482 : }
483 0 : else if ( eButtonType == FormButtonType_URL )
484 : {
485 0 : OUString sURL;
486 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_TARGET_URL ) >>= sURL );
487 0 : const bool bDocumentLocalTarget = sURL.startsWith("#");
488 0 : if ( bDocumentLocalTarget )
489 : {
490 : // Register the destination for future handling ...
491 0 : pButtonWidget->Dest = i_pdfExportData.RegisterDest();
492 :
493 : // and put it into the bookmarks, to ensure the future handling really happens
494 0 : ::std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks( i_pdfExportData.GetBookmarks() );
495 0 : vcl::PDFExtOutDevBookmarkEntry aBookmark;
496 0 : aBookmark.nDestId = pButtonWidget->Dest;
497 0 : aBookmark.aBookmark = sURL;
498 0 : rBookmarks.push_back( aBookmark );
499 : }
500 : else
501 0 : pButtonWidget->URL = sURL;
502 :
503 0 : pButtonWidget->Submit = false;
504 : }
505 :
506 : // TODO:
507 : // In PDF files, buttons are either reset, url or submit buttons. So if we have a simple PUSH button
508 : // in a document, then this means that we do not export a SubmitToURL, which means that in PDF,
509 : // the button is used as reset button.
510 : // Is this desired? If no, we would have to reset Descriptor to NULL here, in case eButtonType
511 : // != FormButtonType_SUBMIT && != FormButtonType_RESET
512 :
513 : // the PDF exporter defaults the text style, if 0. To prevent this, we have to transfer the UNO
514 : // defaults to the PDF widget
515 0 : if ( pButtonWidget->TextStyle == DrawTextFlags::NONE )
516 0 : pButtonWidget->TextStyle = DrawTextFlags::Center | DrawTextFlags::VCenter;
517 : }
518 :
519 :
520 : // check boxes
521 : static const char FM_PROP_STATE[] = "State";
522 0 : if ( Descriptor->getType() == vcl::PDFWriter::CheckBox )
523 : {
524 0 : vcl::PDFWriter::CheckBoxWidget* pCheckBoxWidget = static_cast< vcl::PDFWriter::CheckBoxWidget* >( Descriptor.get() );
525 0 : sal_Int16 nState = 0;
526 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_STATE ) >>= nState );
527 0 : pCheckBoxWidget->Checked = ( nState != 0 );
528 : }
529 :
530 :
531 : // radio buttons
532 0 : if ( Descriptor->getType() == vcl::PDFWriter::RadioButton )
533 : {
534 0 : vcl::PDFWriter::RadioButtonWidget* pRadioWidget = static_cast< vcl::PDFWriter::RadioButtonWidget* >( Descriptor.get() );
535 0 : sal_Int16 nState = 0;
536 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_STATE ) >>= nState );
537 0 : pRadioWidget->Selected = ( nState != 0 );
538 0 : pRadioWidget->RadioGroup = determineRadioGroupId( xModelProps );
539 : try
540 : {
541 : static const char FM_PROP_REFVALUE[] = "RefValue";
542 0 : xModelProps->getPropertyValue( FM_PROP_REFVALUE ) >>= pRadioWidget->OnValue;
543 : }
544 0 : catch(...)
545 : {
546 0 : pRadioWidget->OnValue = "On";
547 : }
548 : }
549 :
550 :
551 : // list boxes
552 0 : if ( Descriptor->getType() == vcl::PDFWriter::ListBox )
553 : {
554 0 : vcl::PDFWriter::ListBoxWidget* pListWidget = static_cast< vcl::PDFWriter::ListBoxWidget* >( Descriptor.get() );
555 :
556 : // drop down
557 : static const char FM_PROP_DROPDOWN[] = "Dropdown";
558 0 : OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_DROPDOWN ) >>= pListWidget->DropDown );
559 :
560 : // multi selection
561 0 : OSL_VERIFY( xModelProps->getPropertyValue("MultiSelection") >>= pListWidget->MultiSelect );
562 :
563 : // entries
564 0 : getStringItemVector( xModelProps, pListWidget->Entries );
565 : // since we explicitly list the entries in the order in which they appear, they should not be
566 : // resorted by the PDF viewer
567 0 : pListWidget->Sort = false;
568 :
569 : // get selected items
570 0 : Sequence< sal_Int16 > aSelectIndices;
571 0 : OSL_VERIFY( xModelProps->getPropertyValue("SelectedItems") >>= aSelectIndices );
572 0 : if( aSelectIndices.getLength() > 0 )
573 : {
574 0 : pListWidget->SelectedEntries.resize( 0 );
575 0 : for( sal_Int32 i = 0; i < aSelectIndices.getLength(); i++ )
576 : {
577 0 : sal_Int16 nIndex = aSelectIndices.getConstArray()[i];
578 0 : if( nIndex >= 0 && nIndex < (sal_Int16)pListWidget->Entries.size() )
579 0 : pListWidget->SelectedEntries.push_back( nIndex );
580 : }
581 0 : }
582 : }
583 :
584 :
585 : // combo boxes
586 0 : if ( Descriptor->getType() == vcl::PDFWriter::ComboBox )
587 : {
588 0 : vcl::PDFWriter::ComboBoxWidget* pComboWidget = static_cast< vcl::PDFWriter::ComboBoxWidget* >( Descriptor.get() );
589 :
590 : // entries
591 0 : getStringItemVector( xModelProps, pComboWidget->Entries );
592 : // same reasoning as above
593 0 : pComboWidget->Sort = false;
594 : }
595 :
596 :
597 : // some post-processing
598 :
599 : // text line ends
600 : // some controls may (always or dependent on other settings) return UNIX line ends
601 0 : Descriptor->Text = convertLineEnd(Descriptor->Text, LINEEND_CRLF);
602 : }
603 0 : catch( const Exception& )
604 : {
605 : OSL_FAIL( "describePDFControl: caught an exception!" );
606 : }
607 0 : return Descriptor;
608 : }
609 :
610 :
611 : } // namespace toolkitform
612 :
613 :
614 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|