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 .
21 #include <toolkit/helper/formpdfexport.hxx>
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>
36 #include <toolkit/helper/vclunohelper.hxx>
37 #include <vcl/pdfextoutdevdata.hxx>
38 #include <vcl/outdev.hxx>
43 //........................................................................
46 //........................................................................
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
;
57 static const char FM_PROP_NAME
[] = "Name";
61 //--------------------------------------------------------------------
62 /** determines the FormComponentType of a form control
64 sal_Int16
classifyFormControl( const Reference
< XPropertySet
>& _rxModel
) SAL_THROW(( Exception
))
66 static const OUString
FM_PROP_CLASSID("ClassId");
67 sal_Int16 nControlType
= FormComponentType::CONTROL
;
69 Reference
< XPropertySetInfo
> xPSI
;
71 xPSI
= _rxModel
->getPropertySetInfo();
72 if ( xPSI
.is() && xPSI
->hasPropertyByName( FM_PROP_CLASSID
) )
74 OSL_VERIFY( _rxModel
->getPropertyValue( FM_PROP_CLASSID
) >>= nControlType
);
80 //--------------------------------------------------------------------
81 /** (default-)creates a PDF widget according to a given FormComponentType
83 ::vcl::PDFWriter::AnyWidget
* createDefaultWidget( sal_Int16 _nFormComponentType
)
85 switch ( _nFormComponentType
)
87 case FormComponentType::COMMANDBUTTON
:
88 return new ::vcl::PDFWriter::PushButtonWidget
;
89 case FormComponentType::CHECKBOX
:
90 return new ::vcl::PDFWriter::CheckBoxWidget
;
91 case FormComponentType::RADIOBUTTON
:
92 return new ::vcl::PDFWriter::RadioButtonWidget
;
93 case FormComponentType::LISTBOX
:
94 return new ::vcl::PDFWriter::ListBoxWidget
;
95 case FormComponentType::COMBOBOX
:
96 return new ::vcl::PDFWriter::ComboBoxWidget
;
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 return new ::vcl::PDFWriter::EditWidget
;
110 //--------------------------------------------------------------------
111 /** determines a unique number for the radio group which the given radio
112 button model belongs to
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>
121 the model must be part of the form component hierarchy in a document
123 sal_Int32
determineRadioGroupId( const Reference
< XPropertySet
>& _rxRadioModel
) SAL_THROW((Exception
))
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.
135 // get the root-level container
136 Reference
< XChild
> xChild( _rxRadioModel
, UNO_QUERY
);
137 Reference
< XForm
> xParentForm( xChild
.is() ? xChild
->getParent() : Reference
< XInterface
>(), UNO_QUERY
);
138 OSL_ENSURE( xParentForm
.is(), "determineRadioGroupId: no parent form -> group id!" );
139 if ( !xParentForm
.is() )
142 while ( xParentForm
.is() )
144 xChild
= xParentForm
.get();
145 xParentForm
= xParentForm
.query( xChild
->getParent() );
147 Reference
< XIndexAccess
> xRoot( xChild
->getParent(), UNO_QUERY
);
148 OSL_ENSURE( xRoot
.is(), "determineRadioGroupId: unable to determine the root of the form component hierarchy!" );
152 // count the leafs in the hierarchy, until we encounter radio button
153 ::std::vector
< Reference
< XIndexAccess
> > aAncestors
;
154 ::std::vector
< sal_Int32
> aPath
;
156 Reference
< XInterface
> xNormalizedLookup( _rxRadioModel
, UNO_QUERY
);
157 OUString sRadioGroupName
;
158 OSL_VERIFY( _rxRadioModel
->getPropertyValue( OUString(FM_PROP_NAME
) ) >>= sRadioGroupName
);
160 Reference
< XIndexAccess
> xCurrentContainer( xRoot
);
161 sal_Int32 nStartWithChild
= 0;
162 sal_Int32 nGroupsEncountered
= 0;
165 Reference
< XNameAccess
> xElementNameAccess( xCurrentContainer
, UNO_QUERY
);
166 OSL_ENSURE( xElementNameAccess
.is(), "determineRadioGroupId: no name container?" );
167 if ( !xElementNameAccess
.is() )
170 if ( nStartWithChild
== 0 )
171 { // we encounter this container the first time. In particular, we did not
173 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*
180 sal_Int32 nCount
= xCurrentContainer
->getCount();
182 for ( i
= nStartWithChild
; i
< nCount
; ++i
)
184 Reference
< XInterface
> xElement( xCurrentContainer
->getByIndex( i
), UNO_QUERY
);
185 if ( !xElement
.is() )
187 OSL_FAIL( "determineRadioGroupId: very suspicious!" );
191 Reference
< XIndexAccess
> xNewContainer( xElement
, UNO_QUERY
);
192 if ( xNewContainer
.is() )
194 // step down the hierarchy
195 aAncestors
.push_back( xCurrentContainer
);
196 xCurrentContainer
= xNewContainer
;
197 aPath
.push_back( i
);
200 // out of the inner loop, but continue with the outer loop
203 if ( xElement
.get() == xNormalizedLookup
.get() )
205 // look up the name of the radio group in the list of all element names
206 Sequence
< OUString
> aElementNames( xElementNameAccess
->getElementNames() );
207 const OUString
* pElementNames
= aElementNames
.getConstArray();
208 const OUString
* pElementNamesEnd
= pElementNames
+ aElementNames
.getLength();
209 while ( pElementNames
!= pElementNamesEnd
)
211 if ( *pElementNames
== sRadioGroupName
)
213 sal_Int32 nLocalGroupIndex
= pElementNames
- aElementNames
.getConstArray();
214 OSL_ENSURE( nLocalGroupIndex
< xElementNameAccess
->getElementNames().getLength(),
215 "determineRadioGroupId: inconsistency!" );
217 sal_Int32 nGlobalGroupId
= nGroupsEncountered
- xElementNameAccess
->getElementNames().getLength() + nLocalGroupIndex
;
218 return nGlobalGroupId
;
222 OSL_FAIL( "determineRadioGroupId: did not find the radios element name!" );
226 if ( !( i
< nCount
) )
228 // the loop terminated because there were no more elements
229 // -> step up, if possible
230 if ( aAncestors
.empty() )
233 xCurrentContainer
= aAncestors
.back(); aAncestors
.pop_back();
234 nStartWithChild
= aPath
.back() + 1; aPath
.pop_back();
241 //--------------------------------------------------------------------
242 /** copies a StringItemList to a PDF widget's list
244 void getStringItemVector( const Reference
< XPropertySet
>& _rxModel
, ::std::vector
< OUString
>& _rVector
)
246 static const OUString
FM_PROP_STRINGITEMLIST("StringItemList");
247 Sequence
< OUString
> aListEntries
;
248 OSL_VERIFY( _rxModel
->getPropertyValue( FM_PROP_STRINGITEMLIST
) >>= aListEntries
);
249 ::std::copy( aListEntries
.getConstArray(), aListEntries
.getConstArray() + aListEntries
.getLength(),
250 ::std::back_insert_iterator
< ::std::vector
< OUString
> >( _rVector
) );
254 //--------------------------------------------------------------------
255 /** creates a PDF compatible control descriptor for the given control
257 void TOOLKIT_DLLPUBLIC
describePDFControl( const Reference
< XControl
>& _rxControl
,
258 ::std::auto_ptr
< ::vcl::PDFWriter::AnyWidget
>& _rpDescriptor
, ::vcl::PDFExtOutDevData
& i_pdfExportData
) SAL_THROW(())
260 _rpDescriptor
.reset( NULL
);
261 OSL_ENSURE( _rxControl
.is(), "describePDFControl: invalid (NULL) control!" );
262 if ( !_rxControl
.is() )
267 Reference
< XPropertySet
> xModelProps( _rxControl
->getModel(), UNO_QUERY
);
268 sal_Int16 nControlType
= classifyFormControl( xModelProps
);
269 _rpDescriptor
.reset( createDefaultWidget( nControlType
) );
270 if ( !_rpDescriptor
.get() )
271 // no PDF widget available for this
274 Reference
< XPropertySetInfo
> xPSI( xModelProps
->getPropertySetInfo() );
275 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
280 // ================================
281 // set the common widget properties
283 // --------------------------------
284 // Name, Description, Text
285 OSL_VERIFY( xModelProps
->getPropertyValue( OUString(FM_PROP_NAME
) ) >>= _rpDescriptor
->Name
);
286 static const OUString
FM_PROP_HELPTEXT("HelpText");
287 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_HELPTEXT
) >>= _rpDescriptor
->Description
);
289 static const OUString
FM_PROP_TEXT("Text");
290 static const OUString
FM_PROP_LABEL("Label");
291 if ( xPSI
->hasPropertyByName( FM_PROP_TEXT
) )
292 aText
= xModelProps
->getPropertyValue( FM_PROP_TEXT
);
293 else if ( xPSI
->hasPropertyByName( FM_PROP_LABEL
) )
294 aText
= xModelProps
->getPropertyValue( FM_PROP_LABEL
);
295 if ( aText
.hasValue() )
296 OSL_VERIFY( aText
>>= _rpDescriptor
->Text
);
298 // --------------------------------
300 static const OUString
FM_PROP_READONLY("ReadOnly");
301 if ( xPSI
->hasPropertyByName( FM_PROP_READONLY
) )
302 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_READONLY
) >>= _rpDescriptor
->ReadOnly
);
304 // --------------------------------
307 static const OUString
FM_PROP_BORDER("Border");
308 if ( xPSI
->hasPropertyByName( FM_PROP_BORDER
) )
310 sal_Int16 nBorderType
= 0;
311 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_BORDER
) >>= nBorderType
);
312 _rpDescriptor
->Border
= ( nBorderType
!= 0 );
314 OUString
sBorderColorPropertyName( "BorderColor" );
315 if ( xPSI
->hasPropertyByName( sBorderColorPropertyName
) )
317 sal_Int32 nBoderColor
= COL_TRANSPARENT
;
318 if ( xModelProps
->getPropertyValue( sBorderColorPropertyName
) >>= nBoderColor
)
319 _rpDescriptor
->BorderColor
= Color( nBoderColor
);
321 _rpDescriptor
->BorderColor
= Color( COL_BLACK
);
326 // --------------------------------
328 static const OUString
FM_PROP_BACKGROUNDCOLOR("BackgroundColor");
329 if ( xPSI
->hasPropertyByName( FM_PROP_BACKGROUNDCOLOR
) )
331 sal_Int32 nBackColor
= COL_TRANSPARENT
;
332 xModelProps
->getPropertyValue( FM_PROP_BACKGROUNDCOLOR
) >>= nBackColor
;
333 _rpDescriptor
->Background
= true;
334 _rpDescriptor
->BackgroundColor
= Color( nBackColor
);
337 // --------------------------------
339 static const OUString
FM_PROP_TEXTCOLOR("TextColor");
340 if ( xPSI
->hasPropertyByName( FM_PROP_TEXTCOLOR
) )
342 sal_Int32 nTextColor
= COL_TRANSPARENT
;
343 xModelProps
->getPropertyValue( FM_PROP_TEXTCOLOR
) >>= nTextColor
;
344 _rpDescriptor
->TextColor
= Color( nTextColor
);
347 // --------------------------------
349 _rpDescriptor
->TextStyle
= 0;
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 OUString
FM_PROP_MULTILINE("MultiLine");
355 if ( xPSI
->hasPropertyByName( FM_PROP_MULTILINE
) )
357 sal_Bool bMultiLine
= sal_False
;
358 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_MULTILINE
) >>= bMultiLine
);
360 _rpDescriptor
->TextStyle
|= TEXT_DRAW_MULTILINE
| TEXT_DRAW_WORDBREAK
;
362 // ............................
363 // horizontal alignment
364 static const OUString
FM_PROP_ALIGN("Align");
365 if ( xPSI
->hasPropertyByName( FM_PROP_ALIGN
) )
367 sal_Int16 nAlign
= awt::TextAlign::LEFT
;
368 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?
373 case awt::TextAlign::LEFT
: _rpDescriptor
->TextStyle
|= TEXT_DRAW_LEFT
; break;
374 case awt::TextAlign::CENTER
: _rpDescriptor
->TextStyle
|= TEXT_DRAW_CENTER
; break;
375 case awt::TextAlign::RIGHT
: _rpDescriptor
->TextStyle
|= TEXT_DRAW_RIGHT
; break;
377 OSL_FAIL( "describePDFControl: invalid text align!" );
380 // ............................
381 // vertical alignment
383 OUString
sVertAlignPropertyName( "VerticalAlign" );
384 if ( xPSI
->hasPropertyByName( sVertAlignPropertyName
) )
386 sal_Int16 nAlign
= VerticalAlignment_MIDDLE
;
387 xModelProps
->getPropertyValue( sVertAlignPropertyName
) >>= nAlign
;
390 case VerticalAlignment_TOP
: _rpDescriptor
->TextStyle
|= TEXT_DRAW_TOP
; break;
391 case VerticalAlignment_MIDDLE
: _rpDescriptor
->TextStyle
|= TEXT_DRAW_VCENTER
; break;
392 case VerticalAlignment_BOTTOM
: _rpDescriptor
->TextStyle
|= TEXT_DRAW_BOTTOM
; break;
394 OSL_FAIL( "describePDFControl: invalid vertical text align!" );
400 static const OUString
FM_PROP_FONT("FontDescriptor");
401 if ( xPSI
->hasPropertyByName( FM_PROP_FONT
) )
403 FontDescriptor aUNOFont
;
404 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_FONT
) >>= aUNOFont
);
405 _rpDescriptor
->TextFont
= VCLUnoHelper::CreateFont( aUNOFont
, Font() );
409 OUString
aTabIndexString( "TabIndex" );
410 if ( xPSI
->hasPropertyByName( aTabIndexString
) )
412 sal_Int16 nIndex
= -1;
413 OSL_VERIFY( xModelProps
->getPropertyValue( aTabIndexString
) >>= nIndex
);
414 _rpDescriptor
->TabOrder
= nIndex
;
417 // ================================
418 // special widget properties
419 // --------------------------------
421 if ( _rpDescriptor
->getType() == ::vcl::PDFWriter::Edit
)
423 ::vcl::PDFWriter::EditWidget
* pEditWidget
= static_cast< ::vcl::PDFWriter::EditWidget
* >( _rpDescriptor
.get() );
424 // ............................
425 // multiline (already flagged in the TextStyle)
426 pEditWidget
->MultiLine
= ( _rpDescriptor
->TextStyle
& TEXT_DRAW_MULTILINE
) != 0;
427 // ............................
429 OUString
sEchoCharPropName( "EchoChar" );
430 if ( xPSI
->hasPropertyByName( sEchoCharPropName
) )
432 sal_Int16 nEchoChar
= 0;
433 if ( ( xModelProps
->getPropertyValue( sEchoCharPropName
) >>= nEchoChar
) && ( nEchoChar
!= 0 ) )
434 pEditWidget
->Password
= true;
436 // ............................
438 static const OUString
FM_SUN_COMPONENT_FILECONTROL("com.sun.star.form.component.FileControl");
439 if ( xSI
->supportsService( FM_SUN_COMPONENT_FILECONTROL
) )
440 pEditWidget
->FileSelect
= true;
441 // ............................
442 // maximum text length
443 static const OUString
FM_PROP_MAXTEXTLEN("MaxTextLen");
444 if ( xPSI
->hasPropertyByName( FM_PROP_MAXTEXTLEN
) )
446 sal_Int16 nMaxTextLength
= 0;
447 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_MAXTEXTLEN
) >>= nMaxTextLength
);
448 if ( nMaxTextLength
<= 0 )
449 // "-1" has a special meaning for database-bound controls
451 pEditWidget
->MaxLen
= nMaxTextLength
;
455 // --------------------------------
457 if ( _rpDescriptor
->getType() == ::vcl::PDFWriter::PushButton
)
459 ::vcl::PDFWriter::PushButtonWidget
* pButtonWidget
= static_cast< ::vcl::PDFWriter::PushButtonWidget
* >( _rpDescriptor
.get() );
460 FormButtonType eButtonType
= FormButtonType_PUSH
;
461 OSL_VERIFY( xModelProps
->getPropertyValue( OUString( "ButtonType" ) ) >>= eButtonType
);
462 static const OUString
FM_PROP_TARGET_URL("TargetURL");
463 if ( eButtonType
== FormButtonType_SUBMIT
)
465 // if a button is a submit button, then it uses the URL at it's parent form
466 Reference
< XChild
> xChild( xModelProps
, UNO_QUERY
);
467 Reference
< XPropertySet
> xParentProps
;
469 xParentProps
= xParentProps
.query( xChild
->getParent() );
470 if ( xParentProps
.is() )
472 Reference
< XServiceInfo
> xParentSI( xParentProps
, UNO_QUERY
);
473 if ( xParentSI
.is() && xParentSI
->supportsService( OUString( "com.sun.star.form.component.HTMLForm" ) ) )
475 OSL_VERIFY( xParentProps
->getPropertyValue( FM_PROP_TARGET_URL
) >>= pButtonWidget
->URL
);
476 pButtonWidget
->Submit
= true;
477 FormSubmitMethod eMethod
= FormSubmitMethod_POST
;
478 OSL_VERIFY( xParentProps
->getPropertyValue( OUString( "SubmitMethod" ) ) >>= eMethod
);
479 pButtonWidget
->SubmitGet
= (eMethod
== FormSubmitMethod_GET
);
483 else if ( eButtonType
== FormButtonType_URL
)
486 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_TARGET_URL
) >>= sURL
);
487 const bool bDocumentLocalTarget
= !sURL
.isEmpty() && ( sURL
.getStr()[0] == '#' );
488 if ( bDocumentLocalTarget
)
490 // Register the destination for for future handling ...
491 pButtonWidget
->Dest
= i_pdfExportData
.RegisterDest();
493 // and put it into the bookmarks, to ensure the future handling really happens
494 ::std::vector
< ::vcl::PDFExtOutDevBookmarkEntry
>& rBookmarks( i_pdfExportData
.GetBookmarks() );
495 ::vcl::PDFExtOutDevBookmarkEntry aBookmark
;
496 aBookmark
.nDestId
= pButtonWidget
->Dest
;
497 aBookmark
.aBookmark
= sURL
;
498 rBookmarks
.push_back( aBookmark
);
501 pButtonWidget
->URL
= sURL
;
503 pButtonWidget
->Submit
= false;
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 _rpDescriptor to NULL here, in case eButtonType
511 // != FormButtonType_SUBMIT && != FormButtonType_RESET
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 if ( !pButtonWidget
->TextStyle
)
516 pButtonWidget
->TextStyle
= TEXT_DRAW_CENTER
| TEXT_DRAW_VCENTER
;
519 // --------------------------------
521 static const OUString
FM_PROP_STATE("State");
522 if ( _rpDescriptor
->getType() == ::vcl::PDFWriter::CheckBox
)
524 ::vcl::PDFWriter::CheckBoxWidget
* pCheckBoxWidget
= static_cast< ::vcl::PDFWriter::CheckBoxWidget
* >( _rpDescriptor
.get() );
525 sal_Int16 nState
= 0;
526 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_STATE
) >>= nState
);
527 pCheckBoxWidget
->Checked
= ( nState
!= 0 );
530 // --------------------------------
532 if ( _rpDescriptor
->getType() == ::vcl::PDFWriter::RadioButton
)
534 ::vcl::PDFWriter::RadioButtonWidget
* pRadioWidget
= static_cast< ::vcl::PDFWriter::RadioButtonWidget
* >( _rpDescriptor
.get() );
535 sal_Int16 nState
= 0;
536 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_STATE
) >>= nState
);
537 pRadioWidget
->Selected
= ( nState
!= 0 );
538 pRadioWidget
->RadioGroup
= determineRadioGroupId( xModelProps
);
541 static const OUString
FM_PROP_REFVALUE("RefValue");
542 xModelProps
->getPropertyValue( FM_PROP_REFVALUE
) >>= pRadioWidget
->OnValue
;
546 pRadioWidget
->OnValue
= OUString( "On" );
550 // --------------------------------
552 if ( _rpDescriptor
->getType() == ::vcl::PDFWriter::ListBox
)
554 ::vcl::PDFWriter::ListBoxWidget
* pListWidget
= static_cast< ::vcl::PDFWriter::ListBoxWidget
* >( _rpDescriptor
.get() );
555 // ............................
557 static const OUString
FM_PROP_DROPDOWN("Dropdown");
558 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_DROPDOWN
) >>= pListWidget
->DropDown
);
559 // ............................
561 OSL_VERIFY( xModelProps
->getPropertyValue( OUString( "MultiSelection" ) ) >>= pListWidget
->MultiSelect
);
562 // ............................
564 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 pListWidget
->Sort
= false;
569 // get selected items
570 Sequence
< sal_Int16
> aSelectIndices
;
571 OSL_VERIFY( xModelProps
->getPropertyValue( OUString( "SelectedItems" ) ) >>= aSelectIndices
);
572 if( aSelectIndices
.getLength() > 0 )
574 pListWidget
->SelectedEntries
.resize( 0 );
575 for( sal_Int32 i
= 0; i
< aSelectIndices
.getLength(); i
++ )
577 sal_Int16 nIndex
= aSelectIndices
.getConstArray()[i
];
578 if( nIndex
>= 0 && nIndex
< (sal_Int16
)pListWidget
->Entries
.size() )
579 pListWidget
->SelectedEntries
.push_back( nIndex
);
584 // --------------------------------
586 if ( _rpDescriptor
->getType() == ::vcl::PDFWriter::ComboBox
)
588 ::vcl::PDFWriter::ComboBoxWidget
* pComboWidget
= static_cast< ::vcl::PDFWriter::ComboBoxWidget
* >( _rpDescriptor
.get() );
589 // ............................
591 getStringItemVector( xModelProps
, pComboWidget
->Entries
);
592 // same reasoning as above
593 pComboWidget
->Sort
= false;
596 // ================================
597 // some post-processing
598 // --------------------------------
600 // some controls may (always or dependent on other settings) return UNIX line ends
601 _rpDescriptor
->Text
= convertLineEnd(_rpDescriptor
->Text
, LINEEND_CRLF
);
603 catch( const Exception
& )
605 OSL_FAIL( "describePDFControl: caught an exception!" );
609 //........................................................................
610 } // namespace toolkitform
611 //........................................................................
613 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */