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 #ifndef EXTENSIONS_SOURCE_PROPCTRLR_FORMCOMPONENTHANDLER_HXX 29 #define EXTENSIONS_SOURCE_PROPCTRLR_FORMCOMPONENTHANDLER_HXX 30 31 #include "propertyhandler.hxx" 32 #include "sqlcommanddesign.hxx" 33 #include "pcrcommon.hxx" 34 #include <comphelper/uno3.hxx> 35 #include <comphelper/proparrhlp.hxx> 36 #include <comphelper/propertycontainer.hxx> 37 /** === begin UNO includes === **/ 38 #include <com/sun/star/frame/XModel.hpp> 39 #include <com/sun/star/beans/XPropertyState.hpp> 40 #include <com/sun/star/sdbc/XRowSet.hpp> 41 #include <com/sun/star/awt/XControlContainer.hpp> 42 #include <com/sun/star/form/XForm.hpp> 43 /** === end UNO includes === **/ 44 #include <tools/fldunit.hxx> 45 #include <vcl/waitobj.hxx> 46 #include <connectivity/dbtools.hxx> 47 48 #include <set> 49 50 //........................................................................ 51 namespace pcr 52 { 53 //........................................................................ 54 55 //==================================================================== 56 //= ComponentClassification 57 //==================================================================== 58 enum ComponentClassification 59 { 60 eFormControl, 61 eDialogControl, 62 eUnknown 63 }; 64 65 //==================================================================== 66 //= FormComponentPropertyHandler 67 //==================================================================== 68 class FormComponentPropertyHandler; 69 typedef HandlerComponentBase< FormComponentPropertyHandler > FormComponentPropertyHandler_Base; 70 typedef ::comphelper::OPropertyArrayUsageHelper<FormComponentPropertyHandler> FormComponentPropertyHandler_PROP; 71 /** default ->XPropertyHandler for all form components. 72 */ 73 class FormComponentPropertyHandler : public FormComponentPropertyHandler_Base, 74 public ::comphelper::OPropertyContainer, 75 public FormComponentPropertyHandler_PROP 76 { 77 private: 78 /// access to property states 79 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState > m_xPropertyState; 80 /// the parent of our component 81 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xObjectParent; 82 83 /// the database connection. Owned by us if and only if we created it ourself. 84 mutable ::dbtools::SharedConnection m_xRowSetConnection; 85 ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > m_xRowSet; 86 /** helper component encapsulating the handling for the QueryDesign component for 87 interactively designing an SQL command 88 */ 89 ::rtl::Reference< SQLCommandDesigner > m_xCommandDesigner; 90 ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI > m_xBrowserUI; 91 92 /// the string indicating a "default" (VOID) value in list-like controls 93 ::rtl::OUString m_sDefaultValueString; 94 /// all properties to whose control's we added ->m_sDefaultValueString 95 ::std::set< ::rtl::OUString > m_aPropertiesWithDefListEntry; 96 /// type of our component 97 ComponentClassification m_eComponentClass; 98 /// is our component a (database) sub form? 99 bool m_bComponentIsSubForm : 1; 100 /// our component has a "ListSource" property 101 bool m_bHaveListSource : 1; 102 /// our component has a "Command" property 103 bool m_bHaveCommand : 1; 104 /// the class id of the component - if appliable 105 sal_Int16 m_nClassId; 106 107 public: 108 FormComponentPropertyHandler( 109 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext 110 ); 111 112 DECLARE_XINTERFACE( ) 113 114 // XPropertySet 115 virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); 116 117 static ::rtl::OUString SAL_CALL getImplementationName_static( ) throw (::com::sun::star::uno::RuntimeException); 118 static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static( ) throw (::com::sun::star::uno::RuntimeException); 119 120 protected: 121 ~FormComponentPropertyHandler(); 122 123 protected: 124 virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; 125 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); 126 // XPropertyHandler overridables 127 virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 128 virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 129 virtual ::com::sun::star::uno::Any SAL_CALL convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rControlValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 130 virtual ::com::sun::star::uno::Any SAL_CALL convertToControlValue( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rPropertyValue, const ::com::sun::star::uno::Type& _rControlValueType ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 131 virtual ::com::sun::star::beans::PropertyState SAL_CALL getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 132 virtual void SAL_CALL addPropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException); 133 virtual void SAL_CALL removePropertyChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& _rxListener ) throw (::com::sun::star::uno::RuntimeException); 134 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupersededProperties() throw (::com::sun::star::uno::RuntimeException); 135 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getActuatingProperties() throw (::com::sun::star::uno::RuntimeException); 136 virtual ::com::sun::star::inspection::LineDescriptor SAL_CALL describePropertyLine( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); 137 virtual ::com::sun::star::inspection::InteractiveSelectionResult 138 SAL_CALL onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool _bPrimary, ::com::sun::star::uno::Any& _rData, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxInspectorUI ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); 139 virtual void SAL_CALL actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const ::com::sun::star::uno::Any& _rNewValue, const ::com::sun::star::uno::Any& _rOldValue, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ) throw (::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); 140 virtual sal_Bool SAL_CALL suspend( sal_Bool _bSuspend ) throw (::com::sun::star::uno::RuntimeException); 141 142 // XComponent 143 virtual void SAL_CALL disposing(); 144 145 // PropertyHandler 146 virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > 147 SAL_CALL doDescribeSupportedProperties() const; 148 virtual void onNewComponent(); 149 150 private: 151 /** initializes some (cached) meta data about the component 152 @throws RuntimeException 153 if a serious error occurs, for instance if the component does not provide an XPropertySetInfo instance 154 */ 155 void impl_initComponentMetaData_throw(); 156 157 /** classifies our component, in case it's a control model, by ClassId 158 159 Note that UNO dialog controls are also classified, though they don't have the ClassId property 160 */ 161 void impl_classifyControlModel_throw(); 162 163 /** const-version of ->getPropertyValue 164 */ 165 ::com::sun::star::uno::Any impl_getPropertyValue_throw( const ::rtl::OUString& _rPropertyName ) const; 166 167 // some property values are faked, and not used in the way they're provided by our component 168 void impl_normalizePropertyValue_nothrow( ::com::sun::star::uno::Any& _rValue, PropertyId _nPropId ) const; 169 170 /** determines whether we should exclude a given property from our "supported properties" 171 */ 172 bool impl_shouldExcludeProperty_nothrow( const ::com::sun::star::beans::Property& _rProperty ) const; 173 174 /** initializes the list of field names, if we're handling a control which supports the 175 DataField property 176 */ 177 void impl_initFieldList_nothrow( ::std::vector< ::rtl::OUString >& rFieldNames ) const; 178 179 /** obtaines the RowSet to which our component belongs 180 181 If the component is a RowSet itself, it's returned directly. Else, the parent 182 is examined for the XRowSet interface. If the parent is no XRowSet, then 183 a check is made whether our component is a grid control column, and if so, 184 the parent of the grid control is examied for the XRowSet interace. 185 186 Normally, at least one of those methods should succeed. 187 */ 188 ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > impl_getRowSet_throw( ) const; 189 190 /** nothrow-version of ->impl_getRowSet_throw 191 */ 192 ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > impl_getRowSet_nothrow( ) const; 193 194 /** connects the row set belonging to our introspected data aware form component, 195 and remembers the connection in ->m_xRowSetConnection. 196 197 If the row set already is connected, ->m_xRowSetConnection will be set, too, but 198 not take the ownership of the connection. 199 200 If ->m_xRowSetConnection is already set, nothing happens, so if you want to 201 force creation of a connection, you need to clear ->m_xRowSetConnection. 202 */ 203 bool impl_ensureRowsetConnection_nothrow() const; 204 205 /** clears ->m_xRowSetConnection 206 */ 207 void impl_clearRowsetConnection_nothrow(); 208 209 /** fills an ->LineDescriptor with information to represent a cursor source 210 of our form - that is, a table, a query, or an SQL statement. 211 212 As an example, if our form has currently a CommandType of TABLE, then the 213 value list in the LineDescriptor will contain a list of all tables 214 of the data source which the form is bound to. 215 216 @seealso impl_fillTableNames_throw 217 @seealso impl_fillQueryNames_throw 218 */ 219 void impl_describeCursorSource_nothrow( 220 ::com::sun::star::inspection::LineDescriptor& _out_rProperty, 221 const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory 222 ) const; 223 224 /** describes the UI for selecting a table name 225 226 @precond 227 m_xRowSetConnection is not <NULL/> 228 */ 229 void impl_fillTableNames_throw( ::std::vector< ::rtl::OUString >& _out_rNames ) const; 230 231 /** describes the UI for selecting a query name 232 233 @precond 234 m_xRowSetConnection is not <NULL/> 235 */ 236 void impl_fillQueryNames_throw( ::std::vector< ::rtl::OUString >& _out_rNames ) const; 237 238 /** describes the UI for selecting a query name 239 240 @precond 241 m_xRowSetConnection is not <NULL/> 242 */ 243 void impl_fillQueryNames_throw( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _xQueryNames 244 ,::std::vector< ::rtl::OUString >& _out_rNames 245 ,const ::rtl::OUString& _sName = ::rtl::OUString() ) const; 246 247 /** describes the UI for selecting a ListSource (for list-like form controls) 248 @precond 249 ->m_xRowSetConnection is not <NULL/> 250 @precond 251 ->m_xComponent is not <NULL/> 252 */ 253 void impl_describeListSourceUI_throw( 254 ::com::sun::star::inspection::LineDescriptor& _out_rDescriptor, 255 const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlFactory >& _rxControlFactory 256 ) const; 257 258 /** displays a datbase-related error to the user 259 */ 260 void impl_displaySQLError_nothrow( const ::dbtools::SQLExceptionInfo& _rErrorDescriptor ) const; 261 262 /** let's the user chose a selection of entries from a string list, and stores this 263 selection in the given property 264 @return 265 <TRUE/> if and only if the user successfully changed the property 266 */ 267 bool impl_dialogListSelection_nothrow( const ::rtl::OUString& _rProperty, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 268 269 /** executes a dialog for chosing a filter or sort criterion for a database form 270 @param _bFilter 271 <TRUE/> if the Filter property should be used, <FALSE/> if it's the Order 272 property 273 @param _out_rSelectedClause 274 the filter or order clause as chosen by the user 275 @precond 276 we're really inspecting a database form (well, a RowSet at least) 277 @return 278 <TRUE/> if and only if the user successfully chose a clause 279 */ 280 bool impl_dialogFilterOrSort_nothrow( bool _bFilter, ::rtl::OUString& _out_rSelectedClause, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 281 282 /** executes a dialog which allows the user to chose the columns linking 283 a sub to a master form, and sets the respective MasterFields / SlaveFields 284 properties at the form. 285 @precond 286 we're inspecting (sub) database form 287 @return 288 <TRUE/> if and only if the user successfully eneter master and slave fields 289 */ 290 bool impl_dialogLinkedFormFields_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 291 292 /** executes a dialog which allows the user to modify the FormatKey 293 property of our component, by chosing a (number) format. 294 @precond 295 Our component actually has a FormatKey property. 296 @param _out_rNewValue 297 the new property value, if the user chose a new formatting 298 @return 299 <TRUE/> if and only if a new formatting has been chosen by the user. 300 In this case, ->_out_rNewValue is filled with the new property value 301 */ 302 bool impl_dialogFormatting_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 303 304 /** executes a dialog which allows to the user to change the ImageURL property 305 of our component by browsing for an image file. 306 @precond 307 our component actually has a ImageURL property 308 @param _out_rNewValue 309 the new property value, if the user chose a new image url 310 @return 311 <TRUE/> if and only if a new image URL has been chosen by the user. 312 In this case, ->_out_rNewValue is filled with the new property value 313 */ 314 bool impl_browseForImage_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 315 316 /** executes a dialog which allows the user to change the TargetURL property of 317 our component 318 @precond 319 our component actually has a TargetURL property 320 @param _out_rNewValue 321 the new property value, if the user chose a new TargetURL 322 @return 323 <TRUE/> if and only if a new TargetURL has been chosen by the user. 324 In this case, ->_out_rNewValue is filled with the new property value 325 */ 326 bool impl_browseForTargetURL_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 327 328 /** executes a dialog which allows the user to change the font, plus related properties, 329 of our component 330 @precond 331 our component actually has a Font property 332 @param _out_rNewValue 333 a value desribing the new font, as <code>Sequence< NamedValue ></code> 334 @return 335 <TRUE/> if and only if the user successfully changed the font of our component 336 */ 337 bool impl_executeFontDialog_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 338 339 /** allows the user browsing for a database document 340 @precond 341 our component actually has a DataSource property 342 @param _out_rNewValue 343 the new property value, if the user chose a new DataSource 344 @return 345 <TRUE/> if and only if a new DataSource has been chosen by the user. 346 In this case, ->_out_rNewValue is filled with the new property value 347 */ 348 bool impl_browseForDatabaseDocument_throw( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 349 350 /** raises a dialog which allows the user to choose a color 351 @param _nColorPropertyId 352 the ID of the color property 353 @param _out_rNewValue 354 the chosen color value 355 @return 356 <TRUE/> if and only if a color was chosen by the user 357 */ 358 bool impl_dialogColorChooser_throw( sal_Int32 _nColorPropertyId, ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 359 360 /** raises a dialog which allows the user to choose a label control for our component 361 @param _out_rNewValue 362 the chosen label control, if any 363 @return 364 <TRUE/> if and only if a label control was chosen by the user 365 */ 366 bool impl_dialogChooseLabelControl_nothrow( ::com::sun::star::uno::Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 367 368 /** raises a dialog which lets the user chose the tab order of controls of a form 369 @precond 370 we have a view control container in which our controls live 371 @return 372 <TRUE/> if and only if the user successfully changed the tab order 373 @seealso impl_getContextControlContainer_nothrow 374 */ 375 bool impl_dialogChangeTabOrder_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const; 376 377 /** retrieves the context for controls, whose model(s) we're inspecting 378 379 If we're inspecting a control model, this is usually part of a set of controls 380 and control models, where the controls live in a certain context (a ->XControlContainer). 381 If we know this context, we can enable additional special functionality. 382 383 The ->XComponentContext in which we were created is examined for a value 384 named "ControlContext", and this value is returned. 385 */ 386 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlContainer > 387 impl_getContextControlContainer_nothrow() const; 388 389 /** opens a query design window for interactively designing the SQL command of a 390 database form 391 @param _rxUIUpdate 392 access to the property browser UI 393 @param _nDesignForProperty 394 the ID for the property for which the designer is opened 395 @return 396 <TRUE/> if the window was successfully opened, or was previously open, 397 <FALSE/> otherwise 398 */ 399 bool impl_doDesignSQLCommand_nothrow( 400 const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxInspectorUI, 401 PropertyId _nDesignForProperty 402 ); 403 404 /** updates a property (UI) whose state depends on more than one other property 405 406 ->actuatingPropertyChanged is called for certain properties in whose changes 407 we expressed interes (->getActuatingProperty). Now such a property change can 408 result in simple UI updates, for instance another property being enabled or disabled. 409 410 However, it can also result in a more complex change: The current (UI) state might 411 depend on the value of more than one other property. Those dependent properties (their 412 UI, more precisly) are updated in this method. 413 414 @param _nPropid 415 the ->PropertyId of the dependent property whose UI state is to be updated 416 417 @param _rxInspectorUI 418 provides access to the property browser UI. Must not be <NULL/>. 419 */ 420 void impl_updateDependentProperty_nothrow( PropertyId _nPropId, const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XObjectInspectorUI >& _rxInspectorUI ) const; 421 422 /** determines whether the given form has a valid data source signature. 423 424 Valid here means that the DataSource property denotes an existing data source, and the 425 Command property is not empty. No check is made whether the value of the Command property 426 denotes an existent object, since this would be way too expensive. 427 428 @param _xFormProperties 429 the form to check. Must not be <NULL/>. 430 @param _bAllowEmptyDataSourceName 431 determine whether an empty data source name is allowed (<TRUE/>), and should not 432 lead to rejection 433 */ 434 static bool impl_hasValidDataSourceSignature_nothrow( 435 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xFormProperties, 436 bool _bAllowEmptyDataSourceName ); 437 438 /** returns the URL of our context document 439 @return 440 */ 441 ::rtl::OUString impl_getDocumentURL_nothrow() const; 442 443 private: 444 DECL_LINK( OnDesignerClosed, void* ); 445 446 private: 447 FormComponentPropertyHandler(); // never implemented 448 FormComponentPropertyHandler( const FormComponentPropertyHandler& ); // never implemented 449 FormComponentPropertyHandler& operator=( const FormComponentPropertyHandler& ); // never implemented 450 451 private: 452 using ::comphelper::OPropertyContainer::addPropertyChangeListener; 453 using ::comphelper::OPropertyContainer::removePropertyChangeListener; 454 }; 455 456 //==================================================================== 457 //= WaitCursor 458 //==================================================================== 459 /** wrapper around a ->WaitObject which can cope with a NULL window 460 */ 461 class WaitCursor 462 { 463 private: 464 ::std::auto_ptr< WaitObject > m_aWaitObject; 465 466 public: 467 WaitCursor( Window* _pWindow ) 468 { 469 if ( _pWindow ) 470 m_aWaitObject.reset( new WaitObject( _pWindow ) ); 471 } 472 }; 473 474 //........................................................................ 475 } // namespace pcr 476 //........................................................................ 477 478 #endif // EXTENSIONS_SOURCE_PROPCTRLR_FORMCOMPONENTHANDLER_HXX 479 480