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